当前位置: 代码迷 >> 综合 >> 【STM32CUBEMX+PWM+UART】
  详细解决方案

【STM32CUBEMX+PWM+UART】

热度:35   发布时间:2023-12-11 19:39:23.0

【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。其他参数使用默认值
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RbH4P9dh-1630739652579)(C:\Users\gf\AppData\Roaming\Typora\typora-user-images\1630734461215.png)]
    ? ——>在 GPIO 页面配置相关引脚的特性,PD12,PD13设置方法同PA6,PA7,PB0, PB1

  • (UART2)串口配置,打印输出信息
    在这里插入图片描述

  • 时钟树配置,在 Clock Configuration 界面配置时钟源,使用外部 8M 晶振作 PLL 时钟输入,并使用 PLL 输出作为系统时钟80MHz
    在这里插入图片描述

  • 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lrao6akm-1630739652585)(C:\Users\gf\AppData\Roaming\Typora\typora-user-images\1630736345648.png)]

    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();//使能 TIM3、TIM4 的各个通道 PWM 输出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;}}}
    // TIM2 输入捕获中断处理回调凼数
    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;}}}}
    

    个人浅见,如有问题欢迎大家留言讨论
    上文中,当函数之行到 HAL_TIM_IC_Start_IT(&htim2 , TIM_CHANNEL_1);时,开启定时器捕获中断,此时,整个代码执行的流程为:
    startup_stm32f411xe.s——> >TIM2_IRQHandler()——>HAL_TIM_IRQHandler()——>HAL_TIM_IC_CaptureCallback();执行完之后在跳回到 HAL_TIM_IC_Start_IT(&htim2 , TIM_CHANNEL_1);处,执行break;——>while()此时campture_cnt = 4 ——>case4:

? 测量思路
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]就是高电 平所占时间。
[外链图片转存中...(img-dJ3604O5-1630739652587)]
——>编译下载。用杜邦线将 PA0 和其他 PWM 信号输出脚(PD12,PD13,PA6,PA7,PB0, PB1任选其1)相连,即可测量信号的周期,高 电平所占时间,以及占空比,在串口 2会输出如下信息:
在这里插入图片描述
具体工程案例见:PWM_Capture.rar

  相关解决方案