闹钟小程序[6] 8月17日

博客围绕编写闹钟程序展开,要求启动程序时设置定时时间,到时间后打印“时间到”并退出。给出了老师编写的Python代码,通过循环获取当前时间,当达到设定时间时输出提示并跳出循环,还使用time.sleep(1)降低CPU占有率。

题目要求:编写一个闹钟程序,启动时设置定时间,到时间后打印一句: “时间到”,然后程序退出

老师程序:
def alarm(h,m):
while True:
#一直循环的得到当前时间
t=time.localtime()
print(“%02d:%02d:%02d”%t[3:6],end=’\r’)
if h==t[3] and m==t[4]: #if (h,m)==t[3:5]:看两个元组是否相等
print(“\n时间到”)
break
time.sleep(1)#降低cpu占有率
hour=int(input(“请输入定时小时”))
minute=int(input(“请输入定时分钟”))
alarm(hour,minute)

#include <reg51.h> // 51单片机寄存器定义 #include <intrins.h> // 包含_nop_()等内部函数 #include <string.h> // 包含字符串操作函数 // 类型定义,简化代码书写 #define uint unsigned int #define uchar unsigned char // 引脚定义 - 明确各引脚功能和连接外设 sbit RS = P2^6; // LCD1602数据/命令选择端 (高电平:数据, 低电平:命令) sbit RW = P2^5; // LCD1602读/写选择端 (高电平:读, 低电平:写) sbit E = P2^7; // LCD1602使能信号 (下降沿有效) sbit shezhi_key = P3^0; // 设置按键 sbit add_key = P3^1; // 增加按键 sbit sub_key = P3^2; // 减少按键 sbit naozhong_key = P3^3; // 闹钟功能按键 sbit beep = P2^5; // 蜂鸣器控制 (低电平触发发声) sbit alarm_led = P2^2; // 报警LED指示灯 (低电平点亮) sbit DQ1 = P3^7; // DS18B20温度传感器数据引脚 // 串口通信相关变量 unsigned char xdata uart_buf[32]; // 串口接收缓冲区,xdata表示外部数据存储 unsigned char xdata uart_cnt = 0; // 串口接收字节计数器 bit uart_cmd_ready = 0; // 命令接收完成标志位 (1:接收完成) // 温度相关变量 bit temp_sfwfs = 0; // 温度显示方式标志 (0:摄氏度, 1:华氏度) unsigned char temp_zs = 0; // 温度整数部分 unsigned char temp_xs = 0; // 温度小数部分(0-5) unsigned int temp_update_count = 0; // 温度更新计数器 bit ng; // 温度正负标志位 (1:负温度, 0:正温度) // 温度小数转换表,用于将DS18B20的16进制小数转换为十进制 uchar code df_Table[]= {0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9}; uchar CurrentT = 0; // 当前温度整数部分 uchar Temp_Value[]={0x00,0x00}; // 存储从DS18B20读取的温度原始值(高8位和低8位) uchar Display_Digit[]={0,0,0,0};// 用于显示的温度数字分解 (百位、十位、个位、小数位) bit DS18B20_IS_OK = 1; // DS18B20传感器状态标志 (1:正常, 0:故障) // 时间期变量 unsigned int year = 2025; // 年份 unsigned char month = 8; // 月份 unsigned char day = 26; // 期 unsigned char week = 2; // 星期 (1=周一...7=周) unsigned char hour = 0; // 小时 unsigned char minute = 0; // 分钟 unsigned char second = 0; // 秒钟 bit UP = 0; // 显示更新标志位 (1:需要更新显示) // 闹钟相关变量 unsigned char alarm_hour = 9; // 闹钟小时设置 unsigned char alarm_minute = 20;// 闹钟分钟设置 bit alarm_flag = 0; // 闹钟显示标志 (0:显示正常时间, 1:显示闹钟时间) bit alarm_trigger = 0; // 闹钟触发标志 (1:到达闹钟时间) bit alarm_enabled = 1; // 闹钟使能标志 (1:开启, 0:关闭) bit alarm_en; // 闹钟使能状态备份(用于串口通信) // 设置相关变量 unsigned char setn = 0; // 设置项标识 (0:无设置, 1-6:时间设置, 8-9:闹钟设置) bit set_flag = 0; // 设置模式标志位 (1:进入设置模式) // 每月天数表(平年),2月为28天 unsigned char dayss_in_month[] = {31,28,31,30,31,30,31,31,30,31,30,31}; // 整点报时相关 bit hourly_chime_trigger = 0; // 整点报时触发标志 unsigned char last_hour = 0; // 上一小时记录,用于检测整点 // 温度异常判断参数 bit temp_abnormal = 0; // 温度异常标志 #define TEMP_HIGH_LIMIT 30 // 温度上限阈值(摄氏度) #define TEMP_LOW_LIMIT 10 // 温度下限阈值(摄氏度) /** * 毫秒级延时函数 * @param ms 延时时长(毫秒) * 注: 基于12MHz晶振校准 */ void delay_ms(unsigned int ms) { unsigned int i, j; for(i = 0; i < ms; i++) for(j = 0; j < 112; j++); // 循环次数对应约1ms延时 } /** * 微秒级延时函数 * @param us 延时时长(微秒) * 注: 基于12MHz晶振校准 */ void delay_us(unsigned char us) { unsigned char i; for(i = 0; i < us; i++) { // 8个_nop_()指令约为1us(12MHz下一个机器周期为1us) _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); } } /** * 短延时函数 * @param x 延时计数 */ void Delay(uint x) { while(--x); } /** * LCD1602写命令函数 * @param cmd 要写入的命令 */ void sentcmd(unsigned char cmd) { P0 = cmd; // 将命令字送到P0口(数据总线) RS = 0; // 命令模式(RS=0) RW = 0; // 写模式(RW=0) E = 1; // 产生使能高电平 _nop_();_nop_(); // 短暂延时,确保信号稳定 E = 0; // 产生下降沿,锁存命令 RW = 1; // 恢复RW为高电平 delay_ms(1); // 等待命令执行完成 } /** * LCD1602写数据函数 * @param dat 要写入的数据 */ void sentdata(unsigned char dat) { P0 = dat; // 将数据送到P0口(数据总线) RS = 1; // 数据模式(RS=1) RW = 0; // 写模式(RW=0) E = 1; // 产生使能高电平 _nop_();_nop_(); // 短暂延时,确保信号稳定 E = 0; // 产生下降沿,锁存数据 RW = 1; // 恢复RW为高电平 delay_ms(1); // 等待数据写入完成 } /** * 在LCD指定位置写入数据 * @param x 列位置(0-15) * @param y 行位置(0-1) * @param Data 要写入的数据 */ void W_lcd(unsigned char x,unsigned char y,unsigned char Data) { if (y == 0){ sentcmd(0x80 + x); // 第一行起始地址为0x80 } else { sentcmd(0xc0 + x); // 第二行起始地址为0xc0 } sentdata(Data); // 写入数据 } /** * LCD1602初始化函数 * 初始化显示模式、清除屏幕、设置光标等 */ void lcd_init() { delay_ms(20); // 等待LCD上电稳定 sentcmd(0x38); // 8位数据接口,2行显示,5×8点阵字符 delay_ms(5); sentcmd(0x38); // 重复设置,确保命令生效 delay_us(100); sentcmd(0x38); sentcmd(0x01); // 清屏命令 delay_ms(2); sentcmd(0x0c); // 开显示,关闭光标 delay_ms(1); sentcmd(0x06); // 字符不动,地址指针自动加1 delay_ms(1); } /** * 在LCD上显示字符串 * @param str 要显示的字符串 * @param start_addr 起始地址(0x80开始为第一行,0xc0开始为第二行) */ void lcd_display_str(unsigned char *str, unsigned char start_addr) { unsigned char i; sentcmd(start_addr); // 设置显示起始地址 delay_ms(1); // 循环显示字符,最多16个字符(一行) for(i = 0; i < 16 && str[i] != '\0'; i++) { sentdata(str[i]); delay_ms(1); } } /** * 清空LCD指定行 * @param line_addr 行地址(0x80:第一行,0xc0:第二行) */ void lcd_clear_line(unsigned char line_addr) { unsigned char i; sentcmd(line_addr); for(i = 0; i < 16; i++) { sentdata(' '); // 用空格填充整行 } } /** * 判断闰年 * @param y 年份 * @return 1:闰年,0:平年 */ bit is_leap_year(unsigned int y) { // 闰年规则:能被4整除且不能被100整除,或能被400整除 return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0); } /** * 获取当月天数 * @param y 年份 * @param m 月份 * @return 当月天数 */ unsigned char get_days_in_month(unsigned int y, unsigned char m) { if(m == 2 && is_leap_year(y)) return 29; // 闰年2月有29天 else return dayss_in_month[m-1]; // 其他情况使用预定义表 } /** * 温度异常报警处理 * 当温度不在正常范围时,蜂鸣器和LED快速闪烁报警 */ void temp_alarm() { unsigned int i; // 快速闪烁200次 for(i = 0; i < 200; i++) { beep = 0; // 蜂鸣器响 alarm_led = 0; // LED亮 delay_ms(1); // 持续1ms beep = 1; // 蜂鸣器停 alarm_led = 1; // LED灭 delay_ms(1); // 间隔1ms } temp_abnormal = 0; // 清除异常标志 alarm_led = 1; // 确保LED最终关闭 beep = 1; // 确保蜂鸣器最终关闭 } /** * 闹钟响铃处理 * 到达设定时间时,蜂鸣器响铃,可通过任意按键停止 */ void alarm_broadcast() { unsigned int count = 0; unsigned int loop; // 响铃循环,直到按键或超时 while(1) { // 蜂鸣器快速响200次 for(loop = 0; loop < 200; loop++) { beep = 0; // 蜂鸣器响 delay_ms(1); // 持续1ms beep = 1; // 蜂鸣器停 delay_ms(1); // 间隔1ms // 检测按键,任何按键都可停止闹钟 if(shezhi_key == 0 || add_key == 0 || sub_key == 0 || naozhong_key == 0) { delay_ms(10); // 消抖 if(shezhi_key == 0 || add_key == 0 || sub_key == 0 || naozhong_key == 0) { beep = 1; // 停止蜂鸣器 // 等待按键释放 while(shezhi_key == 0 || add_key == 0 || sub_key == 0 || naozhong_key == 0); alarm_trigger = 0; // 清除闹钟触发标志 return; } } } count++; // 约30秒后自动停止(每次循环约400ms,75次≈30秒) if(count >= 75) { break; } } beep = 1; // 确保蜂鸣器停止 alarm_trigger = 0; // 清除闹钟触发标志 } /** * 整点报时处理 * 每到整点时,蜂鸣器根据当前小时数报时相应次数 */ void hourly_chime() { unsigned char i, count; unsigned int j; // 计算报时次数(1-12次) count = hour % 12; if(count == 0) count = 12; // 0点和12点报12次 for(i = 0; i < count; i++) // 循环报时 { // 蜂鸣器响200次 for(j = 0; j < 200; j++) { beep = 0; // 蜂鸣器响 delay_ms(1); // 持续1ms beep = 1; // 蜂鸣器停 delay_ms(1); // 间隔1ms } // 每次报时间隔500ms delay_ms(500); } hourly_chime_trigger = 0; // 清除整点报时标志 } /** * 将数字转换为两位字符串 * @param num 要转换的数字(0-99) * @param str 存储转换结果的缓冲区 */ void num_to_str(unsigned char num, unsigned char *str) { str[0] = num / 10 + '0'; // 十位数字 str[1] = num % 10 + '0'; // 个位数字 str[2] = '\0'; // 字符串结束符 } /** * 按键处理函数 * 处理所有按键的短按和长按操作 */ void key_process() { // 闹钟键处理:短按切换显示模式,长按切换闹钟开关 if(naozhong_key == 0) { unsigned int press_time = 0; // 等待按键释放,同时计时 while(naozhong_key == 0) { delay_ms(10); press_time++; if(press_time > 50) // 长按500ms以上 { alarm_enabled = !alarm_enabled; // 切换闹钟开关状态 alarm_en = alarm_enabled; // 同步到串口变量 UP = 1; // 设置显示更新标志 break; } } // 短按(小于500ms)切换显示模式 if(press_time <= 50) { alarm_flag = !alarm_flag; // 切换闹钟显示状态 set_flag = 0; // 退出设置模式 setn = 0; // 清除设置项 sentcmd(0x0c); // 关闭光标 lcd_clear_line(0xC0); // 清空第二行 UP = 1; // 设置显示更新标志 } } // 设置键处理:短按进入/切换设置项,长按退出设置 if(shezhi_key == 0) { unsigned int press_time = 0; // 等待按键释放,同时计时 while(shezhi_key == 0) { delay_ms(10); press_time++; // 长按500ms以上,退出设置模式 if(press_time > 50) { set_flag = 0; setn = 0; sentcmd(0x0c); // 关闭光标 UP = 1; // 等待按键释放 while(shezhi_key == 0); return; } } // 短按(500ms以内)处理 if(press_time > 0 && press_time <= 50) { if(set_flag == 0) // 未在设置模式,进入设置 { set_flag = 1; // 根据当前显示模式选择初始设置项 setn = (alarm_flag == 1) ? 8 : 1; sentcmd(0x0e); // 打开光标(闪烁) } else // 已在设置模式,切换设置项 { if(alarm_flag == 1) // 闹钟设置模式 { setn++; if(setn > 9) setn = 8; // 在8和9之间循环 } else // 时间设置模式 { setn = (setn % 6) + 1; // 在1-6之间循环 } } UP = 1; // 设置显示更新标志 } } // 加键处理:在设置模式下增加数值 if(add_key == 0 && set_flag == 1) { delay_ms(10); // 按键消抖 if(add_key == 0) { if(alarm_flag == 0) // 时间设置模式 { switch(setn) { case 1: second = (second + 1) % 60; break; // 秒加1 case 2: minute = (minute + 1) % 60; break; // 分加1 case 3: hour = (hour + 1) % 24; break; // 时加1 case 4: // 期加1,处理进位 day++; if(day > get_days_in_month(year, month)) { day = 1; month++; if(month > 12) { month = 1; year++; } } week = (week % 7) + 1; break; // 星期加1 case 5: // 月份加1,处理进位 month = (month % 12) + 1; // 调整期(如从31号到小月) if(day > get_days_in_month(year, month)) day = get_days_in_month(year, month); break; case 6: // 年份加1 year++; // 调整期(如闰年变平年) if(day > get_days_in_month(year, month)) day = get_days_in_month(year, month); break; } } else // 闹钟设置模式 { switch(setn) { case 8: alarm_minute = (alarm_minute + 1) % 60; break; // 闹钟分钟加1 case 9: alarm_hour = (alarm_hour + 1) % 24; break; // 闹钟小时加1 } } UP = 1; // 设置显示更新标志 while(add_key == 0); // 等待按键释放 } } // 减键处理:在设置模式下减少数值 if(sub_key == 0 && set_flag == 1) { delay_ms(10); // 按键消抖 if(sub_key == 0) { if(alarm_flag == 0) // 时间设置模式 { switch(setn) { case 1: // 秒减1 second = (second == 0) ? 59 : second - 1; break; case 2: // 分减1 minute = (minute == 0) ? 59 : minute - 1; break; case 3: // 时减1 hour = (hour == 0) ? 23 : hour - 1; break; case 4: // 期减1,处理借位 if(day == 1) { month--; if(month == 0) { month = 12; year--; } day = get_days_in_month(year, month); } else day--; // 星期减1 week = (week == 1) ? 7 : week - 1; break; case 5: // 月份减1,处理借位 month = (month == 1) ? 12 : month - 1; // 调整期 if(day > get_days_in_month(year, month)) day = get_days_in_month(year, month); break; case 6: // 年份减1 year--; // 调整期 if(day > get_days_in_month(year, month)) day = get_days_in_month(year, month); break; } } else // 闹钟设置模式 { switch(setn) { case 8: // 闹钟分钟减1 alarm_minute = (alarm_minute == 0) ? 59 : alarm_minute - 1; break; case 9: // 闹钟小时减1 alarm_hour = (alarm_hour == 0) ? 23 : alarm_hour - 1; break; } } UP = 1; // 设置显示更新标志 while(sub_key == 0); // 等待按键释放 } } } /** * 初始化DS18B20温度传感器 * @return 初始化状态(1:失败,0:成功) */ uchar Init_DS18B20() { uchar status; DQ1 = 1; // 初始拉高总线 Delay(8); // 延时约8us DQ1 = 0; // 拉低总线,发送复位脉冲 Delay(90); // 延时约90us DQ1 = 1; // 释放总线 Delay(8); // 等待8us status = DQ1; // 读取存在脉冲(0:成功,1:失败) Delay(100); // 延时约100us DQ1 = 1; // 拉高总线 return status; } /** * 从DS18B20读取一个字节数据 * @return 读取到的字节 */ uchar ReadOneByte() { uchar i,dat=0; DQ1 = 1; // 初始拉高总线 _nop_(); for(i=0;i<8;i++) // 循环8次,读取8位 { DQ1 = 0; // 拉低总线,产生读时序 dat >>= 1; // 数据右移一位 DQ1 = 1; // 释放总线 _nop_();_nop_(); if(DQ1) // 读取总线状态 dat |= 0X80; // 最高位置1 Delay(30); // 延时约30us DQ1 = 1; // 拉高总线 } return dat; } /** * 向DS18B20写入一个字节数据 * @param dat 要写入的字节 */ void WriteOneByte(uchar dat) { uchar i; for(i=0;i<8;i++) // 循环8次,写入8位 { DQ1 = 0; // 拉低总线,产生写时序 DQ1 = dat & 0x01; // 写入最低位 Delay(5); // 延时约5us DQ1 = 1; // 拉高总线 dat >>= 1; // 数据右移一位 } } /** * 读取DS18B20温度数据 */ void Read_Temperature() { EA=0; // 关闭总中断,防止干扰温度读取 if(Init_DS18B20()==1) DS18B20_IS_OK=0; // 传感器初始化失败 else { WriteOneByte(0xcc); // 发送跳过ROM命令 WriteOneByte(0x44); // 发送温度转换命令 Init_DS18B20(); // 重新初始化 WriteOneByte(0xcc); // 跳过ROM命令 WriteOneByte(0xbe); // 读取温度命令 Temp_Value[0] = ReadOneByte(); // 读取温度低8位 Temp_Value[1] = ReadOneByte(); // 读取温度高8位 DS18B20_IS_OK=1; // 传感器正常 } EA=1; // 恢复总中断 } /** * 处理温度数据,转换为十进制并判断是否异常 */ void Display_Temperature() { uchar t = 150; ng = 0; // 默认温度为正 // 判断温度是否为负数(DS18B20的符号位判断) if((Temp_Value[1]&0xf8)==0xf8) { // 负数处理:取补码 Temp_Value[1] = ~Temp_Value[1]; Temp_Value[0] = ~Temp_Value[0]+1; if(Temp_Value[0]==0x00) Temp_Value[1]++; ng = 1; // 标记为负温度 } else{ ng = 0; // 标记为正温度 } // 处理温度小数部分 Display_Digit[0] = df_Table[Temp_Value[0]&0x0f]; // 处理温度整数部分 CurrentT = ((Temp_Value[0]&0xf0)>>4) | ((Temp_Value[1]&0x07)<<4); // 分解温度数字,便于显示 Display_Digit[3] = CurrentT/100; // 百位 Display_Digit[2] = CurrentT%100/10; // 十位 Display_Digit[1] = CurrentT%10; // 个位 // 温度异常判断:负温度或超出范围 if(ng || CurrentT > TEMP_HIGH_LIMIT || CurrentT < TEMP_LOW_LIMIT) { temp_abnormal = 1; } else { temp_abnormal = 0; // 温度正常 } } /** * 在LCD上显示温度状态 */ void show_temp_status() { if(!DS18B20_IS_OK) { W_lcd(15, 1, 'E'); // 传感器错误显示"E" } else if(temp_abnormal) { W_lcd(15, 1, '!'); // 温度异常显示"!" } else { W_lcd(15, 1, 'C'); // 温度正常显示"C"(摄氏度) } } /** * 初始化串口通信 * 配置为9600波特率,8位数据,1位停止位,无校验 */ void UART_Init() { SCON = 0x50; // 串口工作方式1(8位UART),允许接收 TMOD |= 0x20; // 定时器1工作方式2(8位自动重装) TH1 = 0xFD; // 9600波特率初值(12MHz晶振) TL1 = 0xFD; TR1 = 1; // 启动定时器1 EA = 1; // 开总中断 ES = 1; // 开串口中断 } /** * 串口发送一个字符 * @param dat 要发送的字符 */ void UART_SendChar(unsigned char dat) { SBUF = dat; // 将数据放入发送缓冲区 while(!TI); // 等待发送完成 TI = 0; // 清除发送完成标志 } /** * 串口发送字符串 * @param str 要发送的字符串(常量字符串) */ void UART_SendString(unsigned char code *str) reentrant { while(*str != '\0') // 循环发送直到字符串结束 { UART_SendChar(*str++); } } /** * 串口发送温度数据 * 格式: T:+xx.xC\r\n 或 T:-xx.xC\r\n */ void UART_SendTemperature() { UART_SendString("T:"); if(ng == 1) UART_SendChar('-'); // 负温度符号 UART_SendChar(Display_Digit[2] + '0'); // 十位 UART_SendChar(Display_Digit[1] + '0'); // 个位 UART_SendChar('.'); // 小数点 UART_SendChar(Display_Digit[0] + '0'); // 小数位 UART_SendString("C\r\n"); // 单位和换行 } /** * 解析串口命令 * 目前仅处理温度查询命令 */ void ParseUARTCommand() { // 处理温度查询命令 if(strncmp(uart_buf, "GETTEMP", 7) == 0) { UART_SendTemperature(); } } //串口中断服务函数 //处理串口接收数据 void UART_ISR() interrupt 4 { unsigned char ch; if(RI) // 接收中断标志 { RI = 0; // 清除接收标志 ch = SBUF; // 读取接收数据 // 检测回车换行符,判断命令结束 if(ch == '\r' || ch == '\n') { if(uart_cnt > 0) { uart_buf[uart_cnt] = '\0'; // 添加字符串结束符 uart_cmd_ready = 1; // 设置命令就绪标志 uart_cnt = 0; // 重置计数器 } } // 接收数据并存储到缓冲区 else if(uart_cnt < sizeof(uart_buf)-1) { uart_buf[uart_cnt++] = ch; } } } //初始化定时器0 //配置为16位定时器,1ms中断一次 void timer0_init() { TMOD &= 0xF0; // 清除定时器0配置 TMOD |= 0x01; // 定时器0工作方式1(16位) TH0 = 0xFC; // 初值设置(1ms溢出) TL0 = 0x66; ET0 = 1; // 允许定时器0中断 EA = 1; // 允许总中断 TR0 = 1; // 启动定时器0 } // 定时器0中断服务程序 //1ms触发一次,用于时间计数和定时任务 void timer0_isr() interrupt 1 { static unsigned int count = 0; // 1ms计数器 static unsigned int uart_report_cnt = 0; // 串口上报计数器 TH0 = 0xFC; // 重装载初值(1ms) TL0 = 0x66; count++; if(count >= 1000) // 每1000ms(1秒)执行一次 { count = 0; temp_update_count++; // 每1秒设置显示更新标志 if(temp_update_count >= 1) { temp_update_count = 0; UP = 1; } if(set_flag == 0) // 非设置模式才更新时间 { second++; if(second >= 60) // 秒进位 { second = 0; minute++; if(minute >= 60) // 分进位 { minute = 0; hour++; // 检测整点,触发报时 if(hour != last_hour) { last_hour = hour; if(minute == 0 && second == 0) { hourly_chime_trigger = 1; } } if(hour >= 24) // 时进位 { hour = 0; day++; week++; if(week > 7) week = 1; // 星期循环 // 期进位处理 if(day > get_days_in_month(year, month)) { day = 1; month++; if(month > 12) // 月进位 { month = 1; year++; // 年进位 } } } } } // 检测是否到达闹钟时间 if(alarm_enabled && hour == alarm_hour && minute == alarm_minute && second == 0) { alarm_trigger = 1; } UP = 1; // 设置显示更新标志 } } // 每3秒通过串口上报一次温度 uart_report_cnt++; if(uart_report_cnt >= 3000) // 3秒(3000ms) { uart_report_cnt = 0; UART_SendTemperature(); // 发送温度数据 } } //主函数 //系统初始化和主循环 void main() { unsigned char i=0; unsigned char str_date[17]; // 期显示字符串 unsigned char str_time[17]; // 时间/闹钟显示字符串 unsigned char buf[4]; // 数字转换缓冲区 unsigned char week_str[4]; // 星期字符串 // 初始化IO口为高电平 P0 = 0xFF; P2 = 0xFF; P3 = 0xFF; lcd_init(); // 初始化LCD1602 timer0_init(); // 初始化定时器0 UART_Init(); // 初始化串口通信 beep = 1; // 蜂鸣器初始不响 alarm_led = 1; // 报警LED初始关闭 last_hour = hour; alarm_en = alarm_enabled; // 同步闹钟使能状态 // 初始化温度传感器(多次读取确保稳定) Read_Temperature(); delay_ms(500); Read_Temperature(); delay_ms(500); Read_Temperature(); delay_ms(500); // 主循环 while(1) { key_process(); // 按键处理 // 闹钟触发处理 if(alarm_trigger) { alarm_broadcast(); } // 整点报时处理 if(hourly_chime_trigger) { hourly_chime(); } // 温度异常报警处理 if(temp_abnormal) { temp_alarm(); } // 处理串口命令 if(uart_cmd_ready) { ParseUARTCommand(); uart_cmd_ready = 0; } if(UP) // 需要更新显示 { UP = 0; memset(str_time, 0, sizeof(str_time)); // 清空时间字符串 // 显示时间/闹钟 if(alarm_flag == 0) // 正常模式:显示时间和温度 { // 构建时间字符串 HH:MM:SS num_to_str(hour, buf); strcpy(str_time, buf); strcat(str_time, ":"); num_to_str(minute, buf); strcat(str_time, buf); strcat(str_time, ":"); num_to_str(second, buf); strcat(str_time, buf); // 每3秒更新一次温度 i++; if(i>2) { Read_Temperature(); // 读取温度 if(DS18B20_IS_OK) { Display_Temperature(); // 处理温度数据 } i=0; } // 显示温度符号(正/负) if(ng==1) W_lcd(10,1,'-'); else W_lcd(10,1,' '); // 显示温度值 W_lcd(11,1,Display_Digit[2]+'0'); // 十位 W_lcd(12,1,Display_Digit[1]+'0'); // 个位 W_lcd(13,1,'.'); // 小数点 W_lcd(14,1,Display_Digit[0]+'0'); // 小数位 // 显示温度状态 show_temp_status(); } else // 闹钟模式:显示闹钟时间 { strcpy(str_time, "N Z:"); num_to_str(alarm_hour, buf); strcat(str_time, buf); strcat(str_time, ":"); num_to_str(alarm_minute, buf); strcat(str_time, buf); // 显示闹钟开关状态 strcat(str_time, " "); if(alarm_enabled) strcat(str_time, "ON ZJ"); // 闹钟开启 else strcat(str_time, "OFF"); // 闹钟关闭 } // 构建期字符串 num_to_str(year % 100, buf); strcpy(str_date, "20"); strcat(str_date, buf); strcat(str_date, "/"); num_to_str(month, buf); strcat(str_date, buf); strcat(str_date, "/"); num_to_str(day, buf); strcat(str_date, buf); strcat(str_date, " "); // 转换星期为字符串 switch(week) { case 1: strcpy(week_str, "Mon"); break; case 2: strcpy(week_str, "Tue"); break; case 3: strcpy(week_str, "Wed"); break; case 4: strcpy(week_str, "Thu"); break; case 5: strcpy(week_str, "Fri"); break; case 6: strcpy(week_str, "Sat"); break; case 7: strcpy(week_str, "Sun"); break; default: strcpy(week_str, "---"); break; } strcat(str_date, week_str); // 输出到LCD显示 lcd_display_str(str_date, 0x80); // 第一行显示期 lcd_display_str(str_time, 0xC0); // 第二行显示时间/闹钟 // 设置光标位置(设置模式) if(setn != 0) { if(alarm_flag == 0) // 时间设置模式 { switch(setn) { case 1: sentcmd(0xC0 + 7); break; // 秒位置 case 2: sentcmd(0xC0 + 4); break; // 分位置 case 3: sentcmd(0xC0 + 1); break; // 时位置 case 4: sentcmd(0x80 + 9); break; // 位置 case 5: sentcmd(0x80 + 6); break; // 月位置 case 6: sentcmd(0x80 + 3); break; // 年位置 } } else // 闹钟设置模式 { switch(setn) { case 8: sentcmd(0xC0 + 8); break; // 闹钟分钟位置 case 9: sentcmd(0xC0 + 5); break; // 闹钟小时位置 } } } } delay_ms(10); // 主循环延时,降低CPU占用 } }添加代码 通过上位机串口助手修改时间和闹钟
最新发布
09-04
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值