赞
踩
在我的博客STC32G单片机的开发(2)里说明了定时器延时函数的编写,这边我们对其进行对中断函数的编写,相信接触过单片机的朋友也对中断的了解,我们这里对中断的概念就不一一介绍了,主要谈谈寄存器的一些使用,以及对定时器来一个补充说明(毕竟我们在延时函数只用定时器0),我们来说说其它定时器,毕竟STC32G单片机有5个定时器;
最近的话,思考了一下按键的扫描有感,自己找到并编写了一个不错的扫描方式实现单片机的代码,结合本文定时器一起进行讲解
AUXR:这是老朋友了,在前几章我们一直相遇,这里我们配置它的启动位和12T分频位
T2L/T2H:重载值设置,注意这里TIM2是16位自动重载,所以我们计完一个周期的数就不用再手动重装了哈,但是想设置重载值记得要定时器关闭的时候再设置,这和TIM0和TIM1的设置规则是一样的哈
这里定时器3和4定时器基本锁死,我们就说其中一个。
T4T3M:这个寄存器和AUXR类似,这里定时器我们使用一个12T模式控制分频和定时器启动位就可
T3L/T3H以及T4L/T4H和TIM2,TIM1和TIM0一个道理,换汤不换药。
我们这边为了不让定时器在初始化设置马上进行中断,我们先清空中断请求标志位。
这边在官方手册的位置在中断部分的内容,5个定时器都是一样的,只是3,4,5没用到TCON寄存器
这边的中断配置路线我们就看官方的手册来配置了,这里我就不一一介绍这些寄存器了。
学过51单片机的朋友都制动 每个中断回调函数名后都有个interrupt Num(Num是中断号)查询中断号我们也可以通过手册的中断列表查询
那话就不多说我们配置一下定时器初始化代码
- //初始化函数,设置为1ms中断
- void TIM2_Init(void)
- {
- AUXR|=0x04;//不分频 1T模式
- T2H=0xA2;
- T2L=0x40;
- T2IF=0;//清空标志位
- ET2=1;//使能定时器2中断
- EA=1;//使能全局中断
- AUXR|=0x10;//启动定时器2
- }
-
- void TIM3_Init(void)
- {
- T4T3M |= 0x02; //定时器时钟1T模式
- T3L = 0x40; //设置定时初始值
- T3H = 0xA2; //设置定时初始值
- T3IF=0; //清空标志位
- ET3=1;//使能定时器3中断
- EA=1;//使能全局中断
- T4T3M |= 0x08; //启动定时器3
- }
-
-
- //中断回调函数
- void TIM2_CB(void)interrupt 12
- {
-
- }
- void TIM3_CB(void)interrupt 19
- {
-
- }
这里难点在于双击的判断,我们也要做到一定的消抖,消抖顺序切记要对上,否者判断会出现一些问题的
1,(短按+长按)运用到3态状态机
流程大致为(1)按键按下->(2)消抖->(3)判断是否长按和短按
2,(短按+长按+双击)运用到7态状态机
流程大致为(1)按键按下->(2)消抖->(3)判断是否长按->(4)判断松开->(5)判断短按->
(6)消抖->(7)判断双击
这边消抖的时间我们为了保守使用设置为20ms
这边的话,我之前使用到了STM32单片机来写过于是就直接复制上了,我也懒得再移植就是了,这里我们用到个结构题来存储各个按键的一些值
- typedef struct Keys{
- uint8_t State;//状态
- uint8_t Short_Flag;//短按标志位
- uint8_t Long_Flag;//长按标志位
- uint8_t Double_Flag;//双击标志位
- uint8_t Count;//计数器,计数延时
- uint8_t Value;//存储按键按下为1还是0
- uint8_t Key_Up;//弹起标志位,防止反复触发
- }Keys;
然后我们设置一个结构体数组变量
Keys Key[4];//设置可以扫描四个按键且互不干扰
然后 Coding Time:
短按+长按(STM32实现)少量注释和下列是相同道理的哈
- void TIM8_TRG_COM_TIM14_IRQHandler(void)
- {
-
- if(TIM_GetITStatus(TIM14,TIM_IT_Update)==SET)
- {
- Key[0].Value=!(uint8_t)KEY1;
- Key[1].Value=(uint8_t)KEY2;
- Key[2].Value=(uint8_t)KEY3;
- Key[3].Value=(uint8_t)KEY4;
-
- for(uint8_t i=0;i<4;i++)
- {
- switch(Key[i].State)
- {
- case 0:
- {
- if(Key[i].Value==0&&Key[i].Key_Up)
- {
- Key[i].State=1;
- Key[i].Key_Up=0;
- }
- else Key[i].State=0;
- break;
- }
-
- case 1:
- {
- if(Key[i].Value==0)Key[i].State=2;//消抖处理
- else Key[i].State=0;
- break;
- }
-
- case 2:
- {
- if(Key[i].Count<0xFF)
- Key[i].Count++;
- if(Key[i].Value==1&&Key[i].Count<=40)//超过200毫秒
- {
- Key[i].Count=0;
- Key[i].Short_Flag=1;
- Key[i].State=0;
-
- }
- else if(Key[i].Value==0&&Key[i].Count>40)
- {
- Key[i].Count=0;
- Key[i].Long_Flag=1;
- Key[i].State=0;
- }
-
- break;
- }
-
- }
- if(Key[i].Value==1)Key[i].Key_Up=1;
- }
- Time14++;
- TIM_ClearITPendingBit(TIM14,TIM_IT_Update);
- }
- }
短按+长按+双击(STC32实现)
- void TIM2_CB(void)interrupt 12 //1ms延时
- {
- static uint8_t cnt=0;
- uint8_t i;
- if(cnt++==20)//20ms循环扫描一次按键
- {
- cnt=0;
- Key[0].Value=(uint8_t)KEY1;
- for(i=0;i<1;i++)
- {
- switch(Key[i].State)
- {
- case 0:
- {
- if(Key[i].Value==0&&Key[i].Key_Up)//Key_Up防止长按按下不放反复触发
- {
- Key[i].State=1;
- Key[i].Key_Up=0;
- }
- else Key[i].State=0;
- break;
- }
-
- case 1:
- {
- if(Key[i].Value==0)Key[i].State=2;//第一次消抖处理
- else Key[i].State=0;
- break;
- }
-
- case 2:
- {
- if(Key[i].Count<0xFF)
- Key[i].Count++;//开始计数一个数二十毫秒
- if(Key[i].Value==1)//按键弹起进入按键扫描双击判断
- {
- Key[i].Count=0;
- Key[i].State=3;
-
- }
- else if(Key[i].Value==0&&Key[i].Count>35)//超过700毫秒
- {
- Key[i].Count=0;
- Key[i].Long_Flag=1;
- Key[i].State=0;
- }
- break;
- }
-
- case 3://弹起消抖处理
- {
- if(Key[i].Value==1)Key[i].State=4;
- else Key[i].State=0;
- break;
- }
-
- case 4://判断长按短按
- {
- if(Key[i].Count<0xFF)
- Key[i].Count++;//开始计数一个数二十毫秒
- if(Key[i].Value==1&&Key[i].Count>10)//超过200毫秒
- {
- Key[i].Short_Flag=1;
- Key[i].Count=0;
- Key[i].State=0;
- }
- else if(Key[i].Value==0)//二次按下消抖处理
- {
- Key[i].State=5;
- Key[i].Count=0;
- }
- break;
- }
-
- case 5://二次按下消抖处理
- {
- if(Key[i].Value==0)
- Key[i].State=6;
- else Key[i].State=0;
- break;
- }
- case 6://弹起再做二次标志位,别问为什么,就是正常人快按两次都是弹起
- {
- if(Key[i].Value==1)
- {
- Key[i].Double_Flag=1;
- Key[i].State=0;
- }
- break;
- }
- }
- if(Key[i].Value==1)Key[i].Key_Up=1;//判断是否弹起
- }
- }
- }
main函数:完成一次按键在main中判断做完事记得清除标志位哈
- #include <STC32G.H>
- #define LED1 P40
- #define LED2 P41
- #define LED3 P42
- void main(void)
- {
- P4M1=0x00;
- P4M0=0xFF;
- P40=0;
- P41=0;
- P42=0;
- Key_Init();
- while(1)
- {
- if(Key[0].Short_Flag==1)
- {
- LED1=!LED1;
- Key[0].Short_Flag=0;
- }
- if(Key[0].Long_Flag==1)
- {
- LED2=!LED2;
- Key[0].Long_Flag=0;
- }
- if(Key[0].Double_Flag==1)
- {
- LED3=!LED3;
- Key[0].Double_Flag=0;
- }
- }
- }
(STC32G)最后三个灯可仅靠一个按键来控制,按键200ms后没再按下判断为短按第一个灯亮,按键长按700ms后判断为第二个灯亮,按键200ms后再按下判断为双击第三个灯亮。
要学会多思考,多应用,如果有错误不当的地方请大家指证哈
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。