【STM32CUBEMX+PWM+UART】

8 篇文章 1 订阅
6 篇文章 1 订阅

【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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值