找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2597|回复: 9
打印 上一主题 下一主题
收起左侧

怎么用AT24C02存一个大于256的数?附单片机程序

[复制链接]
跳转到指定楼层
楼主
ID:867963 发表于 2020-12-26 22:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
是设计一个红外计数器的,就差这个计数器计数的保存 存到AT24C02里面好像就最多就255,一到256就清零了
初学者有很多不太懂,at24c02 程序是直接搬书里的 我觉得关键就在我写的那个中断1那里 有大神可以帮看看程序吗

单片机源程序如下:
  1. #include <reg52.h> //51头文件
  2. # include <intrins.h>  
  3. #define uchar unsigned char//宏定义
  4. #define uint  unsigned int //宏定义
  5. #define AT24C02_ADDR  0xa0 //AT24C02地址
  6. sbit we = P2^7; //位定义数码管位选锁存器接口
  7. sbit du = P2^6; //位定义数码管段选锁存器接口
  8. sbit SDA = P2^0;
  9. sbit SCL = P2^1;
  10. sbit key = P2^5;//清零键
  11. sbit LED = P1^2;//指示灯,若灯亮说明IIC数据写入成功
  12. long uint n;
  13. void delay_5us()  
  14. {
  15. _nop_();
  16. _nop_();
  17. _nop_();
  18. _nop_();
  19. _nop_();
  20. }
  21. /*1Ms延时*/
  22. void delay(uint z)
  23. {
  24. uint x,y;
  25. for(x = z; x > 0; x--)
  26.   for(y = 114; y > 0 ; y--);
  27. }
  28. /*I2C初始化*/
  29. void I2C_init()
  30. {
  31. SDA = 1;
  32. _nop_();
  33. SCL = 1;
  34. _nop_();
  35. }
  36. /*I2C起始信号*/
  37. void I2C_Start()  
  38. {
  39. SCL = 1;
  40. _nop_();
  41. SDA = 1;
  42. delay_5us();
  43. SDA = 0;
  44. delay_5us();
  45. }
  46. /*I2C终止信号*/
  47. void I2C_Stop()
  48. {
  49. SDA = 0;
  50. _nop_();
  51. SCL = 1;
  52. delay_5us();
  53. SDA = 1;
  54. delay_5us();
  55. }
  56. /*主机发送应答*/
  57. void Master_ACK(bit i)  
  58. {
  59. SCL = 0; // 拉低时钟总线允许SDA数据总线上的数据变化
  60. _nop_(); // 让总线稳定
  61. if (i)  //如果i = 1 那么拉低数据总线 表示主机应答
  62. {
  63.   SDA = 0;
  64. }
  65. else  
  66. {
  67.   SDA = 1;  //发送非应答
  68. }
  69. _nop_();//让总线稳定
  70. SCL = 1;//拉高时钟总线 让从机从SDA线上读走 主机的应答信号
  71. delay_5us();
  72. SCL = 0;//拉低时钟总线, 占用总线继续通信
  73. _nop_();
  74. SDA = 1;//释放SDA数据总线。
  75. _nop_();
  76. }
  77. /*检测从机应答*/
  78. bit Test_ACK()
  79. {
  80. SCL = 1;
  81. delay_5us();
  82. if (SDA)
  83. {
  84.   SCL = 0;
  85.   _nop_();
  86.   I2C_Stop();
  87.   return(0);
  88. }
  89. else
  90. {
  91.   SCL = 0;
  92.   _nop_();
  93.   return(1);
  94. }
  95. }
  96. /*发送一个字节*/
  97. void I2C_send_byte(uchar byte)
  98. {
  99. uchar i;
  100. for(i = 0 ; i < 8 ; i++)
  101. {
  102.   SCL = 0;
  103.   _nop_();
  104.   if (byte & 0x80)
  105.   {   
  106.    SDA = 1;
  107.    _nop_();      
  108.   }   
  109.   else
  110.   {
  111.    SDA = 0;
  112.    _nop_();
  113.   }
  114.   SCL = 1;
  115.   _nop_();
  116.   byte <<= 1; // 0101 0100B
  117. }
  118. SCL = 0;
  119. _nop_();
  120. SDA = 1;
  121. _nop_();
  122. }

  123. /*I2C 读一字节*/
  124. uchar I2C_read_byte()
  125. {
  126. uchar dat,i;
  127. SCL = 0;
  128. _nop_();
  129. SDA = 1;
  130. _nop_();
  131. for(i = 0 ; i < 8 ; i++)
  132. {
  133.   SCL = 1;
  134.   _nop_();
  135.   if (SDA)      
  136.   {
  137.     dat |= 0x01; //
  138.   }
  139.   else
  140.   {
  141.    dat &=  0xfe; //1111 1110
  142.   }
  143.   _nop_();
  144.   SCL = 0 ;
  145.   _nop_();
  146.   if(i < 7)
  147.   {
  148.    dat = dat << 1;
  149.   }
  150. }
  151. return(dat);
  152. }
  153. /*I2C发送数据*/
  154. bit I2C_TransmitData(uchar ADDR, DAT)
  155. {
  156. I2C_Start();
  157. I2C_send_byte(AT24C02_ADDR+0);
  158. if (!Test_ACK())
  159. {
  160.   return(0);
  161. }
  162. I2C_send_byte(ADDR);
  163. if (!Test_ACK())
  164. {
  165.   return(0);
  166. }
  167. I2C_send_byte(DAT);
  168. if (!Test_ACK())
  169. {
  170.   return(0);
  171. }
  172. I2C_Stop();
  173. return(1);
  174. }
  175. /*I2C接收数据*/
  176. uchar I2C_ReceiveData(uchar ADDR)
  177. {
  178. uchar DAT;
  179. I2C_Start();
  180. I2C_send_byte(AT24C02_ADDR+0);
  181. if (!Test_ACK())     //检测从机应答
  182. {
  183.   return(0);
  184. }
  185. I2C_send_byte(ADDR);   //发送需要读取的数据所在的地址
  186. Master_ACK(0);
  187. I2C_Start();
  188. I2C_send_byte(AT24C02_ADDR+1);
  189. if (!Test_ACK())
  190. {
  191.   return(0);
  192. }
  193. DAT = I2C_read_byte();
  194. Master_ACK(0);      //主机发应答
  195. I2C_Stop();
  196. return(DAT);
  197. }
  198. //数码管段选表
  199. uchar code leddata[]={
  200.                 0x3F,  //"0"
  201.                 0x06,  //"1"
  202.                 0x5B,  //"2"
  203.                 0x4F,  //"3"
  204.                 0x66,  //"4"
  205.                 0x6D,  //"5"
  206.                 0x7D,  //"6"
  207.                 0x07,  //"7"
  208.                 0x7F,  //"8"
  209.                 0x6F,  //"9"
  210.                          };
  211. uchar code WS[]={
  212.       0x7f,
  213.       0xbf,
  214.       0xdf,
  215.       0xef,
  216.       0xf7,
  217.       0xfb,
  218.       0xfd,
  219.       0xfe  //1111 1110
  220.     };
  221. void T0_int() interrupt 1
  222. {
  223. n++;
  224. TH0 = 65535/256;  //重装初值
  225. TL0 = 65535%256; //从15536开始计数
  226. if(!I2C_TransmitData(6,n%1000)); //往AT24C02第255个单元中写入数据,1000 0000的2进制为3个八位,16进制为0x98 96 80,1000 0000%256=80;低八位
  227. delay(5);
  228. if(!I2C_TransmitData(5,n/1000%1000)); //往AT24C02第255个单元中写入数据,1000 0000的2进制为3个八位,16进制为0x98 96 80,1000 0000%256=80;低八位
  229. delay(5);
  230. if(!I2C_TransmitData(4,n/1000/1000)); //往AT24C02第255个单元中写入数据,1000 0000的2进制为3个八位,16进制为0x98 96 80,1000 0000%256=80;高八位
  231. delay(5);
  232. if(n>10000000) //计数次数达到1000W
  233. {
  234. P2 = WS[13];   //数码管显示E代表计数已达上限
  235. P0 = leddata[1];
  236. }
  237. }
  238. void INT0_int() interrupt 2
  239. {
  240. if(!I2C_TransmitData(6,0)); //往AT24C02第255个单元中写入数据,1000 0000的2进制为3个八位,16进制为0x98 96 80,1000 0000%256=80;低八位
  241. delay(5);
  242. if(!I2C_TransmitData(5,0)); //往AT24C02第255个单元中写入数据,1000 0000的2进制为3个八位,16进制为0x98 96 80,1000 0000%256=80;低八位
  243. delay(5);
  244. if(!I2C_TransmitData(4,0)); //往AT24C02第255个单元中写入数据,1000 0000的2进制为3个八位,16进制为0x98 96 80,1000 0000%256=80;高八位
  245. delay(5);
  246. }
  247. void main()
  248. {
  249. uchar a,b,c,d,e,f,g,h,i,j,k;
  250. TH0 = 65535/256;
  251. TL0 = 65535%256; //从15536开始计数
  252. TMOD = 0x05 ;//设置T0为计数器模式,工作方式1,16位计数器
  253. TR0 = 1; //启动T0
  254. EA = 1;
  255. EX1 = 1;
  256. IT1 = 1;
  257. ET0 = 1;//允许T0溢出中断
  258. I2C_init();//I2C初始化
  259.   while(1)
  260.   {   
  261.    i = I2C_ReceiveData(4);//从AT24C02单元中读取数据,高八位
  262.    j = I2C_ReceiveData(5);//从AT24C02单元中读取数据,中八位
  263.    k = I2C_ReceiveData(6);//从AT24C02单元中读取数据,低八位
  264.    n = i*10000+j*100+k;
  265.    a = n%10;
  266.    b = n/10%10;
  267.    c = n/100%10;
  268.    d = n/1000%10;
  269.    e = n/10000%10;
  270.    f = n/100000%10;
  271.    g = n/1000000%10;
  272.    h = n/10000000;
  273.    P0 = WS[0];
  274.    we = 1;//打开位选
  275.    we = 0; //关闭位选
  276.    P0 = leddata[a];
  277.    du = 1; //打开段选
  278.    du = 0; //关闭段选
  279.    delay(2);//延时
  280.    
  281.    we = 1; //打开位选
  282.    P0 = WS[1];//1111 1101  只选通第二位数码管
  283.    we = 0; //关闭位选
  284.    
  285.    P0 = leddata[b]; //显示2
  286.    du = 1;//打开段选
  287.    du = 0; //关闭段选
  288.    delay(2);//延时
  289.    
  290.    P0 = WS[2];// 1111 1011只选通第三位数码管
  291.    we = 1; //打开位选
  292.    we = 0; //关闭位选
  293.    
  294.    P0 = leddata[c]; //显示3
  295.    du = 1;//打开段选
  296.    du = 0; //关闭段选
  297.    delay(2);//延时
  298.    
  299.    P0 = WS[3];//1111 0111  只选通第四位数码管
  300.    we = 1; //打开位选
  301.    we = 0; //关闭位选
  302.         
  303.    P0 = leddata[d]; //显示4
  304.    du = 1;//打开段选
  305.    du = 0; //关闭段选
  306.    delay(2);//延时
  307.    
  308.    P0 = WS[4];//1110 1111  只选通第五位数码管
  309.    we = 1; //打开位选
  310.    we = 0; //关闭位选
  311.    
  312.    P0 = leddata[e];
  313.    du = 1;//打开段选
  314.    du = 0; //关闭段选
  315.    delay(2);//延时
  316.    
  317.    P0 = WS[5];//1101 1111  只选通第六位数码管
  318.    we = 1; //打开位选
  319.    we = 0; //关闭位选
  320.    
  321.    P0 = leddata[f]; //显示6
  322.    du = 1;//打开段选
  323.    du = 0; //关闭段选
  324.    delay(2);//延时
  325.    
  326.    we = 1; //打开位选
  327.    P0 = WS[6];//1011 1111  只选通第七位数码管
  328.    we = 0; //关闭位选
  329.    
  330.    P0 = leddata[g];
  331.    du = 1;//打开段选
  332.    du = 0; //关闭段选
  333.    delay(2);//延时
  334.    
  335.    P0 = WS[7];//0111 1111  只选通第八位数码管
  336.    we = 1; //打开位选
  337.    we = 0; //关闭位选
  338.    
  339.    P0 = leddata[h];
  340.    du = 1;//打开段选
  341.    du = 0; //关闭段选
  342.    delay(2);//延时
  343.   }
  344. }
