下面是基于"KR-51开发板"(51单片机)的简化电子闹钟核心C代码框架,实现如下功能需求:
- 当前时间/闹钟时间设定
- 光敏控制数码管背光
- 按键切换/设置/加减
- 蜂鸣器闹铃&LED闪烁
- /*
- 51单片机电子闹钟 KR-51开发板
- 实现功能:
- 1.可自主设定当前时间与闹钟时间,4位共阳数码管
- 2.利用光敏传感器实现有光时数码管常亮,无光时,按下按键,数码管亮起,可切换,查看当前时间与闹钟时间
- 3.闹钟时间到了,蜂鸣器响起同时,Led灯按 200ms频率闪烁
- 1. 主要口线分配
- | 功能 | 单片机引脚 |
- |----------------|---------------|
- | 数码管段选 a-f | P0.0~P0.7 |
- | 数码管位选 | P2.0~P2.3 |
- | 蜂鸣器 | P2.5 |
- | LED | P1.0 |
- | 光敏传感器 | P1.7 |
- | 按键功能 | P3.2 |
- | 按键切换 | P3.3 |
- | 按键加 | P3.4 |
- | 按键减 | P3.5 |
- 使用说明
- - 按KEY_MODE切换显示当前和闹钟时间。
- - 三个按键:KEY_ADD/KEY_SUB调节小时,KEY_FUNC调节分钟。
- - 光敏自动调节背光,无光时按任一功能键亮屏。
- - 闹钟时间到,蜂鸣器响、LED闪;复位或重新设定可清除闹钟。
- 代码逻辑清晰,各功能子模块独立,易于修改和维护。
- */
- #include <reg51.h>
- #define uint unsigned int
- #define uchar unsigned char
- // 段码表
- uchar code seg_tab[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共阳数码管
- // 硬件口线映射
- sbit BUZZER = P2^5; //蜂鸣器
- sbit LED = P1^0;
- sbit LDR = P1^7; // 光敏
- sbit KEY_FUNC = P3^2;
- sbit KEY_MODE = P3^3;
- sbit KEY_ADD = P3^4;
- sbit KEY_SUB = P3^5;
- //主要数据结构
- // 任务标志
- bit alarm_flag = 0;
- bit display_flag = 1; // 数码管亮/灭
- bit key_enable_flag = 0; // 消抖允许
- uchar key_state = 0; // 按键当前状态
- // 时钟及闹钟变量
- uchar hour=12, minute=0;
- uchar alarm_hour=6, alarm_minute=30;
- uchar display_mode=0; // 0:当前时间 1:闹钟时间
- uint tcount=0; // 定时器计数
- //时间与闹钟管理模块
- void time_update(void) {
- tcount++;
- if(tcount >= 2400) { //假设定时25ms; 2400*25ms=60s
- tcount = 0;
- minute++;
- if(minute >= 60) {
- minute = 0;
- hour++;
- if(hour >= 24) hour=0;
- }
- if(hour == alarm_hour && minute == alarm_minute) {
- alarm_flag = 1; //闹钟触发
- }
- }
- }
- void alarm_clear(void) {
- alarm_flag = 0;
- BUZZER = 0;
- LED = 0;
- }
- //按键扫描与功能切换
- void key_scan(void) {
- if(KEY_MODE == 0) { // 切换显示模式
- while(KEY_MODE == 0); //松手消抖
- display_mode ^= 1;
- }
- if(display_mode == 0) { //当前时间
- if(KEY_ADD == 0) { //小时加
- while(KEY_ADD == 0);
- hour++; if(hour > 23) hour=0;
- }
- if(KEY_SUB == 0) { //小时减
- while(KEY_SUB == 0);
- if(hour == 0) hour=23; else hour--;
- }
- if(KEY_FUNC == 0) { //分钟加
- while(KEY_FUNC == 0);
- minute++; if(minute > 59) minute=0;
- }
- } else { //闹钟时间
- if(KEY_ADD == 0) {
- while(KEY_ADD == 0);
- alarm_hour++; if(alarm_hour > 23) alarm_hour=0;
- }
- if(KEY_SUB == 0) {
- while(KEY_SUB == 0);
- if(alarm_hour == 0) alarm_hour=23; else alarm_hour--;
- }
- if(KEY_FUNC == 0) {
- while(KEY_FUNC == 0);
- alarm_minute++; if(alarm_minute > 59) alarm_minute=0;
- }
- }
- }
- //光敏及显示管理子模块
- void ldr_check(void) {
- // 有光时一直亮,没光时只在按键显示
- if(LDR == 1)
- display_flag = 1;
- else {
- if(KEY_FUNC == 0) display_flag = 1;
- else display_flag = 0;
- }
- }
- //数码管动态显示模块
- void display_time(uchar h, uchar m) {
- uchar disp_buf[4],i;
- disp_buf[0] = h / 10;
- disp_buf[1] = h % 10;
- disp_buf[2] = m / 10;
- disp_buf[3] = m % 10;
- for(i=0; i<4; i++) {
- P2 = ~(1 << i); // 位选P2.0~P2.3共阳
- P0 = seg_tab[disp_buf[i]]; // 段选
- // 若想显示小数点或其它符号,可此处加处理
- // 延时,用于刷新和消影
- }
- }
- //闹钟蜂鸣/LED闪烁模块
- void alarm_task(void) {
- if(alarm_flag) {
- BUZZER = 1;
- // 200ms LED闪烁循环(简单用定时来实现)
- if(tcount % 8 < 4) LED = 1;
- else LED = 0;
- }
- }
- //定时器初始化与中断服务
- void Timer0_Init(void) {
- TMOD = 0x01; //方式1 16位
- TH0 = (65536-25000)/256; //25ms
- TL0 = (65536-25000)%256;
- ET0 = 1; TR0 = 1; EA = 1;
- }
- void Timer0_ISR(void) interrupt 1 {
- TH0 = (65536-25000)/256; TL0 = (65536-25000)%256;
- time_update(); //更新时间,每25ms进一次
- }
- //主循环
- void main(void) {
- Timer0_Init();
- alarm_clear();
- while(1) {
- key_scan();
- ldr_check();
- if(display_flag) {
- if(display_mode == 0) display_time(hour, minute);
- else display_time(alarm_hour, alarm_minute);
- } else {
- //可以关闭数码管
- P0 = 0x00; P2 = 0x00;
- }
- alarm_task();
- // 若需要按键消抖与显示稳定可增加适度延时
- }
- }
复制代码
|