1、使用LCD1602作为显示器。 2、使用单片机定时器作为时间基准 3、使用独立按键,切换秒表和计时器功能 4、秒表模式下以0.01秒为单位显示变化,一个按键用于开始和停止。 5、计时模式进行倒计时,使用组合按键调整计时时间长度,一秒为单位。 计时模式下使用一个按键开始和停止计时,即使时间到蜂鸣器叫,使用该按键关闭提醒,重新回到设定的时间长度显示状态。怎么编写程序
时间: 2024-02-13 07:02:34 浏览: 113
51定时器+按键控制实现的秒表
以下是一个可能的实现方案,基于STC89C52单片机和Keil C编译器:
```c
#include <reg52.h>
// 定义LCD1602引脚
sbit RS = P2^0;
sbit EN = P2^1;
sbit D4 = P1^4;
sbit D5 = P1^5;
sbit D6 = P1^6;
sbit D7 = P1^7;
// 定义按键引脚
sbit START_STOP_BTN = P3^0;
sbit MODE_BTN = P3^1;
sbit UP_BTN = P3^2;
sbit DOWN_BTN = P3^3;
// 定义计时器变量
unsigned char timer_hours = 0;
unsigned char timer_minutes = 0;
unsigned char timer_seconds = 0;
// 定义秒表变量
unsigned int stopwatch_ticks = 0;
unsigned char stopwatch_running = 0;
// LCD1602初始化
void lcd_init() {
delay_ms(15);
lcd_write_command(0x02); // 返回首页
lcd_write_command(0x28); // 4位数据总线,2行显示,5x8字体
lcd_write_command(0x0C); // 显示开,光标关,闪烁关
lcd_write_command(0x06); // 光标右移
lcd_write_command(0x01); // 清屏
delay_ms(5);
}
// LCD1602写入命令
void lcd_write_command(unsigned char command) {
RS = 0;
EN = 0;
D7 = command & 0x80;
D6 = command & 0x40;
D5 = command & 0x20;
D4 = command & 0x10;
EN = 1;
delay_ms(1);
EN = 0;
D7 = command & 0x08;
D6 = command & 0x04;
D5 = command & 0x02;
D4 = command & 0x01;
EN = 1;
delay_ms(1);
EN = 0;
}
// LCD1602写入数据
void lcd_write_data(unsigned char data) {
RS = 1;
EN = 0;
D7 = data & 0x80;
D6 = data & 0x40;
D5 = data & 0x20;
D4 = data & 0x10;
EN = 1;
delay_ms(1);
EN = 0;
D7 = data & 0x08;
D6 = data & 0x04;
D5 = data & 0x02;
D4 = data & 0x01;
EN = 1;
delay_ms(1);
EN = 0;
}
// 显示时间或秒表计时
void display_time() {
lcd_write_command(0x80); // 第一行第一列
lcd_write_data('0' + timer_hours / 10);
lcd_write_data('0' + timer_hours % 10);
lcd_write_data(':');
lcd_write_data('0' + timer_minutes / 10);
lcd_write_data('0' + timer_minutes % 10);
lcd_write_data(':');
lcd_write_data('0' + timer_seconds / 10);
lcd_write_data('0' + timer_seconds % 10);
lcd_write_command(0xC0); // 第二行第一列
if (stopwatch_running) {
lcd_write_data('0' + stopwatch_ticks / 6000 % 10);
lcd_write_data('0' + stopwatch_ticks / 100 % 60 / 10);
lcd_write_data('.');
lcd_write_data('0' + stopwatch_ticks / 100 % 10);
lcd_write_data('0' + stopwatch_ticks % 100 / 10);
lcd_write_data('0' + stopwatch_ticks % 10);
} else {
lcd_write_data('T');
lcd_write_data('I');
lcd_write_data('M');
lcd_write_data('E');
lcd_write_data('R');
lcd_write_data(' ');
lcd_write_data('S');
lcd_write_data('T');
lcd_write_data('O');
lcd_write_data('P');
}
}
// 计时器中断处理
void timer_interrupt() interrupt 1 {
static unsigned char counter = 0;
TH0 = 0xFC; // 定时1ms
TL0 = 0x67;
counter++;
if (counter == 100) { // 1s
counter = 0;
if (stopwatch_running) {
stopwatch_ticks++;
} else {
if (timer_seconds == 0) {
if (timer_minutes == 0) {
if (timer_hours == 0) {
// 时间到
TR0 = 0; // 停止计时器
timer_seconds = 0;
timer_minutes = 0;
timer_hours = 0;
while (START_STOP_BTN == 0) { // 等待按键
lcd_write_command(0x01); // 清屏
lcd_write_command(0x80); // 第一行第一列
lcd_write_data('T');
lcd_write_data('I');
lcd_write_data('M');
lcd_write_data('E');
lcd_write_data('\'');
lcd_write_data('S');
lcd_write_data(' ');
lcd_write_data('U');
lcd_write_data('P');
lcd_write_data('!');
delay_ms(400);
lcd_write_command(0x01); // 清屏
delay_ms(400);
}
lcd_write_command(0x01); // 清屏
display_time();
return;
} else {
timer_hours--;
timer_minutes = 59;
timer_seconds = 59;
}
} else {
timer_minutes--;
timer_seconds = 59;
}
} else {
timer_seconds--;
}
}
}
display_time();
}
// 按键检测
void button_check() {
static unsigned char last_start_stop_btn_state = 0;
static unsigned char last_mode_btn_state = 0;
static unsigned char last_up_btn_state = 0;
static unsigned char last_down_btn_state = 0;
if (START_STOP_BTN != last_start_stop_btn_state) { // 开始/停止计时器
last_start_stop_btn_state = START_STOP_BTN;
if (last_start_stop_btn_state == 0) {
stopwatch_running = !stopwatch_running;
if (stopwatch_running) {
TR0 = 1; // 启动计时器
} else {
TR0 = 0; // 停止计时器
}
}
}
if (MODE_BTN != last_mode_btn_state) { // 切换模式
last_mode_btn_state = MODE_BTN;
if (last_mode_btn_state == 0) {
if (stopwatch_running) {
stopwatch_running = 0;
TR0 = 0; // 停止计时器
}
timer_hours = 0;
timer_minutes = 0;
timer_seconds = 0;
lcd_write_command(0x01); // 清屏
}
}
if (UP_BTN != last_up_btn_state) { // 调整时间或秒表计次
last_up_btn_state = UP_BTN;
if (last_up_btn_state == 0) {
if (stopwatch_running) {
stopwatch_ticks = 0;
} else {
if (timer_hours < 99) {
timer_hours++;
}
}
}
}
if (DOWN_BTN != last_down_btn_state) { // 调整时间
last_down_btn_state = DOWN_BTN;
if (last_down_btn_state == 0) {
if (stopwatch_running) {
stopwatch_ticks = 0;
} else {
if (timer_hours > 0) {
timer_hours--;
}
}
}
}
}
// 主函数
void main() {
TMOD = 0x01; // 设置计时器0为模式1
TH0 = 0xFC; // 定时1ms
TL0 = 0x67;
TR0 = 0; // 先停止计时器
ET0 = 1; // 允许计时器0中断
EA = 1; // 允许总中断
lcd_init();
while (1) {
button_check();
}
}
```
注意:以上代码仅供参考,具体实现可能需要根据具体硬件和需求进行适当修改。另外,为了保证计时器的精度,建议使用外部晶体振荡器,并在程序中配置正确的时钟频率。
阅读全文