枚举IO_TIMER计时器

前提:

1。首先你得了解什么是IO_TIMER计时器

不了解的话可以去看一下《Windows驱动开发详解》第10章

2。你得会简单驱动的编写

不了解的话还是可以看一下《windows驱动开发详解》,或是参照网上的教程,开发环境是拦路虎,搭好了,再跟着书上例子,慢慢来,以及多网上查阅

3。你得清楚我的实验环境是在32bit-XP SP3下,因此我这儿的情况可能并不适用你那儿,但是走走流程还是有必要的



正文:1【编程创建一个IO定时器】

【1】首先你得利用IoCreateDevice 创建一个设备对象

NTSTATUS IoCreateDevice(
  _In_     PDRIVER_OBJECT  DriverObject,
  _In_     ULONG           DeviceExtensionSize,
  _In_opt_ PUNICODE_STRING DeviceName,
  _In_     DEVICE_TYPE     DeviceType,
  _In_     ULONG           DeviceCharacteristics,
  _In_     BOOLEAN         Exclusive,
  _Out_    PDEVICE_OBJECT  *DeviceObject
);

nt!_DEVICE_OBJECT
   +0x000 Type             : Int2B
   +0x002 Size             : Uint2B
   +0x004 ReferenceCount   : Int4B
   +0x008 DriverObject     : Ptr32 _DRIVER_OBJECT
   +0x00c NextDevice       : Ptr32 _DEVICE_OBJECT
   +0x010 AttachedDevice   : Ptr32 _DEVICE_OBJECT
   +0x014 CurrentIrp       : Ptr32 _IRP
   +0x018 Timer            : Ptr32 _IO_TIMER
   +0x01c Flags            : Uint4B
   +0x020 Characteristics  : Uint4B
   +0x024 Vpb              : Ptr32 _VPB
   +0x028 DeviceExtension  : Ptr32 Void
   +0x02c DeviceType       : Uint4B
   +0x030 StackSize        : Char
   +0x034 Queue            : __unnamed
   +0x05c AlignmentRequirement : Uint4B
   +0x060 DeviceQueue      : _KDEVICE_QUEUE
   +0x074 Dpc              : _KDPC
   +0x094 ActiveThreadCount : Uint4B
   +0x098 SecurityDescriptor : Ptr32 Void
   +0x09c DeviceLock       : _KEVENT
   +0x0ac SectorSize       : Uint2B
   +0x0ae Spare1           : Uint2B
   +0x0b0 DeviceObjectExtension : Ptr32 _DEVOBJ_EXTENSION
   +0x0b4 Reserved         : Ptr32 Void

偏移0X18处的Timer 类型显示的是 Ptr32 _IO_TIMER,这个后面有关联的地方的,得注意一下
nt!_IO_TIMER
   +0x000 Type             : Int2B
   +0x002 TimerFlag        : Int2B
   +0x004 TimerList        : _LIST_ENTRY
   +0x00c TimerRoutine     : Ptr32     void 
   +0x010 Context          : Ptr32 Void
