首页 > 代码库 > 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