使用定时器按键扫描数码管制作一个可存储数据的秒表

news/2024/11/7 14:33:12/

目录

1.前言

1.1实验现象

1.2 项目资源

2.主要程序及解释

2.1中断中进行按键扫描

2.2 中断中进行数码管扫描

2.3中断中进行秒表的驱动

2.4主函数


1.前言

1.1实验现象

实验现象:按下K1并松开按键秒表开始计时,按下K2并松开按键秒表停止计时,按下K3并松开数据存储到AT24C02中,按下K4并松开读取AT24C02中存储的数据显示在数码管上;

1.2 项目资源

https://download.csdn.net/download/YLG_lin/86544425

2.主要程序及解释

本次实验用到数码管扫描;按键扫描;AT24C02;还有就是定时器;秒表在运行中按键与数码管都要用到定时器进行不断的定时扫描,但1个定时器只能有1个中断;为了解决这个问题,我们只需要在中断里不断调用按键扫描与数码管扫描这两个模块就ok了;

2.1中断中进行按键扫描

void Timer0_Routine() interrupt 1
{static unsigned int T0Count1,T0Count2,T0Count3;TL0 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值(1ms)T0Count1++;if(T0Count1>=20){T0Count1=0;Key_Loop();	//20ms调用一次按键驱动函数}T0Count2++;if(T0Count2>=2){T0Count2=0;xianshi_Loop();//2ms调用一次数码管驱动函数}T0Count3++;if(T0Count3>=10){T0Count3=0;Sec_Loop();	//10ms调用一次数秒表驱动函数}
}
unsigned char Key_KeyNumber;/*** @brief  获取按键键码* @param  无* @retval 按下按键的键码,范围:0,1~4,0表示无按键按下*/
unsigned char Key(void)
{unsigned char Temp=0;Temp=Key_KeyNumber;Key_KeyNumber=0;return Temp;
}/*** @brief  获取当前按键的状态,无消抖及松手检测* @param  无* @retval 按下按键的键码,范围:0,1~4,0表示无按键按下*/
unsigned char Key_GetState()
{unsigned char KeyNumber=0;if(P3_1==0){KeyNumber=1;}if(P3_0==0){KeyNumber=2;}if(P3_2==0){KeyNumber=3;}if(P3_3==0){KeyNumber=4;}return KeyNumber;
}/*** @brief  按键驱动函数,在中断中调用* @param  无* @retval 无*/
void Key_Loop(void)
{static unsigned char NowState,LastState;LastState=NowState;				//按键状态更新NowState=Key_GetState();		//获取当前按键状态//如果上个时间点按键按下,这个时间点未按下,则是松手瞬间,以此避免消抖和松手检测if(LastState==1 && NowState==0){Key_KeyNumber=1;}if(LastState==2 && NowState==0){Key_KeyNumber=2;}if(LastState==3 && NowState==0){Key_KeyNumber=3;}if(LastState==4 && NowState==0){Key_KeyNumber=4;}
}

2.2 中断中进行数码管扫描

void Timer0_Routine() interrupt 1
{static unsigned int T0Count1,T0Count2,T0Count3;TL0 = 0x18;		//设置定时初值(1ms)TH0 = 0xFC;		//设置定时初值T0Count1++;if(T0Count1>=20){T0Count1=0;Key_Loop();	//20ms调用一次按键驱动函数}T0Count2++;if(T0Count2>=2){T0Count2=0;xianshi_Loop();//2ms调用一次数码管驱动函数}T0Count3++;if(T0Count3>=10){T0Count3=0;Sec_Loop();	//10ms调用一次数秒表驱动函数}
}
//数码管显示缓存区
unsigned char xianshi_Buf[9]={0,10,10,10,10,10,10,10,10};//数码管段码表
unsigned char xianshi_Table[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40};/*** @brief  设置显示缓存区* @param  Location 要设置的位置,范围:1~8* @param  Number 要设置的数字,范围:段码表索引范围* @retval 无*/
void xianshi_SetBuf(unsigned char Location,Number)
{xianshi_Buf[Location]=Number;
}/*** @brief  数码管扫描显示* @param  Location 要显示的位置,范围:1~8* @param  Number 要显示的数字,范围:段码表索引范围* @retval 无*/
void xianshi_Scan(unsigned char Location,Number)
{P0=0x00;				//段码清0,消影switch(Location)		//位码输出{case 1:P2_4=1;P2_3=1;P2_2=1;break;case 2:P2_4=1;P2_3=1;P2_2=0;break;case 3:P2_4=1;P2_3=0;P2_2=1;break;case 4:P2_4=1;P2_3=0;P2_2=0;break;case 5:P2_4=0;P2_3=1;P2_2=1;break;case 6:P2_4=0;P2_3=1;P2_2=0;break;case 7:P2_4=0;P2_3=0;P2_2=1;break;case 8:P2_4=0;P2_3=0;P2_2=0;break;}P0=xianshi_Table[Number];	//段码输出
}/*** @brief  数码管驱动函数,在中断中调用* @param  无* @retval 无*/
void xianshi_Loop(void)
{static unsigned char i=1;xianshi_Scan(i,xianshi_Buf[i]);i++;if(i>=9){i=1;}
}

2.3中断中进行秒表的驱动

static 修饰的是静态变量;把值放到静态区,直到程序全部运行完毕才会销毁;

void Timer0_Routine() interrupt 1
{static unsigned int T0Count1,T0Count2,T0Count3;TL0 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值(1ms)T0Count1++;if(T0Count1>=20){T0Count1=0;Key_Loop();	//20ms调用一次按键驱动函数}T0Count2++;if(T0Count2>=2){T0Count2=0;xianshi_Loop();//2ms调用一次数码管驱动函数}T0Count3++;if(T0Count3>=10){T0Count3=0;Sec_Loop();	//10ms调用一次数秒表驱动函数}
}
/*** @brief  秒表驱动函数,在中断中调用* @param  无* @retval 无*/
void Sec_Loop(void)
{if(RunFlag){MiniSec++;if(MiniSec>=100){MiniSec=0;Sec++;if(Sec>=60){Sec=0;Min++;if(Min>=60){Min=0;}}}}
}

2.4主函数

首先定时器进行初始化(设置初值,定时器工作模式等),在while循环中不断进行着按键扫描与数码管扫描;其中RunFlag 为启动标志位;AT24C02写周期需要延迟5ms,具体可以查看芯片手册;把分写进0地址,把秒写进1地址;Min/10取十位,Min%10取个位. . .

unsigned char KeyNum;
unsigned char Min,Sec,MiniSec;
unsigned char RunFlag;void main()
{Timer0_Init();while(1){KeyNum=Key();if(KeyNum==1)			//K1按键按下{RunFlag=!RunFlag;	}if(KeyNum==2)			//K2按键按下{Min=0;				//分秒清0Sec=0;MiniSec=0;}if(KeyNum==3)			//K3按键按下{AT24C02_WriteByte(0,Min);	//将分秒写入AT24C02Delay(5);AT24C02_WriteByte(1,Sec);Delay(5);AT24C02_WriteByte(2,MiniSec);Delay(5);}if(KeyNum==4)			//K4按键按下{Min=AT24C02_ReadByte(0);	//读出AT24C02数据Sec=AT24C02_ReadByte(1);MiniSec=AT24C02_ReadByte(2);}xianshi_SetBuf(1,Min/10);	//设置显示缓存,显示数据xianshi_SetBuf(2,Min%10);xianshi_SetBuf(3,11);      //显示——xianshi_SetBuf(4,Sec/10);xianshi_SetBuf(5,Sec%10);xianshi_SetBuf(6,11);      //显示——xianshi_SetBuf(7,MiniSec/10);xianshi_SetBuf(8,MiniSec%10);}
}


http://www.ppmy.cn/news/615619.html

相关文章

【51单片机】LCD1602显示字符串,时间、时间+按键校准、秒表计时的功能代码。

LCD1602显示字符和时间是最基本的实验,在综合前面所学知识并结合c语言程序设计,就可以通过独立按键,来对时间进行校准,计时等功能、或者通过矩阵键盘的按键进行输入,进而让LCD屏上显示的出我们想要的内容和效果。应实验…

KST-51单片机:c语言编程实现数码管动态显示秒表的倒计时

/*60S倒计时*/ /*个位每1S变一次&#xff0c;从0&#xff5e;9*/ /*十位,个位为0的下一秒十位发生变化*/#include<reg52.h>sbit ADDR0P1^0; sbit ADDR1P1^1; sbit ADDR2P1^2; sbit ADDR3P1^3; sbit ENLEDP1^4;unsigned char code LedChar[] { 0xC0,0xF9,0xA4,0xB0,0x99,0…

stm32倒计时秒表proteus_单片机课程设计倒计时秒表教程文件

精品文档 精品文档 一、设计目的 此次设计是我们更进一步了解基本电路的设计流程&#xff0c;提高自己的设计理念&#xff0c; 丰富自己的理论知识&#xff0c;巩固所学知识&#xff0c;使自己的动手动脑能力有更进一步提高&#xff0c; 为自己今后的学习和工作打好基础&#x…

android手机时钟、闹钟、计时器、秒表app源码

简 介 此多功能闹钟界面采用TabHost框架&#xff0c;头部包含分别用LinearLayout水平布局显示四个标签闹钟&#xff0c;时钟&#xff0c;计时器和秒表&#xff0c;FrameLayout框架内部采用LinearLayout垂直布局。功能事件的基本实现分别有AlarmView类&#xff0c;AlarmReceiver…

60秒倒计时器 秒表 c语言程序,用单片机设计一个两位LED显示的秒表,按下计时键时,进行60s倒计时显示...

满意答案 w86586tk3y 2017.09.25 采纳率&#xff1a;57% 等级&#xff1a;8 已帮助&#xff1a;214人 #include sbit P3_5 P3^5; unsigned char code dispcode[]{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x00}; unsigned char …

verilog秒表计时器

本设计是使用verilog实现秒表计时器。 秒表指示的时间由nexys4 DDR开发板的8个数码管显示,从左到右数码管的前两个显示小时(范围0-24),第3-4个数码管显示分(范围0-59,计数到60,向小时位进1),第5-6个数码管显示秒(范围0-59,计数到60向分位进1),第7-8个数码管显示毫…

前端文件上传的几种交互造轮子

背景 前端文件上传本来是一个常规交互操作&#xff0c;没什么特殊性可言&#xff0c;但是最近在做文件上传&#xff0c;需要实现截图粘贴上传&#xff0c;去找了下有没有什么好用的组件&#xff0c;网上提供的方法有&#xff0c;但是没找完整的组件来支持 cv 上传&#xff0c;…

基于STM32的多功能秒表

基于STM32的多功能秒表 当上电运行后&#xff0c;按下KEY1,秒表开始正计时&#xff0c;再次按下KEY1秒表停止计时&#xff0c;按下KEY2秒表清零&#xff0c;按下KEY3&#xff0c;手动调节秒表时间递增&#xff0c;按下KEY4手动调节秒表时间递减&#xff0c;按下KEY5秒表倒计时…