找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 375|回复: 6
收起左侧

想把单片机独立按键和数码管倒计时程序结合起来,遇到一些问题

[复制链接]
ID:1101371 发表于 2024-2-6 14:28 来自手机 | 显示全部楼层 |阅读模式
50黑币
想实现KEY1按下开始倒计时,再按一下结束倒计时的功能。
主要是第五张图片的程序,把这个smg_fuc()数码管倒计时的程序和独立按键的程序关联一下,但是独立按键那个波形不是自锁开关,按下就保持低电平,它又回到高电平,我想在低电平的情况下关联smg函数只能加个while(1),不然得一直按保持低电平。不知道该怎么改单片机代码

IMG_20240206_141053.jpg
IMG_20240206_141143.jpg
IMG_20240206_141216.jpg
IMG_20240206_141226.jpg
IMG_20240206_141235.jpg
IMG_20240206_141245.jpg
回复

使用道具 举报

ID:1101371 发表于 2024-2-6 15:02 来自手机 | 显示全部楼层
现在就是我想像独立按键控制led一样加个取反让这个smg的函数取反,不然就只按一下数码管确实开始动了,能够实现倒计时,但是再按就停不下来了
回复

使用道具 举报

ID:1109793 发表于 2024-2-6 16:52 | 显示全部楼层
你这样就是停在key_func()里面的那根while里面了,无法再响应按键了。调整一下思路,不要总是用while。
回复

使用道具 举报

ID:1109793 发表于 2024-2-6 18:48 | 显示全部楼层
另外无觉得你还是粘贴代码吧,这样看着太费劲
回复

使用道具 举报