&nbs
#include "stm32f4xx.h" // Device header #include "systick.h" #include "io_bit.h" // 按键引脚定义,假设接在 GPIOA 的 PA0 #define KEY_GPIO_PORT GPIOA #define KEY_GPIO_PIN GPIO_Pin_0 #define KEY_GPIO_CLK RCC_AHB1Periph_GPIOA // 风扇控制引脚,假设接在 GPIOB 的 PB0 #define FAN_GPIO_PORT GPIOB #define FAN_GPIO_PIN GPIO_Pin_0 #define FAN_GPIO_CLK RCC_AHB1Periph_GPIOB // 继电器控制引脚,假设接在 GPIOB 的 PB1 #define RELAY_GPIO_PORT GPIOB #define RELAY_GPIO_PIN GPIO_Pin_1 #define RELAY_GPIO_CLK RCC_AHB1Periph_GPIOB // LCD 显示相关,需包含对应 LCD 驱动头文件,这里假设已有基础显示函数 //#include "lcd.h" // 按键状态枚举 typedef enum { KEY_STATE_IDLE, // 空闲状态 KEY_STATE_PRESSED, // 按下状态 KEY_STATE_RELEASED, // 0释放状态 KEY_STATE_LONG_PRESS, // 长按状态 KEY_STATE_DOUBLE_CLICK// 双击状态 } KeyState; KeyState key_state = KEY_STATE_IDLE; uint8_t key_press_flag = 0; // 按键按下标志 uint16_t key_press_time = 0; // 按键按下计时 uint16_t key_double_click_time = 0; // 双击检测计时 uint8_t key_double_click_flag = 0; // 双击标志 // 按键 GPIO 初始化 void Key1_Init(void) { GPIO_InitTypeDef gpio_config={0}; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); gpio_config.GPIO_Mode = GPIO_Mode_OUT; gpio_config.GPIO_Pin = GPIO_Pin_0; gpio_config.GPIO_Speed = GPIO_Speed_25MHz; gpio_config.GPIO_PuPd = GPIO_PuPd_NOPULL; gpio_config.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOA, &gpio_config); PAout(0)=1; } void Key2_Init(void) { GPIO_InitTypeDef gpio_config={0}; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); gpio_config.GPIO_Mode = GPIO_Mode_OUT; gpio_config.GPIO_Pin = GPIO_Pin_0; gpio_config.GPIO_Speed = GPIO_Speed_25MHz; gpio_config.GPIO_PuPd = GPIO_PuPd_NOPULL; gpio_config.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOB, &gpio_config); PBout(0)=1; } void Key3_Init(void) { GPIO_InitTypeDef gpio_config={0}; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); gpio_config.GPIO_Mode = GPIO_Mode_OUT; gpio_config.GPIO_Pin = GPIO_Pin_0; gpio_config.GPIO_Speed = GPIO_Speed_25MHz; gpio_config.GPIO_PuPd = GPIO_PuPd_NOPULL; gpio_config.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOB, &gpio_config); PBout(1)=1; } // 风扇 GPIO 初始化(输出) void Fan_GPIO_init(void) { GPIO_InitTypeDef gpio_config={0}; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); gpio_config.GPIO_Mode = GPIO_Mode_OUT; gpio_config.GPIO_Pin = GPIO_Pin_8; gpio_config.GPIO_Speed = GPIO_Speed_25MHz; gpio_config.GPIO_PuPd = GPIO_PuPd_NOPULL; gpio_config.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOC, &gpio_config); PCout(8) = 0; // 初始状态关闭 } // 继电器 GPIO 初始化(输出) void relay_init(void) { GPIO_InitTypeDef gpio_config={0}; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); gpio_config.GPIO_Mode = GPIO_Mode_OUT; gpio_config.GPIO_Pin = GPIO_Pin_0; gpio_config.GPIO_Speed = GPIO_Speed_25MHz; gpio_config.GPIO_PuPd = GPIO_PuPd_NOPULL; gpio_config.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOE, &gpio_config); PEout(0) = 0; // 初始状态关闭 } // 整体初始化,可在 main 函数开头调用 void Hardware_Init(void) { Key1_Init(); Key3_Init(); Key3_Init(); Fan_GPIO_init(); relay_init(); // beep_init(); // LCD_Init(); // 假设 LCD 初始化函数 } // 按键扫描(简易消抖,也可用定时器中断更精准消抖) uint8_t Key_Scan(void) { static uint8_t key_state = 1; uint8_t read_value = GPIO_ReadInputDataBit(KEY_GPIO_PORT, KEY_GPIO_PIN); if (read_value != key_state) { // delay_ms(10); // 消抖延时,需实现 delay_ms 函数 read_value = GPIO_ReadInputDataBit(KEY_GPIO_PORT, KEY_GPIO_PIN); if (read_value != key_state) { key_state = read_value; return key_state == 0 ? 1 : 0; // 按下返回 1,释放返回 0 } } return 0; } // 按键状态机处理,建议在定时器中断或主循环定时调用(如 10ms 一次) void Key_State_Machine_Process(void) { static uint8_t key_last_state = 1; uint8_t key_current_state = Key_Scan(); switch (key_state) { case KEY_STATE_IDLE: if (key_current_state == 1 && key_last_state == 0) // 检测到按键按下 { key_state = KEY_STATE_PRESSED; key_press_time = 0; key_double_click_flag = (key_double_click_time < 300) ? 1 : 0; // 双击判断,300ms 内第二次按下算双击 key_double_click_time = 0; } else if (key_double_click_flag) { key_state = KEY_STATE_DOUBLE_CLICK; // LCD_DisplayString(0, 0, "Double Click"); // LCD 显示双击状态,需适配 LCD 驱动函数参数 key_double_click_flag = 0; } break; case KEY_STATE_PRESSED: key_press_time++; if (key_press_time > 100) // 长按判断,100*10ms=1s,可调整 { key_state = KEY_STATE_LONG_PRESS; // LCD_DisplayString(0, 0, "Long Press"); // LCD 显示长按状态 GPIO_SetBits(FAN_GPIO_PORT, FAN_GPIO_PIN); // 长按开风扇 } else if (key_current_state == 0 && key_last_state == 1) // 短按释放 { key_state = KEY_STATE_RELEASED; // LCD_DisplayString(0, 0, "Short Press"); // LCD 显示短按状态 GPIO_SetBits(RELAY_GPIO_PORT, RELAY_GPIO_PIN); // 短按开继电器 } break; case KEY_STATE_LONG_PRESS: if (key_current_state == 0 && key_last_state == 1) // 长按释放 { key_state = KEY_STATE_IDLE; GPIO_ResetBits(FAN_GPIO_PORT, FAN_GPIO_PIN); // 关闭风扇 } break; case KEY_STATE_RELEASED: key_state = KEY_STATE_IDLE; GPIO_ResetBits(RELAY_GPIO_PORT, RELAY_GPIO_PIN); // 关闭继电器 break; case KEY_STATE_DOUBLE_CLICK: key_state = KEY_STATE_IDLE; // 可扩展双击后动作,这里仅显示 break; default: key_state = KEY_STATE_IDLE; break; } if (key_double_click_flag) { key_double_click_time++; if (key_double_click_time > 300) // 超过 300ms 未第二次按下,清除双击标志 { key_double_click_flag = 0; } } key_last_state = key_current_state; } int main(void) { Hardware_Init(); while (1) { Key_State_Machine_Process(); // delay_ms(10); // 定时扫描,也可用定时器中断实现更精准时序 } } 题目十七:基于STM32F4按键设计 ·基本要求: (1)按键具有长按短按功能 (2)长按开风扇 (3)短按开继电器 (4)LCD显示状态 (5)加入状态机思想实现双击短按长按 必选元器件: (1)系统板蜂鸣器模块 (2)系统板按键模块 (3)LCD模组,作为一名高级工程师,用尽可能简洁修改代码完成题目要求,LCD模块暂时不配置
06-23
#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; // 按键按下时间计数器 // 时间结构体 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; // 使能高电平 _nop_(); // 短暂延时 _nop_(); _nop_(); EN = 0; // 使能下降沿触发 LCD_Delay(100); // 延时确保命令执行完成 } void LCD_WriteData(unsigned char dat) { RS = 1; // 数据模式 RW = 0; // 写操作 LCD_DATA = dat; EN = 1; // 使能高电平 _nop_(); _nop_(); _nop_(); EN = 0; // 使能下降沿触发 LCD_Delay(50); // 延时确保数据写入 } void LCD_Init() { // 上电后延时确保LCD稳定 LCD_Delay(20000); // 初始化序列 - 确保8位模式 LCD_WriteCmd(0x30); // 尝试设置为8位 LCD_Delay(5000); LCD_WriteCmd(0x30); // 再次发送 LCD_Delay(200); LCD_WriteCmd(0x30); // 第三次发送 LCD_Delay(200); // 正式设置 LCD_WriteCmd(0x38); // 8位数据,双行显示,5x8点阵 LCD_WriteCmd(0x0C); // 开显示,关光标 LCD_WriteCmd(0x06); // 增量不移位 LCD_WriteCmd(0x01); // 清屏 LCD_Delay(2000); // 清屏需要较长时间 } 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++); } } // 显示两位数字 void LCD_Show2Digit(unsigned char x, unsigned char y, unsigned char num) { if (y == 0) LCD_WriteCmd(0x80 + x); else LCD_WriteCmd(0xC0 + x); LCD_WriteData('0' + num / 10); // 十位 LCD_WriteData('0' + num % 10); // 个位 } // 显示三位数字 void LCD_Show3Digit(unsigned char x, unsigned char y, unsigned int num) { if (y == 0) LCD_WriteCmd(0x80 + x); else LCD_WriteCmd(0xC0 + x); LCD_WriteData('0' + num / 100); // 百位 LCD_WriteData('0' + (num / 10) % 10); // 十位 LCD_WriteData('0' + num % 10); // 个位 } // 显示温度值 void LCD_ShowTemp(unsigned char x, unsigned char y, float temp) { if (y == 0) LCD_WriteCmd(0x80 + x); else LCD_WriteCmd(0xC0 + x); if (temp < -50) { LCD_ShowStr(x, y, "--.-- C"); return; } unsigned int temp_int = (unsigned int)temp; unsigned int temp_frac = (unsigned int)((temp - temp_int) * 100); // 显示整数部分 if (temp_int < 10) { LCD_WriteData(' '); LCD_WriteData('0' + temp_int); } else { LCD_WriteData('0' + temp_int / 10); LCD_WriteData('0' + temp_int % 10); } LCD_WriteData('.'); LCD_WriteData('0' + temp_frac / 10); LCD_WriteData('0' + temp_frac % 10); LCD_WriteData(' '); LCD_WriteData('C'); } // 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() { switch(display_state) { case 0: // 日期信息 LCD_ShowStr(0, 0, "Date:20"); LCD_Show2Digit(7, 0, current_time.year); LCD_WriteData('-'); LCD_Show2Digit(10, 0, current_time.month); LCD_WriteData('-'); LCD_Show2Digit(13, 0, current_time.day); break; case 1: // 时间信息 LCD_ShowStr(0, 0, "Time: "); LCD_Show2Digit(6, 0, current_time.hour); LCD_WriteData(':'); LCD_Show2Digit(9, 0, current_time.minute); LCD_WriteData(':'); LCD_Show2Digit(12, 0, current_time.second); break; case 2: // 温度信息 LCD_ShowStr(0, 0, "Temp: "); LCD_ShowTemp(6, 0, DS18B20_GetTemp()); break; case 3: // 闹钟设置 LCD_ShowStr(0, 0, "Alarm:"); if (setting_mode && blink) { // 闪烁状态 - 当前设置位置显示空格 switch(setting_pos) { case 0: // 小时闪烁 LCD_WriteData(' '); LCD_WriteData(' '); LCD_WriteData(':'); LCD_Show2Digit(10, 0, alarm_m); LCD_WriteData(':'); LCD_Show2Digit(13, 0, alarm_s); break; case 1: // 分钟闪烁 LCD_Show2Digit(7, 0, alarm_h); LCD_WriteData(':'); LCD_WriteData(' '); LCD_WriteData(' '); LCD_WriteData(':'); LCD_Show2Digit(13, 0, alarm_s); break; case 2: // 秒钟闪烁 LCD_Show2Digit(7, 0, alarm_h); LCD_WriteData(':'); LCD_Show2Digit(10, 0, alarm_m); LCD_WriteData(':'); LCD_WriteData(' '); LCD_WriteData(' '); break; } } else { // 正常显示 LCD_Show2Digit(7, 0, alarm_h); LCD_WriteData(':'); LCD_Show2Digit(10, 0, alarm_m); LCD_WriteData(':'); LCD_Show2Digit(13, 0, alarm_s); } break; case 4: // 倒计时设置 LCD_ShowStr(0, 0, "Timer:"); if (setting_mode && blink) { // 闪烁状态 LCD_ShowStr(7, 0, "--- min"); } else { // 正常显示 LCD_Show3Digit(7, 0, timer_minutes); LCD_ShowStr(10, 0, " min"); } 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; // 初始显示 LCD_ShowStr(0, 0, "Multifunction"); LCD_ShowStr(0, 1, "Clock Ready"); 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(&current_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; // 温度在显示函数中读取 } } } 请将这段简易多功能时钟程序变得更加简洁,删去不必要的程序
最新发布
06-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值