STM32的PWM输入捕获与输出

一、STM32CubeMX配置

1.打开RCC时钟

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

2.配置时钟

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

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

3.设置PWM的输出通道

PWM通道设置:

①Mode:

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

  2. 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波了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值