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         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群:  智能硬件群
时间: 2024-10-26 16:29:47

SmartOS之(C++)------硬件定时器类Timer的相关文章

Java多线程基础(二)定时器类:Timer类和TimerTask类

Java多线程基础(二)定时器类:Timer类和TimerTask类 Timer类和TimerTask类是jdk实现定时器功能的早期方法,jdk1.5以前就支持Timer类和TimerTask类.JDK1.5之后引入了新的机制,将在后续博文中研究. 1 指定时间间隔后执行任务 import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class TraditionalTimerTest {

自定义定时器(Timer)

最近做项目的时候,用到了java.util.Timer定时器类,也初步使用了,个人感觉不错.不过,在某些方面Timer类无法满足项目的需求,比如,在使用Timer时,调用schedule()方法之后(初始化),其循环周期无法改变,只有调用cancel()方法之后再重新启动才能将循环周期改变. 自己自定义了一个定时器线程,可开启.可关闭.可动态的改变循环周期,具体代码如下: /** * @ClassName: MyTimer * @Description: TODO 自定义定时器类 * @auth

自己定义定时器(Timer)

近期做项目的时候,用到了java.util.Timer定时器类.也初步使用了,个人感觉不错.只是,在某些方面Timer类无法满足项目的需求.比方,在使用Timer时,调用schedule()方法之后(初始化),其循环周期无法改变,仅仅有调用cancel()方法之后再又一次启动才干将循环周期改变. 自己自己定义了一个定时器线程,可开启.可关闭.可动态的改变循环周期.详细代码例如以下: /** * @ClassName: MyTimer * @Description: TODO 自己定义定时器类 *

java定时任务类Timer和TimerTask用法详解

原文:java定时任务类Timer和TimerTask用法详解 代码下载地址:http://www.zuidaima.com/share/1550463277550592.htm package com.zuidaima.util; import java.io.IOException; import java.util.Timer; import test.MyTask; /* * 本类给出了使用Timer和TimerTaske的主要方法,其中包括定制任务,添加任务 * 退出任务,退出定时器.

WinForm LED循环显示信息,使用定时器Threading.Timer

原文:WinForm LED循环显示信息,使用定时器Threading.Timer 这里用一个示例来演示timer如何使用.示例:LED屏幕显示描述:这个示例其实很简单,LED屏幕上显示3个信息:        1:排队叫号         2:催缴费         3:等待列表.因为LED屏幕大小的关系,列表需要分页显示. 正常情况下,这3个信息都需要从服务器上去获得,这里的示例只做简单的模拟, 界面很简单,如图,这里我就不美化了. Timer构造函数参数说明: Callback:一个 Ti

Spring mvc 在一个定时器类里实现多个定时器任务

1.新建一个定时器配置文件,这里叫spring-task.xml,内容如下: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context=&

QT学习笔记(14) 定时器类DTimer的使用

一. 在前面的学习笔记中,我们已经学习定时器事件http://www.cnblogs.com/blog-ccs/p/7445323.html 现在,我们学习QTimer定时器类,比较优劣. 二.示例代码 widget.h 1 #ifndef WIDGET_H 2 #define WIDGET_H 3 4 #include <QWidget> 5 #include <QTimer>//定时器对象 6 7 namespace Ui { 8 class Widget; 9 } 10 11

SmartOS之(C++)------输入输出端口类Port

SmartOS (C++)的GPIO驱动,兼容STM32F0/F1/F4/GD32F10x/GD32F1x0 头文件 1 #ifndef _Port_H_ 2 #define _Port_H_ 3 4 #include "Sys.h" 5 #include "ADC.h" 6 7 #ifdef STM32F4 8 #define GPIO_MAX_SPEED 100 9 #else 10 #define GPIO_MAX_SPEED 50 11 #endif 12

C# 定时器 Timers.Timer Forms.Timer

1.定义在System.Windows.Forms里 Windows.Forms里面的定时器比较简单,只要把工具箱中的Timer控件拖到窗体上,然后设置一下事件和间隔时间等属性就可以了 //启动定时器 private void button1_Click(object sender, EventArgs e)        {            timer1.Tick += new EventHandler(timer1_Tick);//执行的方法            timer1.Ena