STM32使用定时器与PWM实现串口通信和点灯
文章目录
一、定时器介绍
1.定时器概念
(1)能够对内部时钟信号或外部输入信号进行计数,数值达到设定要求时,向CPU发起中断请求,完成外部程序的运行。
(2)本质就是进行计数,选择内部时钟脉冲,作为计数器时,技术信号的来源选择非周期脉冲信号。
(3)STM32中定时器可分为高级定时器、通用定时器、基本定时器三类,他们都是由一个可编程的16位预分频器(TIMX_PSC)驱动的16位。
(4)在大容量的 STM32F103xx增强型系列产品包含最多2个高级控制定时器、4个普通定时器和2个基本定时器,以及2个看门狗定时器和1个系统嘀嗒定时器,本次的目标芯片(STM32F103C8T6)也是大容量系列,所以具备以上所述的定时器种类
2.STM32定时器分类
定时器可分为3类:
(1)基本定时器:功能最少,只能充当基本的时基,甚至都没有外部引脚
(2)通用定时器:拥有基本定时器的全部功能,同时有输入捕获模式,用以接收外部的PWM,脉冲之类的信息
(3)高级定时器:又有通用定时器的全部功能,又有互补输出模式,功能最为强大
通常我们使用的都是通用定时器
通用定时器特点:
(1)位于ABP1低速总线上
(2)16位向下,向上/向下(中心对齐模式)计数模式,自动重装载计数器(TIMx_CNT)
(3)16位可编程(可以实现修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为1~65535任意数值
(4)四个独立通道(TIMx_CH1~4),通道用来支持:
①输入捕获
②输出比较
③PWM生成
④单脉冲模式输出
(5)可使用外部信号(TIM_ETR)控制定时器和定时器互连的同步电路
3.计数器模式
4.定时时钟计算方法
Tout = ((arr+1)(psc+1))/Tclk
其中:
Tclk:定时器的输入时钟频率(单位MHZ)
Tout:定时器溢出时间(单位为us)
arr: 计数装载值
psc: 时钟分频系数
二、通过定时器Timer方式实现串口通信和LED等周期性地闪烁
1.通过STM32CubeMX配置项目
(1) 实验过程





这里我们使用定时器2和定时器3来实现定时的功能。
如图所示,配置定时器2和定时器3的时钟源为内部时钟;分频系数为71,向上计数模式,计数周期为5000,使能自动重载模式。


如下图所示,开启定时器2和定时器3的中断。


基础参数:波特率为115200 Bits/s,传输数据长度为8 Bit。无校验位,1位停止位,接收和发送都使能。





2.结果运行
(1)代码修改
① 在int main() 中添加以下代码
该函数表示启动相应的定时器
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim3);
②在main函数中添加串口通信代码
在main.c中定义STM32需要给上位机发送的消息 “hello windows!”
uint8_t hello[20]="hello windows!\r\n";
③在main函数中添加以下代码
用于定时器中断回调
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static uint32_t time_cnt =0;
static uint32_t time_cnt3 =0;
if(htim->Instance == TIM2)
{
if(++time_cnt >= 400)
{
time_cnt =0;
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);
}
}
if(htim->Instance == TIM3)
{
if(++time_cnt3 >= 1000)
{
time_cnt3 =0;
HAL_UART_Transmit(&huart1,hello,20,100000);
}
}
}
例如:time_cnt,当它大于等于400的时候,才会执行if里面的代码。也就是说需要发生400次中断,才会让LED的状态翻转。前面已经算过了,一次定时中断的时间是0.005秒,所以400次中断的时间是0.005400=2秒。也就是说每隔2秒,LED的状态翻转一次。
例如:time_cnt3,当它大于等于1000的时候,才会执行if里面的代码。也就是说需要发生1000次中断,才会让串口发一次消息。0.0051000=5秒,符合题目要求。
(2)运行视频
三、PWM介绍
(1)定义
PWM(Pulse Width Modulation)即脉冲宽度调制,简称脉宽调制。它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术;它是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。
(2)基本原理
PWM就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。也可以这样理解,PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。只要带宽足够,任何模拟值都可以使用 PWM 进行编码。
该信号在预定义的时间和速度中设置为高(5v或3.3v)和低(0v)。通常,我们将PWM的高电平称为1,低电平为0。
(3)优点及应用范围
由于其控制简单、灵活和动态响应好等优点而成为电力电子技术应用最广泛的控制方式,其应用领域包括测量,通信, 功率控制与变换,电动机控制、伺服控制、调光、开关电源,甚至某些音频放大器,因此学习PWM具有十分重要的现实意义。
(4)主要参数
PWM信号保持高电平的时间百分比称为占空比。如果信号始终为高电平,则它处于100%占空比,如果它始终处于低电平,则占空比为0%。
PWM信号的频率决定PWM完成一个周期的速度。STM32的MDK编译器可以选择5MHZ,10MHZ,20MHZ和50MHZ。
(5)PWM的产生
STM32的定时器除了TIM6和7,其他的定时器都可以用来产生PWM输出。其中高级定时器TIM1和TIM8可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出。
通过STM32控制板,有两种方式能产生PWM,第一是利用普通IO口输出PWM,第二种是利用定时器的PWM的IO口或复用IO口。一般能够输出PWM的端口都会在主要功能那一栏出现CHx的标志,而普通定时器没有出现这种标志。如图所示,上面的红框就是普通的定时器,不是专用的PWM端口
注意:一般而言,尽量选用PWM口进行PWM输出,因为普通IO口模拟PWM的输出频率越高,进入定时器中断的次数就越快,中断间隔的时间越短,如果再有其他类型的中断也要处理时,会因为中断的优先级嵌套等待响应,影响控制精度,PWM输出误差增大,也会影响其他如ADC等中断处理,甚至会较出现单片机逻辑出错,死机或者跑飞的情况。
四、使用TIM3和TIM4实现2个LED呼吸灯
1.通过STM32CubeMX配置项目
(1) 实验过程




