51 单片机定时器电子时钟 + 闹钟

📅 2026/7/14 18:15:24
51 单片机定时器电子时钟 + 闹钟
一、项目基础信息1. 项目名称定时器中断电子时钟带自定义初始时间 定时闹钟2. 硬件平台主控STC89C52/AT89C52 晶振11.0592MHz 开发环境Keil C513. 实现功能24 小时制电子时钟上电可自定义初始时分秒定时器 0 中断精准计时自动完成秒→分→时进位24 小时归零8 位共阴极数码管动态扫描显示格式HH MM SS --自定义闹钟时分到达设定时间蜂鸣器间歇滴滴响铃包含多套标准延时函数兼容普中 51 开发板硬件引脚引入intrins.h库预留循环移位流水灯接口本项目未使用。4. 硬件引脚分配表表格外设模块引脚功能说明数码管段选P0输出数字段码数码管位选 AP2^2(LSA)3-8 译码器控制位数码管位选 BP2^3(LSB)3-8 译码器控制位数码管位选 CP2^4(LSC)3-8 译码器控制位无源蜂鸣器P2^5(BEEP)低电平发声高电平静音二、宏定义与数据类型说明1. 通用类型重定义c运行typedef unsigned int u16; // 16位无符号整型用于延时、计时计数 typedef unsigned char u8; // 8位无符号字符用于时分秒、段码、IO控制统一数据类型简化代码书写提升可读性。2. 硬件宏c运行#define SMG_SEG_PORT P0 // 数码管段选端口3. 常量数组smg_code[10]共阴极数码管 0~9 标准段码表存储在 ROM (code) 区节省 RAMdisp_buf[8]8 位数码管显示缓存存放每一位置对应的段码。三、全局变量说明1. 时钟计时变量c运行u16 timer_cnt 0; // 定时器中断计数累计1000次1秒 u8 hour 12; // 上电初始小时0~23可自行修改 u8 min 30; // 上电初始分钟0~59可自行修改 u8 sec 00; // 上电初始秒钟0~59可自行修改2. 闹钟变量c运行u8 alarm_h 12; // 闹钟触发小时 u8 alarm_m 30; // 闹钟触发分钟四、全部函数接口文档1. 延时函数组1void delay_10us(u16 ten_us)功能10 微秒级软件延时参数ten_us延时单位110us用途数码管动态扫描消隐延时2void delay_ms(u16 ms)功能毫秒级长延时参数ms延时毫秒数3void DelayUs2x(unsigned char t)功能微秒级短延时适配 12M 晶振参数t循环次数4void DelayMs(unsigned char t)功能12M 晶振专用毫秒延时基于DelayUs2x封装参数t延时毫秒数备注闹钟响铃间歇使用2. 数码管驱动函数void smg_display(u8 dat[], u8 start_pos)功能8 位数码管动态扫描显示参数dat[]显示段码缓存数组start_pos起始显示位1~8原理3-8 译码器分时点亮每一位数码管输出段码后清 0 消隐消除拖影。void refresh_display(void)功能拆分时分秒十位、个位填充显示缓存disp_buf显示布局disp_buf [0]时十位 disp_buf [1]时个位disp_buf [2]分十位 disp_buf [3]分个位disp_buf [4]秒十位 disp_buf [5]秒个位disp_buf [6]/disp_buf [7]熄灭0x003. 定时器配置与中断void timer0_init(void)功能定时器 0 初始化16 位模式 11ms 定时中断11.0592MHz配置参数TMOD0x01T0 工作模式 116 位定时器TH00xFCTL00x18定时 1ms 初值 65536-1000645360xFC18ET01、TR01、EA1开启定时器 0 中断、启动定时器、开总中断void timer0_isr() interrupt 1中断号1定时器 0 中断服务函数执行逻辑重装定时初值timer_cnt自增计数满 1000 代表 1 秒秒自增秒满 60 进位分分满 60 进位时时满 24 归零实现 24 小时制时钟。4. 闹钟检测函数void alarm_check(void)功能实时判断当前时间是否等于闹钟时间控制蜂鸣器间歇响铃逻辑匹配闹钟时分不断翻转 BEEP 电平实现滴滴间歇声不匹配BEEP 置 1蜂鸣器关闭静音。5. 主函数void main(void)上电执行流程初始化蜂鸣器高电平关闭调用timer0_init()开启定时器计时无限循环刷新时分秒显示缓存数码管动态扫描实时检测闹钟是否到达。五、工作运行流程单片机上电加载自定义初始时间12:30:00定时器 0 开始 1ms 中断计时中断内部自动累计秒、分、时完成进位逻辑主循环持续刷新数码管稳定显示当前HH MM SS实时对比当前时分与闹钟时分到达闹钟时间蜂鸣器间歇鸣叫时间超过闹钟时分后蜂鸣器自动关闭。六、修改使用说明1. 修改上电初始时间找到全局变量直接赋值c运行u8 hour 8; // 0~23 u8 min 5; // 0~59 u8 sec 20; // 0~592. 修改闹钟触发时间c运行u8 alarm_h 18; u8 alarm_m 0;3. 数码管显示起始位主函数中smg_display(disp_buf, 5)改为smg_display(disp_buf, 1)从第一位完整显示时分秒。#include reg52.h #include intrins.h typedef unsigned int u16; typedef unsigned char u8; // 硬件定义 #define SMG_SEG_PORT P0 sbit LSA P2^2; sbit LSB P2^3; sbit LSC P2^4; sbit BEEP P2^5; // 无源蜂鸣器低电平发声 // 共阴极数码管0~9段码 u8 code smg_code[10] {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; u8 disp_buf[8] {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // 时钟全局变量 u16 timer_cnt 0; u8 hour 12; // 自定义初始小时 u8 min 30; // 自定义初始分钟 u8 sec 00; // 自定义初始秒 // 闹钟全局变量 u8 alarm_h 12; // 闹钟小时 u8 alarm_m 30; // 闹钟分钟 /************************* 基础延时 *************************/ void delay_10us(u16 ten_us) { while(ten_us--); } void delay_ms(u16 ms) { u16 i,j; for(ims;i0;i--) for(j110;j0;j--); } void DelayUs2x(unsigned char t) { while(--t); } /*------------------------------------------------ mS延时函数含有输入参数 unsigned char t无返回值 unsigned char 是定义无符号字符变量其值的范围是 0~255 这里使用晶振12M精确延时请使用汇编 ------------------------------------------------*/ void DelayMs(unsigned char t) { while(t--) { //大致延时1mS DelayUs2x(245); DelayUs2x(245); } } // 【修复补上缺失的闭合大括号】 /************************* 8位数码管动态扫描 *************************/ void smg_display(u8 dat[], u8 start_pos) { u8 i; u8 idx start_pos - 1; for(i idx; i 8; i) { switch(i) { case 0: LSC1;LSB1;LSA1; break; case 1: LSC1;LSB1;LSA0; break; case 2: LSC1;LSB0;LSA1; break; case 3: LSC1;LSB0;LSA0; break; case 4: LSC0;LSB1;LSA1; break; case 5: LSC0;LSB1;LSA0; break; case 6: LSC0;LSB0;LSA1; break; case 7: LSC0;LSB0;LSA0; break; } SMG_SEG_PORT dat[i - idx]; delay_10us(100); SMG_SEG_PORT 0x00; // 消隐 } } /************************* 更新显示缓存 HH MM SS *************************/ void refresh_display(void) { // 时 disp_buf[0] smg_code[hour / 10]; disp_buf[1] smg_code[hour % 10]; // 分 disp_buf[2] smg_code[min / 10]; disp_buf[3] smg_code[min % 10]; // 秒 disp_buf[4] smg_code[sec / 10]; disp_buf[5] smg_code[sec % 10]; // 后两位熄灭 disp_buf[6] 0x00; disp_buf[7] 0x00; } /************************* 定时器0初始化 1ms中断 11.0592MHz *************************/ void timer0_init(void) { TMOD | 0x01; // T0 模式1 16位定时器 TH0 0xFC; TL0 0x18; // 65536-10000xFC18 定时1ms ET0 1; TR0 1; EA 1; } /************************* T0中断服务函数 1ms进一次 *************************/ void timer0_isr() interrupt 1 { TH0 0xFC; TL0 0x18; timer_cnt; if(timer_cnt 1000) // 1000ms 1秒 { timer_cnt 0; sec; // 秒进位 if(sec 60) { sec 0; min; // 分进位 if(min 60) { min 0; hour; // 小时24小时制循环 if(hour 24) hour 0; } } } } /************************* 闹钟检测函数 *************************/ void alarm_check(void) { // 当前时分等于闹钟时分蜂鸣器间歇鸣叫 if(hour alarm_h min alarm_m) { DelayUs2x(200); BEEP !BEEP ; } else { BEEP 1; // 非闹钟时间关闭蜂鸣 } } /************************* 主函数 *************************/ void main(void) { BEEP 1; // 上电蜂鸣器关闭 timer0_init(); // 启动定时器计时 while(1) { refresh_display(); // 刷新时分秒段码缓存 smg_display(disp_buf, 5); // 从第一位开始显示时分秒 alarm_check(); // 实时判断是否到闹钟时间 } }