SmartOS (C++)的硬件定时器驱动,兼容STM32F0/F1/F4/GD32F10x/GD32F1x0
头文件
1 #ifndef __Timer_H__ 2 #define __Timer_H__ 3 4 #include "Sys.h" 5 6 // 定时器 7 class Timer 8 { 9 private: 10 TIM_TypeDef* _port; 11 byte _index; // 第几个定时器,从0开始 12 volatile bool _started; // 可能在中断里关闭自己 13 14 void ClockCmd(bool state); 15 public: 16 Timer(TIM_TypeDef* timer); 17 ~Timer(); 18 19 ushort Prescaler; // 预分频。实际值,此时无需减一。默认预分配到1MHz 20 uint Period; // 周期。实际值,此时无需减一。默认1000个周期 21 22 void Start(); // 开始定时器 23 void Stop(); // 停止定时器 24 //void SetScaler(uint scaler); // 设置预分频目标,比如1MHz 25 void SetFrequency(uint frequency); // 设置频率,自动计算预分频 26 27 void Register(EventHandler handler, void* param = NULL); 28 29 private: 30 void OnInterrupt(); 31 static void OnHandler(ushort num, void* param); 32 EventHandler _Handler; 33 void* _Param; 34 35 public: 36 static Timer** Timers; // 已经实例化的定时器对象 37 static const byte TimerCount; // 定时器个数 38 39 static Timer* Create(byte index = 0xFF); // 创建指定索引的定时器,如果已有则直接返回,默认0xFF表示随机分配 40 }; 41 42 #endif源码实现 43 44 #include "Timer.h" 45 46 static TIM_TypeDef* const g_Timers[] = TIMS; 47 Timer** Timer::Timers = NULL; 48 const byte Timer::TimerCount = ArrayLength(g_Timers); 49 50 Timer::Timer(TIM_TypeDef* timer) 51 { 52 assert_param(timer); 53 54 // 初始化静态数组 55 if(!Timers) 56 { 57 Timers = new Timer*[TimerCount]; 58 ArrayZero2(Timers, TimerCount); 59 } 60 61 //TIM_TypeDef* g_Timers[] = TIMS; 62 byte idx = 0xFF; 63 for(int i=0; i<ArrayLength(g_Timers); i++) 64 { 65 if(g_Timers[i] == timer) 66 { 67 idx = i; 68 break; 69 } 70 } 71 assert_param(idx <= ArrayLength(g_Timers)); 72 73 Timers[idx] = this; 74 75 _index = idx; 76 _port = g_Timers[idx]; 77 78 // 默认情况下,预分频到1MHz,然后1000个周期,即是1ms中断一次 79 /*Prescaler = Sys.Clock / 1000000; 80 Period = 1000;*/ 81 SetFrequency(10); 82 83 _started = false; 84 85 _Handler = NULL; 86 _Param = NULL; 87 } 88 89 Timer::~Timer() 90 { 91 if(_started) Stop(); 92 93 if(_Handler) Register(NULL); 94 95 Timers[_index] = NULL; 96 } 97 98 // 创建指定索引的定时器,如果已有则直接返回,默认0xFF表示随机分配 99 Timer* Timer::Create(byte index) 100 { 101 // 特殊处理随机分配 102 if(index == 0xFF) 103 { 104 // 初始化静态数组 105 if(!Timers) 106 { 107 Timers = new Timer*[TimerCount]; 108 ArrayZero2(Timers, TimerCount); 109 } 110 111 // 找到第一个可用的位置,没有被使用,并且该位置定时器存在 112 byte i = 0; 113 for(; i<TimerCount && (Timers[i] || !g_Timers[i]); i++); 114 115 if(i >= TimerCount) 116 { 117 debug_printf("Timer::Create 失败!没有空闲定时器可用!\r\n"); 118 return NULL; 119 } 120 121 index = i; 122 } 123 124 assert_param(index < TimerCount); 125 126 if(Timers[index]) 127 return Timers[index]; 128 else 129 return new Timer(g_Timers[index]); 130 } 131 132 void Timer::Start() 133 { 134 #if DEBUG 135 // 获取当前频率 136 RCC_ClocksTypeDef clock; 137 RCC_GetClocksFreq(&clock); 138 139 #if defined(STM32F1) || defined(STM32F4) 140 uint clk = clock.PCLK1_Frequency; 141 if((uint)_port & 0x00010000) clk = clock.PCLK2_Frequency; 142 clk <<= 1; 143 #elif defined(STM32F0) 144 uint clk = clock.PCLK_Frequency << 1; 145 #endif 146 147 uint fre = clk / Prescaler / Period; 148 debug_printf("Timer%d::Start Prescaler=%d Period=%d Frequency=%d\r\n", _index + 1, Prescaler, Period, fre); 149 #endif 150 151 // 打开时钟 152 ClockCmd(true); 153 154 // 关闭。不再需要,跟上面ClockCmd的效果一样 155 //TIM_DeInit(_port); 156 157 // 配置时钟 158 TIM_TimeBaseInitTypeDef _timer; 159 TIM_TimeBaseStructInit(&_timer); 160 _timer.TIM_Period = Period - 1; 161 _timer.TIM_Prescaler = Prescaler - 1; 162 //_timer.TIM_ClockDivision = 0x0; 163 _timer.TIM_CounterMode = TIM_CounterMode_Up; 164 TIM_TimeBaseInit(_port, &_timer); 165 166 // TIM_PrescalerConfig(_port, _timer.TIM_Period,TIM_PSCReloadMode_Immediate); // 分频数立即加载 167 // 打开中断 168 //TIM_ITConfig(_port, TIM_IT_Update | TIM_IT_Trigger, ENABLE); 169 TIM_ITConfig(_port, TIM_IT_Update, ENABLE); 170 //TIM_UpdateRequestConfig(_port, TIM_UpdateSource_Regular); 171 TIM_ClearFlag( _port, TIM_FLAG_Update ); // 清楚标志位 必须要有!! 否则 开启中断立马中断给你看 172 // TIM_ClearITPendingBit(_port, TIM_IT_Update); 173 // 打开计数 174 TIM_Cmd(_port, ENABLE); 175 176 _started = true; 177 } 178 179 void Timer::Stop() 180 { 181 if(!_started) return; 182 183 debug_printf("Timer%d::Stop\r\n", _index + 1); 184 185 // 关闭时钟 186 ClockCmd(false); 187 TIM_ITConfig(_port, TIM_IT_Update, DISABLE); 188 TIM_ClearITPendingBit(_port, TIM_IT_Update); // 仅清除中断标志位 关闭不可靠 189 TIM_Cmd(_port, DISABLE); 190 191 _started = false; 192 } 193 194 void Timer::ClockCmd(bool state) 195 { 196 FunctionalState st = state ? ENABLE : DISABLE; 197 switch(_index + 1) 198 { 199 case 1: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, st); break; 200 case 2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, st); break; 201 case 3: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, st); break; 202 #if defined(STM32F1) && defined(STM32F4) 203 case 4: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, st); break; 204 case 5: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, st); break; 205 #endif 206 case 6: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, st); break; 207 #if defined(STM32F1) && defined(STM32F4) 208 case 7: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, st); break; 209 case 8: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, st); break; 210 #endif 211 #ifdef STM32F4 212 case 9: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, st); break; 213 case 10: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, st); break; 214 case 11: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11, st); break; 215 case 12: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12, st); break; 216 case 13: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, st); break; 217 case 14: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, st); break; 218 #endif 219 #if defined(STM32F0) 220 case 14: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, st); break; 221 case 15: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, st); break; 222 case 16: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, st); break; 223 case 17: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM17, st); break; 224 #endif 225 } 226 } 227 228 // 设置预分频目标,比如1MHz 229 /*void Timer::SetScaler(uint scaler) 230 { 231 assert_param(scaler); 232 233 uint ps = Sys.Clock / scaler; 234 assert_param(ps > 0 && ps <= 0xFFFF); 235 }*/ 236 237 // 设置频率,自动计算预分频 238 void Timer::SetFrequency(uint frequency) 239 { 240 // 获取当前频率 241 RCC_ClocksTypeDef clock; 242 RCC_GetClocksFreq(&clock); 243 244 #if defined(STM32F1) || defined(STM32F4) 245 uint clk = clock.PCLK1_Frequency; 246 if((uint)_port & 0x00010000) clk = clock.PCLK2_Frequency; 247 clk <<= 1; 248 #elif defined(STM32F0) 249 uint clk = clock.PCLK_Frequency << 1; 250 #endif 251 252 assert_param(frequency > 0 && frequency <= clk); 253 254 uint s = 1; 255 uint p = s / frequency; 256 257 uint pre = clk / s; // prescaler 258 259 //while (pre >= 0x10000 || p == 0) { // prescaler 太大 260 // 周期刚好为1也不行,配置的时候需要先减去1,就变成了0 261 while (pre >= 0x10000 || p <= 1) { // prescaler 太大 262 if (p >= 0x80000000) return; 263 s *= 10; 264 pre /= 10; 265 p = s / frequency; 266 } 267 268 if (_index+1 != 2 && _index+1 != 5) { // 16 bit timer 269 while (p >= 0x10000) { // period too large 270 if (pre > 0x8000) return; 271 pre <<= 1; 272 p >>= 1; 273 } 274 } 275 276 Prescaler = pre; 277 Period = p; 278 279 // 如果已启动定时器,则重新配置一下,让新设置生效 280 if(_started) 281 { 282 TIM_TimeBaseInitTypeDef _timer; 283 TIM_TimeBaseStructInit(&_timer); 284 _timer.TIM_Period = Period - 1; 285 _timer.TIM_Prescaler = Prescaler - 1; 286 //_timer.TIM_ClockDivision = 0x0; 287 _timer.TIM_CounterMode = TIM_CounterMode_Up; 288 TIM_TimeBaseInit(_port, &_timer); 289 } 290 } 291 292 void Timer::Register(EventHandler handler, void* param) 293 { 294 _Handler = handler; 295 _Param = param; 296 297 int irqs[] = TIM_IRQns; 298 if(handler) 299 { 300 Interrupt.SetPriority(irqs[_index], 1); 301 Interrupt.Activate(irqs[_index], OnHandler, this); 302 } 303 else 304 Interrupt.Deactivate(irqs[_index]); 305 } 306 307 void Timer::OnHandler(ushort num, void* param) 308 { 309 Timer* timer = (Timer*)param; 310 if(timer) timer->OnInterrupt(); 311 } 312 313 void Timer::OnInterrupt() 314 { 315 // 检查指定的 TIM 中断发生 316 if(TIM_GetITStatus(_port, TIM_IT_Update) == RESET) return; 317 // 必须清除TIMx的中断待处理位,否则会频繁中断 318 TIM_ClearITPendingBit(_port, TIM_IT_Update); 319 320 if(_Handler) _Handler(this, _Param); 321 }
End!
欢迎大家一起交流 ,分享程序员励志故事。 幸福的程序员 QQ群: 智能硬件群