秒表-六位数码管有效显示
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
∙/************************************************************************** ∙* 标题: 秒表-六位数码管有效显示(C51)
∙* 作者: wentao
∙
∙* 日期: 2007.3.3
∙* 软件: Keil C51 V8.02
∙* 芯片: AT89X51
∙* 说明: 实验板实测通过,数码管为8位共阳
∙* 声明: 自用存档!另仅供需要的朋友参考,请勿用做不道德转载及商业用途!
∙**************************************************************************/∙
∙#include
∙#include
∙#define uchar unsigned char
∙
∙void delay_ms(uchar ms); // 延时毫秒@12M,ms最大值255
∙void key_scan(); // 按键扫描
∙void key_to(); // 按键处理
∙
∙uchar code dis_code[11] = {0xc0,0xf9,0xa4,0xb0,0x99, //段码表
∙// 0 1 2 3 4 对应内容
∙ 0x92,0x82,0xf8,0x80,0x90,0xbf};
∙// 5 6 7 8 9 -
∙
∙uchar data dis[8]; // dis[0]为百分之一秒值,dis[1]为十分之一秒值
∙// dis[2],dis[5]为'-'段码的偏移量
∙// dis[3]为秒个位值,dis[4]为秒十位值
∙// dis[6]为分个位值,dis[7]为分十位值
∙
∙uchar data dot = 0; // 百分之一秒计数器(0.00s-0.99s)
∙uchar data sec = 0; // 秒计数器(00s-59s)
∙uchar data min = 0; // 分计数器(00m-99m)
∙
∙uchar data dis_b; // dis_b为位码选通数码管
∙uchar data dis_r; // dis_r为取段码时的偏移量
∙
∙uchar data key_t = 0; // 按键次数,初始为0
∙
∙sbit K = P1^4; // K键与P1.4相连
∙
∙void main()
∙ {
∙P2 = 0xff; // 关所有数码管
∙P1 = 0xff; // p1为准双向口,作输入时先写1
∙ dis[2] = 10; // '-'在段码表中偏移量为10
∙ dis[5] = 10; // '-'在段码表中偏移量为10
∙ dis_b = 0x7f; // 初始选通P2.7口数码管
∙ dis_r = 0; // 初始化偏移量为0
∙
∙TMOD = 0x11; // 定时/计数器0,1工作于方式1
∙TH0 = 0xd8; // 预置定时常数55536(d8f0),产生10ms时基信号
∙TL0 = 0xf0;
∙TH1 = 0xfc; // 预置定时常数64536(fc18),产生1ms间隔用于动态显示∙TH1 = 0x18;
∙EA = 1; // 开总中断
∙ET0 = 1; // 定时/计数器0允许中断
∙ET1 = 1; // 定时/计数器1允许中断
∙TR0 = 0; // 关闭定时/计数器0
∙TR1 = 1; // 启动定时/计数器1
∙while(1)
∙ {
∙if(K != 1) // 有键按下
∙ {
∙ delay_ms(10); // 延时10ms去抖
∙if(K != 1) // 确定是有键按下
∙ {
∙while(K != 1); // 等待键松开
∙ key_to(); // 按键处理
∙ }
∙ }
∙ }
∙ }
∙void key_to() // 按键处理子程序
∙ {
∙ key_t++; // 按键次数加1
∙if(key_t == 1) // 第一次按下
∙TR0 = 1; // 启动定时器0
∙else
∙ {
∙if(key_t == 2) // 第二次按下
∙TR0 = 0; // 关闭定时器0
∙else
∙ {
∙if(key_t == 3) // 第三次按下
∙ {
∙ dot = 0; // 三个计数器清零
∙ sec = 0;
∙ min = 0;
∙ key_t = 0; // 按键次数清零
∙ }
∙ }
∙ }
∙
∙ }
∙void tiem0(void) interrupt 1 // T/C0中断服务程序(产生10ms时基信号)
∙ {
∙ dot++; // 百分之一秒计数器加1
∙if(dot == 100) // 计数值到100
∙ {
∙ dot = 0; // 清零
∙ sec++; // 秒计数器加1(进位10ms*100=1s)
∙if(sec == 60) // 秒计数值到60
∙ {
∙ sec = 0; // 秒计数器清零
∙ min++; // 分计数器加1(进位60s=1m)
∙if(min == 100) // 分计数到100
∙ min = 0; // 分计数器清零
∙ }
∙ }
∙TH0 = 0xd8; // 重置定时常数
∙TL0 = 0xf0;
∙ }
∙void time1(void) interrupt 3 // T/C1中断服务程序(延时1ms数码管动态显示) ∙ {
∙ dis[0] = dot % 10; // 百分之一秒计数器个位分离出来赋绐dis[0]
∙ dis[1] = dot / 10; // 百分之一秒计数器十位分离出来赋绐dis[1]
∙ dis[3] = sec % 10; // 秒计数器个位赋绐dis[3]
∙ dis[4] = sec / 10; // 秒计数器十位赋绐dis[4]
∙ dis[6] = min % 10; // 分计数器个位赋绐dis[6]
∙ dis[7] = min / 10; // 分计数器十位赋绐dis[7]
∙
∙P0 = dis_code[dis[dis_r]]; // 段码送P0口(dis[0]...dis[7])
∙P2 = dis_b; // 位码送P2口
∙
∙ dis_r++; // 偏移量加1,下次中断时显示下个数
∙ dis_r &= 0x07; // dis_r增到8时自动清0(使之在0到7间循环) ∙
∙ dis_b = _cror_(dis_b,1); // 位码循环右移,下次中断时选通下个数码管
∙
∙TH1 = 0xfc; // 重置定时常数
∙TL1 = 0x18;
∙