找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1362|回复: 1
收起左侧

用单片机做一个带存储一功能的秒表,现在程序有点问题,可以正常计... 求帮助

[复制链接]
ID:476044 发表于 2019-5-3 18:50 | 显示全部楼层 |阅读模式
  1. #include "reg52.h"                        

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

  4. void delay(); //短暂延时
  5. void start(); //开始信号
  6. void stop(); //停止信号
  7. void respons();         //应答
  8. void init();   //初始化 两条线都拉高
  9. void write_byte(u8);        //写一个字节
  10. u8 read_byte();           //读一个字节,带带返回值的函数
  11. void write_add(u8,u8);//写入 指定地址 数据
  12. u8 read_add(u8);                //读出  指定地址 数据
  13. u8 fanye=0;         //定义外部中断1 存数次数标志位,翻页次数
  14. u8 gg=0;                //定义存第几数 ,翻到第几个数
  15. u16 cc=0;                  //定义定时器0溢出次数

  16. sbit LSA=P2^2;
  17. sbit LSB=P2^3;
  18. sbit LSC=P2^4;
  19. sbit int0=P3^2; //外部中断0,端口
  20. sbit int1=P3^3; //外部中断1,端口
  21.   sbit  scl=P1^3;         //时钟线
  22.   sbit  sda=P1^4;         //数据线

  23. u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
  24.                                         0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值

  25. u8 ssec,sec,min;
  26. u8 DisplayData[8];
  27. u8 qc=0;                 //定义长按外部中断0 取出保存的数
  28. u8 zant=0;          //暂停开始标志位,外部中断0控制
  29. /*******************************************************************************
  30. * 函 数 名         : delay
  31. * 函数功能                   : 延时函数,i=1时,大约延时10us
  32. *******************************************************************************/
  33. void delay(u16 i)
  34. {
  35.         while(i--);        
  36. }

  37. /*******************************************************************************
  38. * 函 数 名         : Timer0Init
  39. * 函数功能                   : 定时器0初始化
  40. * 输    入         : 无
  41. * 输    出         : 无
  42. *******************************************************************************/
  43. void Timer0Init()
  44. {
  45.         TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

  46.         TH0=0Xd8;        //给定时器赋初值,定时10ms
  47.         TL0=0Xf0;        
  48.         ET0=1;//打开定时器0中断允许
  49.         EA=1;//打开总中断
  50.         TR0=1;//打开定时器                        
  51. }


  52. /*******************************************************************************
  53. * 函 数 名         : DigDisplay
  54. * 函数功能                   : 数码管动态扫描函数,循环扫描8个数码管显示
  55. *******************************************************************************/
  56. void DigDisplay()
  57. {
  58.         u8 i;
  59.         for(i=0;i<8;i++)
  60.         {
  61.                 switch(i)         //位选,选择点亮的数码管,
  62.                 {
  63.                         case(7):
  64.                                 LSA=0;LSB=0;LSC=0; break;//显示第0位
  65.                         case(6):
  66.                                 LSA=1;LSB=0;LSC=0; break;//显示第1位
  67.                         case(5):
  68.                                 LSA=0;LSB=1;LSC=0; break;//显示第2位
  69.                         case(4):
  70.                                 LSA=1;LSB=1;LSC=0; break;//显示第3位
  71.                         case(3):
  72.                                 LSA=0;LSB=0;LSC=1; break;//显示第4位
  73.                         case(2):
  74.                                 LSA=1;LSB=0;LSC=1; break;//显示第5位
  75.                         case(1):
  76.                                 LSA=0;LSB=1;LSC=1; break;//显示第6位
  77.                         case(0):
  78.                                 LSA=1;LSB=1;LSC=1; break;//显示第7位        
  79.                 }
  80.                 P0=DisplayData[i];//发送段码
  81.                 delay(100); //间隔一段时间扫描        
  82.                 P0=0x00;//消隐
  83.         }
  84. }
  85. /*************************延时********************************/
  86. void delayms(u16 x)   //延时函数
  87. {
  88.   u16 p,q;
  89.   for(p=x;p>0;p--)
  90.         for(q=110;q>0;q--);
  91. }
  92. void datapros()
  93. {
  94.         DisplayData[0]=smgduan[ssec%10];
  95.         DisplayData[1]=smgduan[ssec/10];
  96.         DisplayData[2]=0x40;        
  97.         DisplayData[3]=smgduan[sec%10];
  98.         DisplayData[4]=smgduan[sec/10];
  99.         DisplayData[5]=0x40;
  100.         DisplayData[6]=smgduan[min%10];
  101.         DisplayData[7]=smgduan[min/10];
  102. }
  103. /*******************外部中断0*******************/
  104. void wbzd0()interrupt 0
  105. {
  106.    u8 p=0;    //判断按键按下的时间
  107.    delayms(20); //消抖
  108.    if(int0==0)
  109.    {
  110.           while(!int0&&p<250)        //最多按25秒
  111.               {        p++;
  112.                         delayms(100);}
  113.      if(p>15)        //长按2秒 调出数据,
  114.            {
  115.                 qc=1;           //主程序开始 读eeprom数据
  116.                 TR0=0;          //停止定时器工作
  117.                 }
  118.           else                // 低于两秒
  119.      {
  120.        zant=~zant;
  121.        TR0=zant;        //来回反转实现定时器0的启停
  122.       }
  123.         }
  124. }
  125. void wbzd1()interrupt 2
  126.   {
  127.    delayms(20); //消抖
  128.    if(int1==0)
  129.    {
  130.            fanye=1;   //主程序进入存数据,后跳出,直到下次按键按下
  131.          gg++;           //用于判断存数据位,和读数据位,在不同的位置实现的功能不同
  132.          if(gg==5)
  133.             {gg=1;}
  134.          while(!int1);        //按键不松,程序不往下执行
  135.         }
  136.   }
  137. void T0_time()interrupt 1                 //八位自动装填
  138. {
  139.     cc++;
  140.    if(cc>=400)         //0.1秒到来
  141.         {
  142.          cc=0;
  143.          ssec++;         
  144.         }
  145. }
  146. /*******************************************************************************
  147. * 函 数 名       : main
  148. * 函数功能                 : 主函数
  149. * 输    入       : 无
  150. * 输    出             : 无
  151. *******************************************************************************/
  152. void main()
  153. {        
  154.         Timer0Init();  //定时器0初始化
  155.         while(1)
  156.         {        IT0=1;                //外部0低电平触发
  157.             EX0=1;                //开外部中断0

  158.                IT1=1;                //外部1低电平触发
  159.             EX1=1;                //开外部中断1

  160.             ET0=1;                //开定时器0
  161.             EA=1;                // 开总中断
  162.                            
  163.            IP=0x04;        //外部1优先
  164.                  datapros();
  165.                 DigDisplay();
  166.         /**************************按键处理*************************/
  167. if(fanye==1)                  //存数据 判断外部中断1是否按下
  168.            {                  
  169.                 switch(gg)                  //通过gg的值“按第几下”,存到不同的位置
  170.                   {
  171.                    case 1:
  172.                    init();
  173.            write_add(0x01,DisplayData[0]);
  174.            init();
  175.            write_add(0x02,DisplayData[1]);
  176.                    init();
  177.            write_add(0x03,DisplayData[2]);
  178.                    init();
  179.            write_add(0x04,DisplayData[3]);
  180.                    init();
  181.            write_add(0x05,DisplayData[4]);
  182.                    init();
  183.            write_add(0x06,DisplayData[5]);
  184.                           break;
  185.                   /* case 2:
  186.                    init();
  187.            write_add(0x03,num0);
  188.            init();
  189.            write_add(0x04,num1);
  190.                           break;
  191.                    case 3:
  192.                    init();
  193.            write_add(0x05,num0);
  194.            init();
  195.            write_add(0x06,num1);
  196.                           break;
  197.                    case 4:
  198.                    init();
  199.            write_add(0x07,num0);
  200.            init();
  201.            write_add(0x08,num1);
  202.                           break;  */
  203.                   }
  204.                    fanye=0;                 //退出存数,直到下次外部中断1到来
  205.            }

  206.            if(qc==1)                //判断外部中断0长按键 开始读存进EEPROM的数据
  207.            {        
  208.                    while(1)         
  209.                  {
  210.                         switch(gg)          //通过判断外部中断1,按键次数gg实现翻页功能
  211.                         {                          //因为又进入到现在这个大循环 所以外部中断1中的
  212.                          case 1:          //fanye=1;不能在返回上面控制 存第几个数据了,相当与无用
  213.                          init();
  214.              DisplayData[0]=read_add(0x01);
  215.                          init();
  216.              DisplayData[1]=read_add(0x02);
  217.                          init();
  218.              DisplayData[2]=read_add(0x03);
  219.                          init();
  220.              DisplayData[3]=read_add(0x04);
  221.                          init();
  222.              DisplayData[4]=read_add(0x05);
  223.                          init();
  224.              DisplayData[5]=read_add(0x06);

  225.                                           break;
  226.                          /*case 2:
  227.                          init();
  228.              num0=read_add(0x03);
  229.                          init();
  230.              num1=read_add(0x04);
  231.                                          break;
  232.                          case 3:
  233.                          init();
  234.              num0=read_add(0x05);
  235.                          init();
  236.              num1=read_add(0x06);
  237.                                           break;
  238.                          case 4:
  239.                          init();
  240.              num0=read_add(0x07);
  241.                          init();
  242.              num1=read_add(0x08);
  243.                                            break; */
  244.                         }
  245.                          /*mb[0]=num1%10;           //秒表个位
  246.                                mb[1]=num1/10;           //秒表十位
  247.                            mb[2]=num0;  */
  248.                     //display(num0,num1);                  //程序将在此一直判断gg,实现翻页,显示存的数据
  249.                 }                                          //若想再次计数,按下单片机的RST复位键,程序重头执行
  250.          }     
  251.   }                        
  252. }        
  253.                         


  254. /*******************************************************************************
  255. * 函 数 名         : void Timer0() interrupt 1
  256. * 函数功能                   : 定时器0中断函数
  257. * 输    入         : 无
  258. * 输    出         : 无
  259. *******************************************************************************/
  260. void Timer0() interrupt 1
  261. {
  262.         TH0=0Xd8;        //给定时器赋初值,定时10ms
  263.         TL0=0Xf0;
  264.         ssec++;
  265.         if(ssec>=100)  //1s
  266.         {
  267.                 ssec=0;
  268.                 sec++;
  269.                 if(sec>=60)
  270.                 {
  271.                         sec=0;
  272.                         min++;
  273.                         if(min>=60)
  274.                         {
  275.                                 min=0;
  276.                         }
  277.                 }        
  278.         }        
  279. }
  280. /*void delay2()
  281.   {;;} */
  282.            
  283. void start() //开始信号
  284. {
  285.   sda=1;
  286.   delay2();
  287.   scl=1;
  288.   delay2();
  289.   sda=0;
  290.   delay2();
  291. }

  292.   void stop() //停止信号
  293. {
  294.   sda=0;
  295.   delay2();
  296.   scl=1;
  297.   delay2();
  298.   sda=1;
  299.   delay2();
  300. }

  301. void respons()         //应答
  302. {
  303.   u8 i;
  304.   scl=1;
  305.   delay2();
  306.   while((sda==1)&&(i<250))        //防止一直没有收到应答,程序停止
  307.         {i++;}
  308.   scl=0;
  309.   delay2();
  310. }

  311. void init()   //初始化 两条线都拉高
  312. {
  313.    sda=1;
  314.    delay2();
  315.    scl=1;
  316.    delayms(1); //加延时,否则用不了
  317. }

  318.   void write_byte(u8 date)        //写一个字节
  319. {
  320.   u8 i,temp;
  321.   temp=date;
  322.         for(i=0;i<8;i++)
  323.           {
  324.           temp=temp<<1;
  325.           scl=0;
  326.           delay2();
  327.           sda=CY; //最高位移入PSW寄存器中CY位中
  328.           delay2(); //将CY中的值赋给sda
  329.           scl=1;
  330.           delay2();
  331.          }
  332.           scl=0;
  333.          delay2();
  334.          sda=1;
  335.          delay2();
  336. }

  337. u8 read_byte()           //读一个字节,带带返回值的函数
  338. {
  339.   u8 i,k;
  340.   scl=0;
  341.   delay2();
  342.   sda=1;
  343.   delay2();
  344.    for(i=0;i<8;i++)
  345.    {
  346.          scl=1;
  347.          delay2();
  348.          k=(k<<1)|sda;        //将K左移一位后与sda进行或运算,
  349.          scl=0;                        //依次把8个位放入一个字节中来完成接收
  350.          delay2();
  351.         }
  352.         return k;                  //返回值为k
  353. }


  354.   void write_add(u8 address,u8 date)         //写入 指定地址 数据
  355.   {
  356.    start();
  357.    write_byte(0xa0);  //接下来为写操作
  358.    respons();
  359.    write_byte(address);        //送入地址
  360.    respons();
  361.    write_byte(date);        //写入数据
  362.    respons();
  363.    stop();
  364.     delayms(1);         //加延时,否则用不了
  365.   }

  366.   u8 read_add(u8 address)                                //读出  指定地址 数据
  367.   {
  368.         u8 date;
  369.         start();
  370.         write_byte(0xa0);        //接下来为写操作
  371.    respons();
  372.    write_byte(address);          //送入地址 ,下面读数据的地址
  373.    respons();
  374.    start();
  375.    write_byte(0xa1);        //接下来为读操作 存储器发送数据
  376.    respons();
  377.    date=read_byte();         //把SDA数据线上的数据用date存
  378.    stop();
  379.    return date;
  380.    delayms(1);        //加延时,
  381.   }
复制代码


回复

使用道具 举报

ID:170318 发表于 2019-5-3 23:47 | 显示全部楼层
楼主,请问要帮助解决什么问题?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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