8-STM32F1-pwm输出

STM32F1-pwm输出

以下内容部分摘抄自原子哥的书籍,开发板用的是正点原子的精英板

STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样, STM32 最多可以同时产生 30 路 PWM 输出! 这里使用TIM3输出4路pwm,其实TIM3最多也只能输出4路pwm。

每个定时器不同通道具体对应的哪个IO口在STM32的数据手册上有,这里的TIM3通道1-4分别对应PA6,PA7,PB0,PB1。
要配置pwm输出,主要配置3个部分,IO初始化、定时器初始化和输出通道初始化。

IO初始化;需要把IO配置为复用推挽输出,我记得使用复用功能一般都要打开IO复用时钟,但是这里好像不打开IO复用时钟也是可以正常使用的,这里只是示范其中一个IO的配置,其他pwm输出IO配置也是一样的。
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;//PA6
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;//翻转速度=10MHZ
	GPIO_Init(GPIOA, &GPIO_InitStruct);//TIM3通道1IO口

定时器初始化;设置定时器分频也就是计数器的时钟。设置重装值arr,这个重装值和计数器的时钟决定了pwm的频率。还有就是设置计数器的计数模式了。这里系统时钟为72m,APB1为1分频,所以TIM3的输入时钟为36m。第三个参数是设置计数器的时钟频率,这里是设置为0.5mhz,第四个参数是设置重装值,也就是计数多少个计数器时钟就会溢出,这里设置的是200-1,其实就是计数200个就会溢出。按照这个设置,按理说输出频率应该是2.5khz,但是输出频率会是这个设置频率的2倍,原因是计数器计数到比较值的时候还会翻转一次,所以频率会加倍,比如要输出10k的pwm,那么这里就应该设置为5khz。
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//目前TIM3的时钟是36m
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//向下计数
	TIM_TimeBaseInitStruct.TIM_Period=72-1;//36m的时钟72分频=0.5mhz,这个就是psc
	TIM_TimeBaseInitStruct.TIM_Prescaler=200-1;//这个是预装载值arr ,也就是定时时间,一个时钟0.5us,向下计数值200就是定时0.1ms=10k
	//TIM_TimeBaseInitStruct.TIM_RepetitionCounter=//这个选项是高级定时器才会用到
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);//输出频率=定时器溢出周期的倒数

输出通道;这个部分的配置不同通道需要单独配置。这个需要设置pwm模式,一般为模式1或者模式2.这部分最重要的设置应该就是比较值ccr了,这个比较值决定该通道输出pwm的占空比,占空比=ccr/arr,不过结果和理论中好像对不上号。
	//TIM_OCInitStruct.TIM_OCIdleState=//高级定时器才需要配置这个选项
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//pwm模式1输出
	//TIM_OCInitStruct.TIM_OCNIdleState=//高级定时器才需要配置这个选项
	//TIM_OCInitStruct.TIM_OCNPolarity=//高级定时器才需要配置这个选项
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//高电平有效
	//TIM_OCInitStruct.TIM_OutputNState=//高级定时器才需要配置这个选项
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//使能比较输出
	TIM_OCInitStruct.TIM_Pulse=60;//这个是ccr,占空比=ccr/arr,不过理论值和实际结果好像对不上
	TIM_OC1Init(TIM3,&TIM_OCInitStruct);//TIM3的通道1-PA6

这里需要注意的是;同一个定时器可以输出几路pwm,每路输出的占空比也是可以不一样的。但是几路pwm因为用的都是同一个定时器和同一个计数器,所以他们的输出频率都是一样的,占空比不一样只是因为他们的比较值不一样而已。

本实验的功能是利用TIM3输出4路pwm,代码如下;

#include "sys.h"
#include "delay.h"
/************************************************************
TIM3通道2输出5khz pwm
不使用端口重映射,默认输出口为PA7

****************************************************************/

