51单片机定时器T0产生时钟,定时器T1中断扫描键盘编程
时间: 2023-06-15 22:06:04 浏览: 121
以下是基于51单片机的定时器T0产生时钟、定时器T1中断扫描键盘的简单程序:
```
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar code keymap[4][4]={//键盘按键映射表
{'1','2','3','+'},
{'4','5','6','-'},
{'7','8','9','*'},
{'C','0','=','/'}
};
uchar code keyplace[4]={0x7f,0xbf,0xdf,0xef};//键盘行扫描码
bit row_flag=0;//行扫描标志位
uchar row,column;//当前行、列
uchar key;//当前按键
uchar timer_count=0;//定时器计数
void T0_init(){//定时器T0初始化
TMOD|=0x01;//工作在模式1(16位自动重装载)
TH0=0xfc;//定时器初值,1ms
TL0=0x66;
ET0=1;//使能T0中断
TR0=1;//启动T0
}
void T1_init(){//定时器T1初始化
TMOD|=0x10;//工作在模式2(8位自动重装载)
TH1=0xfd;//定时器初值,5ms
TL1=0xfd;
ET1=1;//使能T1中断
TR1=1;//启动T1
}
void key_scan(){//键盘扫描函数
uchar i,j;
for(i=0;i<4;i++){//按行扫描
P0=keyplace[i];//将当前行扫描码输出到P0口
if(P0!=keyplace[i]){//如果有列有按键按下
for(j=0;j<4;j++){//按列扫描
if(P0!=keyplace[i]){//如果当前列有按键按下
while(P0!=keyplace[i]);//等待按键松开
key=keymap[i][j];//记录当前按键
return;
}
P0=P0<<1;//切换到下一列
}
}
}
}
void main(){
T0_init();//初始化定时器T0
T1_init();//初始化定时器T1
EA=1;//开启总中断
while(1){
if(row_flag){//如果需要扫描键盘
key_scan();//扫描键盘
row_flag=0;//清除扫描标志位
}
}
}
void T0_isr() interrupt 1{//定时器T0中断服务函数
TH0=0xfc;
TL0=0x66;//重新加载计时初值
timer_count++;//计数器加1
if(timer_count>=20){//1ms*20=20ms
timer_count=0;//计数器清零
row_flag=1;//设置扫描标志位
}
}
void T1_isr() interrupt 3{//定时器T1中断服务函数
TH1=0xfd;
TL1=0xfd;//重新加载计时初值
column++;//列计数器加1
if(column>=4){//扫描完4列
column=0;//列计数器清零
row++;//行计数器加1
if(row>=4){//扫描完4行
row=0;//行计数器清零
}
}
P0=keyplace[row];//输出当前行扫描码
P2=0x0f;//设置P2口低4位为1,用于读取列扫描码
if((P2&0x0f)!=0x0f){//如果有列有按键按下
key_scan();//扫描键盘
}
}
```
该程序中,定时器T0产生1ms的时钟信号,计数器每计满20次(20ms)就设置扫描键盘的标志位,定时器T1中断每5ms扫描键盘的一行和一列,如果有按键按下就记录当前按键。需要注意的是,程序中使用了定时器T0、T1中断服务函数,需要在程序开头使用`#include<reg51.h>`来包含51单片机的头文件。
阅读全文