drive_24c02.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. #include "drive_24c02.h"
  2. enum ENUM_TWI_REPLY
  3. {
  4. TWI_NACK=0
  5. ,TWI_ACK=1
  6. };
  7. enum ENUM_TWI_BUS_STATE
  8. {
  9. TWI_READY=0
  10. ,TWI_BUS_BUSY=1
  11. ,TWI_BUS_ERROR=2
  12. };
  13. void I2C_EE_Init(void)
  14. {
  15. GPIO_InitTypeDef GPIO_InitStructure;
  16. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  17. // Configure I2C1 pins: SCL and SDA
  18. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;
  19. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  20. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  21. GPIO_Init(GPIOB, &GPIO_InitStructure);
  22. }
  23. void TWI_delay(void)
  24. {
  25. uint8_t i=10; //i=10延时1.5us//这里可以优化速度 ,经测试最低到5还能写入
  26. while(i--);
  27. }
  28. /**************************************************************************
  29. 延时
  30. ms:延时的毫秒数
  31. CYCLECOUNTER / 72000000
  32. ***************************************************************************/
  33. void DelayMs(uint16_t ms)
  34. {
  35. uint16_t iq0;
  36. uint16_t iq1;
  37. for(iq0 = ms; iq0 > 0; iq0--)
  38. {
  39. for(iq1 = 11998; iq1 > 0; iq1--); // ( (6*iq1+9)*iq0+15 ) / 72000000
  40. }
  41. }
  42. uint8_t TWI_Start(void)
  43. {
  44. SDAH;
  45. SCLH;
  46. TWI_delay();
  47. if(!SDAread)return TWI_BUS_BUSY; //SDA线为低电平则总线忙,退出
  48. SDAL;
  49. TWI_delay();
  50. if(SDAread) return TWI_BUS_ERROR; //SDA线为高电平则总线出错,退出
  51. SCLL;
  52. TWI_delay();
  53. return TWI_READY;
  54. }
  55. /*void TWI_Stop(void)
  56. {
  57. SCLL;
  58. TWI_delay();
  59. SDAL;
  60. TWI_delay();
  61. SCLH;
  62. TWI_delay();
  63. SDAH;
  64. TWI_delay();
  65. }*/
  66. void TWI_Stop(void)
  67. {
  68. SDAL;
  69. SCLL;
  70. TWI_delay();
  71. SCLH;
  72. TWI_delay();
  73. SDAH;
  74. TWI_delay();
  75. }
  76. void TWI_Ack(void)
  77. {
  78. SCLL;
  79. TWI_delay();
  80. SDAL;
  81. TWI_delay();
  82. SCLH;
  83. TWI_delay();
  84. SCLL;
  85. TWI_delay();
  86. }
  87. void TWI_NoAck(void)
  88. {
  89. SCLL;
  90. TWI_delay();
  91. SDAH;
  92. TWI_delay();
  93. SCLH;
  94. TWI_delay();
  95. SCLL;
  96. TWI_delay();
  97. }
  98. uint8_t TWI_WaitAck(void) //返回为:=1有ACK,=0无ACK
  99. {
  100. SCLL;
  101. TWI_delay();
  102. SDAH;
  103. TWI_delay();
  104. SCLH;
  105. TWI_delay();
  106. if(SDAread)
  107. {
  108. SCLL;
  109. return 0;
  110. }
  111. SCLL;
  112. return 1;
  113. }
  114. void TWI_SendByte(uint8_t SendByte) //数据从高位到低位//
  115. {
  116. uint8_t i=8;
  117. while(i--)
  118. {
  119. SCLL;
  120. TWI_delay();
  121. if(SendByte&0x80)
  122. SDAH;
  123. else
  124. SDAL;
  125. SendByte<<=1;
  126. TWI_delay();
  127. SCLH;
  128. TWI_delay();
  129. }
  130. SCLL;
  131. }
  132. uint8_t TWI_ReceiveByte(void) //数据从高位到低位//
  133. {
  134. uint8_t i=8;
  135. uint8_t ReceiveByte=0;
  136. SDAH;
  137. while(i--)
  138. {
  139. ReceiveByte <<= 1;
  140. SCLL;
  141. TWI_delay();
  142. SCLH;
  143. TWI_delay();
  144. if(SDAread)
  145. {
  146. ReceiveByte |= 0x01;
  147. }
  148. }
  149. SCLL;
  150. return ReceiveByte;
  151. }
  152. //返回:3写入成功;0写器件地址出错,1总线忙,2出错
  153. //写入1字节数据 SendByte:待写入数据 WriteAddress:待写入地址
  154. uint8_t TWI_WriteByte(uint8_t SendByte, uint8_t WriteAddress)
  155. {
  156. uint8_t i;
  157. i = TWI_Start();
  158. if(i)
  159. return i;
  160. // TWI_SendByte( ADDR_24CXX & 0xFE);//写器件地址 写入:地址最低位是0,读取:地址最低位是1
  161. TWI_SendByte( ADDR_24CXX);
  162. if(!TWI_WaitAck())
  163. {
  164. TWI_Stop();
  165. return 0;
  166. }
  167. TWI_SendByte(WriteAddress); //设置起始地址
  168. TWI_WaitAck();
  169. TWI_SendByte(SendByte); //写数据
  170. TWI_WaitAck();
  171. TWI_Stop();
  172. //注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
  173. DelayMs(12); //写入延时 12ms 写周期大于10ms即可
  174. return 3;
  175. }
  176. //返回:0写器件地址出错,1总线忙,2出错,
  177. //读出1字节数据
  178. //ReadAddress:待读出地址
  179. uint8_t TWI_ReadByte( uint8_t ReadAddress)
  180. {
  181. uint8_t i,temp;
  182. i = TWI_Start();
  183. if(i)
  184. return i;
  185. TWI_SendByte(ADDR_24CXX);//写器件地址,先执行一次伪写操作
  186. if(!TWI_WaitAck())
  187. {
  188. TWI_Stop();
  189. return 0;
  190. }
  191. TWI_SendByte(ReadAddress); //设置起始地址
  192. TWI_WaitAck();
  193. TWI_Start();
  194. TWI_SendByte(ADDR_24CXX|0x01); //读器件地址 写入:地址最低位是0,读取:地址最低位是1
  195. TWI_WaitAck();
  196. //*pDat = TWI_ReceiveByte();
  197. temp = TWI_ReceiveByte();
  198. TWI_NoAck();
  199. TWI_Stop();
  200. return temp;//返回的如果是0,1,2则与错误代码相同了,再考虑一下
  201. }
  202. /***************************************************************************
  203. 向24c256中写多个字节
  204. psrc_data:指向要写入数据数组的指针
  205. adr:24c256中要写入数据的首地址
  206. nbyte:写入的字节数
  207. 返回值: 0:执行完毕;1:执行出现错误
  208. 形参中:C02只有一个地址adr;C256中有高位地址hadr和低位地址ladr
  209. ***************************************************************************/
  210. uint8_t I2C_EE_BufferWrite(uint8_t *psrc_data,uint8_t adr,uint8_t nbyte)
  211. {
  212. uint8_t i;
  213. for(;nbyte!=0;nbyte--)
  214. {
  215. i = TWI_Start();
  216. if(i)
  217. return i;
  218. TWI_SendByte(ADDR_24CXX);//写器件地址
  219. if(!TWI_WaitAck())
  220. {
  221. TWI_Stop();
  222. return 0;
  223. }
  224. TWI_SendByte(adr); //设置起始地址
  225. TWI_WaitAck();
  226. TWI_SendByte(*psrc_data); //写数据
  227. TWI_WaitAck();
  228. psrc_data++; //指向待写数据的指针加1
  229. adr++; //对24C08的操作地址加1
  230. TWI_Stop();
  231. //注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
  232. DelayMs(12); //写入延时 12ms 写周期大于10ms即可
  233. }
  234. return 0;
  235. }
  236. /***************************************************************************
  237. 从24c02读多个字节
  238. pdin_data:指向要保存读出数据的数组的指针
  239. adr:24c02中要读出数据的首地址
  240. nbyte:读出的字节数
  241. 返回值: 0:执行完毕;1:执行出现错误
  242. ***************************************************************************/
  243. uint8_t I2C_EE_BufferRead(uint8_t *pdin_data,uint8_t adr,uint8_t nbyte)
  244. {
  245. uint8_t i;
  246. i = TWI_Start();
  247. if(i)
  248. return i;
  249. TWI_SendByte(ADDR_24CXX);//写器件地址,先执行一次伪写操作
  250. if(!TWI_WaitAck())
  251. {
  252. TWI_Stop();
  253. return 0;
  254. }
  255. TWI_SendByte(adr); //设置起始地址
  256. TWI_WaitAck();
  257. TWI_Start();
  258. TWI_SendByte(ADDR_24CXX|0x01); //读器件地址 写入:地址最低位是0,读取:地址最低位是1
  259. TWI_WaitAck();
  260. while(nbyte!=1) //读入前(nbyte-1)个字节
  261. {
  262. *pdin_data = TWI_ReceiveByte(); //循环从24C02中读数据,存入pdin_data所指的存储器中
  263. TWI_Ack(); //IIC应答
  264. pdin_data++; //指向存储读入数据的存储器指针加1
  265. nbyte--; //剩余要读入的字节减1
  266. };
  267. *pdin_data = TWI_ReceiveByte(); //读入最后一个字节
  268. TWI_NoAck(); //IIC无应答操作
  269. TWI_Stop();
  270. return 0;
  271. }
  272. /*
  273. void TWI_24CXX_Write(uint8_t* pDat, uint8_t nAddr, uint8_t nLen)
  274. {
  275. uint16_t i;
  276. for(i=0;i<nLen;i++)
  277. {
  278. TWI_WriteByte(*(pDat+i), nAddr+i);
  279. }
  280. }
  281. void TWI_24CXX_Read(uint8_t* pDat, uint8_t nAddr, uint8_t nLen)
  282. {
  283. uint16_t i;
  284. for(i=0; i<nLen; i++)
  285. *(pDat+i) = TWI_ReadByte(nAddr+i);
  286. }
  287. */