找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机IIC总线与数码管程序问题

[复制链接]
跳转到指定楼层
楼主
ID:473410 发表于 2019-2-10 17:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  我的程序是通过AT24C02写入和读取数据,并由四个独立按键控制数码管显示出来。按键1是保存目前的数据,按键2是显示上次保存的数据,按键3是+1功能,按键4是清零功能,开始的时候,数码管会显示4个0,然后按3  +1,按1,保存数据,按4清零,并按2 ,显示数据,前面的都没有问题,就是按2的时候,不管保存的数据是多少,数码管都显示的是0006(6的最下面一横还没有),这是为什么呢?单片机代码如下,初学51,请多指教!

  1. /**************************************************************************************
  2. *                              EEPROM-IIC实验                                                                                                  *
  3. 实现现象:下载程序后数码管后4位显示0,按K1保存显示的数据,按K2读取上次保存的数据,
  4.                   按K3显示数据加一,按K4显示数据清零。最大能写入的数据是255.
  5. 注意事项:由于P3.2口跟红外线共用,所以做按键实验时为了不让红外线影响实验效果,最好把红外线先取下来。                                                                                                                                                                  
  6. ***************************************************************************************/

  7. #include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器
  8. #include "i2c.h"      

  9. typedef unsigned int u16;          //对数据类型进行声明定义
  10. typedef unsigned char u8;

  11. sbit LSA=P2^2;
  12. sbit LSB=P2^3;
  13. sbit LSC=P2^4;

  14. sbit k1=P3^1;
  15. sbit k2=P3^0;
  16. sbit k3=P3^2;
  17. sbit k4=P3^3;         //定义按键端口

  18. char num=0;
  19. u8 disp[4];
  20. u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

  21. /*******************************************************************************
  22. * 函 数 名         : delay
  23. * 函数功能                   : 延时函数,i=1时,大约延时10us
  24. *******************************************************************************/
  25. void delay(u16 i)
  26. {
  27.         while(i--);      
  28. }


  29. /*******************************************************************************
  30. * 函数名         :Keypros()
  31. * 函数功能                 :按键处理函数
  32. * 输入           : 无
  33. * 输出                  : 无
  34. *******************************************************************************/
  35. void Keypros()
  36. {
  37.         if(k1==0)
  38.         {
  39.                 delay(1000);  //消抖处理
  40.                 if(k1==0)
  41.                 {
  42.                         At24c02Write(1,num);   //在地址1内写入数据num
  43.                 }
  44.                 while(!k1);
  45.         }
  46.         if(k2==0)
  47.         {
  48.                 delay(1000);  //消抖处理
  49.                 if(k2==0)
  50.                 {
  51.                         num=At24c02Read(1);          //读取EEPROM地址1内的数据保存在num中
  52.                 }
  53.                 while(!k2);
  54.         }
  55.         if(k3==0)
  56.         {
  57.                 delay(100);  //消抖处理
  58.                 if(k3==0)
  59.                 {
  60.                         num++;           //数据加1
  61.                         if(num>255)num=0;
  62.                 }
  63.                 while(!k3);
  64.         }
  65.         if(k4==0)
  66.         {
  67.                 delay(1000);  //消抖处理
  68.                 if(k4==0)
  69.                 {
  70.                         num=0;                 //数据清零
  71.                 }
  72.                 while(!k4);
  73.         }               
  74. }

  75. /*******************************************************************************
  76. * 函数名         :datapros()
  77. * 函数功能                 :数据处理函数
  78. * 输入           : 无
  79. * 输出                  : 无
  80. *******************************************************************************/
  81. void datapros()
  82. {
  83.         disp[0]=smgduan[num/1000];//千位
  84.         disp[1]=smgduan[num%1000/100];//百位
  85.         disp[2]=smgduan[num%1000%100/10];//个位
  86.         disp[3]=smgduan[num%1000%100%10];               
  87. }


  88. /*******************************************************************************
  89. * 函数名         :DigDisplay()
  90. * 函数功能                 :数码管显示函数
  91. * 输入           : 无
  92. * 输出                  : 无
  93. *******************************************************************************/
  94. void DigDisplay()
  95. {
  96.         u8 i;
  97.         for(i=0;i<4;i++)
  98.         {
  99.                 switch(i)         //位选,选择点亮的数码管,
  100.                 {
  101.                         case(0):
  102.                                 LSA=0;LSB=0;LSC=0; break;//显示第0位
  103.                         case(1):
  104.                                 LSA=1;LSB=0;LSC=0; break;//显示第1位
  105.                         case(2):
  106.                                 LSA=0;LSB=1;LSC=0; break;//显示第2位
  107.                         case(3):
  108.                                 LSA=1;LSB=1;LSC=0; break;//显示第3位      
  109.                 }
  110.                 P0=disp[3-i];//发送数据
  111.                 delay(100); //间隔一段时间扫描      
  112.                 P0=0x00;//消隐
  113.         }               
  114. }

  115. /*******************************************************************************
  116. * 函 数 名       : main
  117. * 函数功能                 : 主函数
  118. * 输    入       : 无
  119. * 输    出             : 无
  120. *******************************************************************************/
  121. void main()
  122. {      
  123.         while(1)
  124.         {
  125.                 Keypros();         //按键处理函数
  126.                 datapros();         //数据处理函数
  127.                 DigDisplay();//数码管显示函数               
  128.         }               
  129. }



  130. #include"i2c.h"

  131. /*******************************************************************************
  132. * 函数名         : Delay10us()
  133. * 函数功能                   : 延时10us
  134. * 输入           : 无
  135. * 输出                  : 无
  136. *******************************************************************************/

  137. void Delay10us()
  138. {
  139.         unsigned char a,b;
  140.         for(b=1;b>0;b--)
  141.                 for(a=2;a>0;a--);

  142. }
  143. /*******************************************************************************
  144. * 函数名         : I2cStart()
  145. * 函数功能                 : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿
  146. * 输入           : 无
  147. * 输出                  : 无
  148. * 备注           : 起始之后SDA和SCL都为0
  149. *******************************************************************************/

  150. void I2cStart()
  151. {
  152.         SDA=1;
  153.         Delay10us();
  154.         SCL=1;
  155.         Delay10us();//建立时间是SDA保持时间>4.7us
  156.         SDA=0;
  157.         Delay10us();//保持时间是>4us
  158.         SCL=0;                       
  159.         Delay10us();               
  160. }
  161. /*******************************************************************************
  162. * 函数名         : I2cStop()
  163. * 函数功能                 : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿
  164. * 输入           : 无
  165. * 输出                  : 无
  166. * 备注           : 结束之后保持SDA和SCL都为1;表示总线空闲
  167. *******************************************************************************/

  168. void I2cStop()
  169. {
  170.         SDA=0;
  171.         Delay10us();
  172.         SCL=1;
  173.         Delay10us();//建立时间大于4.7us
  174.         SDA=1;
  175.         Delay10us();               
  176. }
  177. /*******************************************************************************
  178. * 函数名         : I2cSendByte(unsigned char dat)
  179. * 函数功能                 : 通过I2C发送一个字节。在SCL时钟信号高电平期间,保持发送信号SDA保持稳定
  180. * 输入           : num
  181. * 输出                  : 0或1。发送成功返回1,发送失败返回0
  182. * 备注           : 发送完一个字节SCL=0,SDA=1
  183. *******************************************************************************/

  184. unsigned char I2cSendByte(unsigned char dat)
  185. {
  186.         unsigned char a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。               
  187.         for(a=0;a<8;a++)//要发送8位,从最高位开始
  188.         {
  189.                 SDA=dat>>7;         //起始信号之后SCL=0,所以可以直接改变SDA信号
  190.                 dat=dat<<1;
  191.                 Delay10us();
  192.                 SCL=1;
  193.                 Delay10us();//建立时间>4.7us
  194.                 SCL=0;
  195.                 Delay10us();//时间大于4us               
  196.         }
  197.         SDA=1;
  198.         Delay10us();
  199.         SCL=1;
  200.         while(SDA)//等待应答,也就是等待从设备把SDA拉低
  201.         {
  202.                 b++;
  203.                 if(b>200)         //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
  204.                 {
  205.                         SCL=0;
  206.                         Delay10us();
  207.                         return 0;
  208.                 }
  209.         }
  210.         SCL=0;
  211.         Delay10us();
  212.         return 1;               
  213. }
  214. /*******************************************************************************
  215. * 函数名         : I2cReadByte()
  216. * 函数功能                   : 使用I2c读取一个字节
  217. * 输入           : 无
  218. * 输出                  : dat
  219. * 备注           : 接收完一个字节SCL=0,SDA=1.
  220. *******************************************************************************/

  221. unsigned char I2cReadByte()
  222. {
  223.         unsigned char a=0,dat=0;
  224.         SDA=1;                        //起始和发送一个字节之后SCL都是0
  225.         Delay10us();
  226.         for(a=0;a<8;a++)//接收8个字节
  227.         {
  228.                 SCL=1;
  229.                 Delay10us();
  230.                 dat<<=1;
  231.                 dat|=SDA;
  232.                 Delay10us();
  233.                 SCL=0;
  234.                 Delay10us();
  235.         }
  236.         return dat;               
  237. }


  238. /*******************************************************************************
  239. * 函数名         : void At24c02Write(unsigned char addr,unsigned char dat)
  240. * 函数功能                   : 往24c02的一个地址写入一个数据
  241. * 输入           : 无
  242. * 输出                  : 无
  243. *******************************************************************************/

  244. void At24c02Write(unsigned char addr,unsigned char dat)
  245. {
  246.         I2cStart();
  247.         I2cSendByte(0xa0);//发送写器件地址
  248.         I2cSendByte(addr);//发送要写入内存地址
  249.         I2cSendByte(dat);        //发送数据
  250.         I2cStop();
  251. }
  252. /*******************************************************************************
  253. * 函数名         : unsigned char At24c02Read(unsigned char addr)
  254. * 函数功能                   : 读取24c02的一个地址的一个数据
  255. * 输入           : 无
  256. * 输出                  : 无
  257. *******************************************************************************/

  258. unsigned char At24c02Read(unsigned char addr)
  259. {
  260.         unsigned char num;
  261.         I2cStart();
  262.         I2cSendByte(0xa0); //发送写器件地址
  263.         I2cSendByte(addr); //发送要读取的地址
  264.         I2cStart();
  265.         I2cSendByte(0xa1); //发送读器件地址
  266.         num=I2cReadByte(); //读取数据
  267.         I2cStop();
  268.         return num;      
  269. }



  270. #ifndef __I2C_H_
  271. #define __I2C_H_

  272. #include <reg52.h>

  273. sbit SCL=P2^1;
  274. sbit SDA=P2^0;

  275. void I2cStart();
  276. void I2cStop();
  277. unsigned char I2cSendByte(unsigned char dat);
  278. unsigned char I2cReadByte();
  279. void At24c02Write(unsigned char addr,unsigned char dat);
  280. unsigned char At24c02Read(unsigned char addr);

  281. #endif
复制代码



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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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