SmartOS之(C++)------硬件定时器类Timer
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了SmartOS之(C++)------硬件定时器类Timer,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8187字,纯文字阅读大概需要12分钟。
内容图文
SmartOS (C++)的硬件定时器驱动,兼容STM32F0/F1/F4/GD32F10x/GD32F1x0
头文件
1 #ifndef __Timer_H__ 2 #define __Timer_H__ 3 4 #include "Sys.h" 5 6// 定时器 7class Timer 8{ 9private: 10 TIM_TypeDef* _port; 11byte _index; // 第几个定时器,从0开始 12volatilebool _started; // 可能在中断里关闭自己 13 14void ClockCmd(bool state); 15public: 16 Timer(TIM_TypeDef* timer); 17 ~Timer(); 18 19ushort Prescaler; // 预分频。实际值,此时无需减一。默认预分配到1MHz 20uint Period; // 周期。实际值,此时无需减一。默认1000个周期 21 22void Start(); // 开始定时器 23void Stop(); // 停止定时器 24//void SetScaler(uint scaler); // 设置预分频目标,比如1MHz 25void SetFrequency(uint frequency); // 设置频率,自动计算预分频 26 27void Register(EventHandler handler, void* param = NULL); 28 29private: 30void OnInterrupt(); 31staticvoid OnHandler(ushort num, void* param); 32 EventHandler _Handler; 33void* _Param; 34 35public: 36static Timer** Timers; // 已经实例化的定时器对象 37staticconstbyte TimerCount; // 定时器个数 38 39static Timer* Create(byte index = 0xFF); // 创建指定索引的定时器,如果已有则直接返回,默认0xFF表示随机分配 40}; 41 42#endif源码实现 43 44 #include "Timer.h" 45 46static TIM_TypeDef* const g_Timers[] = TIMS; 47 Timer** Timer::Timers = NULL; 48constbyte Timer::TimerCount = ArrayLength(g_Timers); 49 50 Timer::Timer(TIM_TypeDef* timer) 51{ 52 assert_param(timer); 53 54// 初始化静态数组 55if(!Timers) 56 { 57 Timers = new Timer*[TimerCount]; 58 ArrayZero2(Timers, TimerCount); 59 } 60 61//TIM_TypeDef* g_Timers[] = TIMS; 62byte idx = 0xFF; 63for(int i=0; i<ArrayLength(g_Timers); i++) 64 { 65if(g_Timers[i] == timer) 66 { 67 idx = i; 68break; 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{ 91if(_started) Stop(); 92 93if(_Handler) Register(NULL); 94 95 Timers[_index] = NULL; 96} 97 98// 创建指定索引的定时器,如果已有则直接返回,默认0xFF表示随机分配 99 Timer* Timer::Create(byte index) 100{ 101// 特殊处理随机分配102if(index == 0xFF) 103 { 104// 初始化静态数组105if(!Timers) 106 { 107 Timers = new Timer*[TimerCount]; 108 ArrayZero2(Timers, TimerCount); 109 } 110111// 找到第一个可用的位置,没有被使用,并且该位置定时器存在112byte i = 0; 113for(; i<TimerCount && (Timers[i] || !g_Timers[i]); i++); 114115if(i >= TimerCount) 116 { 117 debug_printf("Timer::Create 失败!没有空闲定时器可用!\r\n"); 118return NULL; 119 } 120121 index = i; 122 } 123124 assert_param(index < TimerCount); 125126if(Timers[index]) 127return Timers[index]; 128else129returnnew Timer(g_Timers[index]); 130} 131132void Timer::Start() 133{ 134#if DEBUG 135// 获取当前频率136 RCC_ClocksTypeDef clock; 137 RCC_GetClocksFreq(&clock); 138139#if defined(STM32F1) || defined(STM32F4) 140uint clk = clock.PCLK1_Frequency; 141if((uint)_port & 0x00010000) clk = clock.PCLK2_Frequency; 142 clk <<= 1; 143#elif defined(STM32F0) 144uint clk = clock.PCLK_Frequency << 1; 145#endif146147uint fre = clk / Prescaler / Period; 148 debug_printf("Timer%d::Start Prescaler=%d Period=%d Frequency=%d\r\n", _index + 1, Prescaler, Period, fre); 149#endif150151// 打开时钟152 ClockCmd(true); 153154// 关闭。不再需要,跟上面ClockCmd的效果一样 155//TIM_DeInit(_port); 156157// 配置时钟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); 165166// 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); 175176 _started = true; 177} 178179void Timer::Stop() 180{ 181if(!_started) return; 182183 debug_printf("Timer%d::Stop\r\n", _index + 1); 184185// 关闭时钟186 ClockCmd(false); 187 TIM_ITConfig(_port, TIM_IT_Update, DISABLE); 188 TIM_ClearITPendingBit(_port, TIM_IT_Update); // 仅清除中断标志位 关闭不可靠189 TIM_Cmd(_port, DISABLE); 190191 _started = false; 192} 193194void Timer::ClockCmd(bool state) 195{ 196 FunctionalState st = state ? ENABLE : DISABLE; 197switch(_index + 1) 198 { 199case1: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, st); break; 200case2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, st); break; 201case3: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, st); break; 202#if defined(STM32F1) && defined(STM32F4) 203case4: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, st); break; 204case5: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, st); break; 205#endif206case6: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, st); break; 207#if defined(STM32F1) && defined(STM32F4) 208case7: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, st); break; 209case8: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, st); break; 210#endif211#ifdef STM32F4 212case9: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, st); break; 213case10: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, st); break; 214case11: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11, st); break; 215case12: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12, st); break; 216case13: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, st); break; 217case14: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, st); break; 218#endif219#if defined(STM32F0) 220case14: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, st); break; 221case15: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, st); break; 222case16: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, st); break; 223case17: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM17, st); break; 224#endif225 } 226} 227228// 设置预分频目标,比如1MHz229/*void Timer::SetScaler(uint scaler) 230{ 231 assert_param(scaler); 232233 uint ps = Sys.Clock / scaler; 234 assert_param(ps > 0 && ps <= 0xFFFF); 235}*/236237// 设置频率,自动计算预分频238void Timer::SetFrequency(uint frequency) 239{ 240// 获取当前频率241 RCC_ClocksTypeDef clock; 242 RCC_GetClocksFreq(&clock); 243244#if defined(STM32F1) || defined(STM32F4) 245uint clk = clock.PCLK1_Frequency; 246if((uint)_port & 0x00010000) clk = clock.PCLK2_Frequency; 247 clk <<= 1; 248#elif defined(STM32F0) 249uint clk = clock.PCLK_Frequency << 1; 250#endif251252 assert_param(frequency > 0 && frequency <= clk); 253254uint s = 1; 255uint p = s / frequency; 256257uint pre = clk / s; // prescaler 258259//while (pre >= 0x10000 || p == 0) { // prescaler 太大 260// 周期刚好为1也不行,配置的时候需要先减去1,就变成了0261while (pre >= 0x10000 || p <= 1) { // prescaler 太大262if (p >= 0x80000000) return; 263 s *= 10; 264 pre /= 10; 265 p = s / frequency; 266 } 267268if (_index+1 != 2 && _index+1 != 5) { // 16 bit timer269while (p >= 0x10000) { // period too large270if (pre > 0x8000) return; 271 pre <<= 1; 272 p >>= 1; 273 } 274 } 275276 Prescaler = pre; 277 Period = p; 278279// 如果已启动定时器,则重新配置一下,让新设置生效280if(_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} 291292void Timer::Register(EventHandler handler, void* param) 293{ 294 _Handler = handler; 295 _Param = param; 296297int irqs[] = TIM_IRQns; 298if(handler) 299 { 300 Interrupt.SetPriority(irqs[_index], 1); 301 Interrupt.Activate(irqs[_index], OnHandler, this); 302 } 303else304 Interrupt.Deactivate(irqs[_index]); 305} 306307void Timer::OnHandler(ushort num, void* param) 308{ 309 Timer* timer = (Timer*)param; 310if(timer) timer->OnInterrupt(); 311} 312313void Timer::OnInterrupt() 314{ 315// 检查指定的 TIM 中断发生316if(TIM_GetITStatus(_port, TIM_IT_Update) == RESET) return; 317// 必须清除TIMx的中断待处理位,否则会频繁中断318 TIM_ClearITPendingBit(_port, TIM_IT_Update); 319320if(_Handler) _Handler(this, _Param); 321 }
End!
欢迎大家一起交流 ,分享程序员励志故事。 幸福的程序员 QQ群: 智能硬件群
原文:http://www.cnblogs.com/1hua1ye/p/4220369.html
内容总结
以上是互联网集市为您收集整理的SmartOS之(C++)------硬件定时器类Timer全部内容,希望文章能够帮你解决SmartOS之(C++)------硬件定时器类Timer所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。