基于51单片机的时钟程序设计
一、实验目的
1.进一步熟悉编程和程序调试
2.学习P1口的使用方法学
3.学习延时子程序的编写和使用
二、实验内容
在keil环境下编写一下程序:
混合应用数码管、计数器和按键,在数码管上显示时、分、秒,并能调整时和分的显示。
三、实验设计及调试:
实验步骤说明:
本实验需要用到单片机最小应用系统和十六位逻辑电平显示模块。
用P1口做输出口,接十六位逻辑电平显示,程序功能使发光二极管点亮。
1.使用单片机最小应用系统。用扁平数据线连接单片机P1口与LED灯相连。
2.用串行数据通信线连接计算机与仿真器,把仿真器插到模块的锁紧插座中,请注意仿真器的方向:缺口朝上。
3.打开Keil uVision2仿真软件,首先建立本实验的项目文件,输入源程序(实验(一)),进行编译,直到编译无误。生成hex文件。
4.打开实验板总电源,将hex文件下载到实验板内,观察发光二极管显示情况。
四、说明:在我们的开发板上有四个按键s2 、 s3 、s4 、 s5。(它们的作用是按一次s2使分加1;按一次s3使分减1;按一次s4使时加1;按一次s5使时减1.);另外每加一秒伴随着蜂鸣器的滴答声
五、实验硬件电路连接图:
/********在自己的开发板上设计时钟程序********/
#include #define uchar unsigned char #define uint unsigned int //定义开发板上的四个按键所接的IO口 sbit s2 = P3^4; //每按一次分加1 sbit s3 = P3^5; //每按一次分减1 sbit s4 = P3^6; //每按一次时加1 sbit s5 = P3^7; //每按一次时减1 //定义开发板上的段选和位选控制的IO口 sbit dula=P2^6; sbit wela=P2^7; sbit buzz=P2^3; //定义buzz为蜂鸣器所接的IO口 //定义无符号一维数组,数组的元素是数字1~9这10个数字在数码管上显示的段码 uchar discode[] = {0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f}; uchar count; //定义无符号字符型数据“count”,用于计数20次达到20*50ms=1s uint shi,fen,miao,shis,shig,fens,feng,miaos,miaog; //定义时、分、秒以及时、分、秒的十位和个位 void delay(uchar z) //延时子程序 { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void display() //数码管显示子程序 { wela=1; //位选 P0=0x1f; //选择开发板上最右端的那个数码管(显示秒的个位) wela=0; dula=1; //段选 P0=discode[miaog]; //显示秒的个位 dula=0; delay(2) ; wela=1; P0=0x2f; //选择第二个数码管(显示秒的十位) wela=0; dula=1; P0=discode[miaos]; //显示秒的十位 dula=0; delay(2) ; wela=1; P0=0x37; //选择第三个数码管(显示分的个位) wela=0; dula=1; P0=discode[feng]; //显示分的个位 dula=0; delay(2) ; wela=1; P0=0x3b; //选择第四个数码管(显示分的个位) wela=0; dula=1; P0=discode[fens]; //显示分的十位 dula=0; delay(2) ; wela=1; P0=0x3d; //选择第五个数码管(显示时的个位) wela=0; dula=1; P0=discode[shig]; //显示时的个位 dula=0; delay(2) ; wela=1; P0=0x3e; //选择第六个数码管(显示时的十位) wela=0; dula=1; P0=discode[shis]; //显示时的十位 dula=0; delay(2) ; } void process() //时、分、秒处理子程序 { miaog=miao%10; miaos=miao/10; feng=fen%10; fens=fen/10; shig=shi%10; shis=shi/10; } //定时器中断函数,定时50ms,每隔1秒,miao++; void timer0() interrupt 1 using 1 { count++; //每50ms,count就+1 if(count==20) //当count=20时即计数到1s的时候执行if大括号内的语句 { buzz=~buzz; //每加一秒钟蜂鸣器响一下 count=0; miao++; if(miao==60) { miao=0; //当到60秒的时候,分+1 ,同时秒从0重新开始计时 fen++; if(fen==60) { fen=0; //当到60分的时候,时+1 ,同时分从0重新开始计时 shi++; if(shi==12) { shi=0; //当到12小时的时候,时从0重新开始计 } } } } TH0 = 0x3c; //到了50ms后重新装入初值 TL0 = 0xb0; } void key() //按键判断子程序 { if(s2==0) //判断s2是否按下键盘 { delay(100); //延时,软件消抖 if(s2==0) //确认按键按下 { fen++; //分加1 if(fen==60) //加到60时返回0继续加 { fen=0; } } while(s2==0); // 等待按键放开. 即每按一次只加1 } if(s3==0) //判断s3是否按下键盘 { delay(100); //延时,软件消抖 if(s3==0) //确认按键按下 { fen--; //分减1 if(fen==0) //减到0时返回60继续减 { fen=60; } } while(s3==0); // 等待按键放开. 即每按一次只加1 } if(s4==0) //判断s4是否按下键盘 { delay(100); //延时,软件消抖 if(s4==0) //确认按键按下 { shi++; //时加1 if(shi==12) //加到12时返回0继续加 { shi=0; } } while(s4==0); // 等待按键放开. 即每按一次只加1 } if(s5==0) //判断s5是否按下键盘 { delay(100); //延时,软件消抖 if(s5==0) //确认按键按下 { shi--; //时减1 if(shi==0) //减到0时返回12继续减 { shi=12; } } while(s5==0); // 等待按键放开. 即每按一次只加1 } } /*主函数*/ void main(void) { count=0; TMOD = 0x01; //选择T0定时器工作方式1 ET0 = 1; //开中断 EA = 1; //开总中断 TH0 = 0x3c; //设置初值,定时50ms TL0 = 0xb0; TR0 = 1; //开启计数 while(1) { process(); //调用时、分、秒处理子程序 key(); //调用键盘扫描子程序 display(); //调用数码管显示子程序 } } .六、动态显示原理 动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。动态显示的亮度比静态显示要差一些,所以在选择限流电阻时应略小于静态显示电路中的。 七、实验后的经验教训总结: 在刚开始做实验时,基本上什么都不懂,根本上就不知道如何通过编写程序去控制单片机,原因是汇编语言和C语言都不怎么会,连最简单的程序都不会编,更何况是编写程序来控制单片机,后来只好从头开始,首先学习了将近一个星期的C语言,汇编没怎么学习(因为汇编在微机原理里学过,基本的知识都还懂,自己写不出程序来但还是看得懂别人的程序)而且通过上网进入单片机的论坛泡了一段时间,逐渐了解到现在基本上都是采用C语言编程,汇编太麻烦,但汇编的执行效率比C语言高,然后又看了郭天祥的单片机视频,觉得这也不是很难,其实只要弄通了还是蛮简单的~~~后来做实验时自己就开始慢慢的模仿别人的程序稍加改动来完成实验中所要求的内容,发现真的还是蛮简单的~~~这次试验让我觉得:任何事情只要下定决心做都可以成功的只是平时在做某件事情时,还没开始做就开始打退堂鼓,认为自己做不来~很多时候这都只是一个借口,只是不想花费时间,花费精力在这方面而已 对实验课的建议: (1)实验室能不能每天都开放,不要只是在做实验的那几次可以进一下实验室,就做那么几次实验根本上就不能掌握知识,也不可能达到运用自如,这样促使很多学生把做实验都不当做一回事,更谈不上什么理论与实际相结合,到让很多学生认为实验只是闹闹眼子而已 (2)能不能把实验课与理论课结合起来每次做实验都是理论课上完后再做实验根本上就无法达到知识的灵活运用~~下载本文