码迷,mamicode.com
首页 > 编程语言 > 详细

SmartOS之(C++)------硬件定时器类Timer

时间:2015-01-13 08:56:13      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:

 

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群:技术分享  智能硬件群技术分享

 

SmartOS之(C++)------硬件定时器类Timer

标签:

原文地址:http://www.cnblogs.com/1hua1ye/p/4220369.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!