目录
实验现象:按下K1并松开按键秒表开始计时,按下K2并松开按键秒表停止计时,按下K3并松开数据存储到AT24C02中,按下K4并松开读取AT24C02中存储的数据显示在数码管上;
https://download.csdn.net/download/YLG_lin/86544425
本次实验用到数码管扫描;按键扫描;AT24C02;还有就是定时器;秒表在运行中按键与数码管都要用到定时器进行不断的定时扫描,但1个定时器只能有1个中断;为了解决这个问题,我们只需要在中断里不断调用按键扫描与数码管扫描这两个模块就ok了;
- 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;
- }
- }
- 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;}
- }
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;
- }
- }
- }
- }
- }
首先定时器进行初始化(设置初值,定时器工作模式等),在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; //分秒清0
- Sec=0;
- MiniSec=0;
- }
- if(KeyNum==3) //K3按键按下
- {
- AT24C02_WriteByte(0,Min); //将分秒写入AT24C02
- Delay(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);
- }
- }