#include <reg52.h>
#include <intrins.h>
#include <string.h>
// 引脚定义
sbit K1 = P3^0; // 状态切换
sbit K2 = P3^1; // 增加/长按确认
sbit K3 = P3^2; // 移位/复位
sbit K4 = P3^3; // 低功耗模式
sbit BEEP = P1^0; // 蜂鸣器
sbit LED = P1^1; // 低功耗指示灯
// LCD1602引脚定义
sbit RS = P2^0;
sbit RW = P2^1;
sbit EN = P2^2;
#define LCD_DATA P0
// DS1302引脚定义
sbit RST = P1^5;
sbit IO = P1^6;
sbit SCLK = P1^7;
// DS18B20引脚定义
sbit DQ = P3^7;
// 全局变量
unsigned char display_state = 0; // 0:日期 1:时间 2:温度 3:闹钟 4:倒计时
unsigned char setting_pos = 0; // 设置位置
bit setting_mode = 0; // 设置模式标志
bit low_power = 0; // 低功耗模式标志
bit alarm_on = 0; // 报警标志
unsigned int timer_minutes = 10; // 倒计时值(分钟)
unsigned char alarm_h = 7, alarm_m = 0, alarm_s = 0; // 闹钟时间
bit blink = 0; // 闪烁控制变量
unsigned int power_off_timer = 0; // 低功耗计时器
unsigned int beep_counter = 0; // 蜂鸣器计数器
unsigned char beep_freq = 10; // 蜂鸣器频率
unsigned int no_reset_counter = 0; // 未复位计数器
unsigned char key_state[4] = {0}; // 按键状态数组
unsigned int key_press_time = 0; // 修复:将key_press_time声明为全局变量
// 时间结构体
struct Time {
unsigned char year, month, day;
unsigned char hour, minute, second;
} current_time;
// LCD1602基础函数
void LCD_Delay(unsigned int t) {
while(t--);
}
void LCD_WriteCmd(unsigned char cmd) {
RS = 0;
RW = 0;
LCD_DATA = cmd;
EN = 1;
LCD_Delay(5);
EN = 0;
}
void LCD_WriteData(unsigned char dat) {
RS = 1;
RW = 0;
LCD_DATA = dat;
EN = 1;
LCD_Delay(5);
EN = 0;
}
void LCD_Init() {
LCD_WriteCmd(0x38); // 8位数据,双行显示
LCD_WriteCmd(0x0C); // 开显示,关光标
LCD_WriteCmd(0x06); // 增量不移位
LCD_WriteCmd(0x01); // 清屏
}
void LCD_ShowStr(unsigned char x, unsigned char y, char *str) {
if (y == 0) LCD_WriteCmd(0x80 + x);
else LCD_WriteCmd(0xC0 + x);
while (*str) {
LCD_WriteData(*str++);
}
}
// DS1302基础函数
void DS1302_WriteByte(unsigned char dat) {
unsigned char i;
for(i=0; i<8; i++) {
IO = dat & 0x01;
dat >>= 1;
SCLK = 1;
_nop_();
SCLK = 0;
_nop_();
}
}
unsigned char DS1302_ReadByte() {
unsigned char i, dat = 0;
for(i=0; i<8; i++) {
dat >>= 1;
if(IO) dat |= 0x80;
SCLK = 1;
_nop_();
SCLK = 0;
_nop_();
}
return dat;
}
void DS1302_WriteReg(unsigned char addr, unsigned char dat) {
RST = 0; _nop_();
SCLK = 0; _nop_();
RST = 1; _nop_();
DS1302_WriteByte(addr);
DS1302_WriteByte(dat);
SCLK = 1; _nop_();
RST = 0; _nop_();
}
unsigned char DS1302_ReadReg(unsigned char addr) {
unsigned char dat;
RST = 0; _nop_();
SCLK = 0; _nop_();
RST = 1; _nop_();
DS1302_WriteByte(addr | 0x01);
dat = DS1302_ReadByte();
SCLK = 1; _nop_();
RST = 0; _nop_();
return dat;
}
// BCD转十进制
unsigned char BCD2Dec(unsigned char bcd) {
return (bcd >> 4) * 10 + (bcd & 0x0F);
}
// 十进制转BCD
unsigned char Dec2BCD(unsigned char dec) {
return ((dec / 10) << 4) | (dec % 10);
}
void DS1302_GetTime(struct Time *t) {
t->second = BCD2Dec(DS1302_ReadReg(0x81));
t->minute = BCD2Dec(DS1302_ReadReg(0x83));
t->hour = BCD2Dec(DS1302_ReadReg(0x85));
t->day = BCD2Dec(DS1302_ReadReg(0x87));
t->month = BCD2Dec(DS1302_ReadReg(0x89));
t->year = BCD2Dec(DS1302_ReadReg(0x8D));
}
// DS18B20基础函数
void DS18B20_Delay(unsigned int t) {
while(t--);
}
bit DS18B20_Init() {
bit ack;
DQ = 1; DS18B20_Delay(8);
DQ = 0; DS18B20_Delay(80);
DQ = 1; DS18B20_Delay(14);
ack = DQ;
DS18B20_Delay(20);
return ack;
}
void DS18B20_WriteByte(unsigned char dat) {
unsigned char i;
for(i=0; i<8; i++) {
DQ = 0;
_nop_();
DQ = dat & 0x01;
DS18B20_Delay(5);
DQ = 1;
dat >>= 1;
}
DS18B20_Delay(5);
}
unsigned char DS18B20_ReadByte() {
unsigned char i, dat = 0;
for(i=0; i<8; i++) {
dat >>= 1;
DQ = 0;
_nop_();
DQ = 1;
_nop_();
if(DQ) dat |= 0x80;
DS18B20_Delay(5);
}
return dat;
}
// DS18B20温度读取函数
float DS18B20_GetTemp() {
unsigned char LSB, MSB;
int temp;
float f_temp;
unsigned int timeout; // 将timeout声明放在函数开头
if(!DS18B20_Init()) return -99.9; // 初始化失败
DS18B20_WriteByte(0xCC); // Skip ROM
DS18B20_WriteByte(0x44); // Convert
// 等待转换完成 (750ms)
timeout = 750;
while(timeout > 0) { // 修复timeout未定义问题
DS18B20_Delay(1000);
if(!DQ) break; // 转换完成DQ变低
timeout--;
}
if(!DS18B20_Init()) return -99.9; // 初始化失败
DS18B20_WriteByte(0xCC);
DS18B20_WriteByte(0xBE); // Read Scratchpad
LSB = DS18B20_ReadByte();
MSB = DS18B20_ReadByte();
temp = (MSB << 8) | LSB;
f_temp = temp * 0.0625;
return f_temp;
}
// 按键处理函数 (非阻塞式)
void Key_Process() {
// K1处理 - 状态切换 (功能4)
if(!K1) {
if(key_state[0] == 0) { // K1首次按下
key_state[0] = 1;
display_state = (display_state + 1) % 5;
setting_mode = (display_state == 3 || display_state == 4);
if(setting_mode) setting_pos = 0; // 进入设置模式时重置位置
LCD_WriteCmd(0x01); // 清屏
}
} else {
key_state[0] = 0;
}
// K2处理 - 增加/长按确认 (功能4)
if(!K2) {
if(key_state[1] == 0) { // K2首次按下
key_state[1] = 1;
key_press_time = 0;
} else {
key_press_time++;
// 长按超过3秒
if(key_press_time > 300) { // 假设10ms中断,3000ms
setting_mode = 0;
display_state = 0; // 返回日期模式
LCD_WriteCmd(0x01);
key_state[1] = 0;
key_press_time = 0;
}
}
// 短按处理 (仅在设置模式) (功能4)
if(key_state[1] == 1 && setting_mode) {
if(display_state == 3) { // 闹钟设置
switch(setting_pos) {
case 0: alarm_h = (alarm_h + 1) % 24; break;
case 1: alarm_m = (alarm_m + 1) % 60; break;
case 2: alarm_s = (alarm_s + 1) % 60; break;
}
} else if(display_state == 4) { // 倒计时设置
if(setting_pos == 0) timer_minutes = (timer_minutes + 1) % 1000;
}
}
} else {
key_state[1] = 0;
}
// K3处理 - 移位/复位 (功能5)
if(!K3) {
if(key_state[2] == 0) { // K3首次按下
key_state[2] = 1;
if(setting_mode) {
setting_pos = (setting_pos + 1) % 3; // 循环移位
} else if(alarm_on) {
alarm_on = 0; // 清除报警
BEEP = 0; // 关闭蜂鸣器
beep_freq = 10; // 重置频率
no_reset_counter = 0; // 复位未响应计数器
}
}
} else {
key_state[2] = 0;
}
// K4处理 - 低功耗模式 (功能6)
if(!K4) {
if(key_state[3] == 0) { // K4首次按下
key_state[3] = 1;
low_power = !low_power;
LED = low_power; // LED指示状态
power_off_timer = 0;
if(!low_power) {
LCD_WriteCmd(0x0C); // 恢复显示
}
}
} else {
key_state[3] = 0;
}
}
// 显示处理函数 (功能3)
void Display_Process() {
char buf[17];
switch(display_state) {
case 0: // 日期信息
sprintf(buf, "Data: 20%02d-%02d-%02d",
current_time.year, current_time.month, current_time.day);
LCD_ShowStr(0, 0, buf);
break;
case 1: // 时间信息
sprintf(buf, "Time: %02d:%02d:%02d",
current_time.hour, current_time.minute, current_time.second);
LCD_ShowStr(0, 0, buf);
break;
case 2: // 温度信息
{
float temp = DS18B20_GetTemp();
if(temp < -50) { // 读取失败
LCD_ShowStr(0, 0, "Temp: --.-- C");
} else {
unsigned int temp_int = (unsigned int)temp;
unsigned int temp_frac = (unsigned int)((temp - temp_int) * 100);
sprintf(buf, "Temp: %d.%02d C", temp_int, temp_frac);
LCD_ShowStr(0, 0, buf);
}
}
break;
case 3: // 闹钟设置 (功能4)
if(setting_mode) {
if(blink) { // 闪烁状态 (显示空格)
switch(setting_pos) {
case 0: sprintf(buf, "Alarm: --:%02d:%02d", alarm_m, alarm_s); break;
case 1: sprintf(buf, "Alarm: %02d:--:%02d", alarm_h, alarm_s); break;
case 2: sprintf(buf, "Alarm: %02d:%02d:--", alarm_h, alarm_m); break;
}
} else { // 正常显示
sprintf(buf, "Alarm: %02d:%02d:%02d", alarm_h, alarm_m, alarm_s);
}
} else {
sprintf(buf, "Alarm: %02d:%02d:%02d", alarm_h, alarm_m, alarm_s);
}
LCD_ShowStr(0, 0, buf);
break;
case 4: // 倒计时设置 (功能4)
if(setting_mode) {
if(blink) {
sprintf(buf, "Timer: --- min");
} else {
sprintf(buf, "Timer: %3d min", timer_minutes);
}
} else {
sprintf(buf, "Timer: %3d min", timer_minutes);
}
LCD_ShowStr(0, 0, buf);
break;
}
}
// 报警处理 (功能7)
void Alarm_Process() {
if(alarm_on) {
beep_counter++;
// 基础报警
if(beep_counter % (500/beep_freq) == 0) {
BEEP = !BEEP;
}
// 5秒内未按下K3则增加频率 (功能7)
if(no_reset_counter++ > 500) { // 5秒
no_reset_counter = 0;
if(beep_freq < 50) beep_freq += 5; // 增加频率
}
} else {
BEEP = 0; // 关闭蜂鸣器
}
}
// 低功耗处理 (功能6)
void LowPower_Process() {
static unsigned char blink_count = 0;
if(low_power) {
power_off_timer++;
// 10秒后闪烁息屏
if(power_off_timer > 1000) { // 10秒
// 闪烁3次后息屏
if(blink_count < 3) {
LCD_WriteCmd(0x08); // 关显示
LCD_Delay(50000);
LCD_WriteCmd(0x0C); // 开显示
blink_count++;
} else if(blink_count == 3) {
LCD_WriteCmd(0x08); // 息屏
blink_count++;
}
}
} else {
blink_count = 0;
}
}
// 倒计时处理
void Timer_Process() {
static unsigned int second_counter = 0;
static unsigned int seconds_remaining = 0; // 将声明移到函数开头
if(timer_minutes > 0 && !alarm_on) {
if(++second_counter >= 100) { // 1秒
second_counter = 0;
if(seconds_remaining == 0) {
timer_minutes--;
seconds_remaining = 59;
if(timer_minutes == 0) {
alarm_on = 1; // 触发报警
no_reset_counter = 0; // 重置未响应计数器
}
} else {
seconds_remaining--;
}
}
}
}
// 主函数
void main() {
// 初始化
LCD_Init();
DS1302_WriteReg(0x8E, 0x00); // 允许写操作
// 设置初始时间 (2023-12-25 08:30:00)
DS1302_WriteReg(0x8C, Dec2BCD(23)); // 2023年
DS1302_WriteReg(0x88, Dec2BCD(12)); // 12月
DS1302_WriteReg(0x86, Dec2BCD(25)); // 25日
DS1302_WriteReg(0x84, Dec2BCD(8)); // 08时
DS1302_WriteReg(0x82, Dec2BCD(30)); // 30分
DS1302_WriteReg(0x80, Dec2BCD(0)); // 00秒
DS1302_WriteReg(0x8E, 0x80); // 写保护
// 定时器0初始化 (10ms中断)
TMOD = 0x01;
TH0 = 0xDC;
TL0 = 0x00;
ET0 = 1;
EA = 1;
TR0 = 1;
// 初始显示
DS1302_GetTime(¤t_time);
LCD_ShowStr(0, 0, "Multifunction Clock");
LCD_ShowStr(0, 1, " Initializing... ");
LCD_Delay(200000);
LCD_WriteCmd(0x01); // 清屏
while(1) {
Key_Process();
Display_Process();
Alarm_Process();
LowPower_Process();
Timer_Process();
}
}
// 定时器0中断服务程序 (10ms)
void Timer0_ISR() interrupt 1 {
static unsigned int ms_count = 0;
static unsigned int blink_count = 0;
static unsigned int temp_update = 0;
// 重装定时器
TH0 = 0xDC;
TL0 = 0x00;
// 闪烁控制 (0.5秒周期) (功能4)
if(++blink_count >= 50) {
blink_count = 0;
blink = !blink;
}
// 时间更新 (每秒)
if(++ms_count >= 100) { // 1秒
ms_count = 0;
DS1302_GetTime(¤t_time);
// 检查闹钟 (功能1)
if(current_time.hour == alarm_h &&
current_time.minute == alarm_m &&
current_time.second == alarm_s) {
alarm_on = 1;
no_reset_counter = 0; // 重置未响应计数器
}
// 温度更新 (每5秒)
if(++temp_update >= 5) {
temp_update = 0;
// 温度在显示函数中读取
}
}
}
程序报错DGNSZ.C(319): warning C206: 'sprintf': missing function-prototype
DGNSZ.C(319): error C267: 'sprintf': requires ANSI-style prototype,请修改并给出完整程序,程序要适用于keil编程软件和普中51单片机