定时器TIM
STM32F1 系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级定时器。基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO。通用定时器 TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部 IO。高级定时器 TIM1/8是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有 8 个外部 IO。
基本定时器
-
时钟源
定时器时钟 TIMxCLK,即内部时钟 CK_INT,经 APB1 预分频器后分频提供,如果 APB1 预分频系数等于 1,则频率不变,否则频率乘以 2,库函数中 APB1 预分频的系数是 2,即 PCLK1=36M,所以定时器时钟 TIMxCLK=36*2=72M 。
-
计数器时钟
定时器时钟经过 PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数。PSC 是一个16 位的预分频器,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。
具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)。
-
计数器
计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
-
自动重装载寄存器
自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
-
定时时间的计算
定时器的定时时间等于计数器的中断周期乘以中断的次数。计数器在 CK_CNT 的驱动下,计一个数的时间则是 CK_CLK 的倒数,等于:1/(TIMxCLK/(PSC+1)),产生一次中断的时间则等于:1/(CK_CLK * ARR)。如果在中断服务程序里面设置一个变量 time,用来记录中断的次数,那么就可以计算出我们需要的定时时间等于: 1/CK_CLK *
(ARR+1)*time。
实验过程
创建工程
这里的时钟源选用是内部时钟源,这里的Prescaler配置的是分频系数,系统会自动加一,所以这里选择71;这里这个mode是计数模式,这里是向上计数的意思;counter period是计数周期,这里的意思是每计数到50000触发一次中断
然后更改一下这个
这里主要的作用就是利用高速外部时钟倍频出一个72M的时钟源
还要开启TIM的中断开关
中断优先级配置,根据工程需求自行配置
其余设置根据自身需求更改。
配置函数
在主函数添加
HAL_TIM_Base_Start_IT(&htim2);
来开启定时器TIM2
HAL库下每个中断源都有一个弱定义的中断回调函数,可以由用户进行自我改写
这里的中断回调函数为
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
不需要更改配置文件,在main中重写即可
这里的中断回调函数我设置的是每两秒翻转一次电平和每五秒发送一次数据给上位机
if(htim->Instance == TIM2)
{
if(++time_cnt >= 40)
{
time_cnt =0;
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);
}
if(++qw>=100)
{
qw=0;
HAL_UART_Transmit(&huart1,(uint8_t*)&ad,14,0xffff);
}
}
这里的两个计数变量需写为全局生效的变量,生存周期为整个函数
程序大致就是这样,但在实验中我遇到了一个问题。我使用的开发环境是stm32 cube ide,在编译完成以后我的hex经常没有更新。甚至于更新了但是实际内容没有发生变化。这里建议找不出问题所在的uu,把hex文件删除以后再重新生成一次,这样就没问题了。
PWM
pwm输出就是利用定时器,来控制输出方波信号的占空比,以此来形成pwm波
PWM输出模式
PWM输出就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装寄存
器 ARR的值决定,占空比由比较寄存器 CCR的值决定
1.PWM边沿对齐模式
在边沿对齐模式下,计数器 CNT 只工作在一种模式,递增或者递减模式。
2.PWM中心对齐模式
在中心对齐模式下,计数器 CNT 是工作做递增/递减模式下。开始的时候,计数器CNT从 0 开始计数到自动重载值减 1(ARR-1),生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从 0 开始重新计数。
程序配置
注意的是配置通道的话,核心板上对应的GPIO口要发生变化,其他配置同上
编写以及编译
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);
这个就是开启定时器以及对应的通道。
这里产生pwm波主要用的是HAL库下的
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_3,ss)
最后一个参数的意思是占空比,可根据自身需求更改占空比的变化规律。
这里pwm的输出口为PA1
这里很奇怪的是明明tim2,3,4都是通用寄存器,但是使用tim3,4不能完成呼吸灯的功能.这个问题我暂时不知道如何解决,就先使用tim2吧。