首页 > 代码库 > SmartOS之(C++)------硬件定时器类Timer
SmartOS之(C++)------硬件定时器类Timer
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 else129 return new Timer(g_Timers[index]);130 }131 132 void Timer::Start()133 {134 #if DEBUG135 // 获取当前频率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 #endif146 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 #endif150 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 #endif206 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 #endif211 #ifdef STM32F4212 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 #endif219 #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 #endif225 }226 }227 228 // 设置预分频目标,比如1MHz229 /*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 #endif251 252 assert_param(frequency > 0 && frequency <= clk);253 254 uint s = 1;255 uint p = s / frequency;256 257 uint pre = clk / s; // prescaler258 259 //while (pre >= 0x10000 || p == 0) { // prescaler 太大260 // 周期刚好为1也不行,配置的时候需要先减去1,就变成了0261 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 timer269 while (p >= 0x10000) { // period too large270 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 else304 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群: 智能硬件群
SmartOS之(C++)------硬件定时器类Timer
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。