单片机万年历c语言程序设计,基于AT89C51单片机的多功能电子万年历的设计(附程序)...
时间: 2023-06-19 17:03:45 浏览: 139
基于AT89C51单片机的多功能电子万年历的设计
以下是一个基于AT89C51单片机的多功能电子万年历的C语言程序设计示例:
```c
#include <reg51.h>
#include <stdio.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
// 定义数码管显示的段码
uchar code led_seg[] = {
0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8,
0x80, 0x98, 0xff, 0x88, 0x83, 0xc6, 0xa1, 0x86
};
// 定义数码管显示的位码
uchar code led_bit[] = {
0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf
};
// 定义当前时间的全局变量
uchar g_year, g_month, g_day, g_week, g_hour, g_minute, g_second;
// 定义当前时间的字符串数组
uchar g_time_str[20];
// 定义当前闹钟的小时和分钟
uchar g_alarm_hour, g_alarm_minute;
// 定义当前闹钟是否已开启的标志
uchar g_alarm_enabled;
// 定义当前模式的枚举类型
enum ModeType {
MODE_TIME,
MODE_ALARM_HOUR,
MODE_ALARM_MINUTE,
MODE_ALARM_ENABLED
};
// 定义当前模式的全局变量
enum ModeType g_mode;
// 定义按键扫描函数
uchar key_scan() {
uchar key_value = 0xff;
uchar i;
// 扫描按键1~4,如果有按键按下,则返回对应的键值
for (i = 0; i < 4; i++) {
P1 = ~(1 << i);
if (P1 != 0xf0) {
key_value = P1;
while (P1 != 0xf0);
break;
}
}
// 扫描按键5,如果有按键按下,则返回对应的键值
P1 = 0x0f;
if (P1 != 0x0f) {
key_value = P1;
while (P1 != 0x0f);
}
return key_value;
}
// 定义数码管显示函数
void led_display(uchar bit_value, uchar seg_value) {
P2 = led_seg[seg_value];
P0 = led_bit[bit_value];
}
// 定义更新时间函数
void update_time() {
// 获取当前时间,并保存到全局变量中
// 这里需要根据实际硬件情况来实现
g_year = get_year();
g_month = get_month();
g_day = get_day();
g_week = get_week();
g_hour = get_hour();
g_minute = get_minute();
g_second = get_second();
// 根据当前模式更新数码管显示
switch (g_mode) {
case MODE_TIME:
sprintf(g_time_str, "%02d-%02d-%02d %02d:%02d:%02d",
g_year, g_month, g_day, g_hour, g_minute, g_second);
led_display(0, g_hour / 10);
led_display(1, g_hour % 10);
led_display(2, g_minute / 10);
led_display(3, g_minute % 10);
led_display(4, g_second / 10);
led_display(5, g_second % 10);
break;
case MODE_ALARM_HOUR:
led_display(0, g_alarm_hour / 10);
led_display(1, g_alarm_hour % 10);
led_display(2, 10);
led_display(3, 10);
led_display(4, 10);
led_display(5, 10);
break;
case MODE_ALARM_MINUTE:
led_display(0, g_alarm_minute / 10);
led_display(1, g_alarm_minute % 10);
led_display(2, 10);
led_display(3, 10);
led_display(4, 10);
led_display(5, 10);
break;
case MODE_ALARM_ENABLED:
led_display(0, g_alarm_enabled ? 11 : 12);
led_display(1, 10);
led_display(2, 10);
led_display(3, 10);
led_display(4, 10);
led_display(5, 10);
break;
}
}
// 定义主函数
void main() {
// 初始化全局变量
g_year = 0;
g_month = 0;
g_day = 0;
g_week = 0;
g_hour = 0;
g_minute = 0;
g_second = 0;
g_alarm_hour = 0;
g_alarm_minute = 0;
g_alarm_enabled = 0;
g_mode = MODE_TIME;
// 初始化按键扫描需要的IO口
P1 = 0xf0;
// 循环处理
while (1) {
uchar key_value = key_scan();
// 根据当前模式处理按键事件
switch (g_mode) {
case MODE_TIME:
if (key_value == 0x7e) { // 按键1
g_mode = MODE_ALARM_HOUR;
} else if (key_value == 0xbe) { // 按键2
g_mode = MODE_ALARM_MINUTE;
} else if (key_value == 0xde) { // 按键3
g_mode = MODE_ALARM_ENABLED;
}
break;
case MODE_ALARM_HOUR:
if (key_value == 0x7e) { // 按键1
g_alarm_hour++;
if (g_alarm_hour >= 24) {
g_alarm_hour = 0;
}
} else if (key_value == 0xbe) { // 按键2
g_mode = MODE_ALARM_MINUTE;
} else if (key_value == 0xde) { // 按键3
g_mode = MODE_TIME;
}
break;
case MODE_ALARM_MINUTE:
if (key_value == 0x7e) { // 按键1
g_alarm_minute++;
if (g_alarm_minute >= 60) {
g_alarm_minute = 0;
}
} else if (key_value == 0xbe) { // 按键2
g_mode = MODE_ALARM_ENABLED;
} else if (key_value == 0xde) { // 按键3
g_mode = MODE_ALARM_HOUR;
}
break;
case MODE_ALARM_ENABLED:
if (key_value == 0x7e || key_value == 0xbe) { // 按键1或按键2
g_alarm_enabled = !g_alarm_enabled;
} else if (key_value == 0xde) { // 按键3
g_mode = MODE_TIME;
}
break;
}
// 更新时间,并根据当前模式显示数码管
update_time();
// 检查闹钟是否已经响了
if (g_alarm_enabled && g_hour == g_alarm_hour && g_minute == g_alarm_minute) {
// 这里需要根据实际硬件情况来实现
ring_alarm();
}
}
}
```
注意,这只是一个示例程序,实际实现中需要根据实际硬件情况进行相应的修改。
阅读全文