AT24C128.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. #include "includes.h"
  2. #include "trace.h"
  3. #include "AT24C128.h"
  4. #include "stdio.h"
  5. //#include "sys.h"
  6. #include "delay.h"
  7. //#include "sys.h"
  8. /* AT24C128C organized as 256 pages of 64-bytes each
  9. AT24C512C, organized as 512 pages of 128 bytes each
  10. 不同的的EEPROM对应的页大小不一样,注意修改
  11. */
  12. #define PAGE_SIZE 64
  13. OS_SEM i2c_sem;
  14. void I2C_init(void)
  15. {
  16. // OS_ERR err;
  17. GPIO_InitTypeDef GPIO_InitStructure = {0};
  18. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);//使能GPIOB时钟
  19. //解除写保护
  20. GPIO_InitStructure.GPIO_Pin = IIC_WP_PIN;
  21. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//
  22. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;//2MHz
  23. GPIO_Init(IIC_WP_PORT, &GPIO_InitStructure);
  24. //解除写保护
  25. // GPIO_ResetBits(IIC_WP_PORT,IIC_WP_PIN);
  26. //打开写保护
  27. GPIO_SetBits(IIC_WP_PORT,IIC_WP_PIN);
  28. //IIC时钟信号位
  29. GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN;
  30. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
  31. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  32. GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_PIN);
  33. GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);//初始化
  34. //IIC数据信号位
  35. GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
  36. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//OD
  37. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  38. GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_PIN);
  39. GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);//初始化
  40. // OSSemCreate(&i2c_sem, "i2c_sem", 1, &err);
  41. }
  42. u8 iic_cmd_delay=0;
  43. /***********************iic**************************/
  44. void delay_nop(void)
  45. {
  46. unsigned int i;
  47. for(i=0;i<50;i++)
  48. __nop();
  49. }
  50. //产生IIC起始信号
  51. void IIC_Start(void)
  52. {
  53. /*while(iic_cmd_delay < E_DELAY) // 距上一个命令时间太短
  54. {
  55. R_WDT_Restart();
  56. }*/
  57. SDA_OUT();//sda线输出
  58. IIC_SDA = 1;
  59. IIC_SCL = 1;
  60. delay_us(4);
  61. IIC_SDA = 0;//START:when CLK is high,DATA change form high to low
  62. delay_us(4);
  63. IIC_SCL = 0;//钳住I2C总线,准备发送或接收数据
  64. }
  65. //产生IIC停止信号
  66. void IIC_Stop(void)
  67. {
  68. SDA_OUT();//sda线输出
  69. IIC_SDA = 0;
  70. IIC_SCL = 0;
  71. delay_us(4);
  72. IIC_SCL = 1;
  73. IIC_SDA = 1;//发送I2C总线结束信号
  74. delay_us(4);
  75. iic_cmd_delay=0;
  76. }
  77. //等待应答信号到来
  78. //返回值:
  79. // 1,接收应答失败
  80. // 0,接收应答成功
  81. u8 IIC_Wait_Ack(void)
  82. {
  83. u8 ucErrTime=0;
  84. SDA_IN(); //SDA设置为输入
  85. IIC_SDA=1;delay_us(1);
  86. IIC_SCL=1;delay_us(1);
  87. while(READ_SDA)
  88. {
  89. ucErrTime++;
  90. if(ucErrTime>250)
  91. {
  92. IIC_Stop();
  93. return 1;
  94. }
  95. }
  96. IIC_SCL=0;//时钟输出0
  97. return 0;
  98. }
  99. //产生ACK应答
  100. void IIC_Ack(void)
  101. {
  102. IIC_SCL = 0;
  103. SDA_OUT();//sda线输出
  104. IIC_SDA = 0;
  105. delay_us(4);
  106. IIC_SCL = 1;
  107. delay_us(2);
  108. IIC_SCL = 0;
  109. }
  110. //不产生ACK应答
  111. void IIC_NAck(void)
  112. {
  113. IIC_SCL = 0;
  114. SDA_OUT();//sda线输出
  115. IIC_SDA = 1;
  116. delay_us(4);
  117. IIC_SCL = 1;
  118. delay_us(2);
  119. IIC_SCL = 0;
  120. }
  121. //IIC发送一个字节
  122. //返回从机有无应答
  123. //1,有应答
  124. //0,无应答
  125. void IIC_Send_Byte(u8 txd)
  126. {
  127. u8 t;
  128. IIC_SCL=0;//拉低时钟开始数据传输
  129. SDA_OUT();
  130. for(t=0;t<8;t++)
  131. {
  132. IIC_SDA=(txd&0x80)>>7;
  133. // SDA_OUT();
  134. // if((txd&0x80)>>7)
  135. // IIC_SDA=1;
  136. // else
  137. // IIC_SDA=0;
  138. txd<<=1;
  139. delay_us(4); //对TEA5767这三个延时都是必须的
  140. IIC_SCL=1;
  141. delay_us(2);
  142. IIC_SCL=0;
  143. delay_us(2);
  144. }
  145. }
  146. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
  147. u8 IIC_Read_Byte(u8 ack)
  148. {
  149. u8 i,receive=0;
  150. SDA_IN();//SDA设置为输入
  151. for(i=0;i<8;i++ )
  152. {
  153. IIC_SCL=0;
  154. delay_us(4);
  155. IIC_SCL=1;
  156. receive<<=1;
  157. if(READ_SDA)receive++;
  158. delay_us(1);
  159. }
  160. if (!ack)
  161. IIC_NAck();//发送nACK
  162. else
  163. IIC_Ack(); //发送ACK
  164. return receive;
  165. }
  166. /***********************以上为IIC驱动**************************/
  167. /***********************iic**************************/
  168. //在AT24CXX指定地址读出一个数据
  169. //ReadAddr:开始读数的地址
  170. //返回值 :读到的数据
  171. u8 AT24CXX_ReadOneByte(u32 ReadAddr)
  172. {
  173. u8 temp;
  174. u8 addrH,addrL;
  175. addrH=ReadAddr>>8;
  176. addrL=ReadAddr&0xff;
  177. IIC_Start();
  178. IIC_Send_Byte(0xa0);
  179. IIC_Wait_Ack();
  180. IIC_Send_Byte(addrH); //发送高地址
  181. IIC_Wait_Ack();
  182. IIC_Send_Byte(addrL); //发送低地址
  183. IIC_Wait_Ack();
  184. IIC_Start();
  185. IIC_Send_Byte(0xa1); //进入接收模式
  186. IIC_Wait_Ack();
  187. temp= IIC_Read_Byte(0);
  188. IIC_Stop();//产生一个停止条件
  189. delay_us(4);
  190. return temp;
  191. }
  192. //在AT24CXX指定地址写入一个数据
  193. //WriteAddr :写入数据的目的地址
  194. //DataToWrite:要写入的数据
  195. void AT24CXX_WriteOneByte(u32 WriteAddr,u8 DataToWrite)
  196. {
  197. u8 addrH,addrL;
  198. addrH=WriteAddr>>8;
  199. addrL=WriteAddr&0xff;
  200. IIC_Start();
  201. IIC_Send_Byte(0xa0);
  202. IIC_Wait_Ack();
  203. IIC_Send_Byte(addrH); //发送高地址
  204. IIC_Wait_Ack();
  205. IIC_Send_Byte(addrL); //发送低地址
  206. IIC_Wait_Ack();
  207. IIC_Send_Byte(DataToWrite); //发送字节
  208. IIC_Wait_Ack();
  209. IIC_Stop();//产生一个停止条件
  210. delay_ms(10);//两次写操作,必须加间隔,否则写不进去
  211. }
  212. //在AT24CXX里面的指定地址开始读出指定个数的数据
  213. //ReadAddr :开始读出的地址 对24c02为0~255
  214. //pBuffer :数据数组首地址
  215. //NumToRead:要读出数据的个数
  216. void AT24CXX_Read(u32 ReadAddr,u8 *pBuffer,u16 NumToRead)
  217. {
  218. u8 addrH,addrL;
  219. u16 lentmp,lentow,lens;
  220. u8 tmp;
  221. OS_ERR err;
  222. CPU_SR_ALLOC();
  223. if(NumToRead==0)
  224. return;
  225. OS_CRITICAL_ENTER();
  226. OSSemPend(&i2c_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
  227. I2C_init();
  228. delay_ms(100);//两次写操作,必须加间隔,否则写不进去
  229. IWDG_ReloadCounter();
  230. lentmp=NumToRead;
  231. while(lentmp)
  232. {
  233. tmp=ReadAddr%PAGE_SIZE;
  234. tmp=PAGE_SIZE-tmp;
  235. if(tmp>=lentmp)//当页剩余空间大于要写入的长度
  236. {
  237. lentow=lentmp;
  238. }
  239. else
  240. {
  241. lentow=tmp;//写入长度只能是剩余空间长度
  242. }
  243. lentmp=lentmp-lentow;//计算要在下一页写入的长度
  244. lens=lentow;
  245. addrH=ReadAddr>>8;
  246. addrL=ReadAddr&0xff;
  247. IIC_Start();
  248. IIC_Send_Byte(0xa0);//写
  249. IIC_Wait_Ack();
  250. IIC_Send_Byte(addrH); //发送高地址
  251. IIC_Wait_Ack();
  252. IIC_Send_Byte(addrL); //发送低地址
  253. IIC_Wait_Ack();
  254. delay_us(4);
  255. IIC_Start();
  256. IIC_Send_Byte(0xa1); //读 //进入接收模式
  257. IIC_Wait_Ack();
  258. while(lentow)
  259. {
  260. *pBuffer=IIC_Read_Byte(1);
  261. pBuffer++;
  262. //ReadAddr++;
  263. lentow--;
  264. }
  265. IIC_Read_Byte(0);
  266. IIC_Stop();//产生一个停止条件
  267. delay_us(4);
  268. //printf("at24 read %d %d\r\n", ReadAddr, lens);
  269. ReadAddr=ReadAddr+lens;//下一页的地址
  270. }
  271. GPIO_SetBits(IIC_WP_PORT,IIC_WP_PIN);
  272. OSSemPost(&i2c_sem, OS_OPT_POST_ALL, &err);
  273. OS_CRITICAL_EXIT();
  274. }
  275. //在AT24CXX里面的指定地址开始写入指定个数的数据
  276. //WriteAddr :开始写入的地址 对24c02为0~255
  277. //pBuffer :数据数组首地址
  278. //NumToWrite:要写入数据的个数
  279. // 每128bytes为一个page,写操作不能跨页
  280. void AT24CXX_Write(u32 WriteAddr,u8 *pBuffer,u16 NumToWrite)
  281. {
  282. u8 addrH,addrL;
  283. u16 lentmp,lentow,lens;
  284. u8 tmp;
  285. OS_ERR err;
  286. CPU_SR_ALLOC();
  287. if(NumToWrite==0)
  288. return;
  289. OS_CRITICAL_ENTER();
  290. OSSemPend(&i2c_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
  291. I2C_init();
  292. IIC_WRITE_PROTECT_OFF();
  293. delay_ms(10);//两次写操作,必须加间隔,否则写不进去
  294. IWDG_ReloadCounter();
  295. lentmp=NumToWrite;
  296. while(lentmp)
  297. {
  298. tmp=WriteAddr%PAGE_SIZE;
  299. tmp=PAGE_SIZE-tmp;
  300. if(tmp>=lentmp)//当页剩余空间大于要写入的长度
  301. {
  302. lentow=lentmp;
  303. }
  304. else
  305. {
  306. lentow=tmp;//写入长度只能是剩余空间长度
  307. }
  308. lentmp=lentmp-lentow;//计算要在下一页写入的长度
  309. lens=lentow;
  310. addrH=WriteAddr>>8;
  311. addrL=WriteAddr&0xff;
  312. IIC_Start();
  313. IIC_Send_Byte(0xa0);
  314. IIC_Wait_Ack();
  315. IIC_Send_Byte(addrH); //发送高地址
  316. IIC_Wait_Ack();
  317. IIC_Send_Byte(addrL); //发送低地址
  318. IIC_Wait_Ack();
  319. while(lentow--)
  320. {
  321. IIC_Send_Byte(*pBuffer);
  322. IIC_Wait_Ack();
  323. pBuffer++;
  324. }
  325. IIC_Stop();//产生一个停止条件
  326. delay_ms(10);
  327. //printf("at24 write %d %d %d, %d\r\n", WriteAddr, lens, addrH, addrL);
  328. WriteAddr=WriteAddr+lens;//下一页的地址
  329. }
  330. delay_ms(10);//两次写操作,必须加间隔,否则写不进去
  331. IIC_WRITE_PROTECT_ON();
  332. OSSemPost(&i2c_sem, OS_OPT_POST_ALL, &err);
  333. OS_CRITICAL_EXIT();
  334. }
  335. void AT24CXX_clr(u32 WriteAddr,u32 NumToWrite)
  336. {
  337. u8 addrH,addrL;
  338. u16 lentmp,lentow,lens;
  339. u8 tmp;
  340. lentmp=NumToWrite;
  341. while(lentmp)
  342. {
  343. tmp=WriteAddr%PAGE_SIZE;
  344. tmp=PAGE_SIZE-tmp;
  345. if(tmp>=lentmp)
  346. {
  347. lentow=lentmp;
  348. }
  349. else
  350. {
  351. lentow=tmp;
  352. }
  353. lentmp=lentmp-lentow;
  354. lens=lentow;
  355. addrH=WriteAddr>>8;
  356. addrL=WriteAddr&0xff;
  357. IIC_Start();
  358. IIC_Send_Byte(0xa0);
  359. IIC_Wait_Ack();
  360. IIC_Send_Byte(addrH); //发送高地址
  361. IIC_Wait_Ack();
  362. IIC_Send_Byte(addrL); //发送低地址
  363. IIC_Wait_Ack();
  364. while(lentow--)
  365. {
  366. IIC_Send_Byte(0xff);
  367. IIC_Wait_Ack();
  368. }
  369. IIC_Stop();//产生一个停止条件
  370. delay_ms(10);
  371. WriteAddr=WriteAddr+lens;
  372. }
  373. delay_ms(10);
  374. }
  375. //----------------------EEPROM---------------------------//
  376. //--------------------------------------------------------EEPROM DATA
  377. /*********************************************END OF FILE**********************/
  378. #define I2C_DATA_LEN 256
  379. u8 I2c_Buf_Write[I2C_DATA_LEN], I2c_Buf_Read[I2C_DATA_LEN];
  380. /**
  381. * @brief I2C(AT24C02)读写测试
  382. * @param 无
  383. * @retval 正常返回 1 ,不正常返回 0
  384. */
  385. uint8_t I2C_Test(void)
  386. {
  387. u16 i;
  388. I2C_init();
  389. EEPROM_INFO("\r\nI2C(AT24C128)字节读写测试\r\n");
  390. memset(I2c_Buf_Write, 0, I2C_DATA_LEN);
  391. memset(I2c_Buf_Read, 0, I2C_DATA_LEN);
  392. for ( i=0; i< I2C_DATA_LEN; i++ ) //填充缓冲
  393. {
  394. I2c_Buf_Write[i] = i;
  395. AT24CXX_WriteOneByte(i, i);
  396. I2c_Buf_Read[i] = AT24CXX_ReadOneByte(i);
  397. }
  398. data_dump("I2C Write", I2c_Buf_Write, I2C_DATA_LEN);
  399. data_dump("I2C Read", I2c_Buf_Read, I2C_DATA_LEN);
  400. EEPROM_INFO("\r\nI2C(AT24C128)连续地址读写测试\r\n");
  401. memset(I2c_Buf_Write, 0, I2C_DATA_LEN);
  402. memset(I2c_Buf_Read, 0, I2C_DATA_LEN);
  403. for ( i=0; i< I2C_DATA_LEN; i++ ) //填充缓冲
  404. {
  405. I2c_Buf_Write[i] = i+100;
  406. }
  407. AT24CXX_clr(I2C_DATA_LEN, I2C_DATA_LEN);
  408. AT24CXX_Read(I2C_DATA_LEN, I2c_Buf_Read, I2C_DATA_LEN);
  409. data_dump("I2C Read", I2c_Buf_Read, I2C_DATA_LEN);
  410. AT24CXX_Write(I2C_DATA_LEN, I2c_Buf_Write, I2C_DATA_LEN);
  411. AT24CXX_Read(I2C_DATA_LEN, I2c_Buf_Read, I2C_DATA_LEN);
  412. data_dump("I2C Write", I2c_Buf_Write, I2C_DATA_LEN);
  413. data_dump("I2C Read", I2c_Buf_Read, I2C_DATA_LEN);
  414. EEPROM_INFO("\r\nI2C(AT24C128)读写测试成功\r\n");
  415. return 1;
  416. }
  417. void Tmp75_read(u8 *pBuffer)
  418. {
  419. u16 lentow;//lentmp,,lens;
  420. lentow = 2;
  421. IIC_Start();
  422. IIC_Send_Byte(0x90);//写
  423. IIC_Wait_Ack();
  424. IIC_Send_Byte(0x00); //发送寄存器地址
  425. IIC_Wait_Ack();
  426. delay_us(4);
  427. IIC_Start();
  428. IIC_Send_Byte(0x91); //读 //进入接收模式
  429. IIC_Wait_Ack();
  430. while(lentow)
  431. {
  432. *pBuffer=IIC_Read_Byte(1);
  433. pBuffer++;
  434. //ReadAddr++;
  435. lentow--;
  436. }
  437. IIC_Stop();//产生一个停止条件
  438. }
  439. float Temp_test(void)
  440. {
  441. float temp_data,tmp;
  442. u8 Temp_buf[4];
  443. I2C_init();
  444. Tmp75_read(Temp_buf);
  445. //data_dump("temp Read", Temp_buf, 2);
  446. tmp = (float)(Temp_buf[1]>>4);
  447. tmp /= 16.0;
  448. temp_data = (float)Temp_buf[0] + tmp;
  449. // printf("\ntmp: ");
  450. // printf("%.4f ℃\n",temp_data);
  451. return temp_data;
  452. }