资讯详情

单片机开源项目之Stopwatch数码管显示-实用秒表

此程序是在51hei单片机上面做的,如需要移植到自己的电路上,修改相应的端口即可,开发板完整的电路图下载: 点这里 (注意:只需要看相关部分即可,其他部分可以忽略)

/** **************************************************************************************** *file : main.c *author : xr *date : 2014年4月15日10:08:26- 2014年4月15日12:40:51 *version: V1.2.3 *brief : Stopwatch数码管显示-实用秒表 单片机C89C52RC 晶振 11.0592MHZ **************************************************************************************** */ #include <reg52.h>

//74HC138 sbit A 0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4; //矩阵按键 sbit KEY_IN_1 = P2^4;//列 sbit KEY_IN_2 = P2^5; sbit KEY_IN_3 = P2^6; sbit KEY_IN_4 = P2^7; // 编码 unsigned char code LedTable[] = { 0xC0, //"0" 0xF9, //"1" 0xA4, //"2" 0xB0, //"3" 0x99, //"4" 0x92, //"5" 0x82, //"6" 0xF8, //"7" 0x80, //"8" 0x90, //"9" 0x88, //"A" 0x83, //"B" 0xC6, //"C" 0xA1, //"D" 0x86, //"E" 0x8E //"F" }; //数码管显示缓冲区 unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; bit flag10ms = 0;//10ms标志位 bit stopwatchRunning = 0;//秒表启动和停止标志 unsigned char thr0, tlr0;//T0重载值的高低字节 unsigned char decimal = 0;//小数位 unsigned int integer = 0;//整数位 static unsigned char volatile KeySta[4] = {1, 1, 1, 1}; //保存按键的当前值(static 保存在静态存储区,加上volatile关键字使KeySta[i]的值每次都从静态存储区读取,避免读取错误!) /****************function definition**********************/ void Initial(); void ConfigTimer0(unsigned long xms); void StopwatchDisplay(); void KeyAction(); /*主程序main()*/ void main(void) { Initial(); ConfigTimer0(1);//定时1ms while (1) { KeyAction(); //检测按键动作 if (flag10ms) //10ms检测秒表的运行状态,当stopwatchRunning标志=1时进行计时++,否则就停止计时 { flag10ms = 0; if (stopwatchRunning) //10ms刷新秒表计数 { decimal++; if (decimal >= 100) { decimal = 0; integer++; if (integer >= 10000) { integer = 0; } } StopwatchDisplay();//分解decimal和integer,存入LedBuff数码管缓冲区 } } } } /*程序初始化*/ void Initial() { ADDR3 = 1; ENLED = 0;//选择数码管 P2 = 0xFE;//选择第四行按键检测(原理图上是第四列) P0 = 0xFF;//默认关闭段选 LedBuff[0] = LedTable[decimal % 10]; //初始显示0.00 LedBuff[1] = LedTable[decimal / 10 % 10]; LedBuff[2] = LedTable[integer % 10]; LedBuff[2] &= 0x7F;//点亮小数点 } /*配置定时器T0*/ void ConfigTimer0(unsigned long xms) { unsigned long tmp;//32bit 注意:此处必须用unsigned long 数据,因为11059200已经超出了16位unsigned int tmp = 11059200/12;//单片机的机器周期频率 tmp = (tmp * xms) / 1000;//定时xms所需的频率 tmp = 65536-tmp;//定时xms的初始装载值 tmp += 18;//补偿值 thr0 = (unsigned char)(tmp >> 8); tlr0 = (unsigned char)tmp; TMOD &= 0xF0;//清零T0控制位 TMOD |= 0x01;//配置T0工作在方式1,16位可设定定时器 TH0 = thr0; TL0 = tlr0; TR0 = 1; ET0 = 1; EA = 1; } /*数码管刷新*/ void LedCharRefresh() { static unsigned char j = 0; P0 = 0xFF;//消隐 P1 = (P1 & 0xF8) | j;//先清零P1口低三位,再|j P0 = LedBuff[j++]; if (j > 5) j = 0; } /*分解decimal和integer,存入LedBuff数码管缓冲区*/ void StopwatchDisplay() { signed char i = 0; unsigned char buf[6]; buf[0] = decimal % 10; buf[1] = decimal / 10 % 10; buf[2] = integer % 10; buf[3] = integer / 10 % 10; buf[4] = integer / 100 % 10; buf[5] = integer / 1000 % 10; for (i = 5; i >= 3; i--) //去掉无效位 { if (buf[i] == 0) buf[i] = 0xFF; else break; } //处理有效位 for (; i >=0; i--) { buf[i] = LedTable[buf[i]]; //转为实际的数字 } //拷贝 for (i = 0; i <= 5; i++) { LedBuff[i] = buf[i];//拷贝到显示缓冲区 } LedBuff[2] &= 0x7F;//点亮小数点 } /*秒表启动和停止*/ void StopwatchAction() { if (stopwatchRunning) //当前状态为运行 { stopwatchRunning = 0; //停止运行 } else { stopwatchRunning = 1; //启动 } } /*秒表复位*/ void StopwatchReset() { stopwatchRunning = 0;//停止秒表计时 decimal = 0; integer = 0;//清零 StopwatchDisplay();//显示 } /*按键动作*/ void KeyAction() { static unsigned char keybackup[4] = {1, 1, 1, 1};//按键的备份值(前一次按键值) 必须是静态的 unsigned char i = 0; for (i = 0; i < 4; i++) { if (keybackup[i] != KeySta[i]) //按键的上一次的状态和当前状态不相同,即按键有动作 { if (keybackup[i] != 0) //如果上一次按键的值是1,则此时按键是按下动作 { switch (i) { case 1: StopwatchReset(); break; //ESC键秒表复位 case 2: StopwatchAction(); break;//Enter键控制秒表的启动和停止 default: break; } } keybackup[i] = KeySta[i];//备份当前按键值 } } } /*按键扫描函数*/ void KeyScan() { static unsigned char KeyBuf[4] = {0xFF, 0xFF, 0xFF, 0xFF}; //按键扫描缓冲区 unsigned char i = 0; //检测一行按键的状态并存入按键检测缓冲区中 KeyBuf[0] = (KeyBuf[0] << 1) | KEY_IN_1; KeyBuf[1] = (KeyBuf[1] << 1) | KEY_IN_2; KeyBuf[2] = (KeyBuf[2] << 1) | KEY_IN_3; KeyBuf[3] = (KeyBuf[3] << 1) | KEY_IN_4; //更新消抖后按键的值(1ms检测一次,8ms检测) for (i = 0; i < 4; i++) { if ((KeyBuf[i] & 0xFF) == 0x00) KeySta[i] = 0;//8次检测按键状态都是0,即按键稳定按下 else if ((KeyBuf[i] & 0xFF) == 0xFF) KeySta[i] = 1;//8次检测按键的状态都是1,即按键稳定弹起 } } /*定时器Timer0中断服务*/ void Timer0_I () interrupt 1 { static unsigned char counter = 0;// TH0 = thr0; TL0 = tlr0;//重新装载定时器初值 counter++; LedCharRefresh();//数码管刷新 KeyScan(); //按键扫描 if (counter >= 10) { counter = 0; flag10ms = 1; } } -电子元器件采购网(www.ruidan.com)是本土元器件目录分销商,采用“小批量、现货、样品”销售模式,致力于满足客户多型号、高质量、快速交付的采购需求。 自建高效智能仓储,拥有自营库存超过50,000种,提供一站式正品现货采购、个性化解决方案、选型替代等多元化服务。
锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台