已经好久没有登陆EDN了
最后一个51例程也在2个星期之前就做完了,这个时期也算是在调整吧
加入的电子园的USB学习小组,也申请了免费PCB,并且两次跑到元器件市场
终于买到了大部分的零件,下一个阶段就准备从51进阶到USB开发的学习上来
下面是我整理出来51开发板的最后一个学习程序
用定时器,按键,1602液晶做一个电子钟程序 另外说明一下,其实这并非是最
后一个我学习的51程序,只是因为那最后一个程序是运用DS12887做一个精密
的电子钟,但是12887板上没有下载口,调试起来很麻烦,为了不插拔弄坏单片
机,所以决定暂时先不做这个程序了。好了言归正传。
首先这个电子钟主要就是对51单片机的几个学习重点进行回顾和综合运用,键
盘扫描,定时器与中断,1602液晶的显示等等,如果把这个程序做好的话,基
本上51算是入门了,当然,学习之路还是很漫长的,入门不算是精通,还有很
多要继续学习掌握。
首先,我想先说说,至于C语言编程,还是能省则省,毕竟不是汇编。比如说一
个取字符串长度的函数就可以直接加入到头文件中,这样以后就不要一个个数
字符串的长度了(就视频教程的一些不尽人意之处而发,作为教学我觉得应该要
早培养学习者尽量写简洁代码的意识)。首先是位定义,这里应该基本上都没什
么问题。之后的延时函数也很有必要,我发现在大部分的学习程序中延时函数都
是必不可少的的函数。之后就是一些1602相关的字程序,在上一篇日志中已经做
了详尽描述。接着是键盘扫描程序,我觉得本程序的关键点有两个,一个就是键
盘扫描,另外一个就是中断,基本上所有的工作都要在上述两个关键点中完成。
我们设想,当定时器每1S产生一个中断,之后在中断中要刷新液晶显示,以实现
秒分时的跳动,另外一个就是我们可以通过键盘来设置时间。这就是这个电子种
的基本功能(多说两句,用定时器做的电子钟误差很大,所以这个程序没有实用
价值,纯粹是作为学习用途而已)定时器运用就很简单了,1S产生一个中断,使
得秒自加1,当然,秒分时都要做溢出判断,这是外话,之后在1602液晶中刷新
显示即可。而按键扫描稍微复杂一点,首先要先检测主按键是否按下,在主按键
按下的情况下,要把中断暂停,进而执行余下的按键扫描程序,这样的话主按键
按下后时钟就停止跳动,并且此时,假若再按下一次主按键,那么光标就会跳动
到时位上,依此类推,再按一次主按键,光标就跳到分,直至秒为止,假若光标
跳到秒以后,并无其他按键操作的情况下再按一次主按键,则光标消失,同时时
钟恢复跳动。剩下的难点就是按键扫描工作,主要是对时间+键和时间-键的检
测,时间+ 键按下一次对应的数字+1,时间-键则正好相反,只要注意这余下的
键盘扫描必需是嵌套在主按键按下时的服务程序中就可以了,这样的话基本上整
个程序就没什么难点,相当于是一个51开发板复习的好程序。
下面把代码贴出:
#include <reg52.h>
#include <string.h>
#define uchar unsigned char
sbit lcden="P2"^1;
sbit FM="P2"^2;
sbit rs="P2"^0;
sbit s1=P3^0;
sbit s2=P3^1;
sbit s3=P3^2;
uchar table1[]="2008-10-20 MON";
uchar table2[]=" 11:58:00";
uchar i,long1,long2,cnum=0,pnum=0;
char miao="0",shi=11,fen=58;
void delay(uchar z) //延时函数
{
uchar x,y;
for(x=z;x>0;x--)
for(y=100;y>0;y--);
}
void write_con(uchar con) //写指令函数
{
rs=0;
P0=con;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar dat) //写数据函数
{
rs=1;
P0=dat;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
//初始化函数
{
FM=1;
lcden=0;
write_con(0x38); //开显
示
write_con(0x0e); //显示
指针,不闪烁
write_con(0x06); //每写
一字符指针自动+1
write_con(0x01); //清屏
指针归零
write_con(0x80); //定义
指针位置
}
void keyscan(); //键盘扫描
void main()
{
init();
long1=strlen(table1); //取table1长度
long2=strlen(table2); //取talbe2长度
for(i=0;i<long1;i++)
{
write_data(table1);
delay(30);
}
write_con(0x80+0x40);
for(i=0;i<long2;i++)
{
write_data(table2);
delay(30);
}
EA=1;
//开总中断
ET0=1;
//打开定时器0
TMOD=0x01;
//设置定时器工作方式为方式1
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;
while(1)
{
keyscan();
if(cnum==20)
{
cnum=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
write_con(0x80+0x44);
write_data(0x30+shi/10);
write_data(0x30+shi%10);
}
write_con(0x80+0x47);
write_data(0x30+fen/10);
write_data(0x30+fen%10);
}
write_con(0x80+0x4a);
write_data(0x30+miao/10);
write_data(0x30+miao%10);
}
}
}
void intertimer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
cnum++;
}
void keyscan() //键盘
扫描程序
{
if(s1==0)
{
delay(10);
if(s1==0)
{
while(!s1);
delay(10);
while(!s1);
pnum++;
TR0=0;
if(pnum==4)
{
write_con(0x80+0x4c);
pnum=0;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;
}
}
}
if(pnum!=0)
{
if(pnum==1)
{
write_con(0x80+0x45);
if(s2==0)
{
delay(20);
if(s2==0)
{
while(!s2);
delay(20);
while(!s2);
shi++;
if(shi==24)
shi=0;
write_con(0x80+0x44);
write_data(0x30+shi/10);
write_data(0x30+shi%10);
write_con(0x80+0x45);
}
}
if(s3==0)
{
delay(20);
if(s3==0)
{
while(!s3);
delay(20);
while(!s3);
shi--;
if(shi==-1)
shi=23;
write_con(0x80+0x44);
write_data(0x30+shi/10);
write_data(0x30+shi%10);
write_con(0x80+0x45);
}
}
}
else if(pnum==2)
{
write_con(0x80+0x48);
if(s2==0)
{
delay(20);
if(s2==0)
{
while(!s2);
delay(20);
while(!s2);
fen++;
if(fen==60)
fen=0;
write_con(0x80+0x47);
write_data(0x30+fen/10);
write_data(0x30+fen%10);
write_con(0x80+0x48);
}
}
if(s3==0)
{
delay(20);
if(s3==0)
{
while(!s3);
delay(20);
while(!s3);
fen--;
if(fen==-1)
fen=59;
write_con(0x80+0x47);
write_data(0x30+fen/10);
write_data(0x30+fen%10);
write_con(0x80+0x48);
}
}
}
else
{
write_con(0x80+0x4b);
if(s2==0)
{
delay(20);
if(s2==0)
{
while(!s2);
delay(10);
while(!s2);
miao++;
if(miao==60)
miao=0;
write_con(0x80+0x4a);
write_data(0x30+miao/10);
write_data(0x30+miao%10);
write_con(0x80+0x4b);
}
}
if(s3==0)
{
delay(20);
if(s3==0)
{
while(!s3);
delay(20);
while(!s3);
miao--;
if(miao==-1)
miao=59;
write_con(0x80+0x4a);
write_data(0x30+miao/10);
write_data(0x30+miao%10);
write_con(0x80+0x4b);
}
}
}
}
}
后记:学些51有两个月了,其实我觉得真正要入门的话,半个月够了,只是这
中间进度拖拖拉拉,并不是一直继续的而已。另外,这两个月我在学习51板的
同时也自己仿照做了一块51开发板,目前原理图和PCB图的绘制已经完毕,正
在修改错误,并在适当的时机送厂家试试自己的第一块PCB板
呵呵 我争取在下一篇日志中把上述的开发板原理图和PCB图都贴出来晒晒
一起学习共同进步
用户1480039 2008-11-11 16:43
用户153164 2008-11-6 22:31
ilove314_323192455 2008-11-5 20:28
ilove314_323192455 2008-11-5 20:27
用户1612104 2008-11-5 15:17