本帖最后由 enderman1 于 2019-2-25 19:59 编辑
说在前面的话:真正开学了!从今天开始,楼主要一星期两更了,而且每次更新附带工程源代码,真的!
定时计数器作为51单片机的一个基础外设是必须掌握且熟练掌握的,它的功能不单单和它的名字一样简单,用定时器的功能可以有很多很多,之后会给大家一一列举,在这里就结合数码管和按键来操作吧!
【思路】
首先按键,在之前的经验分享中有提到过按键的使用,包括松手检测和软件消抖,但是都没有基于定时器中断,在松手检测的过程中我们都知道单片机是不干任何事情的,如果把数码管显示的部分写在while(1)循环里面甚至会导致按键按下的时候数码管无法正常显示,而今天的例程结合定时器中断数码管显示一定可以完美解决这个问题。
先放一下之前的代码:
//改进方法
sbit key1=P3^0;
if(key1==0){
delay_ms(5);
if(key1==0){
num++;
}
}while(!key1){display();}
这是之前的按键松手检测保持数码管显示的解决方法,但是这不是一个最好的方法,不妨想一想,将数码管显示函数放到定时器中断服务函数里面就可以解决这个问题,在此之前先配置一下定时计数器。
【定时计数器配置】
关于定时计数器的配置,个人认为,阅读芯片使用手册是一个最好的选择。下图:
定时器相关寄存器:
TCON各个位功能介绍:
TMOD各个位功能介绍:
中断允许寄存器:
通过上面的芯片使用手册,就可以对定时计数器或者中断进行配置了,配置参数依据具体使用情况。以下是本节的配置参数:
void timer0(){
TMOD=0x01;
TH0=0xdc;
TL0=0x00; //定时10ms请求一次中断
EA=1;
ET0=1;
TR0=1; //开定时器
}
定时器中断之所以配置10ms中断一次是因为经实验证明这个刷新频率可以维持数码管的稳定显示,那么我们基于这个配置参数完成一个简单的程序:KEY1=P30 负责加数据 KEY2=P31 负责减数据 数码管显示两位显示数据,数据范围是0~99。
以下是源代码:
#include "stc15f2k60s2.h"
#include "intrins.h"
sbit key1=P3^0;
sbit key2=P3^1;
unsigned char disNum;
unsigned char code leddata[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char disBuf[2];
unsigned char wela=0x80;
bit we=0;
void switch_138(unsigned char dat){
switch(dat){
case 0:P27=0;P26=0;P25=0;break;
case 1:P27=0;P26=0;P25=1;break;
case 2:P27=0;P26=1;P25=0;break;
case 3:P27=0;P26=1;P25=1;break;
case 4:P27=1;P26=0;P25=0;break;
case 5:P27=1;P26=0;P25=1;break;
case 6:P27=1;P26=1;P25=0;break;
case 7:P27=1;P26=1;P25=1;break;
default:break;
}
}
void timer0(){
TMOD=0x01;
TH0=0xdc;
TL0=0x00; //定时10ms请求一次中断
EA=1;
ET0=1;
TR0=1; //开定时器
}
void display(){
wela=_cror_(wela,1);
if(wela==0x20)wela=0x80;
switch_138(6);
P0=wela;
switch_138(7);
P0=leddata[disBuf[we=~we]];
}
void main(){
timer0();
while(1){
disBuf[0]=disNum%10;
disBuf[1]=disNum/10;
if(key1==0){
disNum++;
if(disNum==99)disNum=0;
}while(key1==0);
if(key2==0){
disNum--;
if(disNum==0)disNum=99;
}while(key2==0);
}
}
void timerIT() interrupt 1{
TH0=0xdc;
TL0=0x00;
display();
}
不难发现,在等待松手检测的时候仍然不影响定时器中断,也就是说仍然不影响数码管的显示,而且又能保证数码管的稳定显示。
|