上期为大家介绍串口这个重要工具,这期为大家介绍一下Coretx-M3的滴答时钟,
也就是大家常说的Systemtick,此外还用TIM2的PWM控制RGB做个简单的demo。
问题一,什么是滴答时钟?
所有的 Coretx-M3以下简称CM3 芯片都带有这个定时器,软件在不同芯片生产厂商的 CM3 器件间的移植工作就得以化简。 该定时器的时钟源可以是内部时钟( FCLK, CM3 上的自由运行时钟),或者是外部时钟(CM3 处理器上的 STCLK 信号)。不过, STCLK 的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同。因此,需要阅读芯片的使用手册来确定选择什么作为时钟源。下图就是STM32F10xx系列的时钟树图,了解下
问题二,为啥要使用滴答时钟?
操作系统和有所有使用了时基的系统,都必须要一个硬件定时器来产生需要的“滴答”中断,作为整个系统的时基。滴答中断对操作系统尤其重要。例如,操作系统可以为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。Cortex-M3 在内核部分 包含了一个简单的定时器——SysTick timer。说了这么多,同学们如果想深入了解systicktimer,可以参阅《 CortexM3 权威指南》,里面有深入讲解。
****************************************完美分割线**********************************************************************
1.初始化systick,我这边是1ms进一次中断,
- void bsp_InitSysTick(void)
- {
- /* SystemFrequency / 1000 1ms 进一次中断
- * SystemFrequency / 100000 10us 进一次中断
- * SystemFrequency / 1000000 1us 进一次中断
- */
- if (SysTick_Config(SystemCoreClock / 1000))
- {
- /* Capture error */
- while (1);
- }
- }
- static __IO uint32_t TimingDelay;
************************************完美分割线**********************************************************************
下面说下RGB三色灯的驱动原理,实现让LED模块呈现不同的颜色,主要依靠人的视觉间歇惰性原理,利用对R、G、B三原色的LED的占空比实现颜色的混合。PWM Dimming (脉宽调制),是LED最佳的灰度调节方式。PWM说的容易理解些,就是控制LED开和关的时间比例,将开和关的时间比例划分为若干等级,LED就会显示出相应数量的灰阶。
uFun硬件上面控制RGB3个PIN是PA0,PA1,PA2也就是TIM2的CH1,CH2,CH3通道,
所以我们先初始化TIM2的PWM三个通道,频率定位1KHz
- void RGB_Init(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
- //TIM2 clock enable
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- TIM_TimeBaseStructure.TIM_Period = 1000; //1ms
- TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //TIM_OCPolarity_High
- TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_Low;
- TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
- TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
- TIM_OCInitStructure.TIM_Pulse = 0;
- TIM_OC1Init(TIM2, &TIM_OCInitStructure);
- TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
- TIM_OCInitStructure.TIM_Pulse = 0;
- TIM_OC2Init(TIM2, &TIM_OCInitStructure);
- TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
- TIM_OCInitStructure.TIM_Pulse = 0;
- TIM_OC3Init(TIM2, &TIM_OCInitStructure);
- TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
- TIM_ARRPreloadConfig(TIM2, ENABLE);
- TIM_Cmd(TIM2, ENABLE);
- TIM_CtrlPWMOutputs(TIM2, ENABLE);
- }
- void RGB_Control(unsigned int r_pwm, unsigned int g_pwm, unsigned int b_pwm)
- {
- if (r_pwm >= 1000)
- r_pwm = 1000;
- if (g_pwm >= 1000)
- g_pwm = 1000;
- if (b_pwm >= 1000)
- b_pwm = 1000;
- TIM2->CCR1 = g_pwm; //b_pwm
- TIM2->CCR2 = r_pwm;
- TIM2->CCR3 = b_pwm; //g_pwm
- }
全部回复 4
- 122 主题
- 342 帖子
- 4759 积分
身份:LV5 资深技术员
E币:744
发消息
沙发自己坐
whik 发表于 2019-3-25 20:29
哈哈,写的不错嘛!systick能再详细介绍一下就更好了,一直搞不懂这个定时器到底是怎么定时的?公众号关注 ...
最近公司项目比较忙,公众号也是最近才有的想法,慢慢会丰富起来的,你的公众号我也关注了,一起学习交流。