【STM32CUBEMX+PWM+UART】
1.案例应用
? 本案例为使用STM32CUBEMX配置TIM2生成PWM捕获信号,并对TIM3,TIM4(也可捕获其它设备输出)输出的PWM波进行捕获(本例捕获上升沿,极性可以自己设置),最后求取并串口打印TIM3,TIM4输出PWM的周期、占空比以及1个周期内高电平的持续时间。
2.工具
-
STM32CUBEMX -
IAR -
STM32F411VET6
3.PWM实验
3.1.1 STM32CUBEMX 工程配置
-
打开 STM32CubeMX,点击“New Project”,选择芯片型号,STM32F411VETx -
RCC、SYS配置 ? ——>这里如下图所示配置,不懂的可以百度 -
TIM2配置 ,使用内部时钟源,CH1 作为输入捕获通道,默认映射到 PA0 引脚 ,如下图所示 ? ——>在 Parameter Settings 页配置预分频系数为 7,其计数时钟就是 80MHz/(7+1)=10MHz(时钟树配置后边说),计数周期(自动加载值),转换为十六进制形式(也可十进制),输入 32bit 最大值 0xFFFFFFFF。 ——>设置通道1的捕获极性,初始设置为上升沿(也可以修改,根据实际需求) ? ——>在 NVIC页面使能捕获/比较中断 ? ——>在 GPIO 页面设置捕获输入引脚下拉电阻,设置成上拉也可以,主要是为了使在没有信号输入时在输 入引脚上得到稳定的电平 -
TIM3配置, 使用内部时钟,CH1~CH4 为 PWM 输出通道,默认映射引脚分别为 PA6,PA7,PB0, PB1 ? ——>在 Parameter 页配置预分频系数为 7,计数周期(自动加载值)为 9999。其溢出频率就是 80MHz/(7+1)/(9999+1)=1kHz(即 周期,1ms ),这就是 TIM3 各通道输出的 PWM 信号的频率,配置各通道输出极性以及脉宽,将通道1,通道2,通道3,通道4 分别设为1234, 2345,5678, 6789,即1个周期内高电平时长0.1234ms,0.2345ms,0.5678ms, 0.6789ms,2, 3 ,4通道设置方法同通道1。其他参数使用默认值 ? ——>在 GPIO 页面配置相关引脚的特性,PA6,PA7,PB0, PB1设置相同 -
TIM4 配置 ,使用内部时钟,CH1,CH2 为 PWM 输出通道,映射引脚分别为 PD12,PD13 ? ——>在 Parameter 页配置预分频系数为 7,计数周期(自动加载值)为 999。其溢出频率就是 80MHz/(7+1)/(999+1)=10kHz(即 周期,0.1ms ),配置各通道输出极性以及脉宽,将通道1,通道2 分别设为234, 567,即1个周期内高电平时长0.0234ms,0.05678ms, 2通道设置方法同通道1。其他参数使用默认值 ? ——>在 GPIO 页面配置相关引脚的特性,PD12,PD13设置方法同PA6,PA7,PB0, PB1 -
(UART2)串口配置,打印输出信息 -
时钟树配置,在 Clock Configuration 界面配置时钟源,使用外部 8M 晶振作 PLL 时钟输入,并使用 PLL 输出作为系统时钟80MHz -
配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目。 3.1.2 代码编写 ——>定义printf函数,具体操作见STM32CUBEMX+UART串口调试,循环接受发送数据 ——>main.c #include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include <stdio.h>
void SystemClock_Config(void);
uint32_t campture_buf[3] = {0};
uint8_t campture_cnt = {0};
uint32_t pwm_cycle, high_time;
uint64_t duty;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_TIM4_Init();
MX_USART2_UART_Init();
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2);
while (1)
{
switch( campture_cnt)
{
case 0 :
campture_cnt ++;
__HAL_TIM_SET_CAPTUREPOLARITY(&htim2 , TIM_CHANNEL_1 , TIM_INPUTCHANNELPOLARITY_RISING);
HAL_TIM_IC_Start_IT(&htim2 , TIM_CHANNEL_1);
break;
case 4 :
pwm_cycle = campture_buf[2] - campture_buf[0];
printf("cycle: %.4fms\r\n ", pwm_cycle/10000.0);
high_time = campture_buf[1] - campture_buf[0];
printf("High: %.4fms\r\n ", high_time/10000.0);
duty = high_time;
duty *= 1000;
duty /= pwm_cycle;
printf("Duty: %.1f%%\r\n ", duty/10.0);
HAL_Delay(1000);
campture_cnt = 0;
break;
}
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(TIM2 == htim ->Instance)
{
if(HAL_TIM_ACTIVE_CHANNEL_1 == htim ->Channel)
{
switch(campture_cnt)
{
case 1:
campture_buf[0] = __HAL_TIM_GET_COMPARE(htim, TIM_CHANNEL_1);
__HAL_TIM_SET_CAPTUREPOLARITY(htim , TIM_CHANNEL_1 , TIM_INPUTCHANNELPOLARITY_FALLING);
campture_cnt ++;
break;
case 2:
campture_buf[1] = __HAL_TIM_GET_COMPARE(htim, TIM_CHANNEL_1);
__HAL_TIM_SET_CAPTUREPOLARITY(htim , TIM_CHANNEL_1 , TIM_INPUTCHANNELPOLARITY_RISING);
campture_cnt ++;
break;
case 3:
campture_buf[2] = __HAL_TIM_GET_COMPARE(htim, TIM_CHANNEL_1);
HAL_TIM_IC_Stop_IT(htim, TIM_CHANNEL_1);
campture_cnt ++;
break;
default:
break;
}
}
}
}
? 测量思路:
1.设置 TIM2 CH1 为输入捕获功能;
2.设置上升沿捕获;
3.使能 TIM2 CH1 捕获功能;
4.捕获到上升沿后,存入 capture_buf[0],改为捕获下降沿;
5.捕获到下降沿后,存入 capture_buf[1],改为捕获上升沿;
6.捕获到上升沿后,存入 capture_buf[2],关闭 TIM2 CH1 捕获功能;
7.计算:capture_buf[2] - capture_buf[0]就是周期,capture_buf[1] - capture_buf[0]就是高电 平所占时间。 ——>编译下载。用杜邦线将 PA0 和其他 PWM 信号输出脚(PD12,PD13,PA6,PA7,PB0, PB1任选其1)相连,即可测量信号的周期,高 电平所占时间,以及占空比,在串口 2会输出如下信息:
|