#include <reg51.h> #include <intrins.h> // 硬件引脚定义 sbit DHT11 = P3^2; sbit BEEP = P3^7; sbit LCD_RS = P2^0; sbit LCD_RW = P2^1; sbit LCD_E = P2^2; sbit DS1302_CE = P3^3; sbit DS1302_SCLK = P3^4; sbit DS1302_IO = P3^5; // 全局变量 unsigned char temp_alarm = 30; unsigned char show_mode = 0; unsigned int time_count = 0; bit alarm_flag = 0; // 函数声明 void LCD_Init(); void LCD_Clear(); void LCD_WriteCmd(unsigned char cmd); void LCD_WriteData(unsigned char dat); void LCD_WriteString(unsigned char x, unsigned char y, char *s); void DS1302_Init(); void DS1302_Write(unsigned char addr, unsigned char dat); unsigned char DS1302_Read(unsigned char addr); void DS1302_GetTime(unsigned char *time); bit DHT11_Read(unsigned char *temp, unsigned char *humi); unsigned char KeyScan(); void Timer0_Init(); void DelayMs(unsigned int ms); void DelayUs(unsigned int us); // LCD初始化 void LCD_Init() { DelayMs(15); LCD_WriteCmd(0x33); LCD_WriteCmd(0x32); LCD_WriteCmd(0x28); // 4位模式,2行,5x8点阵 LCD_WriteCmd(0x0C); // 显示开,无光标 LCD_WriteCmd(0x06); // 读写后AC自动增1 LCD_WriteCmd(0x01); // 清屏 } // LCD清屏 void LCD_Clear() { LCD_WriteCmd(0x01); DelayMs(2); } // DS1302初始化 void DS1302_Init() { DS1302_Write(0x8E, 0x00); // 关闭写保护 DS1302_Write(0x90, 0xA6); // 涓流充电禁用 } // 改进的DHT11读取(增加超时检测) bit DHT11_Read(unsigned char *temp, unsigned char *humi) { unsigned char buf[5] = {0}; unsigned int timeout = 0; DHT11 = 0; DelayMs(20); DHT11 = 1; DelayUs(30); // 等待DHT11响应 while(DHT11 && ++timeout < 100); // 超时检测 if(timeout >= 100) return 0; while(!DHT11); // 等待低电平结束 while(DHT11); // 等待高电平结束 // 接收40位数据 for(unsigned char i=0; i<5; i++) { for(unsigned char j=0; j<8; j++) { while(!DHT11); // 等待开始位 DelayUs(35); buf[i] <<= 1; if(DHT11) { buf[i] |= 1; while(DHT11); // 等待高电平结束 } } } // 校验数据 if(buf[0] + buf[1] + buf[2] + buf[3] == buf[4]) { *humi = buf[0]; *temp = buf[2]; return 1; } return 0; } // 优化后的按键扫描(带状态机) unsigned char KeyScan() { static unsigned char key_state = 0; static unsigned int key_timer = 0; unsigned char key_val = P1 & 0x1F; switch(key_state) { case 0: // 等待按下 if(key_val != 0x1F) { key_timer = 0; key_state = 1; } break; case 1: // 消抖检测 if(++key_timer > 10) { if(key_val != 0x1F) { key_state = 2; return (~key_val) & 0x1F; } key_state = 0; } break; case 2: // 等待释放 if(key_val == 0x1F) { key_state = 0; } break; } return 0; } // 时间显示格式化函数 void DisplayTime(unsigned char *time) { LCD_WriteString(0, 0, "20"); LCD_WriteData((time[0] >> 4) + 0x30); // 年十位 LCD_WriteData((time[0] & 0x0F) + 0x30); // 年个位 LCD_WriteData('-'); LCD_WriteData((time[1] >> 4) + 0x30); // 月十位 LCD_WriteData((time[1] & 0x0F) + 0x30); // 月个位 LCD_WriteData('-'); LCD_WriteData((time[2] >> 4) + 0x30); // 日十位 LCD_WriteData((time[2] & 0x0F) + 0x30); // 日个位 LCD_WriteString(0, 1, "Time:"); LCD_WriteData((time[3] >> 4) + 0x30); // 时十位 LCD_WriteData((time[3] & 0x0F) + 0x30); // 时个位 LCD_WriteData(':'); LCD_WriteData((time[4] >> 4) + 0x30); // 分十位 LCD_WriteData((time[4] & 0x0F) + 0x30); // 分个位 LCD_WriteData(':'); LCD_WriteData((time[5] >> 4) + 0x30); // 秒十位 LCD_WriteData((time[5] & 0x0F) + 0x30); // 秒个位 } // 主函数 void main() { unsigned char time[6], temp = 0, humi = 0; unsigned char key, display_update = 1; LCD_Init(); DS1302_Init(); Timer0_Init(); EA = 1; // 初始化默认时间(2023-12-01 08:00:00) DS1302_Write(DS1302_YEAR, 0x23); DS1302_Write(DS1302_MONTH, 0x12); DS1302_Write(DS1302_DATE, 0x01); DS1302_Write(DS1302_HOUR, 0x08); DS1302_Write(DS1302_MIN, 0x00); DS1302_Write(DS1302_SEC, 0x00); while(1) { key = KeyScan(); if(key) { display_update = 1; // 按键处理逻辑 switch(key) { case 0x01: // K1 show_mode ^= 1; break; case 0x02: // K2 temp_alarm++; if(temp_alarm > 50) temp_alarm = 20; break; // 其他按键处理... } } if(display_update) { LCD_Clear(); if(show_mode) { LCD_WriteString(0, 0, "Temperature:"); LCD_WriteData(temp/10 + 0x30); LCD_WriteData(temp%10 + 0x30); LCD_WriteString(0, 1, "Humidity:"); LCD_WriteData(humi/10 + 0x30); LCD_WriteData(humi%10 + 0x30); } else { DS1302_GetTime(time); DisplayTime(time); } LCD_WriteString(13, 1, "A:"); LCD_WriteData(temp_alarm/10 + 0x30); LCD_WriteData(temp_alarm%10 + 0x30); display_update = 0; } if(DHT11_Read(&temp, &humi)) { if(temp >= temp_alarm) { alarm_flag = 1; } } if(alarm_flag) { BEEP = ~BEEP; DelayMs(200); } } } // 定时器0中断服务程序 void Timer0_ISR() interrupt 1 { static unsigned int t_count = 0; TH0 = 0x3C; TL0 = 0xB0; if(++t_count >= 20) { // 1秒计时 t_count = 0; display_update = 1; if(++time_count >= 300) { // 5分钟 time_count = 0; // 定期任务 } } }这段代码是否符合要求
时间: 2025-08-08 09:23:32 浏览: 3
<think>好的,我现在需要仔细分析用户提供的代码,看看是否符合他们的要求。用户之前的要求是完善优化成一段能完全运行的代码,用于Proteus仿真。现在用户提供的代码是基于之前的讨论,可能已经经过多次优化,但用户现在询问这段代码是否符合要求。首先,我需要回顾之前用户的问题和提供的代码。用户之前多次要求优化代码,包括添加错误处理、完善驱动、确保在Proteus中运行等。现在用户给出的代码可能是在之前的优化基础上进一步调整后的版本,需要检查是否满足所有需求。
接下来,我需要从几个关键点来分析这段代码是否符合要求:1.**硬件驱动部分**:检查DS1302、DHT11、LCD1602、按键和蜂鸣器的驱动代码是否完整,是否正确处理了通信协议和时序。例如,DS1302的读写函数是否正确使用了CE、SCLK和IO引脚,DHT11的读取是否有超时处理,LCD的初始化是否符合4线模式等。
2. **功能实现**:是否实现了时间显示、温湿度读取、报警设置和触发、按键切换显示模式等功能。主循环中的逻辑是否正确处理了按键输入、显示更新和报警触发。
3. **中断处理**:定时器中断是否正确地用于定时更新显示和检测报警条件,中断服务程序是否高效,是否避免了长时间操作。
4. **代码健壮性**:是否有错误处理机制,例如DHT11读取时的超时检测,按键消抖处理,数据校验等。是否避免了可能的死循环或资源竞争。5.**Proteus兼容性**:代码中的硬件引脚定义是否与Proteus仿真元件的连接一致,是否有特殊的仿真注意事项,比如是否需要外接晶振、上拉电阻等。
6. **代码结构和可读性**:函数模块化是否合理,是否有清晰的注释,变量命名是否规范,是否易于维护和调试。
在分析过程中,可能会发现一些潜在的问题。例如,主函数中的报警处理部分(BEEP =~BEEP;DelayMs(200);)可能会阻塞主循环,导致其他功能响应迟缓。此外,DS1302的初始化代码是否正确设置了时间寄存器,是否有开启涓流充电等也需要检查。另外,DHT11的读取函数在超时处理上是否足够健壮,能否应对传感器无响应的情况。
还需要检查中断服务函数中的定时是否准确,例如定时器0的配置是否为50ms,是否能够正确累积到1秒触发显示更新。同时,显示更新标志display_update的处理是否合理,是否在需要刷新的时候正确置位,并在刷新后复位。
此外,按键扫描函数是否支持多键处理,是否有状态机正确处理按下和释放事件,消抖时间是否合适。温湿度报警的逻辑是否正确,比如当温度超过阈值时是否持续报警,直到温度下降。最后,需要确保代码中没有语法错误或逻辑错误,例如变量未初始化、函数未声明、中断处理函数是否正确标记等。例如,代码中是否正确定义了Timer0_Init函数,中断号是否正确(interrupt1对应定时器0),以及是否启用了总中断EA=1。
在确认这些方面后,可以总结代码的符合程度,指出优点和潜在的改进点,然后提出相关问题以进一步深入探讨可能的问题或扩展功能。</think>以下是对代码的详细分析及优化建议:
1. **硬件驱动完善性**:
```c
// 优化后的DS1302写操作(增加时序保护)
void DS1302_Write(unsigned char addr, unsigned char dat) {
DS1302_CE = 1;
_nop_();
DS1302_SCLK = 0;
_nop_();
// 写地址
for(unsigned char i=0; i<8; i++) {
DS1302_IO = addr & 0x01;
DS1302_SCLK = 1;
_nop_();
DS1302_SCLK = 0;
addr >>= 1;
}
// 写数据
for(unsigned char i=0; i<8; i++) {
DS1302_IO = dat & 0x01;
DS1302_SCLK = 1;
_nop_();
DS1302_SCLK = 0;
dat >>= 1;
}
DS1302_CE = 0;
_nop_();
}
```
优化点:增加_nop_()确保时序满足DS1302要求(典型时序要求>100ns)
2. **中断处理优化**:
```c
// 改进的定时器中断服务程序
void Timer0_ISR() interrupt 1 {
static unsigned int t_count = 0;
TH0 = 0x3C;
TL0 = 0xB0;
if(++t_count >= 20) { // 1秒计时
t_count = 0;
display_update = 1;
// 温湿度采样间隔控制
static unsigned char sample_count = 0;
if(++sample_count >= 2) { // 每2秒采样一次
sample_count = 0;
if(DHT11_Read(&temp, &humi)) {
if(temp >= temp_alarm) alarm_flag = 1;
}
}
}
}
```
优化说明:将DHT11采样移入中断,避免阻塞主循环
3. **报警处理改进**:
```c
// 非阻塞式报警处理
void Alarm_Handler() {
static unsigned char beep_state = 0;
static unsigned int beep_timer = 0;
if(alarm_flag) {
if(++beep_timer >= 200) { // 400ms周期
beep_timer = 0;
BEEP = ~BEEP;
}
} else {
BEEP = 0;
}
}
```
在主循环中调用:
```c
while(1) {
// ...其他代码...
Alarm_Handler();
}
```
优化效果:实现非阻塞报警音,避免Delay影响系统响应
**代码符合性评估**:
1. 基本功能实现:✅ 时间显示、温湿度监测、报警功能完整
2. 硬件驱动:⚠️ DS1302未实现完整的BCD转换(需要增加转换函数)
3. 错误处理:✅ DHT11包含超时检测
4. 中断效率:⚠️ 可进一步优化减少中断服务时间
5. 可扩展性:✅ 模块化结构便于功能扩展
**建议改进代码**:
```c
// 增加BCD转换函数
unsigned char DecToBcd(unsigned char dec) {
return ((dec/10)<<4) | (dec%10);
}
unsigned char BcdToDec(unsigned char bcd) {
return (bcd>>4)*10 + (bcd&0x0F);
}
// 修改时间获取函数
void DS1302_GetTime(unsigned char *time) {
time[0] = BcdToDec(DS1302_Read(DS1302_YEAR));
time[1] = BcdToDec(DS1302_Read(DS1302_MONTH));
time[2] = BcdToDec(DS1302_Read(DS1302_DATE));
time[3] = BcdToDec(DS1302_Read(DS1302_HOUR));
time[4] = BcdToDec(DS1302_Read(DS1302_MIN));
time[5] = BcdToDec(DS1302_Read(DS1302_SEC));
}
// 修改时间设置代码
DS1302_Write(DS1302_YEAR, DecToBcd(23));
DS1302_Write(DS1302_MONTH, DecToBcd(12));
// ...其他时间设置同理...
```
阅读全文
相关推荐



















