根据单片机定时器和按键原理,用八位共阳极数码管显示时间,格式为“16-59-54”(时-分-秒),中间用短横线隔开,按键S7用于切换正常计时模式和设置时间模式;S6用于在设置时间模式下切换时分秒的修改;S5用于数值加1;S4用于确认调节时间。,给出keil4C语言源程序
时间: 2024-05-15 18:19:36 浏览: 113
```c
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit S5 = P3^0;
sbit S6 = P3^1;
sbit S7 = P3^2;
uchar code seg_tab[] = { // 八位共阳数码管段码表
0xc0, // 0
0xf9, // 1
0xa4, // 2
0xb0, // 3
0x99, // 4
0x92, // 5
0x82, // 6
0xf8, // 7
0x80, // 8
0x90, // 9
};
uchar code time_init[] = { // 初始时间
0x16, // 时
0x59, // 分
0x54 // 秒
};
uchar code time_limit[] = { // 时间上限
0x23, // 时
0x59, // 分
0x59 // 秒
};
uchar time_disp[3]; // 当前时间,用于显示
uchar time_set[3]; // 设置时间
bit time_mode = 1; // 时间模式,1为正常计时模式,0为设置时间模式
uchar time_pos = 0; // 设置时间位置,0为小时,1为分钟,2为秒钟
// 延时函数
void delay(uint t)
{
uint i, j;
for (i = 0; i < t; i++)
for (j = 0; j < 125; j++);
}
// 数码管显示函数
void display()
{
uchar i;
for (i = 0; i < 3; i++) {
P2 = 1 << i; // 选择位
P0 = seg_tab[time_disp[i] / 10]; // 显示十位
delay(1);
P0 = 0x00; // 熄灭
delay(1);
P2 = 1 << (i + 4); // 选择位
P0 = seg_tab[time_disp[i] % 10]; // 显示个位
delay(1);
P0 = 0x00; // 熄灭
delay(1);
}
}
// 数值加1
void inc_value(uchar* value, uchar limit)
{
if (*value < limit)
(*value)++;
else
*value = 0;
}
// 数值减1
void dec_value(uchar* value, uchar limit)
{
if (*value > 0)
(*value)--;
else
*value = limit;
}
// 更新当前时间
void update_time()
{
uchar i;
for (i = 0; i < 3; i++)
time_disp[i] = time_init[i];
}
// 更新设置时间
void update_set_time()
{
uchar i;
for (i = 0; i < 3; i++)
time_set[i] = time_init[i];
}
// 定时器0中断服务函数
void timer0_isr() interrupt 1
{
static uchar cnt = 0;
TH0 = (65536 - 1000) / 256; // 定时1ms
TL0 = (65536 - 1000) % 256;
cnt++;
if (cnt == 100) { // 计时1s
cnt = 0;
if (time_mode) { // 正常计时模式
inc_value(&time_init[2], 60); // 秒加1
if (time_init[2] == 0) { // 分钟加1
inc_value(&time_init[1], 60);
if (time_init[1] == 0) // 小时加1
inc_value(&time_init[0], 24);
}
}
}
}
// 外部中断0服务函数
void ext0_isr() interrupt 0
{
if (!time_mode) { // 设置时间模式
time_pos = (time_pos + 1) % 3; // 切换时间位置
} else { // 正常计时模式
time_mode = 0; // 切换到设置时间模式
update_set_time(); // 更新设置时间
}
}
// 外部中断1服务函数
void ext1_isr() interrupt 2
{
if (!time_mode) { // 设置时间模式
switch (time_pos) {
case 0: // 修改小时
inc_value(&time_set[0], 24);
break;
case 1: // 修改分钟
inc_value(&time_set[1], 60);
break;
case 2: // 修改秒钟
inc_value(&time_set[2], 60);
break;
}
} else { // 正常计时模式
time_mode = 1; // 切换到正常计时模式
update_time(); // 更新当前时间
}
}
// 外部中断2服务函数
void ext2_isr() interrupt 3
{
if (!time_mode) { // 设置时间模式
switch (time_pos) {
case 0: // 修改小时
dec_value(&time_set[0], 24);
break;
case 1: // 修改分钟
dec_value(&time_set[1], 60);
break;
case 2: // 修改秒钟
dec_value(&time_set[2], 60);
break;
}
} else { // 正常计时模式
// do nothing
}
}
void main()
{
TMOD = 0x01; // 定时器0工作模式1,16位自动重载计数器模式
TH0 = (65536 - 1000) / 256; // 定时1ms
TL0 = (65536 - 1000) % 256;
ET0 = 1; // 允许定时器0中断
TR0 = 1; // 启动定时器0
EX0 = 1; // 允许外部中断0
IT0 = 1; // 下降沿触发外部中断0
EX1 = 1; // 允许外部中断1
IT1 = 1; // 下降沿触发外部中断1
EX2 = 1; // 允许外部中断2
IT2 = 1; // 下降沿触发外部中断2
EA = 1; // 全局中断使能
update_time(); // 初始化当前时间
while (1) {
if (!time_mode) { // 设置时间模式
time_disp[0] = time_set[0];
time_disp[1] = time_set[1];
time_disp[2] = time_set[2];
} else { // 正常计时模式
time_disp[0] = time_init[0];
time_disp[1] = time_init[1];
time_disp[2] = time_init[2];
}
display(); // 数码管显示
}
}
```
阅读全文