【STM32 PWM输出+串口调整PWM周期和占空比】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

上次学习了STM32的基本定时器功能,它只是最基本的功能,STM32的功能非常强大,定时器还有输出功能,即PWM。


提示:以下是本篇文章正文内容,下面案例可供参考

一、PWM是什么?

PWM是脉冲宽度调制,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。

1. PWM 图解

在这里插入图片描述
T1:为高电平时间
T2:为低电平时间
T1+T2-=T
占空比为 = T/T *100%

二、认识STM32的PWM功能

1.哪些定时器有PWM输出功能

1.1 高级定时器,7路PWM输出,3组是互补输出,CH1与CH1N输出的波形相反,2*3=6;CH4是独立的1 6+1=7

在这里插入图片描述

1.2通用定时器,4路独立输出

在这里插入图片描述

2.STM32 PWM框图

2.1高级定时器简介

在这里插入图片描述

在这里插入图片描述

2.2高级定时器框图

在这里插入图片描述
1、2讲过了,重点在3

2.3高级定时器rcc时钟

1.RCC
在这里插入图片描述

2.4 高级定时器时基

在这里插入图片描述

在这里插入图片描述

2.5 PWM输出框图

在这里插入图片描述
PWM输出与 周期和比较值的关系
在这里插入图片描述
输出过程
在这里插入图片描述

三、.配置PWM输出的步骤

    1. 配置引脚
    1. 配置时钟
    1. 配置时基(PWM的周期)
    1. 配置比较值,配置输出极性,使能输出

3.1 配置引脚

在这里插入图片描述
在这里插入图片描述

void timer1_gpio_init()
{

    GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitStruct.GPIO_Pin=  GPIO_Pin_8;          //TX
	GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	
	GPIO_Init(GPIOA, &GPIO_InitStruct);   //&x
}

3.2 配置PWM比较输出

配置输出
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

