前言
定时器是一种用于在指定时间间隔后执行特定任务的工具。它可以用于循环执行某个操作、定时触发事件或者周期性地执行任务。
定时器分别有三种类型:
-
基本定时器(Basic Timer):基本定时器也被称为独立定时器(Independent Timer)。是一个16 位的只能向上计数的定时器,只能定时,没有外部 IO。。
-
通用定时器(Generic Timer):通用定时器是一种基本的定时器。是一个16位可以向上、向下、中央定时的定时器,可以定时,输出比较,输入捕获。
-
高级定时器(Advanced Timer):高级定时器是一种更灵活和功能更强大的定时器。是一个16位可以向上、向下、中央定时的定时器,可以定时,输出比较,输入捕获,还有三相电机互补输出信号,相比于通用定时器功能更丰富更灵活性,精度和灵敏度也更高。
在stm32f103c8这个单片机上,有四个定时器,一个高级定时器TIM1,三个通用定时器TIM2~3。
输出比较
定时器输出比较最常见的就是输出PWM了,输出比较功能用于比较定时器的计数值与比较值,确定何时改变输出状态。PWM输出模式利用输出比较功能来控制脉冲的宽度,从而实现PWM输出占空比。
- 设置比较值(比如占空比),决定了PWM信号的脉冲宽度。
- 配置输出比较通道,将比较值与定时器计数值进行比较,并在达到或超过比较值时触发输出状态的改变。
PWM简介
PWM(Pulse Width Modulation)是一种调制脉冲宽度的技术,用于控制模拟信号的强度或数字设备的输出。PWM通过调整脉冲的占空比来实现对电压或功率的控制。在PWM中,一个周期被分成若干个等长的时间间隔,其中一个或多个时间间隔被称为脉冲。占空比是指脉冲时间与一个周期时间之比。通过调整脉冲的宽度和周期时间,可以控制输出信号的强度或设备的工作状态。
如下图,下面是PWM上面是对应的有效电压。电压幅度一样,占空比越大,表示的实时有效电压越大,最大100%占空比时,就是恒定的直流电。(此处严格来说,不能说实时和有效电压,便于理解的比喻)
工程配置
由规格书可知,TIM3是挂在APB1时钟线上的。打开时钟树,APB1 Timer的时钟频率是64MHz。现在切到配置页,开始配置TIM3。
为了方便,选择之前使用外设附近的IO口,PA5没有挂TIM通道,因此选择PA6 -> TIM3_CH1,此时选择完是黄色的,然后左边选择Timers -> 勾选Internal Clock -> Channel1 -> PWM Generation CH1,选择完通道功能后,右边模拟单片机的IO口就由黄转绿了。
PWM参数配置:
预分频:64-1
计数模式:向上计数
重装载值:1000-1
内部时钟再分频:不分频
自动重装载:使能
这里的64-1和1000-1之前嘀嗒计时器说过,因为64其实就是0~63,1000就是0~999,计算公式如下:
定时时间 = ((预分频 + 1) * (重装载值 + 1)) / 时钟频率
PWM只需要修改这几个参数就行了,别的可以不用管。
最后输出程序。
解释一下本次没有管的参数的意思:
Master/Slave Mode :用来选择定时器的主从模式。当设置为 "Disable" 时,一旦触发条件满足,定时器的触发输出将立即生成,而不会有任何延迟。
Trigger Event Selection:用于选择触发事件的类型。
Mode:表示PWM的工作模式。
PWM mode1表示PWM信号是上升沿对齐的,也就是说,PWM信号的高电平始终从周期的起始点开始。这意味着PWM信号的高电平时间是固定的,并且在每个周期内始终保持一致。只有在下一个周期开始时,PWM信号的高电平时间才会根据设定的占空比进行调整。
PWM mode 2下,通道1的PWM信号是下降沿对齐的,也就是说,PWM信号的高电平结束时会与周期的结束点对齐。这意味着PWM信号的高电平时间是可变的,并且在每个周期内根据设定的占空比进行动态调整。占空比表示高电平的时间占整个周期的比例,因此在PWM mode 2中,高电平时间与占空比直接相关。
说的我自己都蒙了,简单来说就是,模式1可以做到PWM的每个周期一样的,模式2每个周期都是变化的,但是占空比都是设定的占空比。
Pulse:是指定脉冲信号的占空比。它是一个16位的值,表示脉冲的高电平时间占整个周期的比例。根据这个值,定时器会自动调整脉冲的宽度。比如设置成6553,占空比=6553/65535=10%。因为此次实验中,占空比在程序中每时每刻都在改变,所以没有设置的必要。
Output compare preload:是指定脉冲的输出比较预装值。根据这个值,定时器会在每个周期的特定时间点上进行比较,并决定脉冲信号的输出。
Fast Mode:是指定定时器是否使用快速模式。快速模式可以提高PWM信号的更新速度和精度。
CH Polarity:是指定定时器的极性。它决定了脉冲信号的电平极性,是高电平占周期的比例还是低电平占周期的比例。
程序
PWM的相关函数都在这,老样子:Functions -> ...hal_tim.c,这里有关于tim的所有函数。用户用到的主要就是6个PWM开始和结束的函数, IT代表中断方式,DMA代表DMA方式。
首先,我们回到main.c文件,在TIM3初始化之后,添加PWM开始函数。
有示波器的可以用示波器检测,没有示波器的可以用LED灯观察(万物皆可点灯,单片机的起点是点灯,终点也是点灯/手动滑稽/狗头保命)。
这里我们使用LED直接观察。
可以根据使用led的导通条件,简单估算一下电量的电压值,然后根据使用的限流电阻计算一下LED分到的电压,可以更好地观察呼吸灯的情况。
*有效电压=占空比*3.3
*注if里面不要写反了,dir初始值为0,我这LED低电平电亮,刚开始没注意写反了,然后直接0xffff开始,等好久才亮。不过降下来之后就好了。最好是定义pwm_val的时候直接赋值在max到min之间。
uint16_t pwm_val; //占空比
uint16_t max_val = 0x400;
uint16_t min_val = 0x300
uint8_t dir; //占空比增减方向
while(1)
{
if(dir)
{
pwm_val--;
if(pwm_val<=min_val )
dir=0;
}
else
{
pwm_val++;
if(pwm_val>=max_val)
dir=1;
}
TIM3->CCR1 = pwm_val; //把pwm_val的值给到TIM3的1通道,修改TIM3的1通道的占空比。
delay_ms(7);
}
查规格书可知,CCR1为定时器比较寄存器的值,寄存器为16位,取值范围为0~0xffff,
TIM3->CCR1 = pwm_val;可以理解为,周期为65535份,高电平占pwm_val份。
如果不想使用寄存器想使用库函数,转到...hal_tim.h(刚刚的启动结束函数在.c),翻到1395行,如下所示,就是对CCR寄存器操作的库函数,
__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwm_val);
或者使用老版本HAL库的__HAL_TIM_SetCompare(),全局搜索__HAL_TIM_SET_COMPARE就能找到。