Advertisement
edartuz

ul_i2c

Feb 26th, 2012
317
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.90 KB | None | 0 0
  1. /** \addtogroup group_i2c I2C
  2.   * For software I2C define functions/macros
  3.   *     USE_I2C_SOFT
  4.   *     i2c_soft_delay_halfbit(),
  5.   *     i2c_soft_scl_wr_0(),
  6.   *     i2c_soft_scl_wr_1(),
  7.   *     i2c_soft_sda_wr_0()
  8.   *     i2c_soft_sda_wr_1()
  9.   * For AVR hardware I2C realization define constant
  10.   *     USE_I2C_AVR
  11.   */
  12.  
  13. #ifndef I2C_INCLUDED
  14.     #define I2C_INCLUDED
  15.  
  16.  
  17. #ifdef USE_I2C_SOFT
  18.     /** \brief START generation <br>генерация START \ingroup group_i2c */
  19.     void i2c_soft_start(void);
  20.     /** \brief generate STOP condition <br>генерация условия STOP \ingroup group_i2c */
  21.     void i2c_soft_stop(void);
  22.     /** \brief write 1 bit to I2C bus <br>записать 1 бит на I2C \ingroup group_i2c */
  23.     void i2c_soft_wr_bit(U8 abit);
  24.     /** \brief read 1 bit from I2C bus to 0th bit of result <br>прочитать 1 бит из I2C \ingroup group_i2c */
  25.     U8 i2c_soft_rd_bit(void);
  26.     /** \brief write 1 byte to I2C, returns ACK bit <br>записать 1 байт, возвращает бит ACK \ingroup group_i2c */
  27.     U8 i2c_soft_wr_U8(U8 abyte);
  28.     /** \brief read 1 byte from I2C, then writes ACK bit <br>прочитать байт из I2C и записать бит ACK \ingroup group_i2c */
  29.     U8 i2c_soft_rd_U8(U8 bit_ack);
  30.     /** \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 */
  31.     U8 i2c_soft_chkack(U8 i2c_addr);
  32.  
  33.     #define i2c_start i2c_soft_start
  34.     #define i2c_stop i2c_soft_stop
  35.     #define i2c_wr_U8 i2c_soft_wr_U8
  36.     #define i2c_rd_U8 i2c_soft_rd_U8
  37.     #define i2c_chkack i2c_soft_chkack
  38. #endif
  39.  
  40. //to include AVR hardware I2C realization define use_i2c_avr (если нужно, подключить функции аппаратного I2C AVR)
  41. #ifdef USE_I2C_AVR
  42.  
  43.     #define I2C_AVR_CMD_START   ((1 << TWINT)|(1 << TWEN)|(1 << TWSTA)) /** \brief AVR TWI START command <br>команда для генерации условия START \ingroup group_i2c */
  44.     #define I2C_AVR_CMD_STOP    ((1 << TWINT)|(1 << TWEN)|(1 << TWSTO)) /** \brief AVR TWI STOP command <br>команда для генерации условия STOP \ingroup group_i2c */
  45.     #define I2C_AVR_CMD_WR      ((1 << TWINT)|(1 << TWEN))              /** \brief AVR TWI write byte command <br>команда записи байта \ingroup group_i2c */
  46.     #define I2C_AVR_CMD_RD_ACK  ((1 << TWINT)|(1 << TWEN)|(1 << TWEA))  /** \brief AVR TWI read byte command, ACK <br>команда чтения байта с выдачей ACK \ingroup group_i2c */
  47.     #define I2C_AVR_CMD_RD_NACK ((1 << TWINT)|(1 << TWEN))              /** \brief AVR TWI read byte command, NO ACK <br>команда чтения байта с выдачей NO ACK \ingroup group_i2c */
  48.     #define I2C_AVR_STATUS_MASK (0xf8) /**< mask for status bits of AVR TWI <br>маска битов статуса TWI \ingroup group_i2c */
  49.  
  50.     #define i2c_avr_busy()  (!(TWCR & (1 << TWINT))) /** \brief AVR TWI busy flag <br>проверка занятости модуля TWI \ingroup group_i2c */
  51.     #define i2c_avr_start() i2c_avr_cmd_wait(I2C_AVR_CMD_START) /**< \brief use AVR hardware for START generation \ingroup group_i2c */
  52.     #define i2c_avr_stop()  {i2c_avr_cmd(I2C_AVR_CMD_STOP); delay_us(5);} /**< \brief use AVR hardware for STOP generation \ingroup group_i2c */
  53.  
  54.     /** \brief wait for AVR TWI action to end <br>ожидание завершения выполнения команды TWI \ingroup group_i2c */
  55.     void i2c_avr_wait(void);
  56.     /** \brief execute TWI command cmd<br>выполнить команду \ingroup group_i2c */
  57.     void i2c_avr_cmd(U8 cmd);
  58.     /** \brief process AVR TWI command: TWCR=action, wait, return status of operation <br>выполнить команду, вернуть статус ее завершения \ingroup group_i2c */
  59.     U8 i2c_avr_cmd_wait(U8 cmd);
  60.     /** \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 */
  61.     U8 i2c_avr_chkack(U8 i2c_addr);
  62.     /** \brief write 1 byte to I2C, return ACK bit <br>записать 1 байт, возвращает бит ACK \ingroup group_i2c */
  63.     U8 i2c_avr_wr_U8(U8 abyte);
  64.     /** \brief read 1 byte from I2C, then write ACK bit <br>прочитать байт из I2C и записать бит ACK \ingroup group_i2c */
  65.     U8 i2c_avr_rd_U8(U8 ack_bit);
  66.    
  67.     #define i2c_start  i2c_avr_start
  68.     #define i2c_stop   i2c_avr_stop
  69.     #define i2c_wr_U8  i2c_avr_wr_U8
  70.     #define i2c_rd_U8  i2c_avr_rd_U8
  71.     #define i2c_chkack i2c_avr_chkack
  72. #endif
  73.  
  74. /** \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 */
  75. U8 i2c_wr_a8_buf8(U8 addr_i2c, U8 addr_start, U8 *buf, U8 buf_size);
  76.  
  77. /** \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 */
  78. U8 i2c_rd_a8_buf8(U8 addr_i2c, U8 addr_start, U8 *buf, U8 buf_size);
  79.  
  80.  
  81.  
  82. // DS1307 definitions
  83. #define DS1307_ADDR      0xd0
  84. #define DS1307_SIZE      0x3f
  85. #define DS1307_REGS_SIZE 0x08
  86. #define DS1307_SECOND    0x00
  87. #define DS1307_MINUTE    0x01
  88. #define DS1307_HOUR      0x02
  89. #define DS1307_DAY       0x03
  90. #define DS1307_DATE      0x04
  91. #define DS1307_MONTH     0x05
  92. #define DS1307_YEAR      0x06
  93. #define DS1307_CNTR      0x07
  94. #define DS1307_CH        0x80
  95. #define DS1307_12_24     0x40
  96. #define DS1307_AM_PM     0x20
  97. #define DS1307_OUT       0x80
  98. #define DS1307_SQWE      0x10
  99. #define DS1307_RS1       0x02
  100. #define DS1307_RS0       0x01
  101.  
  102. // DS3231 definitions
  103. #define DS3231_ADDR      0xd0
  104. #define DS3231_SIZE      0x13
  105. #define DS3231_REGS_SIZE 0x13
  106. #define DS3231_SECOND    0x00
  107. #define DS3231_MINUTE    0x01
  108. #define DS3231_HOUR      0x02
  109. #define DS3231_DAY       0x03
  110. #define DS3231_DATE      0x04
  111. #define DS3231_MONTH     0x05
  112. #define DS3231_YEAR      0x06
  113. #define DS3231_ALM1_SEC  0x07
  114. #define DS3231_ALM1_MIN  0x08
  115. #define DS3231_ALM1_HOUR 0x09
  116. #define DS3231_ALM1_DAY  0x0a
  117. #define DS3231_ALM1_DATE 0x0a
  118. #define DS3231_ALM2_MIN  0x0b
  119. #define DS3231_ALM2_HOUR 0x0c
  120. #define DS3231_ALM2_DAY  0x0d
  121. #define DS3231_ALM2_DATE 0x0d
  122. #define DS3231_CNTR      0x0e
  123. #define DS3231_STAT      0x0f
  124. #define DS3231_AGING     0x10
  125. #define DS3231_TEMP_MSB  0x11
  126. #define DS3231_TEMP_LSB  0x12
  127. #define DS3231_12_24     0x40
  128. #define DS3231_AM_PM     0x20
  129. #define DS3231_DY_DT     0x40
  130. #define DS3231_EOSC      0x80
  131. #define DS3231_BBSQW     0x40
  132. #define DS3231_CONV      0x20
  133. #define DS3231_RS2       0x10
  134. #define DS3231_RS1       0x08
  135. #define DS3231_INTCN     0x04
  136. #define DS3231_A2IE      0x02
  137. #define DS3231_A1IE      0x01
  138. #define DS3231_OSF       0x80
  139. #define DS3231_EN32KHZ   0x08
  140. #define DS3231_BSY       0x04
  141. #define DS3231_A2F       0x02
  142. #define DS3231_A1F       0x01
  143.  
  144. // DS3232 definitions
  145. #define DS3232_ADDR      0xd0
  146. #define DS3232_SIZE      0x100
  147. #define DS3232_REGS_SIZE 0x13
  148.  
  149. // M41T56 definitions
  150. #define M41T56_ADDR      0xd0
  151. #define M41T56_SIZE      0x3f
  152. #define M41T56_REGS_SIZE 0x08
  153. #define M41T56_SECOND    0x00
  154. #define M41T56_MINUTE    0x01
  155. #define M41T56_HOUR      0x02
  156. #define M41T56_DAY       0x03
  157. #define M41T56_DATE      0x04
  158. #define M41T56_MONTH     0x05
  159. #define M41T56_YEAR      0x06
  160. #define M41T56_CNTR      0x07
  161. #define M41T56_ST        0x80
  162. #define M41T56_CEB       0x80
  163. #define M41T56_CB        0x40
  164. #define M41T56_OUT       0x80
  165. #define M41T56_FT        0x40
  166. #define M41T56_S         0x20
  167.  
  168. // PCF8563 definitions
  169. #define PCF8563_ADDR      0xa2
  170. #define PCF8563_SIZE      0x0f
  171. #define PCF8563_REGS_SIZE 0x0f
  172. #define PCF8563_SECOND    0x02
  173. #define PCF8563_MINUTE    0x03
  174. #define PCF8563_HOUR      0x04
  175. #define PCF8563_DAY       0x05
  176. #define PCF8563_WEEKDAY   0x06
  177. #define PCF8563_MONTH     0x07
  178. #define PCF8563_YEAR      0x08
  179. #define PCF8563_ALM_MIN   0x09
  180. #define PCF8563_ALM_HOUR  0x0a
  181. #define PCF8563_ALM_DAY   0x0b
  182. #define PCF8563_ALM_WEEKDAY 0x0c
  183. #define PCF8563_CNTR1     0x00
  184. #define PCF8563_CNTR2     0x01
  185. #define PCF8563_CLKOUT    0x0d
  186. #define PCF8563_TIMER     0x0e
  187. #define PCF8563_TIMER_CD  0x0f
  188. #define PCF8563_VL        0x80
  189. #define PCF8563_C         0x80
  190. #define PCF8563_TEST1     0x80
  191. #define PCF8563_STOP      0x20
  192. #define PCF8563_TESTC     0x08
  193. #define PCF8563_TI_TP     0x10
  194. #define PCF8563_AF        0x08
  195. #define PCF8563_TF        0x04
  196. #define PCF8563_AIE       0x02
  197. #define PCF8563_TIE       0x01
  198. #define PCF8563_FE        0x80
  199. #define PCF8563_FD1       0x02
  200. #define PCF8563_FD0       0x01
  201. #define PCF8563_TE        0x80
  202. #define PCF8563_TD1       0x02
  203. #define PCF8563_TD0       0x01
  204.  
  205. #endif
  206.  
  207. //--------------------------------------------------------------------------------------------
  208.  
  209. #include "ul_i2c.h"
  210.  
  211. // Soft I2C
  212. #ifdef USE_I2C_SOFT
  213.  
  214.     void i2c_soft_start(void) {
  215.         //prepare SDA level in case of repeated start (подготовить уровень на SDA перед стартом)
  216.         i2c_soft_scl_wr_0();
  217.         i2c_soft_sda_wr_1(); i2c_soft_delay_halfbit();
  218.         //1-0 transition on SDA while SCL=1 (перепад на SDA 1-0 при SCL=1)
  219.         i2c_soft_scl_wr_1(); i2c_soft_delay_halfbit();
  220.         i2c_soft_sda_wr_0(); i2c_soft_delay_halfbit();
  221.         i2c_soft_scl_wr_0(); i2c_soft_delay_halfbit();
  222.     }
  223.  
  224.     void i2c_soft_stop(void) {
  225.         //0-1 transition on SDA while SCL=1 (перепад на SDA 0-1 при SCL=1)
  226.         i2c_soft_sda_wr_0(); i2c_soft_delay_halfbit();
  227.         i2c_soft_scl_wr_1(); i2c_soft_delay_halfbit();
  228.         i2c_soft_sda_wr_1(); i2c_soft_delay_halfbit();
  229.     }
  230.  
  231.     void i2c_soft_wr_bit(U8 abit) {
  232.         if (abit) i2c_soft_sda_wr_1(); else i2c_soft_sda_wr_0(); i2c_soft_delay_halfbit();
  233.         i2c_soft_scl_wr_1(); i2c_soft_delay_halfbit();
  234.         i2c_soft_scl_wr_0(); i2c_soft_delay_halfbit();
  235.     }
  236.  
  237.     U8 i2c_soft_rd_bit(void) {
  238.         U8 bit_in;
  239.         i2c_soft_sda_wr_1(); i2c_soft_delay_halfbit();
  240.         i2c_soft_scl_wr_1(); i2c_soft_delay_halfbit();
  241.         bit_in = i2c_soft_sda_rd();
  242.         i2c_soft_scl_wr_0(); i2c_soft_delay_halfbit();
  243.         return(bit_in);
  244.     }
  245.  
  246.     U8 i2c_soft_wr_U8(U8 abyte) {
  247.         for (U8 bits_cnt = 8; bits_cnt; bits_cnt--) {
  248.             i2c_soft_wr_bit(abyte & 0x80);
  249.             abyte <<= 1;
  250.         }
  251.         return(i2c_soft_rd_bit());
  252.     }
  253.  
  254.     U8 i2c_soft_rd_U8(U8 bit_ack) {
  255.         U8 result = 0;
  256.         for (U8 bits_cnt = 8; bits_cnt; bits_cnt--) {
  257.             result <<= 1;
  258.             if (i2c_soft_rd_bit()) result |= 1;
  259.         }
  260.         i2c_soft_wr_bit(bit_ack);
  261.         return(result);
  262.     }
  263.  
  264.     U8 i2c_soft_chkack(U8 i2c_addr) {
  265.         U8 result;
  266.         i2c_soft_start();    /*START*/
  267.         result = i2c_soft_wr_U8( i2c_addr & 0xfe ); /*send device address in write mode*/
  268.         if (result) result = 1; /*if ACK received,return 0, else 1*/
  269.         i2c_soft_stop(); /*STOP*/
  270.         return(result); /*return 0 if ACK received, else 1*/
  271.     }
  272. #endif
  273.  
  274.  
  275. //to include AVR hardware I2C realization define use_i2c_avr (если нужно, подключить функции аппаратного I2C AVR)
  276. #ifdef USE_I2C_AVR
  277.  
  278.     void i2c_avr_wait(void) {
  279.         while (i2c_avr_busy());
  280.     }
  281.  
  282.     void i2c_avr_cmd(U8 cmd) {
  283.         TWCR = cmd;
  284.     }
  285.  
  286.     U8 i2c_avr_cmd_wait(U8 cmd) {
  287.         i2c_avr_cmd(cmd);
  288.         i2c_avr_wait();
  289.         return(TWSR);
  290.     }
  291.  
  292.     U8 i2c_avr_chkack(U8 i2c_addr) {
  293.         U8 result;
  294.         i2c_avr_start();    /*START*/
  295.         TWDR = i2c_addr & 0xfe; /*send device address in write mode*/
  296.         result = i2c_avr_cmd_wait(I2C_AVR_CMD_WR);
  297.         if (result == 0x18) result = 0; else result = 1; /*if ACK received,return 0*/
  298.         i2c_avr_stop(); /*STOP*/
  299.         return(result); /*return 0 if ACK received, else result of operation*/
  300.     }
  301.  
  302.     U8 i2c_avr_wr_U8(U8 abyte) {
  303.         TWDR = abyte;
  304.         i2c_avr_cmd_wait(I2C_AVR_CMD_WR);
  305.         return(TWSR & 8);
  306.     }
  307.  
  308.     U8 i2c_avr_rd_U8(U8 ack_bit) {
  309.         i2c_avr_cmd_wait(ack_bit ? I2C_AVR_CMD_RD_NACK : I2C_AVR_CMD_RD_ACK);
  310.         return(TWDR);
  311.     }
  312. #endif
  313.  
  314.  
  315.  
  316. U8 i2c_wr_a8_buf8(U8 addr_i2c, U8 addr_start, U8 *buf, U8 buf_size) {
  317.     i2c_start();
  318.     i2c_wr_U8(addr_i2c);
  319.     i2c_wr_U8(addr_start);
  320.     while (buf_size) {
  321.         i2c_wr_U8(*buf);
  322.         buf++;
  323.         buf_size--;
  324.     }
  325.     i2c_stop();
  326.     return(0);
  327. }
  328.  
  329. U8 i2c_rd_a8_buf8(U8 addr_i2c, U8 addr_start, U8 *buf, U8 buf_size) {
  330.     /*setup starting address*/
  331.     i2c_start();
  332.     i2c_wr_U8(addr_i2c);
  333.     i2c_wr_U8(addr_start);
  334.     /*if size>0 start reading*/
  335.     if (buf_size) {
  336.         /*repeated start for reading*/
  337.         i2c_start();
  338.         i2c_wr_U8(addr_i2c | 1);
  339.         while (buf_size) {
  340.             /*read next byte to buffer, generate NA in the end*/
  341.             buf_size--;
  342.             *buf = i2c_rd_U8(buf_size == 0);
  343.             buf++;
  344.         }
  345.     }
  346.     /*stop all transactions*/
  347.     i2c_stop();
  348.     return(0);
  349. }
  350.  
  351.  
  352. #ifdef USE_I2C_PAGED
  353.    
  354.     //for paged EEPROM read/write define use_i2c_paged (если нужно, подключить функции для записи в устройства с страничной организацией)
  355.     U8  i2c_paged_dev_addr;  /**< \brief I2C paged device address <br>адрес устройства \ingroup group_i2c */
  356.     U16 i2c_paged_size;      /**< \brief I2C paged device size <br>размер \ingroup group_i2c */
  357.     U8  i2c_paged_page_mask; /**< \brief I2C paged device page address mask <br>маска адреса страницы \ingroup group_i2c */
  358.     U16 i2c_paged_byte_addr; /**< \brief I2C paged device byte address <br>текущий адрес записи \ingroup group_i2c */
  359.     U8  i2c_paged_flags;     /**< \brief I2C paged device state <br>текущее состояние записи и другие флаги \ingroup group_i2c */
  360.  
  361.     #define I2C_PAGED_FLAG_STARTED 1 /**< \brief I2C paged device write started <br>=1 если запись страницы уже начата \ingroup group_i2c */
  362.     #define I2C_PAGED_FLAG_16BIT   2 /**< \brief I2C paged device uses 16-bit address <br>=1 для использования 16-битной адресации \ingroup group_i2c */
  363.  
  364.     /** \brief start paged write to I2C device <br>начать страничную запись \ingroup group_i2c */
  365.     void i2c_paged_wr_start(U8 dev_addr, U16 byte_addr) {
  366.         i2c_paged_dev_addr  = dev_addr;  //remember device address (запомнить адрес устройства)
  367.         i2c_paged_byte_addr = byte_addr; //remember starting byte (запомнить адрес первого байта)
  368.         i2c_paged_flags &= ~I2C_PAGED_FLAG_STARTED; //clear started flag (обнулить флаг начала записи)
  369.     }
  370.  
  371.     /** \brief end paged write to I2C device <br>завершить страничную запись \ingroup group_i2c */
  372.     void i2c_paged_wr_stop(void) {
  373.         //if data was written, stop writing and wait to the end of write cycle (если данные уже записывались, прекратить запись и ожидать завершения цикла записи)
  374.         if (i2c_paged_flags & I2C_PAGED_FLAG_STARTED) {
  375.             i2c_stop(); //I2C STOP
  376.             //ACK polling (проверка завершения записи страницы)
  377.             while (i2c_chkack(i2c_paged_dev_addr));
  378.         }
  379.         i2c_stop(); //I2C STOP
  380.         i2c_paged_flags &= ~I2C_PAGED_FLAG_STARTED; //clear STARTED flag (обнулить флаг начатой записи)
  381.     }
  382.  
  383.     /** \brief paged mode byte write <br>побайтовая запись в страничном режиме \ingroup group_i2c */
  384.     void i2c_paged_wr_U8(U8 adata) {
  385.         //if not overflow, write (если достигнут полный объем, не писать больше)
  386.         if (i2c_paged_byte_addr < i2c_paged_size) {
  387.                 //if first data, setup address (если начало записи, дать команду начала записи и настроить адрес)
  388.                 if ((i2c_paged_flags & I2C_PAGED_FLAG_STARTED) == 0) {
  389.                     //mark that writing was started (отметить что запись уже происходила)
  390.                     i2c_paged_flags |= I2C_PAGED_FLAG_STARTED;
  391.                     i2c_start();
  392.                     //write device address, write mode (записать адрес устройства)
  393.                     i2c_wr_U8(i2c_paged_dev_addr);
  394.                     //if necessary, write high address byte (в 16-битном режиме адресации записать старший байт адреса)
  395.                     if (i2c_paged_flags & I2C_PAGED_FLAG_16BIT) i2c_wr_U8(i2c_paged_byte_addr >> 8);
  396.                     //write low address byte (записать младший байт адреса)
  397.                     i2c_wr_U8(i2c_paged_byte_addr);
  398.             }
  399.             i2c_wr_U8(adata); //write data byte (записать байт данных)
  400.             i2c_paged_byte_addr++; //increment byte address (увеличить счетчик адреса)
  401.             //if end of current page, end write cycle (если достигнут конец страницы, завершить ее запись)
  402.             if (((U8)i2c_paged_byte_addr & i2c_paged_page_mask) == 0) i2c_paged_wr_stop();
  403.         }
  404.     }
  405.  
  406. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement