实验四-键盘与中断 参考程序

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

1、基本要求:在mini80E单片机实验板上实现教材【例4.1.1】对应的功能。

画出电路原理图、编写程序、在实验板上实现。

【例4.1.1】用数码管前两位显示一个十进制数,变化范围为00~59,开始时显示00,每按下S2(key1)键一次,数值加1;每按下S3(key2)键一次,数值减1;每按下S4(key3)键一次,数值归零;按下S5(key4)键一次,利用定时器功能使数值开始自动每秒加1,再次按下S5(key4)键,数值停止加1,保持显示原数。

(P82)
说明:
实验室的实验板与教材上程序对应的硬件电路稍有区别,程序要做少许修改。

主要是修改按键和显示器对应的接口定义。

请对下面程序中注释部分标有“删除或修改”的地方删除或修改,修改原理见实验报告或QQ群中mini80e实验板的原理图。

#include <reg52.h> //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
sbit key1=P3^4; //S1,删除或修改
sbit key2=P3^5; //S2,删除或修改
sbit key3=P3^6; //S3,删除或修改
sbit key4=P3^7; //S4,删除或修改
sbit dula=P2^6; //删除或修改
sbit wela=P2^7; //删除或修改
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,//0-9
0x77,0x7c,0x39,0x5e,0x79,0x71}; //A-F
void delayms(uint); //延时ms函数
uchar numt0,num; //numt0-对T0定时计数,num-变化的数(0-59)
void display(uchar numdis) //显示子函数(电路原理见P58)
{
uchar shi,ge; //局部变量,存放要显示的十位、个位数
shi=numdis/10; //分离两个分别要显示的数
ge=numdis%10;
dula=1; //删除或修改
P0=table[shi]; //保留
dula=0; //删除或修改
P0=0xff; //删除或修改
wela=1; //删除或修改
P0=0xfe; //修改
wela=0; //删除或修改
delayms(5); //延时保证亮度(实际延时1-2ms即可)
dula=1; //删除或修改
P0=table[ge]; //保留
dula=0; //删除或修改
P0=0xff; //删除或修改
wela=1; //删除或修改
P0=0xfd; //修改
wela=0; //删除或修改
delayms(5);
}
//以下程序不变
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒for(j=110;j>0;j--);
}
void init() //初始化函数
{
TMOD=0x01; //设置T0方式1定时
TH0=(65536-45872)/256; //装初值定时50ms
TL0=(65536-45872)%256;
EA=1; //开总中断
ET0=1; //开T0中断
}
void keyscan() //键处理函数
{
if(key1==0) // key1按下否?
{
delayms(10); //延时10ms消抖
if(key1==0) //再判别是否按下
{
num++; //如果key1按下,num加1
if(num==60)//当到60时重新归0
num=0;
while(!key1); //等待按键释放}
}
if(key2==0) // key2按下否?
{
delayms(10);
if(key2==0)
{
if(num==0)//当到0时重新归60
num=60;
num--;
while(!key2);
}
}
if(key3==0) // key3按下否?
{
delayms(10);
if(key3==0)
{
num=0; //清0
while(!key3);
}
}
if(key4==0)// key4按下否?
{
delayms(10);
if(key4==0)
{
while(!key4);
TR0=~TR0; //启动或停止定时器0
}
}
}
void main() //主函数
{
init(); //初始化
while(1) //循环执行程序(注意不要把初始化包括在内){
keyscan(); //按键识别与处理
display(num); //刷新显示
}
}
void T0_time() interrupt 1 //T0定时50ms中断服务函数
{
TH0=(65536-45872)/256;//重装初值
TL0=(65536-45872)%256;
numt0++; //对50ms计数
if(numt0==20) //如果到了20次,说明1秒时间到
{
numt0=0; //然后把num清0重新再计20次
num++; //1秒到num加1
if(num==60)
num=0;
}
}
2、创新要求:在mini80E 单片机实验板上实现时钟显示与设置。

(1)按如下格式显示时分秒(按实际时间变化):
(2)使用4个
独立式按键(K1、K2、K3、
K4)实现对时间的设置,在设置时间时显示器按如下格式显示(以设置小时为例,设置时、分时
相应变化格式):
参考程序:
说明:个别地方老师设置了修改点,注意修改
/*程序功能:数码管显示时间hh-mm-ss
并用4个独立式按键实现显示与设置切换*/
#include <reg52.h> //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
uchar code table[ ]= //七段码表
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, //0-9
0x77,0x7c,0x39,0x5e,0x79,0x71, //A-F
0x40}; //-
uchar data buf_disp[ ]={1,0,16,2,5,16,5,9,16}; //显示缓冲区,存放1-8位数码管显示代码序号
uchar time[]={10,26,59}; //存放时分秒的数组
uchar time_max[]={23,59,59}; //时分秒的最大值(可以放在code 区)
uchar k_val; //存放键值的变量,1为显示时分秒,2,3,4为设置时分秒 uchar num_50ms; //对50ms 中断计数的变量
//定义独立按键对应的接口
sbit key1=P3^4; //S1,注意修改
sbit key2=P3^5; //S2,注意修改
sbit key3=P3^6; //S3,注意修改
sbit key4=P3^7; //S4,注意修改
//声明程序中用到的函数
void delayms(uint); //声明延时函数
void display(); //显示函数
void keyscan(); //按键扫描与处理函数
//主函数
void main()
{
//T0初始化
TMOD=0x01; //T0方式1定时
TH0=(65536-50000)/256; //12M晶振定时50ms
TL0=(65536-50000)%256; //11.0592M晶振时要相应修改
EA=1; //CPU开中断
ET0=1; //T0开中断
TR0=1; //启动T0
//大循环,反复调用键处理函数和显示函数
while(1)
{
uchar num;
keyscan(); //键扫描与处理
//根据键值k_val在显缓中设置显示格式与内容
if(k_val==1) //如果是显示键,按规定格式显示时分秒
{
for(num=0;num<3;num++)
{
buf_disp[num*3]=time[num]/10;
buf_disp[num*3+1]=time[num]%10;
buf_disp[num*3+2]=16;
}
}
if(k_val>1) //如果是设置键按下
{
//先将显缓全部设成"-"
for(num=0;num<8;num++)
{
buf_disp[num]=16;
}
//再根据键值显示设置值
buf_disp[(k_val-2)*3]=time[k_val-2]/10;
buf_disp[(k_val-2)*3+1]=time[k_val-2]%10;
}
display();//刷新显示
}
}
//延时函数
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
//T0中断服务函数,定时50ms中断
void timer0() interrupt 1
{
TH0=(65536-50000)/256; //重装50ms初值
TL0=(65536-50000)%256; //
num_50ms++; //对50ms中断计数
if(num_50ms>=20) //50mS*20=1S时间到
{
num_50ms=0;
time[2]++; //秒加1
if(time[2]>=60) //如果秒>=60
{
time[2]=0;
time[1]++; //分加1
if(time[1]>=60) //如果分>=60
{
time[1]=0;
time[0]++; //时加1
if(time[0]>=24) //如果时>=24
{
time[0]=0;
}
}
}
}
}
//显示函数,根据显缓内容显示对应字符
void display()
{
uchar num;
for(num=0;num<8;num++)
{
P0= table[buf_disp[num]]; //输出段选码
P0=num; //输出位选码,注意修改
delayms(10); //每位延时,注意修改}
}
//键扫描与处理函数
void keyscan()
{
if(key1==0) // key1(显示键)按下否?
{
delayms(10);//延时10ms消抖
if(key1==0) //再判别是否按下
{
k_val=1; //如果key1按下,键值赋1
while(!key1); //等待按键释放
}
}
if(key2==0) // key2(设置键)按下否?
{
delayms(10);
if(key2==0)
{
k_val++; // k_val=2,3,4分别表示设置时分秒
if(k_val>4) //当到5时重新归2
k_val=2;
while(!key2);
}
}
if(key3==0) // key3(加1键)按下否?
{
delayms(10);
if(key3==0)
{
if(k_val>1) //判别是否是设置状态(加1键在设置状态才有效)
{
time[k_val-2]++;
if(time[k_val-2]>time_max[k_val-2]){time[k_val-2]=0;}
}
while(!key3);
}
}
if(key4==0) // key4(减1键)按下否?
{
delayms(10);
if(key4==0)
{
if(k_val>1) //判别是否是设置状态(减1键在设置状态才有效)
{
if(time[k_val-2]==0){time[k_val-2]=time_max[k_val-2];}
else time[k_val-2]--;
}
while(!key4);
}
}
}。

相关文档
最新文档