复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2020-12-26 22:37 | 只看该作者
大于255的数分解为两个字节保存,读取后再合并。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:235200 发表于 2020-12-26 22:48 | 只看该作者
24C02k的一个字节是8位,能够存的最大数是255,所以在存入时要判断,当计数值小于255时,直接存一次,当计数值大于255时,要把计数值/256存一次,计数值%256再存一次

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

地板
ID:420836 发表于 2020-12-27 09:32 | 只看该作者
8位存储器最多可以存储255,如果该数字大于255,则必须将其存储在低半字节和高半字节中。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

5#
ID:57657 发表于 2020-12-27 12:38 | 只看该作者
csmyldl 发表于 2020-12-26 22:48
24C02k的一个字节是8位,能够存的最大数是255,所以在存入时要判断,当计数值小于255时,直接存一次,当计 ...

还可以用C语言的union

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

6#
ID:867963 发表于 2020-12-27 14:18 | 只看该作者
wulin 发表于 2020-12-26 22:37
大于255的数分解为两个字节保存,读取后再合并。

具体是怎么分解 合并呀
回复

使用道具 举报

7#
ID:553941 发表于 2020-12-28 15:50 | 只看该作者
善良的00yy 发表于 2020-12-27 14:18
具体是怎么分解 合并呀

当你寸一个数的时候,比如temp的值是257,先计算一个temp_h=temp/256,存入一个地址。再计算一个temp_l=temp%256,放入下一个地址。当要读这个数的时候,分别读这两个数据,然后temp=temp_h*256+temp_l;
回复

使用道具 举报

8#
ID:867963 发表于 2020-12-31 22:35 | 只看该作者
13303022280 发表于 2020-12-28 15:50
当你寸一个数的时候,比如temp的值是257,先计算一个temp_h=temp/256,存入一个地址。再计算一个temp_l=t ...

成功啦 谢谢啦
回复

使用道具 举报

9#
ID:399179 发表于 2021-11-22 09:28 来自手机 | 只看该作者
善良的00yy 发表于 2020-12-31 22:35
成功啦 谢谢啦

楼主能不能分享一下成功的源代码?我也遇到了这样的问题,我是比菜鸟还菜的菜鸟,只会照搬 先谢谢了!
回复

使用道具 举报

10#
ID:399179 发表于 2021-11-22 11:06 来自手机 | 只看该作者
善良的00yy 发表于 2020-12-31 22:35
成功啦 谢谢啦

楼主能不能分享一下成功后程序代码?造福我等菜鸟,谢谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表