找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1891|回复: 7
收起左侧

请教一个用单片机定时器通过按键对参数连续的问题

[复制链接]
ID:476909 发表于 2019-11-14 17:35 | 显示全部楼层 |阅读模式
平时对单片机一知半解的,工作不对口,但很久以前学过一些,
今天想做一个小的显示电路,通过一个按键对一个数据进行加操作,比如0~9999吧。
想用stc的单片机,型号无所谓了,大致能用就行,当按键按下时用定时器实现数据的连续加,用延时的方法实现连续加可以实现,但延时的方法不理想,
想请教一下坛子里的师傅们能不能给一个简单的程序学习一下
实际上为了节省IO,我是用了一个74HC595来驱动数码管,但考虑到不想多浪费大家的精力,就简单通过IO来驱动了。
方法对了换个驱动芯片就简单了。
这里先谢谢了

999.jpg
回复

使用道具 举报

ID:213173 发表于 2019-11-14 21:38 | 显示全部楼层
给你写了一个按键短按加减,长按连加减 4位数码管显示0~9999程序,端口根据实际电路自行修改。
无标题.jpg

  1. //按键短按加减,长按连加减 4位数码管显示0~9999
  2. #include <REG51.H>
  3. #define uint unsigned int                         //宏定义数据类型uint
  4. #define uchar unsigned char                 //宏定义数据类型uchar
  5. #define key_S 10                                        //宏定义短按20ms
  6. #define key_L 500                                        //宏定义长按1000ms
  7. #define key_M 400                                        //宏定义长按间隔200ms
  8. sbit key1=P1^6;                                                //加键
  9. sbit key2=P1^7;                                                //减键
  10. uchar code table[]={
  11.         0x3f,0x06,0x5b,0x4f,
  12.         0x66,0x6d,0x7d,0x07,
  13.         0x7f,0x6f,0x77,0x7c,
  14.         0x39,0x5e,0x79,0x71};
  15. uchar code wela[]={0xfe,0xfd,0xfb,0xf7};
  16. uint num=0;

  17. void Timer0Init()        //2毫秒@12.000MHz
  18. {
  19.         TMOD= 0x01;                //设置定时器模式
  20.         TL0 = 0x30;                //设置定时初值
  21.         TH0 = 0xF8;                //设置定时初值
  22.         TF0 = 0;                //清除TF0标志
  23.         TR0 = 1;                //定时器0开始计时
  24.         EA  = 1;                //开总中断
  25.         ET0 = 1;                //开定时器0中断       
  26. }

  27. void keyscan()                                                        //按键扫描
  28. {
  29.         static uint count1=0,count2=0;//计数变量
  30.         if(!key1)   
  31.         {  
  32.                 count1++;  
  33.                 if(count1>=key_L)                                //长按
  34.                 {
  35.                         if(num<9999)
  36.                                 num++;        
  37.                         count1=key_M;
  38.                 }
  39.         }  
  40.         else                                                                        //按键抬起
  41.         {  
  42.                 if(count1>key_S && count1<key_L)//短按
  43.                 {
  44.                         if(num<9999)
  45.                                 num++;
  46.                 }
  47.                 count1=0;                                                        //count清0
  48.         }   
  49.         if(!key2)   
  50.         {  
  51.                 count2++;  
  52.                 if(count2>=key_L)                                //长按
  53.                 {
  54.                         if(num>0)
  55.                                 num--;        
  56.                         count2=key_M;
  57.                 }
  58.         }  
  59.         else                                                                        //按键抬起
  60.         {  
  61.                 if(count2>key_S && count2<key_L)//短按
  62.                 {
  63.                         if(num>0)
  64.                                 num--;
  65.                 }
  66.                 count2=0;                                                        //count清0
  67.         }
  68. }
  69. void display()//显示程序
  70. {
  71.         static uchar i=0;
  72.         P2=0x00;
  73.         P3=wela[i];
  74.         switch(i)
  75.         {
  76.                 case 0: P2=table[num/1000%10]; break;
  77.                 case 1: P2=table[num/100%10]; break;
  78.                 case 2: P2=table[num/10%10]; break;
  79.                 case 3: P2=table[num%10]; break;
  80.         }
  81.         i++;
  82.         i%=4;
  83. }

  84. void main()
  85. {
  86.         Timer0Init();
  87.         while(1);
  88. }

  89. void timer0() interrupt        1
  90. {
  91.         TL0 = 0x30;
  92.         TH0 = 0xF8;       
  93.         keyscan();
  94.         display();
  95. }
复制代码



回复

使用道具 举报

ID:235200 发表于 2019-11-15 01:43 | 显示全部楼层
一般用定时计数器可以实现,其思路是用一个整型变量进行加,所加的值分配按千百十个位存入数组定义的显示缓冲区,程序扫描显示缓冲区的数据即可
如定义1秒钟加1次的实现方法:
定时中断的程序
void time0() interrupt 1
{
    n++;        //2ms定时加到500即为1秒
   if (n==500)
     {
        n=0;
        sec++;          //秒钟加1
      }
    P2=0;                          //共阴数码管消影
    P2=disp[dispbuf[i]];     //dispbuf数组存千百十个位数据 disp数组存0-9的段码
    P3=wei[i];                    //数组wei存放显示的位码依次为0x0e,0x0d,0x0b,0x07
    i++;                            //i用于计数数码管的显示位
   if (j==4) j=0;
   TH0=(65536-2000)/256;     //重装2ms初值
   TL0=(65536-2000)%256;
}

主程序应包括如下内容:
dispbuf[0]=sec/1000;                     //千位数字
dispbuf[1]=(sec/100)%10;          //百位数字
dispbuf[2]=(sec/10)%10;           //十位数字
dispbuf[3]=sec%10;                     //个位数字
回复

使用道具 举报

ID:642363 发表于 2019-11-15 03:37 | 显示全部楼层
很简单的 github 有源码 直接找
回复

使用道具 举报

ID:476909 发表于 2019-11-15 10:46 | 显示全部楼层
谢谢大家,我这就仔细学习一下
回复

使用道具 举报

ID:230975 发表于 2019-11-16 10:31 | 显示全部楼层
wulin 发表于 2019-11-14 21:38
给你写了一个按键短按加减,长按连加减 4位数码管显示0~9999程序,端口根据实际电路自行修改。

师傅在定时器里可以执行这么多语句,为何我在定时器0里执行一个,用定时器1产生波特率的串口发送程序就不行呢。
回复

使用道具 举报

ID:642249 发表于 2019-11-16 14:09 | 显示全部楼层
wulin 发表于 2019-11-14 21:38
给你写了一个按键短按加减,长按连加减 4位数码管显示0~9999程序,端口根据实际电路自行修改。

真厉害
回复

使用道具 举报

ID:213173 发表于 2019-11-16 18:20 | 显示全部楼层
hmgqljz111 发表于 2019-11-16 10:31
师傅在定时器里可以执行这么多语句,为何我在定时器0里执行一个,用定时器1产生波特率的串口发送程序就不 ...

玩单片机就是玩逻辑和时间,原则上定时器中断中不要执行过么多语句,以免影响主程序执行任务,但只要把时序安排好,完全可以只在定时器中断中完成任务,基本没有主函数什么事。串口发送程序也可以在T0中断中运行,串口发送程序在主函数中运行时如果受到T0中断干扰可以在发送时短暂关闭T0中断,如果不能关,也可以在T0中断中设个标志,串口发送程序查询这个标志决定发送,可以有效避免互相干扰。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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