ID:213173 发表于 2024-2-6 21:12 | 显示全部楼层
单键控制9分59秒倒计时
  1. #include <reg51.H>
  2. #include <intrins.H>
  3. #define uint unsigned int
  4. #define uchar unsigned char

  5. sbit bai=P3^0;
  6. sbit shi=P3^1;
  7. sbit  ge=P3^2;
  8. sbit key=P3^6;

  9. //定义需要显示的数字
  10. //反序共阴极数码管段码表,段码a-h顺序接PX7-PX0
  11. unsigned char code dis[]={//共阴数码管段码"0~f-."
  12.         0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,
  13.         0xFE,0xF6,0xEE,0x3E,0x9C,0x7A,0x9E,0x8E,0x02,0x01};
  14. uchar data buf[3];
  15. char sec=0,sec_1=0,min=1,min_1=1;      //秒、分
  16. uchar Key_value;              //键值
  17. uchar set=0;                  //设置标志
  18. uint cnt=0,cnt1=0;            //中断计数
  19. uint count=0;                 //长/短按计数
  20. uint rst=0;                                             //复位计数
  21. bit flag_ms=0;                //1ms中断标志
  22. bit flicker=0;                //闪烁标志
  23. bit start=0;                  //开始标志
  24. bit On_Off=1;                 //开关标志


  25. void Timer0Init(void)                //1毫秒@12.000MHz
  26. {
  27.         TMOD |= 0x01;                //设置定时器模式
  28.         TL0 = 0x18;                //设置定时初始值
  29.         TH0 = 0xFC;                //设置定时初始值
  30.         TF0 = 0;                //清除TF0标志
  31.         TR0 = 1;                //定时器0开始计时
  32.         EA  = 1;
  33.         ET0 = 1;
  34. }

  35. //数码管显示函数
  36. void display()
  37. {
  38.         static uchar i;
  39.         if(On_Off)
  40.         {
  41.                 P1=0x00;
  42.                 if(set==0)
  43.                 {
  44.                         switch(i)
  45.                         {
  46.                                 case 0: bai=0;shi=1;ge=1;P1=dis[min]|0x01; break;
  47.                                 case 1: bai=1;shi=0;ge=1;P1=dis[sec/10]; break;
  48.                                 case 2: bai=1;shi=1;ge=0;P1=dis[sec%10]; break;
  49.                         }
  50.                 }
  51.                 if(set==1)
  52.                 {
  53.                         switch(i)
  54.                         {
  55.                                 case 0: bai=0;shi=1;ge=1;
  56.                                                 if(flicker)P1=dis[min]|0x01; else P1=0x01; break;                                               
  57.                                 case 1: bai=1;shi=0;ge=1;P1=dis[sec/10]; break;
  58.                                 case 2: bai=1;shi=1;ge=0;P1=dis[sec%10]; break;
  59.                         }
  60.                 }
  61.                 if(set==2)
  62.                 {
  63.                         switch(i)
  64.                         {
  65.                                 case 0: bai=0;shi=1;ge=1;P1=dis[min]|0x01; break;
  66.                                 case 1: bai=1;shi=0;ge=1;
  67.                                                 if(flicker)P1=dis[sec/10];else P1=0x00; break;                                               
  68.                                 case 2: bai=1;shi=1;ge=0;P1=dis[sec%10]; break;
  69.                         }
  70.                 }
  71.                 if(set==3)
  72.                 {
  73.                         switch(i)
  74.                         {
  75.                                 case 0: bai=0;shi=1;ge=1;P1=dis[min]|0x01; break;
  76.                                 case 1: bai=1;shi=0;ge=1;P1=dis[sec/10]; break;
  77.                                 case 2: bai=1;shi=1;ge=0;
  78.                                                 if(flicker)P1=dis[sec%10];else P1=0x00; break;       
  79.                         }
  80.                 }
  81.         }
  82.         else
  83.         {
  84.                 P1=0xff;
  85.                 bai=1;
  86.                 shi=1;
  87.                 ge=1;
  88.         }
  89.         i=++i%4;
  90. }
  91. //按键扫描
  92. void key_scan()
  93. {
  94.         if(!key)
  95.         {
  96.                 count++;
  97.                 if(count>1000)         //长按时长
  98.                         count=1001;
  99.                 if(count==10)          //大于10ms小于500ms算短按
  100.                 {
  101.                         Key_value=0x01;
  102.                 }
  103.                 if(count==1000)          //达到1s算长按
  104.                 {
  105.                         Key_value|=0x10;
  106.                 }
  107.         }
  108.         else    //按键松手
  109.         {
  110.                 if(count>0)rst=5000;//复位计数赋值
  111.                 count=0;//长/短按计数清0
  112.         }
  113. }      
  114. //按键服务程序
  115. void key_service()
  116. {
  117.         //短按等待松手后响应,长按达1s不论是否松手立即响应
  118.         if((count==0||count==1000) && Key_value!=0x00)
  119.         {
  120.                 switch(Key_value)
  121.                 {
  122.                         case 0x01://短按1任务
  123.                                 if(On_Off==0 && !start && set==0)On_Off=1;//开机
  124.                                 else if(On_Off && !start && set==0){min=min_1;sec=sec_1;start=1;}//启动倒计时
  125.                                 else if(On_Off && !start && set>0)//设置时间
  126.                                 {
  127.                                         switch(set)
  128.                                         {
  129.                                                 case 1: min++;  if(min>9)min=0; break;//设置分
  130.                                                 case 2: sec+=10;if(sec>=60)sec%=10; break;//设置秒十位
  131.                                                 case 3: sec++;  if(sec%10==0)sec-=10; break;//设置秒个位
  132.                                         }       
  133.                                         min_1=min;//缓存分
  134.                                         sec_1=sec;//缓存秒
  135.                                 }                               
  136.                         break;

  137.                         case 0x11:                
  138.                                 if(On_Off && !start)
  139.                                 {
  140.                                         if(++set==4)set=0;//操作设置状态
  141.                                         rst=5000;
  142.                                 }
  143.                         break;
  144.                 }
  145.                 Key_value=0x00;//键值清0
  146.         }
  147. }
  148. //复位/关机函数
  149. void reset()
  150. {
  151.         if(rst>0)
  152.         {
  153.                 rst--;
  154.                 if(rst==0)
  155.                 {
  156.                         if(count==0)//按键已松手
  157.                                 set=0;//设置状态复位
  158.                         else if(!start)//长按5秒不松手关机(倒计时运行中不可关机)
  159.                         {
  160.                                 set=0;//设置状态复位
  161.                                 On_Off=0;//关机
  162.                         }
  163.                 }
  164.         }
  165. }
  166. //主函数
  167. void main()
  168. {
  169.         Timer0Init();
  170.         while(1)
  171.         {
  172.                 if(flag_ms)
  173.                 {
  174.                         flag_ms=0;//1ms标志清0
  175.                         display();//数码管显示函数
  176.                         key_scan();//按键扫描函数
  177.                         key_service();//按键服务函数
  178.                         reset();//复位/关机函数
  179.                 }
  180.         }
  181. }

  182. //T0中断服务函数
  183. void InterruptTimer0() interrupt 1
  184. {
  185.         TL0 = 0x18;                //设置定时初始值
  186.         TH0 = 0xFC;                //设置定时初始值
  187.         if(start)
  188.         {
  189.                 if(++cnt>=1000)//1s
  190.                 {
  191.                         cnt=0;
  192.                         sec--;
  193.                         if(sec==0 && min==0)//倒计时结束
  194.                         {
  195.                                 start=0;        //开始标志清0
  196.                         }
  197.                         else if(sec<0)
  198.                         {
  199.                                 sec=59;
  200.                                 min --;
  201.                         }
  202.                 }
  203.         }
  204.         if(++cnt1>=200)        //200ms 5Hz闪烁,可以任意调整闪烁频率
  205.         {
  206.                 cnt1=0;
  207.                 flicker=~flicker;  //闪烁标志取反
  208.         }
  209.         flag_ms=1;//1ms中断标志赋值
  210. }
复制代码
回复

使用道具 举报

ID:584814 发表于 2024-2-7 08:13 | 显示全部楼层
对用图片求助表示呵呵,如果程序保密不如找个算命的可能帮助更大
回复

使用道具 举报

ID:619259 发表于 2024-4-18 22:12 | 显示全部楼层
思路:按键第一次按下,启动定时器,TR0 = 1;第二次按下,停止定时器,TR0 = 0;
按键加个状态标示。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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