设计一个定时倒计时器。要求:能够输入定时时长,定时最长时间为59分59秒;按启动键后开始计时,数码管显示当前计时时长,显示格式为:XX.XX.X;每100 ms刷新一次数码管显示的数值;定时时间到达后,用数码管闪烁指示。 定时器的工作状态用功能按键控制,设功能按键为:启动键、暂停键、清零键。 当单片机复位后进入等待输入定时时间状态,用户可以输入定时时间,输入的时间同时在数码管上显示;当输入定时时间后,按启动键,定时器开始计时,数码管显示当前计时时间。再次按暂停键,定时器暂停计时,数码管显示当前计时时间;再次按暂停键,定时器继续计时。按清零键,定时器停止计时,并清零计时值,数码管显示为零,定时器进入等待输入状态。用C语言编写,单片机为c8051f020
时间: 2024-03-02 10:49:12 浏览: 44
以下是一个使用C语言编写的基本代码,实现了输入定时时长、按启动键后开始计时、数码管显示当前计时时长、每100ms刷新一次数码管显示的数值、定时时间到达后,用数码管闪烁指示的功能。同时,程序还添加了暂停键、清零键的控制。
```c
#include <C8051F020.h> // 单片机头文件
#define SYSCLK 22118400L // 系统时钟频率
#define BAUDRATE 9600L // 串口波特率
// 定义按键端口和引脚
#define KEY_START P1_0
#define KEY_PAUSE P1_1
#define KEY_CLEAR P1_2
// 定义数码管端口和引脚
#define DISP_SEG P2
#define DISP_COM P3
// 定义定时器计数值和中断服务函数
#define TIMER0_VAL 65536 - SYSCLK / 12 / 10000 // 定时器0计数值,使定时器每10ms中断一次
unsigned char timer_count; // 定时器计数器
unsigned char timer_sec; // 定时器秒数
unsigned char timer_min; // 定时器分钟数
unsigned char timer_running; // 定时器运行状态标志
unsigned char timer_paused; // 定时器暂停状态标志
unsigned char timer_blink; // 定时器闪烁标志
void timer0_isr() interrupt 1 { // 定时器0中断服务函数
TH0 = TIMER0_VAL / 256; // 重新设置定时器计数值
TL0 = TIMER0_VAL % 256;
if (!timer_paused && timer_running) { // 如果定时器没有暂停且正在运行
if (timer_sec == 0 && timer_min == 0) { // 定时时间到达
timer_running = 0; // 停止计时
timer_blink = 1; // 开始闪烁
} else { // 定时时间未到
timer_count++; // 计数器加1
if (timer_count == 10) { // 100ms到达
timer_count = 0; // 计数器清零
timer_sec--; // 秒数减1
if (timer_sec > 59) { // 秒数不能大于59
timer_sec = 59;
}
if (timer_sec == 255 && timer_min > 0) { // 秒数归零,分钟减1
timer_sec = 59;
timer_min--;
if (timer_min > 59) { // 分钟不能大于59
timer_min = 59;
}
}
}
}
}
}
// 定义数码管显示函数
void display() {
unsigned char digit[3];
if (timer_paused) { // 定时器暂停状态下,闪烁显示当前计时时长
digit[0] = timer_min / 10;
digit[1] = timer_min % 10;
digit[2] = timer_sec / 10;
if ((timer_blink && timer_count < 5) || (!timer_blink && timer_count >= 5)) {
DISP_SEG = ~(1 << 7); // 数码管小数点
} else {
DISP_SEG = 0xFF;
}
} else { // 定时器正常工作状态下,显示当前计时时长
digit[0] = timer_min % 10;
digit[1] = timer_sec / 10;
digit[2] = timer_sec % 10;
DISP_SEG = 0xFF; // 关闭数码管小数点
}
DISP_COM = ~(1 << 2); DISP_SEG = ~(1 << digit[0]); // 显示分钟的十位
DISP_COM = ~(1 << 1); DISP_SEG = ~(1 << digit[1]); // 显示秒钟的十位
DISP_COM = ~(1 << 0); DISP_SEG = ~(1 << digit[2]); // 显示秒钟的个位
}
void main() {
// 初始化定时器、中断、按键、数码管
TMOD |= 0x01; // 定时器0工作在模式1
TH0 = TIMER0_VAL / 256; // 初始化定时器计数值
TL0 = TIMER0_VAL % 256;
TR0 = 1; // 启动定时器0
ET0 = 1; // 允许定时器0中断
EA = 1; // 允许总中断
KEY_START = 1; // 启动键设置为上拉输入
KEY_PAUSE = 1; // 暂停键设置为上拉输入
KEY_CLEAR = 1; // 清零键设置为上拉输入
DISP_SEG = 0xFF; // 初始化数码管
DISP_COM = 0xFF;
// 进入等待输入状态
while (1) {
unsigned char input_sec = 0;
unsigned char input_min = 0;
unsigned char input_done = 0;
while (!input_done) { // 等待用户输入定时时间
// 程序可以在此处添加其他任务
// 检测是否按下启动键
if (!KEY_START) {
input_done = 1; // 输入完成
timer_running = 1; // 开始计时
timer_paused = 0;
timer_blink = 0;
timer_sec = input_sec;
timer_min = input_min;
break;
}
// 检测是否按下清零键
if (!KEY_CLEAR) {
input_sec = 0;
input_min = 0;
}
// 检测是否按下加时键
if (!KEY_PAUSE) {
input_sec++; // 秒数加1
if (input_sec > 59) { // 秒数不能大于59
input_sec = 0;
input_min++; // 分钟数加1
if (input_min > 59) { // 分钟数不能大于59
input_min = 0;
}
}
}
// 显示当前输入的计时时间
unsigned char digit[3] = {input_min / 10, input_sec / 10, input_sec % 10};
DISP_COM = ~(1 << 2); DISP_SEG = ~(1 << digit[0]); // 显示分钟的十位
DISP_COM = ~(1 << 1); DISP_SEG = ~(1 << digit[1]); // 显示秒钟的十位
DISP_COM = ~(1 << 0); DISP_SEG = ~(1 << digit[2]); // 显示秒钟的个位
}
// 定时器运行状态下,显示当前计时时长
while (timer_running) {
// 程序可以在此处添加其他任务
// 检测是否按下暂停键
if (!KEY_PAUSE) {
timer_paused = !timer_paused; // 切换暂停状态
while (!KEY_PAUSE) {} // 等待按键释放
}
display(); // 显示当前计时时长
}
// 定时器时间到达,数码管闪烁指示
while (timer_blink) {
// 程序可以在此处添加其他任务
display(); // 显示当前计时时长
}
}
}
```
注意,以上代码仅供参考,实际使用时还需要根据具体情况进行调整和优化。