AT24C128.c 11 KB

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