这里我们使用定时器3和定时器4来实现定时的功能。
如图所示,配置定时器3和定时器4的时钟源为内部时钟;分频系数为71,向上计数模式,计数周期为5000,使能自动重载模式。


基础参数:波特率为115200 Bits/s,传输数据长度为8 Bit。无校验位,1位停止位,接收和发送都使能。





2.结果运行
(1)代码修改
① 在main函数中设置占空比
定义一个变量,用来存储占空比:初值设为0
uint16_t duty_num3 = 0;
②在main函数中添加开启PWM信道代码
开启TIM3的通道3,输出PWM。
开启TIM4的通道4,输出PWM。
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
③在int main() 函数的while循环中添加以下代码
设置每隔200毫秒,进入while循环
当占空比小于5000(设置的PWM周期),占空比加10。(即灯会逐渐从亮到暗)
当占空比超过5000(设置的PWM周期),占空比减10。(即灯会逐渐从暗到亮)
HAL_Delay(200);
while (duty_num<5000)
{
duty_num = duty_num + 10;
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,duty_num);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_1,duty_num);
HAL_Delay(10);
}
while (duty_num)
{
duty_num = duty_num - 10;
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,duty_num);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_1,duty_num);
HAL_Delay(10);
}
(2)硬件连接
查询数据手册可发现定时器3,4的一通道分别对应引脚PA6,PB6
题目要求需要直接驱动PC13(最小开发板上已焊接的LED(固定接在 PC13 GPIO端口)),因此我们将对应PWM波作为输入,连接其对应引脚即可实现所需完成功能。
将引脚PA6与引脚PC13相连
PA6 —> PC13
(3)运行视频
总结
通过本次作业,深入理解了定时器在嵌入式系统中的重要性和强大功能。
在实现多任务并发运行方面,定时器提供了一种高效且精准的解决方案。相比于传统的循环和 delay
函数,定时器能够让 CPU 在定时任务等待期间去处理其他任务,提高了系统的整体效率和响应能力。例如,在同时实现串口发送和 LED 闪烁任务时,定时器中断机制确保了这两个任务能够按照预定的时间间隔独立运行,互不干扰。如果不采用定时器而仅依靠循环和 delay
函数来实现上述两个周期性任务,会面临一些问题。在执行 delay
函数时,CPU 会被阻塞,无法进行其他操作,导致系统资源浪费且无法实现真正的多任务并发。而且,使用循环和 delay
函数难以保证任务执行的精准性,尤其是在涉及多个任务且时间要求严格的情况下。
在实现 PWM 呼吸灯效果时,进一步熟悉了 TIM 定时器的 PWM 输出功能。通过动态调整 PWM 的占空比,可以轻松实现 LED 亮度的渐变效果。同时,使用不同的 TIM 定时器来控制不同的 LED,展示了定时器资源在多外设控制中的灵活应用。这也让我认识到在嵌入式系统设计中,合理利用硬件定时器资源能够创造出丰富多样的功能和效果,对于提升系统的性能和用户体验具有重要意义。
总的来说,本次作业不仅提升了在定时器使用方面的技术能力,还加深了对嵌入式系统多任务处理和外设控制的理解,为今后更复杂的嵌入式项目开发奠定了坚实的基础。
作者:不饶霜