void timer1(u16 period,u16 prescaler)
{
      /*
	
	1.开启APB1时钟   72MHz
	2.配置定时器6    TimeInit()  72预分配,0-65535     1000000us/50000us =CNT=20         定时时间/中断溢出时间=计数值
	3.中断配置       分组,优先级 。开启中断源
	4.中断服务函数   计数值, 1us  ,计数20次后让一个LED取反
	*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef  TIM_OCInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
	
	//TIM_TimeBaseInitStruct.TIM_ClockDivision=
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period=period-1;//50000-1;
	TIM_TimeBaseInitStruct.TIM_Prescaler=prescaler-1;// 72-1;
	//TIM_TimeBaseInitStruct.TIM_RepetitionCounter=
	
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);
	
	 //TIM_OCInitStruct.TIM_OCIdleState=	 
	// TIM_OCInitStruct.TIM_OCNIdleState=
	  TIM_OCInitStruct.TIM_OCMode= TIM_OCMode_PWM1;
	  TIM_OCInitStruct.TIM_OCPolarity= TIM_OCPolarity_High;
	//  TIM_OCInitStruct.TIM_OCNPolarity=
	//  TIM_OCInitStruct.TIM_OutputNState=
	  TIM_OCInitStruct.TIM_OutputState= TIM_OutputState_Enable;
	  TIM_OCInitStruct.TIM_Pulse= period/2; //百分之50占空比
		 	
	TIM_OC1Init(TIM1, &TIM_OCInitStruct);
	
	TIM_CtrlPWMOutputs(TIM1, ENABLE);
	
	
	//开启中断:
	TIM_ITConfig( TIM1, TIM_IT_CC1, ENABLE);
	
	TIM_Cmd( TIM1, ENABLE);      //使能
	
}

3.3 可以配置比较中断

在这里插入图片描述

TIM_ITConfig( TIM1, TIM_IT_CC1, ENABLE);

3.4高级定时器还有一个主使能输出

在这里插入图片描述
在这里插入图片描述

TIM_CtrlPWMOutputs(TIM1, ENABLE);

四、参考程序

void timer1_gpio_init()
{

    GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitStruct.GPIO_Pin=  GPIO_Pin_8;          //TX
	GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	
	GPIO_Init(GPIOA, &GPIO_InitStruct);   //&x
}


void timer1(u16 period,u16 prescaler)
{
      /*
	
	1.开启APB1时钟   72MHz
	2.配置定时器6    TimeInit()  72预分配,0-65535     1000000us/50000us =CNT=20         定时时间/中断溢出时间=计数值
	3.中断配置       分组,优先级 。开启中断源
	4.中断服务函数   计数值, 1us  ,计数20次后让一个LED取反
	*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef  TIM_OCInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
	
	//TIM_TimeBaseInitStruct.TIM_ClockDivision=
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period=period-1;//50000-1;
	TIM_TimeBaseInitStruct.TIM_Prescaler=prescaler-1;// 72-1;
	//TIM_TimeBaseInitStruct.TIM_RepetitionCounter=
	
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);
	
	 //TIM_OCInitStruct.TIM_OCIdleState=	 
	// TIM_OCInitStruct.TIM_OCNIdleState=
	  TIM_OCInitStruct.TIM_OCMode= TIM_OCMode_PWM1;
	  TIM_OCInitStruct.TIM_OCPolarity= TIM_OCPolarity_High;
	//  TIM_OCInitStruct.TIM_OCNPolarity=
	//  TIM_OCInitStruct.TIM_OutputNState=
	  TIM_OCInitStruct.TIM_OutputState= TIM_OutputState_Enable;
	  TIM_OCInitStruct.TIM_Pulse= period/2; //百分之50占空比
		 	
	TIM_OC1Init(TIM1, &TIM_OCInitStruct);
	
	TIM_CtrlPWMOutputs(TIM1, ENABLE);
	
	
	//开启中断:
	TIM_ITConfig( TIM1, TIM_IT_CC1, ENABLE);
	
	TIM_Cmd( TIM1, ENABLE);      //使能
	
}

五、实验测试

六、串口控制PWM的周期和占空比

6.1 思考如何改变周期和占空比


周期->是由时基来决定的。
时基->是由预分频和周期决定的
RCC时钟也是关键,最高设置为了72MHz

公式 1:72000000=分频系数*周期数

分频系数的范围是 0-65535
周期数的范围是:0-65535。
所以公式1 将得到很多种可能,这正是STM32预分频的神奇之处


之前定时1s实现,

72000000 =72*(5000020)
20是在定时器中断里面放变量自加的。现在配置PWM没有这个内容,根据大小值都不能超过65535的原则,将20分给预分频
timer1(50000,72
20);
方法1:写一个函数 关联公式1


6.2占空比的思考

通过看图,占空比就是改变比较值,所以改变比较值就可以了

在这里插入图片描述

TIM_SetCompare1(TIM1, i++);

总结

  • 6
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是实现该功能的示例代码: ```c #include "stm32f4xx.h" void UART_Config(void); void PWM_Config(void); int main(void) { UART_Config(); PWM_Config(); while(1) { uint8_t data; if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) { data = USART_ReceiveData(USART1); TIM_SetCompare1(TIM4, data); } } } void UART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); } void PWM_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure; TIM_OCInitTypeDef TIM_OC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4); TIM_TimeBase_InitStructure.TIM_Prescaler = 83; // =84-1, 84MHz/84=1MHz TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBase_InitStructure.TIM_Period = 999; // PWM frequency = 1MHz/(999+1) = 1kHz TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM4,&TIM_TimeBase_InitStructure); TIM_OC_InitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OC_InitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OC_InitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC_InitStructure.TIM_Pulse = 500; // initial PWM duty cycle = 50% TIM_OC1Init(TIM4, &TIM_OC_InitStructure); TIM_Cmd(TIM4, ENABLE); } ``` 这段代码实现了一个基于STM32串口控制PWM的功能。用户可以通过串口发送值来改变PWM占空比。具体实现方式是,每当串口接收到一个字节时,就将该字节的值设为PWM占空比。例如,如果用户发送的字节为 128,则PWM占空比就会被设置为 50%。另外,为了方便起见,本代码假设用户是以 9600bps 的波特率通过USART1发送数据的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值