当前位置:   article > 正文

24c0x读写 大于256字节读写方式,以24c08为例(24c04/08/16同理)_24c08 读写实验

24c08 读写实验

最近在做一个点阵屏的项目,其中用到了储存芯片20c08,当找资料时时发现全网都是24c02的读写例程然后程序下进去后发现能用,就没有在意(开始测试的时候数据用的很少不到256个)。

当程序框架基本完成时我开始进行多数测试,突然发现我的程序只能进行0-255的数据存储,当数据超过255时就会重头开始。

后来我从网上找了很多资料发现都是24c02的程序,存储数量都不能超过256。于是经过一天的研究终于解决了这个问题。记录一下,希望能帮助与到同样问题的小伙伴。

第一部分 原理说明

在读写过程中24c0x是分页写的,每页可以存256个字节,网上的驱动程序多为24c02,默认为第一页,当输入大于256时需要加一个换页,以24c08为例,一共有1K字节,每页256,一共为4页,以下为I²C的发送命令格式,前面四个1010是eeprom的固定格式不能动,对应16进制为A;后面四位的前三位数据(P0,P1,P2)就是翻页所需的地址(也可以理解为页地址),第四位R/W为读写控制位,最重要的就是图中的P0,P1,P2数据位,因为24c08只有四页所以只需要两个二进制数据即可(P2位强制为0)

P1  P2值
00第0页
01第1页
10第2页
00第3页

第二部分 程序编写

我的程序并没有从头开始写,由于我是在24c02的基础上搭好了程序框架才发现的问题,所以我的程序修改宗旨就是:以最少的修改完成读写任务,

下面是我原本的24C02程序

  1. #include<reg52.h>
  2. #include <intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. sbit sda = P2 ^ 1; //IO口定义
  6. sbit scl = P2 ^ 0;
  7. //此为待写入24c02的数据。为了便于验证结果,数组的内容为周期重复的。
  8. void UART_TX_Send(uchar i);
  9. char code music[] = {
  10. 0x55, 0xaa, 0x0f, 0xf0, 0x55, 0xaa, 0x0f, 0xf0, 0x55, 0xaa, 0x0f, 0xf0,
  11. 0x55, 0xaa, 0x0f, 0xf0, 0x55, 0xaa, 0x0f, 0xf0, 0x55, 0xaa, 0x0f, 0xf0
  12. }; //由于最后还要讲这些数据通过串口发送到电脑 波特率9600
  13. uchar data buffer[100]; //用于缓存从24c02中读取的数据。
  14. void delay(unsigned int m)
  15. {
  16. unsigned int n, p;
  17. for (n = m; n>0; n--)
  18. for (p = 125; p>0; p--);
  19. }
  20. void nop()
  21. {
  22. _nop_();
  23. _nop_();
  24. }
  25. /24C02读写驱动程序
  26. void delay1(unsigned int m)
  27. {
  28. unsigned int n;
  29. for (n = 0; n<m; n++);
  30. }
  31. void init() //24c02初始化子程序
  32. {
  33. scl = 1;
  34. nop();
  35. sda = 1;
  36. nop();
  37. }
  38. void start() //启动I2C总线
  39. {
  40. sda = 1;
  41. nop();
  42. scl = 1;
  43. nop();
  44. sda = 0;
  45. nop();
  46. scl = 0;
  47. nop();
  48. }
  49. void stop() //停止I2C总线
  50. {
  51. sda = 0;
  52. nop();
  53. scl = 1;
  54. nop();
  55. sda = 1;
  56. nop();
  57. }
  58. void writebyte(unsigned char j) //写一个字节
  59. {
  60. unsigned char i, temp;
  61. temp = j;
  62. for (i = 0; i<8; i++)
  63. {
  64. temp = temp << 1;
  65. scl = 0;
  66. nop();
  67. sda = CY; //temp左移时,移出的值放入了CY中
  68. nop();
  69. scl = 1; //待sda线上的数据稳定后,将scl拉高
  70. nop();
  71. }
  72. scl = 0;
  73. nop();
  74. sda = 1;
  75. nop();
  76. }
  77. unsigned char readbyte() //读一个字节
  78. {
  79. unsigned char i, j, k = 0;
  80. scl = 0; nop(); sda = 1;
  81. for (i = 0; i<8; i++)
  82. {
  83. nop(); scl = 1; nop();
  84. if (sda == 1)
  85. j = 1;
  86. else
  87. j = 0;
  88. k = (k << 1) | j;
  89. scl = 0;
  90. }
  91. nop();
  92. return(k);
  93. }
  94. void clock() //I2C总线时钟
  95. {
  96. unsigned char i = 0;
  97. scl = 1;
  98. nop();
  99. while ((sda == 1) && (i<255))
  100. i++;
  101. scl = 0;
  102. nop();
  103. }
  104. 24c02的地址address中读取一个字节数据/
  105. unsigned char read24c02(unsigned char address)
  106. {
  107. unsigned char i;
  108. start();
  109. writebyte(0xa0);
  110. clock();
  111. writebyte(address);
  112. clock();
  113. start();
  114. writebyte(0xa1);
  115. clock();
  116. i = readbyte();
  117. stop();
  118. delay1(100);
  119. return(i);
  120. }
  121. //24c02address地址中写入一字节数据info/
  122. void write24c02(unsigned char address, unsigned char info)
  123. {
  124. start();
  125. writebyte(0xa0);
  126. clock();
  127. writebyte(address);
  128. clock();
  129. writebyte(info);
  130. clock();
  131. stop();
  132. delay1(5000); //这个延时一定要足够长,否则会出错。因为24c02在从sda上取得数据后,还需要一定时间的烧录过程。
  133. }
  134. //24c02的地址address中读取一个字节数据/
  135. //串口初始化
  136. void UARTInit()
  137. {
  138. EA = 1; //打开总中断
  139. ES = 1; //打开串口中断
  140. SM0 = 0;
  141. SM1 = 1;//串口工作方式1,8位UART波特率可变
  142. REN = 1;//串口允许接收
  143. TR1 = 1;//启动定时器1
  144. TMOD |= 0x20;//定时器1,工作模式2 8位自动重装
  145. TH1 = 0xfd;
  146. TL1 = 0xfd;//设置比特率9600
  147. }
  148. //串口发送程序
  149. void UART_TX_Send(uchar i)
  150. {
  151. SBUF=i;
  152. while(!TI);
  153. TI=0;
  154. }
  155. void main()
  156. {
  157. uchar add, j;
  158. init(); //初始化24C02
  159. UARTInit();
  160. while (add != sizeof(music))
  161. {
  162. write24c02(0x05 + add, music[add]);
  163. add++;
  164. if (add % 4 == 0)
  165. P1 = ~P1;
  166. }
  167. //到此为止,向24C02中写入数据的过程均已结束。下面的程序为附加的。
  168. //将已写入的数据再读出,送到串口助手
  169. for (j=0;j<sizeof(music);j++)
  170. {
  171. UART_TX_Send(read24c02(0x05+j));
  172. delay(50);
  173. }
  174. // while (j != add)
  175. // {
  176. //
  177. // UART_TX_Send(read24c02(0x05+j));
  178. // j++;
  179. // delay(50);
  180. // }
  181. while (1);
  182. }