void init_pwmIO()
{
	GPIO_InitTypeDef GPIO_InitStruct;//GPIO结构体
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);//打开PB,PA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//复用时钟,好像不用打开复用时钟也可以正常输出
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;//PA6
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;//翻转速度=10MHZ
	GPIO_Init(GPIOA, &GPIO_InitStruct);//TIM3通道1IO口
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7;//PA7
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;//翻转速度=10MHZ
	GPIO_Init(GPIOA, &GPIO_InitStruct);//TIM3通道2IO口
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;//PB0
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;//翻转速度=10MHZ
	GPIO_Init(GPIOB, &GPIO_InitStruct);//TIM3通道3IO口
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;//PB1
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;//翻转速度=10MHZ
	GPIO_Init(GPIOB, &GPIO_InitStruct);//TIM3通道4IO口
}
void init_tim3()
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//TIM3是挂接在APB1时钟上的
	
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//目前TIM3的时钟是36m
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//向下计数
	TIM_TimeBaseInitStruct.TIM_Period=72-1;//36m的时钟72分频=0.5mhz,这个就是psc
	TIM_TimeBaseInitStruct.TIM_Prescaler=200-1;//这个是预装载值arr ,也就是定时时间,一个时钟0.5us,向下计数值200就是定时0.1ms=10k
	//TIM_TimeBaseInitStruct.TIM_RepetitionCounter=//这个选项是高级定时器才会用到
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);//输出频率=定时器溢出周期的倒数
	
	//TIM_OCInitStruct.TIM_OCIdleState=//高级定时器才需要配置这个选项
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//pwm模式1输出
	//TIM_OCInitStruct.TIM_OCNIdleState=//高级定时器才需要配置这个选项
	//TIM_OCInitStruct.TIM_OCNPolarity=//高级定时器才需要配置这个选项
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//高电平有效
	//TIM_OCInitStruct.TIM_OutputNState=//高级定时器才需要配置这个选项
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//使能比较输出
	TIM_OCInitStruct.TIM_Pulse=60;//这个是ccr,占空比=ccr/arr,不过理论值和实际结果好像对不上
	TIM_OC1Init(TIM3,&TIM_OCInitStruct);//TIM3的通道1-PA6

	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//pwm模式1输出
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//高电平有效
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//使能比较输出
	TIM_OCInitStruct.TIM_Pulse=50;//初始化占空比,高电平有效情况下,低电平的占空比
	TIM_OC2Init(TIM3,&TIM_OCInitStruct);//TIM3的通道2-PA7
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//pwm模式1输出
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//高电平有效
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//使能比较输出
	TIM_OCInitStruct.TIM_Pulse=25;//初始化占空比,高电平有效情况下,低电平的占空比
	TIM_OC3Init(TIM3,&TIM_OCInitStruct);//TIM3的通道3-PB0

	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//pwm模式1输出
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//高电平有效
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//使能比较输出
	TIM_OCInitStruct.TIM_Pulse=10;//初始化占空比,高电平有效情况下,低电平的占空比
	TIM_OC4Init(TIM3,&TIM_OCInitStruct);//TIM3的通道4-PB1
	
	TIM_Cmd(TIM3,ENABLE);//打开定时器3
	//TIM_CtrlPWMOutputs(TIM1, ENABLE); //如果是使用高级定时器一定要使能pwm功能,这里使用的是通用定时器所以不需要这条语句
}
 int main(void)
 {	
	delay_init();	//系统初始化
	//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//pwm输出如果没有使能中断的话是不需要中断分组的
	init_pwmIO();	 //LED初始化
	init_tim3(); //TIM3初始化
	while(1)
	{
		//TIM_SetCompare1(TIM3,20);//这个可以 在运行中改变通道1占空比
		//TIM_SetCompare2(TIM3,20);//这个可以 在运行中改变通道2占空比
		//TIM_SetCompare3(TIM3,20);//这个可以 在运行中改变通道3占空比
		//TIM_SetCompare4(TIM3,20);//这个可以 在运行中改变通道4占空比
	}
 }
 

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
定时器8输出PWM的代码如下所示: ```c #include "PWM.h" int main() { u16 led0pwmval = 0; u8 dir = 1; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // NVIC初始化分组 LED_Init(); // LED初始化 delay_init(); // 延时初始化 TIM_PWM_Init(899, 0); // 不分频。PWM频率=72000000/900=80Khz while(1) { delay_ms(10); if(dir) { led0pwmval++; } else { led0pwmval--; } if(led0pwmval > 300) { dir = 0; } if(led0pwmval == 0) { dir = 1; } // 往CCR2寄存器写入不断变化的led0pwmval值,调整比较值,就能输出不断变化的占空比了 TIM_SetCompare2(TIM8, led0pwmval); } } ``` 在这段代码中,我们使用了定时器8来输出PWM信号。首先,我们需要进行一些初始化工作,包括设置NVIC分组、LED初始化和延时初始化。然后,我们调用TIM_PWM_Init函数来初始化定时器8,设置不分频,使得PWM频率为80KHz。接下来,我们进入一个循环,每隔10毫秒调整led0pwmval的值,从而改变占空比。最后,我们使用TIM_SetCompare2函数将led0pwmval的值写入CCR2寄存器,实现PWM输出。 #### 引用[.reference_title] - *1* [STM32F103C8T6---定时器1&定时器8输出PWM信号注意事项](https://blog.csdn.net/weixin_51134981/article/details/129971600)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [STM32F1定时器-PWM输出](https://blog.csdn.net/weixin_46251230/article/details/126796005)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值