Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /** \addtogroup group_i2c I2C
- * For software I2C define functions/macros
- * USE_I2C_SOFT
- * i2c_soft_delay_halfbit(),
- * i2c_soft_scl_wr_0(),
- * i2c_soft_scl_wr_1(),
- * i2c_soft_sda_wr_0()
- * i2c_soft_sda_wr_1()
- * For AVR hardware I2C realization define constant
- * USE_I2C_AVR
- */
- #ifndef I2C_INCLUDED
- #define I2C_INCLUDED
- #ifdef USE_I2C_SOFT
- /** \brief START generation <br>генерация START \ingroup group_i2c */
- void i2c_soft_start(void);
- /** \brief generate STOP condition <br>генерация условия STOP \ingroup group_i2c */
- void i2c_soft_stop(void);
- /** \brief write 1 bit to I2C bus <br>записать 1 бит на I2C \ingroup group_i2c */
- void i2c_soft_wr_bit(U8 abit);
- /** \brief read 1 bit from I2C bus to 0th bit of result <br>прочитать 1 бит из I2C \ingroup group_i2c */
- U8 i2c_soft_rd_bit(void);
- /** \brief write 1 byte to I2C, returns ACK bit <br>записать 1 байт, возвращает бит ACK \ingroup group_i2c */
- U8 i2c_soft_wr_U8(U8 abyte);
- /** \brief read 1 byte from I2C, then writes ACK bit <br>прочитать байт из I2C и записать бит ACK \ingroup group_i2c */
- U8 i2c_soft_rd_U8(U8 bit_ack);
- /** \brief check presence or busy state of I2C device with bus address i2c_addr, return 0 if ack received, else status code <br>проверить наличие ответа от устройства с адресом i2c_adr, возвращает состояние ACK \ingroup group_i2c */
- U8 i2c_soft_chkack(U8 i2c_addr);
- #define i2c_start i2c_soft_start
- #define i2c_stop i2c_soft_stop
- #define i2c_wr_U8 i2c_soft_wr_U8
- #define i2c_rd_U8 i2c_soft_rd_U8
- #define i2c_chkack i2c_soft_chkack
- #endif
- //to include AVR hardware I2C realization define use_i2c_avr (если нужно, подключить функции аппаратного I2C AVR)
- #ifdef USE_I2C_AVR
- #define I2C_AVR_CMD_START ((1 << TWINT)|(1 << TWEN)|(1 << TWSTA)) /** \brief AVR TWI START command <br>команда для генерации условия START \ingroup group_i2c */
- #define I2C_AVR_CMD_STOP ((1 << TWINT)|(1 << TWEN)|(1 << TWSTO)) /** \brief AVR TWI STOP command <br>команда для генерации условия STOP \ingroup group_i2c */
- #define I2C_AVR_CMD_WR ((1 << TWINT)|(1 << TWEN)) /** \brief AVR TWI write byte command <br>команда записи байта \ingroup group_i2c */
- #define I2C_AVR_CMD_RD_ACK ((1 << TWINT)|(1 << TWEN)|(1 << TWEA)) /** \brief AVR TWI read byte command, ACK <br>команда чтения байта с выдачей ACK \ingroup group_i2c */
- #define I2C_AVR_CMD_RD_NACK ((1 << TWINT)|(1 << TWEN)) /** \brief AVR TWI read byte command, NO ACK <br>команда чтения байта с выдачей NO ACK \ingroup group_i2c */
- #define I2C_AVR_STATUS_MASK (0xf8) /**< mask for status bits of AVR TWI <br>маска битов статуса TWI \ingroup group_i2c */
- #define i2c_avr_busy() (!(TWCR & (1 << TWINT))) /** \brief AVR TWI busy flag <br>проверка занятости модуля TWI \ingroup group_i2c */
- #define i2c_avr_start() i2c_avr_cmd_wait(I2C_AVR_CMD_START) /**< \brief use AVR hardware for START generation \ingroup group_i2c */
- #define i2c_avr_stop() {i2c_avr_cmd(I2C_AVR_CMD_STOP); delay_us(5);} /**< \brief use AVR hardware for STOP generation \ingroup group_i2c */
- /** \brief wait for AVR TWI action to end <br>ожидание завершения выполнения команды TWI \ingroup group_i2c */
- void i2c_avr_wait(void);
- /** \brief execute TWI command cmd<br>выполнить команду \ingroup group_i2c */
- void i2c_avr_cmd(U8 cmd);
- /** \brief process AVR TWI command: TWCR=action, wait, return status of operation <br>выполнить команду, вернуть статус ее завершения \ingroup group_i2c */
- U8 i2c_avr_cmd_wait(U8 cmd);
- /** \brief check presence or busy state of I2C device with bus address i2c_addr, return 0 if ack received, else status code <br>проверить наличие ответа от устройства с адресом i2c_adr, возвращает состояние ACK \ingroup group_i2c */
- U8 i2c_avr_chkack(U8 i2c_addr);
- /** \brief write 1 byte to I2C, return ACK bit <br>записать 1 байт, возвращает бит ACK \ingroup group_i2c */
- U8 i2c_avr_wr_U8(U8 abyte);
- /** \brief read 1 byte from I2C, then write ACK bit <br>прочитать байт из I2C и записать бит ACK \ingroup group_i2c */
- U8 i2c_avr_rd_U8(U8 ack_bit);
- #define i2c_start i2c_avr_start
- #define i2c_stop i2c_avr_stop
- #define i2c_wr_U8 i2c_avr_wr_U8
- #define i2c_rd_U8 i2c_avr_rd_U8
- #define i2c_chkack i2c_avr_chkack
- #endif
- /** \brief write \b buf_size bytes from \b *buf starting from 8-bit \b addr_start to device with 8-bit address \b addr_i2c <br>записать блок данных в устройство с 8-битной адресацией \b addr_i2c \ingroup group_i2c */
- U8 i2c_wr_a8_buf8(U8 addr_i2c, U8 addr_start, U8 *buf, U8 buf_size);
- /** \brief read \b buf_size bytes to \b *buf starting from 8-bit \b addr_start to device with 8-bit address \b addr_i2c <br>прочитать блок данных из устройства с 8-битовой адресацией \ingroup group_i2c */
- U8 i2c_rd_a8_buf8(U8 addr_i2c, U8 addr_start, U8 *buf, U8 buf_size);
- // DS1307 definitions
- #define DS1307_ADDR 0xd0
- #define DS1307_SIZE 0x3f
- #define DS1307_REGS_SIZE 0x08
- #define DS1307_SECOND 0x00
- #define DS1307_MINUTE 0x01
- #define DS1307_HOUR 0x02
- #define DS1307_DAY 0x03
- #define DS1307_DATE 0x04
- #define DS1307_MONTH 0x05
- #define DS1307_YEAR 0x06
- #define DS1307_CNTR 0x07
- #define DS1307_CH 0x80
- #define DS1307_12_24 0x40
- #define DS1307_AM_PM 0x20
- #define DS1307_OUT 0x80
- #define DS1307_SQWE 0x10
- #define DS1307_RS1 0x02
- #define DS1307_RS0 0x01
- // DS3231 definitions
- #define DS3231_ADDR 0xd0
- #define DS3231_SIZE 0x13
- #define DS3231_REGS_SIZE 0x13
- #define DS3231_SECOND 0x00
- #define DS3231_MINUTE 0x01
- #define DS3231_HOUR 0x02
- #define DS3231_DAY 0x03
- #define DS3231_DATE 0x04
- #define DS3231_MONTH 0x05
- #define DS3231_YEAR 0x06
- #define DS3231_ALM1_SEC 0x07
- #define DS3231_ALM1_MIN 0x08
- #define DS3231_ALM1_HOUR 0x09
- #define DS3231_ALM1_DAY 0x0a
- #define DS3231_ALM1_DATE 0x0a
- #define DS3231_ALM2_MIN 0x0b
- #define DS3231_ALM2_HOUR 0x0c
- #define DS3231_ALM2_DAY 0x0d
- #define DS3231_ALM2_DATE 0x0d
- #define DS3231_CNTR 0x0e
- #define DS3231_STAT 0x0f
- #define DS3231_AGING 0x10
- #define DS3231_TEMP_MSB 0x11
- #define DS3231_TEMP_LSB 0x12
- #define DS3231_12_24 0x40
- #define DS3231_AM_PM 0x20
- #define DS3231_DY_DT 0x40
- #define DS3231_EOSC 0x80
- #define DS3231_BBSQW 0x40
- #define DS3231_CONV 0x20
- #define DS3231_RS2 0x10
- #define DS3231_RS1 0x08
- #define DS3231_INTCN 0x04
- #define DS3231_A2IE 0x02
- #define DS3231_A1IE 0x01
- #define DS3231_OSF 0x80
- #define DS3231_EN32KHZ 0x08
- #define DS3231_BSY 0x04
- #define DS3231_A2F 0x02
- #define DS3231_A1F 0x01
- // DS3232 definitions
- #define DS3232_ADDR 0xd0
- #define DS3232_SIZE 0x100
- #define DS3232_REGS_SIZE 0x13
- // M41T56 definitions
- #define M41T56_ADDR 0xd0
- #define M41T56_SIZE 0x3f
- #define M41T56_REGS_SIZE 0x08
- #define M41T56_SECOND 0x00
- #define M41T56_MINUTE 0x01
- #define M41T56_HOUR 0x02
- #define M41T56_DAY 0x03
- #define M41T56_DATE 0x04
- #define M41T56_MONTH 0x05
- #define M41T56_YEAR 0x06
- #define M41T56_CNTR 0x07
- #define M41T56_ST 0x80
- #define M41T56_CEB 0x80
- #define M41T56_CB 0x40
- #define M41T56_OUT 0x80
- #define M41T56_FT 0x40
- #define M41T56_S 0x20
- // PCF8563 definitions
- #define PCF8563_ADDR 0xa2
- #define PCF8563_SIZE 0x0f
- #define PCF8563_REGS_SIZE 0x0f
- #define PCF8563_SECOND 0x02
- #define PCF8563_MINUTE 0x03
- #define PCF8563_HOUR 0x04
- #define PCF8563_DAY 0x05
- #define PCF8563_WEEKDAY 0x06
- #define PCF8563_MONTH 0x07
- #define PCF8563_YEAR 0x08
- #define PCF8563_ALM_MIN 0x09
- #define PCF8563_ALM_HOUR 0x0a
- #define PCF8563_ALM_DAY 0x0b
- #define PCF8563_ALM_WEEKDAY 0x0c
- #define PCF8563_CNTR1 0x00
- #define PCF8563_CNTR2 0x01
- #define PCF8563_CLKOUT 0x0d
- #define PCF8563_TIMER 0x0e
- #define PCF8563_TIMER_CD 0x0f
- #define PCF8563_VL 0x80
- #define PCF8563_C 0x80
- #define PCF8563_TEST1 0x80
- #define PCF8563_STOP 0x20
- #define PCF8563_TESTC 0x08
- #define PCF8563_TI_TP 0x10
- #define PCF8563_AF 0x08
- #define PCF8563_TF 0x04
- #define PCF8563_AIE 0x02
- #define PCF8563_TIE 0x01
- #define PCF8563_FE 0x80
- #define PCF8563_FD1 0x02
- #define PCF8563_FD0 0x01
- #define PCF8563_TE 0x80
- #define PCF8563_TD1 0x02
- #define PCF8563_TD0 0x01
- #endif
- //--------------------------------------------------------------------------------------------
- #include "ul_i2c.h"
- // Soft I2C
- #ifdef USE_I2C_SOFT
- void i2c_soft_start(void) {
- //prepare SDA level in case of repeated start (подготовить уровень на SDA перед стартом)
- i2c_soft_scl_wr_0();
- i2c_soft_sda_wr_1(); i2c_soft_delay_halfbit();
- //1-0 transition on SDA while SCL=1 (перепад на SDA 1-0 при SCL=1)
- i2c_soft_scl_wr_1(); i2c_soft_delay_halfbit();
- i2c_soft_sda_wr_0(); i2c_soft_delay_halfbit();
- i2c_soft_scl_wr_0(); i2c_soft_delay_halfbit();
- }
- void i2c_soft_stop(void) {
- //0-1 transition on SDA while SCL=1 (перепад на SDA 0-1 при SCL=1)
- i2c_soft_sda_wr_0(); i2c_soft_delay_halfbit();
- i2c_soft_scl_wr_1(); i2c_soft_delay_halfbit();
- i2c_soft_sda_wr_1(); i2c_soft_delay_halfbit();
- }
- void i2c_soft_wr_bit(U8 abit) {
- if (abit) i2c_soft_sda_wr_1(); else i2c_soft_sda_wr_0(); i2c_soft_delay_halfbit();
- i2c_soft_scl_wr_1(); i2c_soft_delay_halfbit();
- i2c_soft_scl_wr_0(); i2c_soft_delay_halfbit();
- }
- U8 i2c_soft_rd_bit(void) {
- U8 bit_in;
- i2c_soft_sda_wr_1(); i2c_soft_delay_halfbit();
- i2c_soft_scl_wr_1(); i2c_soft_delay_halfbit();
- bit_in = i2c_soft_sda_rd();
- i2c_soft_scl_wr_0(); i2c_soft_delay_halfbit();
- return(bit_in);
- }
- U8 i2c_soft_wr_U8(U8 abyte) {
- for (U8 bits_cnt = 8; bits_cnt; bits_cnt--) {
- i2c_soft_wr_bit(abyte & 0x80);
- abyte <<= 1;
- }
- return(i2c_soft_rd_bit());
- }
- U8 i2c_soft_rd_U8(U8 bit_ack) {
- U8 result = 0;
- for (U8 bits_cnt = 8; bits_cnt; bits_cnt--) {
- result <<= 1;
- if (i2c_soft_rd_bit()) result |= 1;
- }
- i2c_soft_wr_bit(bit_ack);
- return(result);
- }
- U8 i2c_soft_chkack(U8 i2c_addr) {
- U8 result;
- i2c_soft_start(); /*START*/
- result = i2c_soft_wr_U8( i2c_addr & 0xfe ); /*send device address in write mode*/
- if (result) result = 1; /*if ACK received,return 0, else 1*/
- i2c_soft_stop(); /*STOP*/
- return(result); /*return 0 if ACK received, else 1*/
- }
- #endif
- //to include AVR hardware I2C realization define use_i2c_avr (если нужно, подключить функции аппаратного I2C AVR)
- #ifdef USE_I2C_AVR
- void i2c_avr_wait(void) {
- while (i2c_avr_busy());
- }
- void i2c_avr_cmd(U8 cmd) {
- TWCR = cmd;
- }
- U8 i2c_avr_cmd_wait(U8 cmd) {
- i2c_avr_cmd(cmd);
- i2c_avr_wait();
- return(TWSR);
- }
- U8 i2c_avr_chkack(U8 i2c_addr) {
- U8 result;
- i2c_avr_start(); /*START*/
- TWDR = i2c_addr & 0xfe; /*send device address in write mode*/
- result = i2c_avr_cmd_wait(I2C_AVR_CMD_WR);
- if (result == 0x18) result = 0; else result = 1; /*if ACK received,return 0*/
- i2c_avr_stop(); /*STOP*/
- return(result); /*return 0 if ACK received, else result of operation*/
- }
- U8 i2c_avr_wr_U8(U8 abyte) {
- TWDR = abyte;
- i2c_avr_cmd_wait(I2C_AVR_CMD_WR);
- return(TWSR & 8);
- }
- U8 i2c_avr_rd_U8(U8 ack_bit) {
- i2c_avr_cmd_wait(ack_bit ? I2C_AVR_CMD_RD_NACK : I2C_AVR_CMD_RD_ACK);
- return(TWDR);
- }
- #endif
- U8 i2c_wr_a8_buf8(U8 addr_i2c, U8 addr_start, U8 *buf, U8 buf_size) {
- i2c_start();
- i2c_wr_U8(addr_i2c);
- i2c_wr_U8(addr_start);
- while (buf_size) {
- i2c_wr_U8(*buf);
- buf++;
- buf_size--;
- }
- i2c_stop();
- return(0);
- }
- U8 i2c_rd_a8_buf8(U8 addr_i2c, U8 addr_start, U8 *buf, U8 buf_size) {
- /*setup starting address*/
- i2c_start();
- i2c_wr_U8(addr_i2c);
- i2c_wr_U8(addr_start);
- /*if size>0 start reading*/
- if (buf_size) {
- /*repeated start for reading*/
- i2c_start();
- i2c_wr_U8(addr_i2c | 1);
- while (buf_size) {
- /*read next byte to buffer, generate NA in the end*/
- buf_size--;
- *buf = i2c_rd_U8(buf_size == 0);
- buf++;
- }
- }
- /*stop all transactions*/
- i2c_stop();
- return(0);
- }
- #ifdef USE_I2C_PAGED
- //for paged EEPROM read/write define use_i2c_paged (если нужно, подключить функции для записи в устройства с страничной организацией)
- U8 i2c_paged_dev_addr; /**< \brief I2C paged device address <br>адрес устройства \ingroup group_i2c */
- U16 i2c_paged_size; /**< \brief I2C paged device size <br>размер \ingroup group_i2c */
- U8 i2c_paged_page_mask; /**< \brief I2C paged device page address mask <br>маска адреса страницы \ingroup group_i2c */
- U16 i2c_paged_byte_addr; /**< \brief I2C paged device byte address <br>текущий адрес записи \ingroup group_i2c */
- U8 i2c_paged_flags; /**< \brief I2C paged device state <br>текущее состояние записи и другие флаги \ingroup group_i2c */
- #define I2C_PAGED_FLAG_STARTED 1 /**< \brief I2C paged device write started <br>=1 если запись страницы уже начата \ingroup group_i2c */
- #define I2C_PAGED_FLAG_16BIT 2 /**< \brief I2C paged device uses 16-bit address <br>=1 для использования 16-битной адресации \ingroup group_i2c */
- /** \brief start paged write to I2C device <br>начать страничную запись \ingroup group_i2c */
- void i2c_paged_wr_start(U8 dev_addr, U16 byte_addr) {
- i2c_paged_dev_addr = dev_addr; //remember device address (запомнить адрес устройства)
- i2c_paged_byte_addr = byte_addr; //remember starting byte (запомнить адрес первого байта)
- i2c_paged_flags &= ~I2C_PAGED_FLAG_STARTED; //clear started flag (обнулить флаг начала записи)
- }
- /** \brief end paged write to I2C device <br>завершить страничную запись \ingroup group_i2c */
- void i2c_paged_wr_stop(void) {
- //if data was written, stop writing and wait to the end of write cycle (если данные уже записывались, прекратить запись и ожидать завершения цикла записи)
- if (i2c_paged_flags & I2C_PAGED_FLAG_STARTED) {
- i2c_stop(); //I2C STOP
- //ACK polling (проверка завершения записи страницы)
- while (i2c_chkack(i2c_paged_dev_addr));
- }
- i2c_stop(); //I2C STOP
- i2c_paged_flags &= ~I2C_PAGED_FLAG_STARTED; //clear STARTED flag (обнулить флаг начатой записи)
- }
- /** \brief paged mode byte write <br>побайтовая запись в страничном режиме \ingroup group_i2c */
- void i2c_paged_wr_U8(U8 adata) {
- //if not overflow, write (если достигнут полный объем, не писать больше)
- if (i2c_paged_byte_addr < i2c_paged_size) {
- //if first data, setup address (если начало записи, дать команду начала записи и настроить адрес)
- if ((i2c_paged_flags & I2C_PAGED_FLAG_STARTED) == 0) {
- //mark that writing was started (отметить что запись уже происходила)
- i2c_paged_flags |= I2C_PAGED_FLAG_STARTED;
- i2c_start();
- //write device address, write mode (записать адрес устройства)
- i2c_wr_U8(i2c_paged_dev_addr);
- //if necessary, write high address byte (в 16-битном режиме адресации записать старший байт адреса)
- if (i2c_paged_flags & I2C_PAGED_FLAG_16BIT) i2c_wr_U8(i2c_paged_byte_addr >> 8);
- //write low address byte (записать младший байт адреса)
- i2c_wr_U8(i2c_paged_byte_addr);
- }
- i2c_wr_U8(adata); //write data byte (записать байт данных)
- i2c_paged_byte_addr++; //increment byte address (увеличить счетчик адреса)
- //if end of current page, end write cycle (если достигнут конец страницы, завершить ее запись)
- if (((U8)i2c_paged_byte_addr & i2c_paged_page_mask) == 0) i2c_paged_wr_stop();
- }
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement