单片机C语言模块三.docx
《单片机C语言模块三.docx》由会员分享,可在线阅读,更多相关《单片机C语言模块三.docx(12页珍藏版)》请在冰豆网上搜索。
![单片机C语言模块三.docx](https://file1.bdocx.com/fileroot1/2022-11/28/4930fed1-3259-448c-a900-d0697e846502/4930fed1-3259-448c-a900-d0697e8465021.gif)
单片机C语言模块三
模块三智能报时器调试
一、显示器
例16位显示器动态显示
(一)硬件接口(6位共阳数码管)
如图所示,用单片机的P0口和P2口作为段码和位码输出口,并由两片74HC373作为每个端口的同相驱动器。
(二)动态显示程序(C51)
显示器用于显示时、分、秒值(从左到右),用6位共阳数码管动态显示,显示缓冲区与设置在片内RAM中的数组LEDBuf[]相对应,数组的6个元素与显示器的对应关系如下(从左到右):
LED5
LDE4
LED3
LED2
LED1
LED0
LEDBuf[0]
LEDBuf[1]
LEDBuf[2]
LEDBuf[3]
LEDBuf[4]
LEDBuf[5]
时分秒
显示缓冲区中存放的是待显示的数据。
#defineledlen6
unsignedcharledbuf[ledlen];//显示缓冲区,存放待显示数据
codeunsignedcharledmap[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}//0~9共阳字形码
voiddisplay()
{
unsignedchari,pos,led;
pos=0x20;//从左边开始显示
for(i=0;iled=ledmap[ledbuf[i]];
P0=led;
P2=pos;//显示一位字符
delay
(1);//延时1ms
pos>>=1;//位码右移,准备显示下一位
P2=0x00;//关所有八段管
}
}
例2电子时钟(具有计时和显示功能)(6位共阳数码管)
(一)电子钟原理
实时时钟是用单片机的定时/计数器T0产生100us的时基信号,每隔100us定时器T0向CPU发出一次中断请求,CPU响应中断后转入中断服务程序,中断服务程序以100us、秒、分、时为单位对实时时钟进行计数。
(二)电子钟硬件系统(如例1图)
(三)电子钟软件系统
系统程序包括以下几部分:
1.主程序(main函数):
主要完成系统的初始化,以及对显示器子程序的调用。
2.定时器中断服务程序(t0_int函数):
判断1秒到否?
如到了,就修改时间
3.显示子程序(display函数):
将显示缓冲区的数据送6位LED显示器显示,6位LED采用动态显示方式。
显示器用于显示时、分、秒值(从左到右),用6位共阳数码管动态显示,显示缓冲区与设置在片内RAM中的数组ledbuf[]相对应,数组的6个元素与显示器的对应关系如下(从左到右):
LED5
LDE4
LED3
LED2
LED1
LED0
ledbuf[0]
ledbuf[1]
ledbuf[2]
ledbuf[3]
ledbuf[4]
ledbuf[5]
时分秒
#include
#defineledlen6
unsignedcharledbuf[ledlen];//显示缓冲区,存放显示数据
codeunsignedcharledmap[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}//0~9共阳字形码
#defineTick10000//10000x100us=1s
#defineT100us(256-50)//100us时间常数(6M)
unsignedcharHour,Minute,Second;
unsignedintC100us;//100us记数单元
voiddelay(unsignedcharCNT)
{
unsignedchari;
while(CNT--!
=0)
for(i=125;i!
=0;i--);
}
voiddisplay()
{
unsignedchari,pos,led;
pos=0x20;//从左边开始显示
for(i=0;i{
led=ledmap[ledbuf[i]];
P0=led;
P2=pos;//显示一位字符
delay
(1);//延时
pos>>=1;//位码右移,准备显示下一位
P2=0x00;//关所有八段管
}
}
voidt0_int()interrupt1
{
C100us--;
if(C100us==0){
C100us=Tick;//100us记数器为0,重置计数器初值
Second++;
if(Second==60){
Second=0;
Minute++;
if(Minute==60){
Minute=0;
Hour++;
if(Hour==24)Hour=0;
}
}
}
}
voidmain()
{
TMOD=0x02;//方式2,定时器
TH0=T100us;
TL0=T100us;
EA=1;
ET0=1;
Hour=0;
Minute=0;
Second=0;
C100us=Tick;
TR0=1;//启动定时器0
while
(1){
ledbuf[0]=Hour/10;
ledbuf[1]=Hour%10;
ledbuf[2]=Minute/10;
ledbuf[3]=Minute%10;
ledbuf[4]=Second/10;
ledbuf[5]=Second%10;
display();
}
}
二、键盘
例:
电子钟键盘(补充)
(一)电子钟键盘功能
键盘部分使用4位独立式键盘,直接使用单片机的P3口连接。
4位键盘设置如下:
功能键:
P3.0确认键:
P3.1减1键:
P3.2加1键:
P3.3
(1)功能键用于选择要修改的时、分、秒值的位置
(2)减1、加1键用于时间值的修改
(3)确认键用于对修改操作的确认
(二)电子钟键盘处理子程序分析
功能:
判断key的值,根据不同的值分别作相应的处理。
(1)如果是0X02则表明检测到确认键,清标志单元key_flag和小数点。
(2)如果是0X01则表明检测到功能键,修改标志单元key_flag的值和小数点位置,小数点的作用相当于光标。
(3)如果是0x04则表明检测到减1键,则根据key_flag的值情况,对相应的显示缓冲单元中的内容进行减1;若减1后小于0则回到9。
(4)如果是0X08则表明检测到加1键,则根据key_flag的值情况,对相应的显示缓冲单元中的内容进行加1;若加1后大于9则归0。
(三)电子钟程序(带键盘)
#include
//#include
#defineucharunsignedchar
#defineuintunsignedint
#defineledlen6
#defineTick10000//10000x100us=1s
#defineT100us(256-50)//fosc=6Mhz,T0定时时间100us
ucharhour,minute,second;
uintC100us;//100us计数单元
ucharidataledbuf[ledlen]={0x00,0x00,0x00,0x00,0x00,0x00};
ucharcodeledmap[32]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00};//0~9,6个0x00,0.~9.,6个0x00字形码,共阳
ucharkey_flag,time_flag,key;
voiddelay(ucharCNT)
{uchari;
while(CNT--!
=0)
for(i=125;i!
=0;i--);
}
voiddisplay()
{
uchari,pos,led;
pos=0x20;//从左边开始显示
for(i=0;iled=ledmap[ledbuf[i]];
P0=led;
P2=pos;//显示一位八段管
delay
(1);//延时1ms
pos>>=1;//位码右移1位
P2=0x00;//关所有八段管
}
}
ucharkeyscan()
{
uchari,j;
key=P3;
i=key&0x0f;/*扫描键盘*/
if(i==0x0f)return(0);/*没键时返回键值=0*/
display();/*调用显示程序延时去抖动*/
display();
key=P3;
i=key&0x0f;
if(i==0x0f)return(0);
j=(~i)&0x0f;
while(key&0x0f!
=0x0f)/*等键释放*/
{
display();
display();
key=P3;
}
return(j);/*返回键值*/
}
voidtimeset(ucharkey)
{
switch(key){
case0x01:
/*功能键处理*/
time_flag=0;
switch(key_flag){
case0x00:
key_flag=0x01;/*置调时标志值*/
ledbuf[1]|=0x10;/*点亮时位小数点*/
ledbuf[3]&=0x0f;/*灭秒位小数点*/
ledbuf[5]&=0x0f;/*灭分位小数点*/
break;
case0x01:
key_flag=0x02;/*置调分标志值*/
ledbuf[3]|=0x10;/*点亮分位小数点*/
ledbuf[1]&=0x0f;/*灭秒位小数点*/
ledbuf[5]&=0x0f;/*灭时位小数点*/
break;
case0x02:
key_flag=0x03;/*置调秒标志值*/
ledbuf[5]|=0x10;/*点亮秒位小数点*/
ledbuf[1]&=0x0f;/*灭分位小数点*/
ledbuf[3]&=0x0f;/*灭时位小数点)*/
break;
case0x03:
key_flag=0x01;/*置调时标志值*/
ledbuf[1]|=0x10;/*点亮时位小数点*/
ledbuf[3]&=0x0f;/*灭秒位小数点*/
ledbuf[5]&=0x0f;/*灭分位小数点*/
break;
default:
break;
}
break;
case0x02:
/*确认键处理*/
time_flag=1;
key_flag=0;/*修改标志清0*/
ledbuf[1]=ledbuf[1]&0x0f;/*清小数点位*/
ledbuf[3]=ledbuf[3]&0x0f;
ledbuf[5]=ledbuf[5]&0x0f;
break;
case0x04:
/*减1键处理*/
switch(key_flag){
case0x00:
break;
case0x01:
hour--;/*时减1*/
if(hour>24)hour=23;/*减过0回23*/
ledbuf[0]=hour/10;
ledbuf[1]=hour%10|0x10;
break;
case0x02:
minute--;/*分减1*/
if(minute>60)minute=59;/*减过0回59*/
ledbuf[2]=minute/10;
ledbuf[3]=minute%10|0x10;
break;
case0x03:
second--;/*秒减1*/
if(second>60)second=59;/*减过0回59*/
ledbuf[4]=second/10;
ledbuf[5]=second%10|0x10;
break;
default:
break;
}
break;
case0x08:
/*加1键处理*/
switch(key_flag){
case0x00:
break;
case0x01:
hour++;/*时加1*/
if(hour>=24)hour=0;/*加到24归0*/
ledbuf[0]=hour/10;
ledbuf[1]=hour%10|0x10;
break;
case0x02:
minute++;/*分加1*/
if(minute>=60)minute=0;/*加到60归0*/
ledbuf[2]=minute/10;
ledbuf[3]=minute%10|0x10;
break;
case0x03:
second++;/*秒加1*/
if(second>=60)second=0;/*加到60归0*/
ledbuf[4]=second/10;
ledbuf[5]=second%10|0x10;
break;
default:
break;
}
break;
default:
break;
}
}
voidt0_int(void)interrupt1using1
{
C100us--;
if(C100us==0){
C100us=Tick;
second++;
if(second==60){
second=0;
minute++;
if(minute==60){
minute=0;
hour++;
if(hour==24){
hour=0;
}
}
}
}
if(time_flag){
ledbuf[0]=hour/10;
ledbuf[1]=hour%10;
ledbuf[2]=minute/10;
ledbuf[3]=minute%10;
ledbuf[4]=second/10;
ledbuf[5]=second%10;
}
}
voidmain()
{
uchari=0;
C100us=Tick;
display();
time_flag=1;
key_flag=0;
TMOD=0x02;
TH0=T100us;
TL0=T100us;
EA=1;
ET0=1;
TR0=1;
hour=0;minute=0;second=0;
while
(1)
{do
{
i=keyscan();
if(i!
=0)timeset(i);
display();//显示时间
}while(i!
=0x02);
}
}