这个本来是帮同学做的期末设计,后来那位同学自己做出来了,因此就没用我这个……
为了便于同学读懂代码,里面几乎每一行都加了注释,依旧分享出来,希望对需要的人有所帮助。
这个设计的原题要求如下:
1.设计一个精度为0.1s的秒表系统。
2.设计启动按钮、暂停按钮及清零按钮。
3*.设计每到一秒钟有声音提醒功能,可通过按钮打开及关闭该提醒音。
运行图如下:
程序代码如下:
代码太长,已被折叠。点击展开查看
- /**************************************************************************************************
- 模块名称:51单片机简易秒表
- 模块功能:实现精确到毫秒的简易秒表
- 编写人员:mengkun (http://mkblog.cn)
- 编写日期:2016/12/18
- **************************************************************************************************/
- #include <reg51.h>
- #define false 0
- #define true 1
- #define uchar unsigned char //0——255
- #define uint unsigned int //0——65535
- #define ulong unsigned long //0——4294967295
- sbit start_key = P3^0; //启动按钮
- sbit pause_key = P3^1; //暂停按钮
- sbit reset_key = P3^2; //重置按钮
- sbit beep_key = P3^3; //声音按钮
- sbit start_led = P3^4; //启动指示灯
- sbit pause_led = P3^5; //暂停指示灯
- sbit beep_led = P3^6; //喇叭指示灯
- sbit beep = P3^7; //喇叭
- uchar disCode[10] = {0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09}; //数码管段码 0~9
- uchar locCode[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
- void displayTime(void); //刷新时间显示
- void disPlay(uchar num, uchar loc); //数码管、led显示函数
- void Delay1ms(unsigned int n); //延时1ms
- uchar state; //状态:0-停止,1-启动,2-暂停
- ulong ms = 0; //存储毫秒值
- uchar fen = 0; //分钟数
- uchar miao; //秒数
- uchar ms2; //毫秒数的10位
- bit isBeep = false; //是否开启蜂鸣器
- /*******************************************************************************
- * 函 数 名 : T0_INT
- * 函数功能 : T0定时器中断函数10ms
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void T0_INT(void) interrupt 1
- {
- //这里不是减去10000是因为在C51单片机中,每执行一条语句需要花费 1ms 时间。减去的是误差值。
- //经过测试,大概每一分钟还是会有 0.8 s的误差……
- //实际的秒表还是得专业的时钟芯片
- TL0= (65536-9000)/256;
- TH0= (65536-9000)%256;
- ms ++;
- }
- /*******************************************************************************
- * 函 数 名 : main
- * 函数功能 : 主函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void main(void)
- {
- TMOD=0x61; //0110 0001 //方式一
- TL0= (65536-10000)/256; // 10ms
- TH0= (65536-10000)%256;
- TR0=1; //开启T0
- //ET0=1; //T0中断允许(要在点击了启动按钮在开启,所以这里不需要开启)
- EA=1; //总中断开启
- //以下指示灯一开始都应该是灭的
- start_led = 0; //启动指示灯
- pause_led = 0; //暂停指示灯
- beep_led = 0; //喇叭指示灯
- while(1)
- {
- displayTime(); //刷新时间显示
- //检测启动、停止按钮
- if(start_key == 0) //按下了启动、停止按钮
- {
- Delay1ms(10); //延时消抖
- if(start_key == 0)
- {
- if(state == 0)//之前是未启动,按了按钮要变成已启动
- {
- state = 1; //更新状态为已启动
- ms = 0; //毫秒数归零
- fen = 0; //分钟数归零
- ET0 = 1; //T0中断允许打开,开始计时
- start_led = 1; //启动led指示灯亮
- }else{
- state = 0; //更新状态为未启动
- ET0 = 0; //关闭T0中断,停止计时
- start_led = 0; //启动led指示灯灭
- pause_led = 0; //暂停指示灯灭
- }
- while(start_key == 0) displayTime(); //防止按键重复检测
- }
- }
- //检测暂停按钮
- if(state != 0 && pause_key == 0) //已启动计时,并且暂停按钮按下
- {
- Delay1ms(10); //延时消抖
- if(pause_key == 0)
- {
- if(state == 2) //之前是暂停,现在要启动
- {
- state = 1; //更新状态为已启动
- pause_led = 0; //暂停指示灯灭
- ET0 = 1; //打开T0中断允许,恢复计时
- }else{
- state = 2;
- pause_led = 1; //暂停指示灯亮起
- ET0 = 0; //关闭T0定时器,暂停计时
- }
- while(pause_key == 0) displayTime(); //防止按键重复检测
- }
- }
- //检测归零按钮
- if(state == 0 && reset_key == 0) //已停止计时,并且归零按钮按下
- {
- Delay1ms(10); //延时消抖
- if(reset_key == 0)
- {
- ms = 0; //毫秒数归零
- fen = 0; //分钟数归零
- while(reset_key == 0) displayTime(); //防止按键重复检测
- }
- }
- //检测声音按钮
- if(beep_key == 0) //归零按钮按下
- {
- Delay1ms(10); //延时消抖
- if(beep_key == 0)
- {
- isBeep = ~isBeep; //取反,原来是开启的,变为关闭。原来是关闭的则变为开启
- beep_led = isBeep; //更新声音指示灯
- while(beep_key == 0) displayTime(); //防止按键重复检测
- }
- }
- }
- }
- void displayTime(void) //刷新时间显示
- {
- miao = ms/100 - fen*60; //秒数
- ms2 = ms/10%10; //毫秒数的10位
- //已启动计时,并且开启了声音 并且处于一秒刚开始的0.1秒内(即新的一秒刚刚开始)
- if(state == 1 && isBeep == true && ms2 < 1)
- {
- beep = 0; //蜂鸣器发出响声
- }else{
- beep = 1; //关闭蜂鸣器
- }
- if(miao >= 60) //秒数大于60
- {
- miao = 0;
- fen++; //分钟数加一
- }
- disPlay(fen/10, 0); //显示分钟数的十位
- disPlay(fen%10, 1); //显示分钟数的个位
- disPlay(miao/10, 2); //显示秒数的十位
- disPlay(miao%10, 3); //显示秒数的个位
- disPlay(ms2, 4); //0.1s
- disPlay(ms%10, 5); //0.01s
- }
- void disPlay(uchar num, uchar loc) //数码管、led显示函数
- {
- P0 = 0xff; //消除重影
- P2 = locCode[loc]; //位码输出
- P0 = disCode[num]; //段码输出
- Delay1ms(1); //增加显示时间,防止显示过暗
- }
- /*******************************************************************************
- * 函 数 名 : Delay1ms (多个)
- * 函数功能 : 延时函数,延时n*1ms
- * 输 入 : n-延时次数
- * 输 出 : 无
- *******************************************************************************/
- void Delay1ms(unsigned int n)
- {
- unsigned char i, j;
- for (; n>0; n--)
- for(i=0;i<10;i++)
- for(j=0;j<33;j++);
- }
完整proteus仿真图如下:
程序和仿真图打包下载:
下载地址本文作者为mengkun,转载请注明。
想学习一下
可以,来学习一下
可以
很不错哦
学习一下
不错。
好东西谢谢
可以收藏
我看看
正需要这个 谢谢
看看
嵌入式看看 [呲牙] [憨笑]
确实不错!佩服
谢谢!
hxhxjsj你好
谢谢
很强,很厉害
不明觉厉! [坏笑]
感觉好麻烦
@歹匕礻申什么好麻烦
我也是玩单片机的
不明觉厉! [鼓掌]
[呲牙]
1好文帮顶 & 顺便留个名~时间:下午8:10:28