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群:幸福的程序员 智能硬件群中国嵌入式物联网群

 

你可能感兴趣的:(timer)