打印
[应用相关]

STM32的PWM输入捕获与输出

[复制链接]
411|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-12-9 08:42 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一、STM32CubeMX配置
1.打开RCC时钟



选项 Master Clock Output 用来选择是否使能 MCO(PA8) 引脚时钟输出(冲突时会变红)

2.配置时钟



STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4

其中TIM1在APB2总线上,属于高级定时器,TIM2、3、4在APB1总线上,属于通用定时器

3.设置PWM的输出通道



PWM通道设置:

①Mode:

PWM模式1:无论是向上计数还是向下计数,只要CNT ⩽⩽CCRx,PWM输出高电平。

PWM模式2:无论是向上计数还是向下计数。只要CNT ⩽⩽CCRx,PWM输出低电平。

②Pulse:即初始的CCR值

        类似于改占空比,例如Pulse=500,占空比则为 500/999(上图),占空比约为50%

③Output compare preload:输出比较值预加载

        当使能此功能时,设置Pulse输出比较值时,该值不会立即生效,而是会等到当前PWM完成一个周期的输出后才把当前值设置至Pulse输出比较值的寄存器中。这样可以实现设置的平滑切换。不使能则是立即生效。这里建议使能该功能。

④Fast Mode:快速模式

⑤CH Polarity:通道极性,选择为高,若选择极性为低,则输出高低电平取反

4.PWM捕获配置



①Slave Mode(从机模式):可以在多种模式下与外部触发器同步

        重置模式(输入出现上升沿时复位定时器计数并更新寄存器值)

        门控模式(输入高电平时启动计数,输入低电平时停止计数,不重置寄存器)

        触发模式(输入出现上升沿时启动计数,不能控制停止)。

②Trigger Source(触发源):如下图所示



③Clock Source(时钟源):一般使用内部时钟源即可。

④Channel x(第x通道):可以配置每个通道的功能

⑤One Pulse Mode(单脉冲模式):启用该功能时,当定时器计数值达到重装载值时停止计数。

⑥Input Capture Channel1 和  Input Capture Channel2设置:

       

        Channel1选择上升沿捕获,储存的是CCR1的值,Channel2选择下降沿捕获,储存的是CCR2的值,由于是重置模式(输入出现上升沿时复位定时器计数并更新寄存器值),下降沿时计数器并不会清零。

⑦IC Selection:输入信号交叉,选择直通,不交叉(如下图所示)



⑧Prescaler Division Ratio:捕获预分频,选择不分频,每次信号都触发捕获

⑨Input Filter:滤波器参数,可以过滤信号抖动

5.使能所有用到的定时器



6.配置调试串口(非必要)



7.设置定时器优先级



因为用到多个定时器中断,需要设置中断优先级,具体需要自己判断

8.生成基本代码



二、编写主程序
个人认为在keil中更加简洁方便



以下是基于上述模板的示例代码

#include "my_main.h"

//TIM1输入捕获
u16 CCR1_1, CCR1_2, Duty1 = 0;
//TIM2输入捕获
u16 CCR2_1, CCR2_2, Duty2 = 0;
//TIM4输入捕获
u16 CCR4_1, CCR4_2, Duty4 = 0;
//TIM3输出PWM
u16 ARR3, Duty3_1, Duty3_2, Duty3_3, Duty3_4 = 0;

//串口
u8 UART_TX_Buffer[200] = "";

//我的初始化函数
void My_Init(void)
{
        //TIM3输出PWM
        HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);                //开启通道1输出
        HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);                //开启通道2输出
        HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);                //开启通道3输出
//        HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);                //开启通道4输出

        // 通过设置预分频器值设置PWM频率(CubeMX中已经配置了,但是可以在程序中再次修改)
        __HAL_TIM_SET_PRESCALER(&htim3, 71);                        //72000000 Hz / (71 + 1) / (19999 + 1) = 50 Hz
        __HAL_TIM_SET_AUTORELOAD(&htim3, 19999);                //TIM3的ARR值
       
        //TIM1输入捕获
        HAL_TIM_IC_Start (&htim1, TIM_CHANNEL_1);                //开启通道1输入捕获
        HAL_TIM_IC_Start (&htim1, TIM_CHANNEL_2);                //开启通道2输入捕获
        //TIM2输入捕获
        HAL_TIM_IC_Start (&htim2, TIM_CHANNEL_1);                //开启通道1输入捕获
        HAL_TIM_IC_Start (&htim2, TIM_CHANNEL_2);                //开启通道2输入捕获
        //TIM4输入捕获
        HAL_TIM_IC_Start (&htim4, TIM_CHANNEL_1);                //开启通道1输入捕获
        HAL_TIM_IC_Start (&htim4, TIM_CHANNEL_2);                //开启通道2输入捕获
}

//我的循环函数
void My_While(void)
{
        // CCR2/CCR1 就是占空比
        CCR1_1 = TIM1->CCR1;
        CCR1_2 = TIM1->CCR2;
        CCR2_1 = TIM2->CCR1;
        CCR2_2 = TIM2->CCR2;
        CCR4_1 = TIM4->CCR1;
        CCR4_2 = TIM4->CCR2;
       
        //为了便于计算(不出现浮点)
        ARR3 = TIM3->ARR + 1;                       
        Duty3_1 = CCR1_2 * ARR3 / CCR1_1;        //输出TIM1捕获的PWM
        Duty3_2 = CCR2_2 * ARR3 / CCR2_1;        //输出TIM2捕获的PWM
        Duty3_3 = CCR4_2 * ARR3 / CCR4_1;        //输出TIM4捕获的PWM
       
        // 确保TIM3的Duty在0到ARR3之间(无符号整数不可能小于0)
        Duty3_1 = Duty3_1 > ARR3 ? ARR3 : Duty3_1;
        Duty3_2 = Duty3_2 > ARR3 ? ARR3 : Duty3_2;
        Duty3_3 = Duty3_3 > ARR3 ? ARR3 : Duty3_3;
       
        //设置占空比
        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, Duty3_1);
        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, Duty3_2);
        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, Duty3_3);
       
        //使用串口观察数据
        //计算占空比
        Duty1 = (u16)((float)CCR1_2 / CCR1_1 * 100);
        Duty2 = (u16)((float)CCR2_2 / CCR2_1 * 100);
        Duty4 = (u16)((float)CCR4_2 / CCR4_1 * 100);
        //使用串口输出到电脑
        sprintf((char*)UART_TX_Buffer, "Duty1=%u%%;\nDuty2=%u%%;\nDuty4=%u%%;\nTIM3: ARR3=%u, Duty3_1=%u, Duty3_2=%u, Duty3_3=%u\n",
                Duty1, Duty2, Duty4, ARR3, Duty3_1, Duty3_2, Duty3_3);
        HAL_UART_Transmit(&huart2, (uint8_t*)UART_TX_Buffer, strlen((char*)UART_TX_Buffer), 200);
        HAL_Delay(1000);
       
}


烧录到你的单片机中后,连接好电路,可以在电脑串口程序中看到捕获并输出的不同占空比的PWM波了。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/m0_70649291/article/details/144241039

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2028

主题

15903

帖子

13

粉丝