- 打卡等级:初来乍到
- 打卡总天数:7
- 最近打卡:2026-01-14 15:10:29
已绑定手机
注册会员
- 积分
- 59
|
今天学习了时钟和按键的结合,利用按键可以调整时钟的时、分、秒,结果太棒了!
#include <AI8051U.H>
#include "ai_usb.h"
#include "seg.h"
#include "timer.h"
#include "key.h"
unsigned int xms = 0; // 毫秒计时变量
unsigned char Seg_String[10]; // 显示字符串缓存(预留小数点/结束符)
unsigned char Seg_Code[8] = {0,0,0,0,0,0,0,0}; // 数码管段码数组
unsigned char pos = 0; // 数码管扫描位置
unsigned int Seg_Dly = 0; // 显示刷新延时
unsigned char Key_Value; // 按键扫描值
unsigned char Key_Old,Key_Down; // 按键状态(旧值/下降沿)
unsigned char Key_Dly = 0; // 按键消抖延时
unsigned char Seg_Mode = 0; // 显示模式:0-正常时钟 1-调时 2-调分 3-调秒
// RTC时间变量
unsigned char hour = 22;
unsigned char min = 42;
unsigned char sec = 00;
void Seg_Proc(void);
void Key_Proc(void);
void RTC_Proc(void);
void main(void)
{
EAXFR = 1;
WTST = 0;
CKCON = 0;
// 所有端口设为推挽输出(根据硬件调整)
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
Timer0_Init();
usb_init();
EA = 1;
while(1)
{
RTC_Proc();
Seg_Proc();
Key_Proc();
}
}
void Seg_Proc(void)
{
if(Seg_Dly < 500) return;
Seg_Dly = 0;
// 根据显示模式切换显示内容
switch(Seg_Mode)
{
case 0: // 正常运行:显示时分秒(格式:HH:MM:SS)
sprintf(Seg_String,"%02d-%02d-%02d", (int)hour, (int)min, (int)sec);
break;
case 1: // 调时模式:仅显示小时(闪烁/高亮,此处简化)
sprintf(Seg_String," %02d ", (int)hour);
break;
case 2: // 调分模式:仅显示分钟
sprintf(Seg_String," %02d ", (int)min);
break;
case 3: // 调秒模式:仅显示秒
sprintf(Seg_String," %02d", (int)sec);
break;
}
Seg_Trans(Seg_String, Seg_Code);
}
void Key_Proc(void)
{
if(Key_Dly < 20) return; // 按键消抖(20ms)
Key_Dly = 0;
// 按键扫描:下降沿检测
Key_Value = Key_Du_Read();
Key_Down = Key_Value & (Key_Old ^ Key_Value); // 仅捕获按键按下的下降沿
Key_Old = Key_Value;
switch(Key_Down)
{
case 2: // 模式切换键:0→1→2→3→0
Seg_Mode++;
if(Seg_Mode == 4) Seg_Mode = 0;
break;
case 3: // P33按键:调小时(仅在调时模式/正常模式下生效)
if(Seg_Mode == 0 || Seg_Mode == 1)
{
hour++;
if(hour >= 24) hour = 0; // 24小时制循环
}
break;
case 4: // P34按键:调分钟(仅在调分模式/正常模式下生效)
if(Seg_Mode == 0 || Seg_Mode == 2)
{
min++;
if(min >= 60) min = 0; // 分钟0-59循环
}
break;
case 5: // P35按键:调秒(仅在调秒模式/正常模式下生效)
if(Seg_Mode == 0 || Seg_Mode == 3)
{
sec++;
if(sec >= 60) sec = 0; // 秒0-59循环
}
break;
default:
break;
}
}
void Timer0_Isr(void) interrupt 1
{
xms++;
Seg_Dly++;
Key_Dly++;
// 数码管动态扫描
Seg_Disp(Seg_Code, pos);
if(++pos == 8) pos = 0;
}
void RTC_Proc(void)
{
if(xms == 1000) // 1秒计时
{
xms = 0;
if(++sec == 60) // 秒满60进1分
{
sec = 0;
if(++min == 60) // 分满60进1小时
{
min = 0;
if(++hour == 24) // 小时满24重置
{
hour = 0; // 修复原代码未重置hour的BUG
}
}
}
}
}
|
-
|