经过分析后我仅仅修改了读写函数  以下是修改部分

主函数测试 直接从0xf5开始读写 最后打印的数据正常

 

 这个改法好处是其他部分的程序都不用动,直接往里面扔数据就行大于256也可以。

下面是改好的程序

  1. #include<reg52.h>
  2. #include <intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. sbit sda = P2 ^ 1; //IO口定义
  6. sbit scl = P2 ^ 0;
  7. //此为待写入24c02的数据。为了便于验证结果,数组的内容为周期重复的。
  8. void UART_TX_Send(uchar i);
  9. char code music[] = {
  10. 0x55, 0xaa, 0x0f, 0xf0, 0x55, 0xaa, 0x0f, 0xf0, 0x55, 0xaa, 0x0f, 0xf0,
  11. 0x55, 0xaa, 0x0f, 0xf0, 0x55, 0xaa, 0x0f, 0xf0, 0x55, 0xaa, 0x0f, 0xf0
  12. }; //由于最后还要讲这些数据通过串口发送到电脑 波特率9600
  13. uchar data buffer[100]; //用于缓存从24c02中读取的数据。
  14. void delay(unsigned int m)
  15. {
  16. unsigned int n, p;
  17. for (n = m; n>0; n--)
  18. for (p = 125; p>0; p--);
  19. }
  20. void nop()
  21. {
  22. _nop_();
  23. _nop_();
  24. }
  25. /24C02读写驱动程序
  26. void delay1(unsigned int m)
  27. {
  28. unsigned int n;
  29. for (n = 0; n<m; n++);
  30. }
  31. void init() //24c02初始化子程序
  32. {
  33. scl = 1;
  34. nop();
  35. sda = 1;
  36. nop();
  37. }
  38. void start() //启动I2C总线
  39. {
  40. sda = 1;
  41. nop();
  42. scl = 1;
  43. nop();
  44. sda = 0;
  45. nop();
  46. scl = 0;
  47. nop();
  48. }
  49. void stop() //停止I2C总线
  50. {
  51. sda = 0;
  52. nop();
  53. scl = 1;
  54. nop();
  55. sda = 1;
  56. nop();
  57. }
  58. void writebyte(unsigned char j) //写一个字节
  59. {
  60. unsigned char i, temp;
  61. temp = j;
  62. for (i = 0; i<8; i++)
  63. {
  64. temp = temp << 1;
  65. scl = 0;
  66. nop();
  67. sda = CY; //temp左移时,移出的值放入了CY中
  68. nop();
  69. scl = 1; //待sda线上的数据稳定后,将scl拉高
  70. nop();
  71. }
  72. scl = 0;
  73. nop();
  74. sda = 1;
  75. nop();
  76. }
  77. unsigned char readbyte() //读一个字节
  78. {
  79. unsigned char i, j, k = 0;
  80. scl = 0; nop(); sda = 1;
  81. for (i = 0; i<8; i++)
  82. {
  83. nop(); scl = 1; nop();
  84. if (sda == 1)
  85. j = 1;
  86. else
  87. j = 0;
  88. k = (k << 1) | j;
  89. scl = 0;
  90. }
  91. nop();
  92. return(k);
  93. }
  94. void clock() //I2C总线时钟
  95. {
  96. unsigned char i = 0;
  97. scl = 1;
  98. nop();
  99. while ((sda == 1) && (i<255))
  100. i++;
  101. scl = 0;
  102. nop();
  103. }
  104. unsigned int read24c02(unsigned int address)
  105. {
  106. uchar i,addr;
  107. addr=(address/0xff*2); //address 0 1 2 3, addr 0 2 4 6
  108. //UART_TX_Send(addr);
  109. start();
  110. writebyte(0xa0+addr);//选页 写:第1页A02页A23页A44页A6
  111. clock();
  112. writebyte(address%0xff);//写地址0-255
  113. clock();
  114. start();
  115. writebyte(0xa1+addr);///选页 读:第1页A12页A33页A44页A7 就是写+1
  116. clock();
  117. i = readbyte();
  118. stop();
  119. delay1(100);
  120. return(i);
  121. }
  122. //24c02address地址中写入一字节数据info/
  123. void write24c02(unsigned int address, unsigned char info)
  124. {
  125. uchar addr;
  126. addr=address/0xff*2; //address/0xff= 0 1 2 3, addr= 0 2 4 6
  127. start();
  128. writebyte(0xa0+addr);//选页 写:第1页A02页A23页A44页A6
  129. clock();
  130. writebyte(address%0xff);//写地址0-255
  131. clock();
  132. writebyte(info);
  133. clock();
  134. stop();
  135. delay1(5000); //这个延时一定要足够长,否则会出错。因为24c02在从sda上取得数据后,还需要一定时间的烧录过程。
  136. }
  137. //24c02的地址address中读取一个字节数据/
  138. //串口初始化
  139. void UARTInit()
  140. {
  141. EA = 1; //打开总中断
  142. ES = 1; //打开串口中断
  143. SM0 = 0;
  144. SM1 = 1;//串口工作方式1,8位UART波特率可变
  145. REN = 1;//串口允许接收
  146. TR1 = 1;//启动定时器1
  147. TMOD |= 0x20;//定时器1,工作模式2 8位自动重装
  148. TH1 = 0xfd;
  149. TL1 = 0xfd;//设置比特率9600
  150. }
  151. //串口发送程序
  152. void UART_TX_Send(uchar i)
  153. {
  154. SBUF=i;
  155. while(!TI);
  156. TI=0;
  157. }
  158. void main()
  159. {
  160. uchar add, j;
  161. init(); //初始化24C02
  162. UARTInit();
  163. while (add != sizeof(music))
  164. {
  165. write24c02(0xf5 + add, music[add]);
  166. add++;
  167. if (add % 4 == 0)
  168. P1 = ~P1;
  169. }
  170. //到此为止,向24C02中写入数据的过程均已结束。下面的程序为附加的。
  171. //将已写入的数据再读出,送到串口助手
  172. for (j=0;j<sizeof(music);j++)
  173. {
  174. UART_TX_Send(read24c02(0xf5+j));
  175. delay(50);
  176. }
  177. while (1);
  178. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/438251
推荐阅读
相关标签
  

闽ICP备14008679号