#include <reg51.h> #include <string.h> #include <stdio.h> /************************ 硬件引脚定义 ************************/ // LCD1602 控制引脚 sbit LCD_RS = P2^0; // 数据/命令选择 sbit LCD_RW = P2^1; // 读/写选择 sbit LCD_EN = P2^2; // 使能信号 #define LCD_PORT P0; // 数据端口 // 按键引脚(K1-K5) sbit K1 = P3^0; // 分钟+1 sbit K2 = P3^1; // 设定5分钟 sbit K3 = P3^2; // 设定10分钟 sbit K4 = P3^3; // 设定20分钟 sbit K5 = P3^4; // 启动/暂停 // LED 与蜂鸣器 sbit LED = P1^0; // 倒计时运行指示灯 sbit BEEP = P1^1; // 蜂鸣器(音乐输出) /************************ 全局变量 ************************/ unsigned char hour = 0; // 小时(实际用不到,可忽略) unsigned char min = 30; // 分钟(默认30分钟,可通过按键调整) unsigned char sec = 0; // 秒 bit isRunning = 0; // 倒计时运行标志:0=停止,1=运行 /************************ 函数声明 ************************/ void DelayMs(unsigned int ms); // 毫秒延时 void LcdWriteCmd(unsigned char cmd); // LCD写命令 void LcdWriteData(unsigned char dat); // LCD写数据 void LcdInit(void); // LCD初始化 void LcdShowStr(unsigned char row, unsigned char col, unsigned char *str); // LCD显示字符串 void KeyScan(void); // 按键扫描 void Timer0Init(void); // 定时器0初始化(1秒定时) void PlayMusic(void); // 倒计时结束音乐提醒 /************************ 主函数 ************************/ void main() { unsigned char dispBuf[20]; // 显示缓冲区 LcdInit(); // 初始化LCD Timer0Init(); // 初始化定时器0 // 初始显示默认时间 sprintf(dispBuf, "TIME %02d:%02d", min, sec); LcdShowStr(0, 0, dispBuf); while(1) { KeyScan(); // 扫描按键 // 如果倒计时运行中,更新显示 if(isRunning) { sprintf(dispBuf, "TIME %02d:%02d", min, sec); LcdShowStr(0, 0, dispBuf); LED = ~LED; // LED闪烁 } DelayMs(100); // 主循环延时,降低CPU占用 } } /************************ 定时器0中断服务函数(1秒定时) ************************/ void Timer0_ISR(void) interrupt 1{ TH0 = 0x3C; TL0 = 0xB0; static unsigned char count = 0; count++; if(count >= 20){ count = 0; if(isRunning){ if(sec == 0){ if(min == 0){ isRunning = 0; LED=0; } else{ min--; sec = 59; } } else{ sec--; } } } } /************************ 毫秒延时函数(软件延时,需根据晶振调整) ************************/ void DelayMs(unsigned int ms) { unsigned int i, j; for(i=0; i<ms; i++) for(j=0; j<123; j++); // 12MHz晶振下,约1ms延时 } /************************ LCD1602 驱动函数 ************************/ void LcdWriteCmd(unsigned char cmd) { LCD_RS = 0; // 选择命令模式 LCD_RW = 0; // 选择写操作 LCD_PORT = cmd; DelayMs(1); LCD_EN = 1; // 使能脉冲 DelayMs(1); LCD_EN = 0; DelayMs(5); // 命令执行延时 } void LcdWriteData(unsigned char dat) { LCD_RS = 1; // 选择数据模式 LCD_RW = 0; // 选择写操作 LCD_PORT = dat; DelayMs(1); LCD_EN = 1; // 使能脉冲 DelayMs(1); LCD_EN = 0; DelayMs(5); // 数据写入延时 } void LcdInit(void) { LcdWriteCmd(0x38); // 8位接口,2行显示,5x7点阵 LcdWriteCmd(0x0C); // 显示开,光标关 LcdWriteCmd(0x06); // 写入后地址自动+1 LcdWriteCmd(0x01); // 清屏 DelayMs(2); } void LcdShowStr(unsigned char row, unsigned char col, unsigned char *str) { // 设置显示起始地址 if(row == 0) LcdWriteCmd(0x80 + col); else LcdWriteCmd(0xC0 + col); // 连续写入字符串 while(*str) { LcdWriteData(*str); str++; } } /************************ 按键扫描函数 ************************/ void KeyScan(void) { // 消抖延时(可根据硬件调整) #define KEY_DELAY() DelayMs(20) if(K1 == 0) { // K1:分钟+1(1~60分钟) KEY_DELAY(); if(K1 == 0) { if(min < 60) min++; while(K1 == 0); // 等待按键释放 } } if(K2 == 0) { // K2:设定5分钟 KEY_DELAY(); if(K2 == 0) { min = 5; sec = 0; while(K2 == 0); } } if(K3 == 0) { // K3:设定10分钟 KEY_DELAY(); if(K3 == 0) { min = 10; sec = 0; while(K3 == 0); } } if(K4 == 0) { // K4:设定20分钟 KEY_DELAY(); if(K4 == 0) { min = 20; sec = 0; while(K4 == 0); } } if(K5 == 0) { // K5:启动/暂停 KEY_DELAY(); if(K5 == 0) { isRunning = !isRunning; // 切换状态 while(K5 == 0); } } } /************************ 音乐提醒函数(简单示例:播放一段频率变化的声音) ************************/ void PlayMusic(void) { unsigned int freq[] = {1000, 1500, 2000, 1500, 1000}; // 频率数组 unsigned int dur[] = {500, 300, 300, 300, 500}; // 时长数组(ms) unsigned char i; for(i=0; i<5; i++) { // 简单频率控制(实际需结合定时器精准实现,这里简化演示) unsigned int period = 12000000 / (12 * freq[i]); // 计算半周期 unsigned int cnt = dur[i] / 10; // 持续次数 while(cnt--) { BEEP = 1; DelayMs(5); BEEP = 0; DelayMs(5); } } } /************************ 定时器0初始化(50ms定时,凑1秒) ************************/ void Timer0Init(void) { TMOD = 0x01; // 定时器0,模式1(16位定时器) TH0 = 0xB8; // 初值:50ms定时(12MHz晶振) TL0 = 0x00; ET0 = 1; // 使能定时器0中断 EA = 1; // 使能总中断 TR0 = 1; // 启动定时器0 }
时间: 2025-06-23 21:52:44 浏览: 27
### 基于51单片机的倒计时程序示例
以下是一个基于51单片机的倒计时程序代码示例,该程序实现了定时器初始化、按键控制、LCD1602显示以及蜂鸣器提醒功能。代码分为多个部分,包括定时器配置、按键处理逻辑、LCD显示驱动和蜂鸣器控制。
#### 定时器初始化
通过设置定时器0为模式1(16位定时器),并利用中断服务程序实现1秒的时间间隔。
```c
#include <reg52.h>
sbit Buzzer = P3^7; // 蜂鸣器连接到P3.7
unsigned char second = 0; // 记录秒数
unsigned int countdown_time = 10; // 初始倒计时时间(单位:秒)
void Timer0_Init() {
TMOD |= 0x01; // 设置定时器0为模式1
TH0 = (65536 - 50000) / 256; // 设置初值以产生50ms中断
TL0 = (65536 - 50000) % 256;
EA = 1; // 开启总中断
ET0 = 1; // 开启定时器0中断
}
void Timer0_ISR() interrupt 1 {
static unsigned char count = 0;
TH0 = (65536 - 50000) / 256; // 重新加载初值
TL0 = (65536 - 50000) % 256;
count++;
if (count >= 20) { // 每20次中断为1秒
count = 0;
second++;
if (second >= countdown_time) { // 倒计时结束
Buzzer = ~Buzzer; // 蜂鸣器提示
}
}
}
```
#### LCD1602显示驱动
使用LCD1602模块显示倒计时时间。参考LCD写数据函数[^2]。
```c
sbit LCD_RS = P2^0; // 数据/命令选择
sbit LCD_RW = P2^1; // 读/写选择
sbit LCD_E = P2^2; // 使能信号
sbit LCD_DataPort = P0; // 数据端口
void LCD_WriteCommand(unsigned char Command) {
LCD_RS = 0;
LCD_RW = 0;
LCD_DataPort = Command;
LCD_E = 1;
Delay(1);
LCD_E = 0;
Delay(1);
}
void LCD_WriteData(unsigned char Data) {
LCD_RS = 1;
LCD_RW = 0;
LCD_DataPort = Data;
LCD_E = 1;
Delay(1);
LCD_E = 0;
Delay(1);
}
void LCD_Init() {
LCD_WriteCommand(0x38); // 8位数据,2行显示,5x7点阵
LCD_WriteCommand(0x0C); // 显示开,光标关
LCD_WriteCommand(0x06); // 自增地址,无屏幕移动
LCD_WriteCommand(0x01); // 清屏
Delay(2);
}
void LCD_DisplayTime(unsigned int time) {
LCD_WriteCommand(0x80); // 设置光标到第一行第一个字符位置
LCD_WriteData('T'); LCD_WriteData('i'); LCD_WriteData('m'); LCD_WriteData('e');
LCD_WriteCommand(0xC0); // 设置光标到第二行第一个字符位置
LCD_WriteData(time / 10 + '0'); // 十位
LCD_WriteData(':');
LCD_WriteData(time % 10 + '0'); // 个位
}
```
#### 按键控制
实现开始、暂停、继续和复位功能。
```c
sbit Key_Start = P1^0; // 开始按键
sbit Key_Pause = P1^1; // 暂停按键
sbit Key_Reset = P1^2; // 复位按键
unsigned char key_flag = 0; // 按键标志
void Key_Scan() {
if (!Key_Start && !key_flag) {
key_flag = 1; // 开始倒计时
} else if (!Key_Pause && key_flag) {
key_flag = 0; // 暂停倒计时
} else if (!Key_Reset) {
second = 0; // 复位倒计时
key_flag = 0;
}
}
```
#### 主函数
将上述功能整合到主函数中。
```c
void main() {
Timer0_Init();
LCD_Init();
while (1) {
Key_Scan();
if (key_flag) {
LCD_DisplayTime(countdown_time - second);
} else {
LCD_DisplayTime(countdown_time - second);
}
}
}
```
阅读全文
相关推荐



















