SmartOS (C++)的GPIO驱动,兼容STM32F0/F1/F4/GD32F10x/GD32F1x0
头文件
1 #ifndef __WatchDog_H__ 2 #define __WatchDog_H__ 3 4 #include "Sys.h" 5 6 // 看门狗 7 class WatchDog 8 { 9 private: 10 11 public: 12 WatchDog(uint ms = 3000); 13 ~WatchDog(); 14 15 uint Timeout; // 当前超时时间 16 17 bool Config(uint ms); // 配置看门狗喂狗重置时间,超过该时间讲重启MCU 18 void ConfigMax(); // 看门狗无法关闭,只能设置一个最大值 19 void Feed(); // 喂狗 20 }; 21 22 #endif源码实现 23 24 #include "WatchDog.h" 25 26 /* 27 独立看门狗IWDG——有独立时钟(内部低速时钟LSI---40KHz),所以不受系统硬件影响的系统故障探测器。主要用于监视硬件错误。 28 窗口看门狗WWDG——时钟与系统相同。如果系统时钟不走了,这个狗也就失去作用了,主要用于监视软件错误。 29 30 独立看门狗 31 看门狗定时时限=IWDG_SetReload()的值 / 看门狗时钟频率 32 看门狗时钟频率=LSI(内部低速时钟)的频率(40KHz)/ 分频数 33 34 独立看门狗(IWDG)由专用的40kHz的低速时钟为驱动。因此,即使主时钟发生故障它也仍然有效。 35 窗口看门狗由从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的行为。 36 IWDG_SetPrescaler() 分频,4~256 37 IWDG_SetReload() 计数值12位 0~0x0FFF 38 IWDG_ReloadCounter() 喂狗,必须在计数值减到1之前喂狗 39 40 IWDG_PR和IWDG_RLR寄存器具有写保护功能。要修改这两个寄存器的值,必须先向IWDG_KR寄存器中写入0x5555。 41 以不同的值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。重装载操作(即写入0xAAAA)也会启动写保护功能。 42 43 #define IWDG_WriteAccess_Enable ((uint16_t)0x5555) 44 #define IWDG_WriteAccess_Disable ((uint16_t)0x0000) 45 46 void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess) 47 { 48 assert_param(IS_IWDG_WRITE_ACCESS(IWDG_WriteAccess)); 49 IWDG->KR = IWDG_WriteAccess; 50 } 51 52 void IWDG_ReloadCounter(void) 53 { 54 IWDG->KR = KR_KEY_Reload; 55 } 56 void IWDG_Enable(void) 57 { 58 IWDG->KR = KR_KEY_Enable; 59 } 60 61 void IWDG_SetPrescaler(uint8_t IWDG_Prescaler) 62 { 63 assert_param(IS_IWDG_PRESCALER(IWDG_Prescaler)); 64 IWDG->PR = IWDG_Prescaler; 65 } 66 void IWDG_SetReload(uint16_t Reload) 67 { 68 assert_param(IS_IWDG_RELOAD(Reload)); 69 IWDG->RLR = Reload; 70 } 71 72 */ 73 74 WatchDog::WatchDog(uint ms) 75 { 76 Timeout = ms; 77 Config(ms); 78 } 79 80 WatchDog::~WatchDog() 81 { 82 ConfigMax(); 83 } 84 85 bool WatchDog::Config(uint ms) 86 { 87 if(ms == 0) 88 { 89 debug_printf("WatchDog msTimeout %dms must larger than 0ms\r\n", ms); 90 return false; 91 } 92 RCC_LSICmd(ENABLE); 93 /* 检查系统是否从IWDG重置恢复 */ 94 if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET) 95 { 96 /* 清除重置标识 */ 97 RCC_ClearFlag(); 98 } 99 /* 打开IWDG_PR和IWDG_RLR寄存器的写访问 */ 100 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); 101 102 byte pre = IWDG_Prescaler_4; 103 int mul = 4; 104 // 计数器12位 0~0x0FFF,有reload = ms/1000 / (1/(LSI/mul)) = ms * LSI / (mul*1000) = ms * 40 / mul 105 // 考虑到reload溢出的可能,每种分频最大ms = reload * mul / 40 ~= 102 * mul 106 int i=0; 107 /* 108 #define IWDG_Prescaler_4 ((uint8_t)0x00) 109 #define IWDG_Prescaler_8 ((uint8_t)0x01) 110 #define IWDG_Prescaler_16 ((uint8_t)0x02) 111 #define IWDG_Prescaler_32 ((uint8_t)0x03) 112 #define IWDG_Prescaler_64 ((uint8_t)0x04) 113 #define IWDG_Prescaler_128 ((uint8_t)0x05) 114 #define IWDG_Prescaler_256 ((uint8_t)0x06) 115 */ 116 for(i = IWDG_Prescaler_4; i <= IWDG_Prescaler_256; i++) 117 { 118 pre = i; 119 mul = 1 << (i + 2); 120 121 // 判断是否在范围之内 122 if(ms * 40 / mul < 0x0FFF) break; 123 } 124 if(i > IWDG_Prescaler_256) 125 { 126 debug_printf("WatchDog msTimeout must smaller than %dms\r\n", 0x0FFF * 256 / 40); 127 return false; 128 } 129 IWDG_SetPrescaler(pre); 130 /*if(ms < (0x0FFF * 32 / 40)) 131 { 132 // IWDG计数器时钟: LSI/32=40KHz/32=1250Hz,每周期0.8ms 133 IWDG_SetPrescaler(IWDG_Prescaler_32); 134 } 135 else 136 { 137 // IWDG计数器时钟: LSI/64=40KHz/64=625Hz,每周期0.4ms 138 IWDG_SetPrescaler(IWDG_Prescaler_64); 139 140 // 直接除以2,后面不用重复计算 141 ms >>= 2; 142 }*/ 143 144 /* 设置计数器重载值为超时时间 145 Counter Reload Value = ms / 1000 / IWDG计数器时钟周期 146 = ms / 1000 / (1/(LSI/mul)) 147 = ms * LSI / (mul * 1000) 148 = ms * 40k / (mul * 1000) 149 = ms * 40 / mul 150 */ 151 IWDG_SetReload(ms * 40 / mul); 152 153 /* 重载 IWDG 计数器 */ 154 IWDG_ReloadCounter(); 155 156 /* 打开 IWDG (LSI将由硬件打开) */ 157 IWDG_Enable(); 158 159 Timeout = ms; 160 161 return true; 162 } 163 164 void WatchDog::ConfigMax() 165 { 166 /* 打开IWDG_PR和IWDG_RLR寄存器的写访问 */ 167 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); 168 169 // 独立看门狗无法关闭 170 IWDG_SetPrescaler(IWDG_Prescaler_256); 171 IWDG_SetReload(0x0FFF); 172 IWDG_ReloadCounter(); 173 } 174 175 void WatchDog::Feed() 176 { 177 IWDG_ReloadCounter(); 178 }
End!
欢迎大家一起交流 ,分享程序员励志故事。 幸福的程序员 QQ群:
智能硬件群![中国嵌入式物联网群 中国嵌入式物联网群](http://img.e-com-net.com/image/product/671be750a3924cddb913d7a29d79b718.png)