基于正点原子stm32的mini板的PWM输出的实验学习

本文详细介绍了如何在STM32上实现PWM输出,包括PWM的基本概念、实验思路和具体步骤。实验中涉及了开启TIM1时钟、配置PA8为复用输出、设置ARR和PSC、配置PWM模式、使能TIM1以及修改TIM1_CCR1控制占空比等关键步骤。通过调整这些参数,可以控制PWM的占空比和频率,从而控制负载的亮度或速度。
摘要由CSDN通过智能技术生成

本章将讲述PWM输出实验,小白总结,如有错误,请大神指教。

目录

一、PWM的简介

二、PWM输出实验的思路

三、PWM的输出实验


一、PWM的简介

PWM:脉冲宽度调制,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制,PWM 原理如下图所示:

 我们假定定时器工作在向上计数PWM 模式,且当 CNT<CCRx 时,输出 0,当 CNT>=CCRx 时输出 1。那么就可以得到如上的PWM 示意图:当 CNT 值小于 CCRx 的时候,IO 输出低电平(0),当 CNT 值大于等于 CCRx 的时候,IO 输出高电平(1),当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数,依次循环。改变 CCRx 的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM输出的频率,这就是 PWM 输出的原理。

二、PWM输出实验的思路

1)开启 TIM1 时钟,配置 PA8 为复用输出。 
要使用 TIM1,我们必须先开启 TIM1 的时钟,这点相信大家看了这么多代码,应该明白了。
这里我们还要配置 PA8 为复用输出(当然还要时能 PORTA 的时钟),这是因为 TIM1_CH1 通
道将使用 PA8 的复用功能作为输出。库函数使能 TIM3 时钟的方法是: 

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器 3 时钟 

设置 PA8 为复用功能输出的方法在前面的几个实验都有类似的讲解,相信大家很明白,这里简单
列出 GPIO 初始化的一行代码即可: 

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 

2)设置 TIM1 的 ARR 和 PSC。 
在开启了 TIM1 的时钟之后,我们要设置 ARR 和 PSC 两个寄存器的值来控制输出 PWM 的
周期。当 PWM 周期太慢(低于 50Hz)的时候,我们就会明显感觉到闪烁了。因此,PWM 周
期在这里不宜设置的太小。这在库函数是通过 TIM_TimeBaseInit 函数实现的,在上一节定时器
中断章节我们已经有讲解,这里就不详细讲解,调用的格式为: 

TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值 
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值 
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim 
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式 
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的 

3)设置 TIM1_CH1 的 PWM 模式及通道方向, 使能 TIM1 的 CH1 输出。 
接下来,我们要设置 TIM1_CH1 为 PWM 模式(默认是冻结的),因为我们的 DS0 是低电
平亮,而我们希望当 CCR1 的值小的时候,DS0 就暗,CCR1 值大的时候,DS0 就亮,所以我
们要通过配置 TIM1_CCMR1 的相关位来控制 TIM1_CH1 的模式。在库函数中,PWM 通道设
置是通过函数 TIM_OC1Init()~TIM_OC4Init()来设置的,不同的通道的设置函数不一样,这里我
们使用的是通道 1,所以使用的函数是 TIM_OC1Init()。 

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); 

这种初始化格式大家学到这里应该也熟悉了,所以我们直接来看看结构体 TIM_OCInitTypeDef
的定义: 

typedef struct 
{ 
 uint16_t TIM_OCMode; 
 uint16_t TIM_OutputState; 
 uint16_t TIM_OutputNState; 
 uint16_t TIM_Pulse; 
 uint16_t TIM_OCPolarity; 
 uint16_t TIM_OCNPolarity; 
 uint16_t TIM_OCIdleState; 
 uint16_t TIM_OCNIdleState; 
} TIM_OCInitTypeDef; 

这里我们讲解一下与我们要求相关的几个成员变量: 
参数 TIM_OCMode 设置模式是 PWM 还是输出比较,这里我们是 PWM 模式。 
 参数 TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。 
参数 TIM_OCPolarity 用来设置极性是高还是低。 
其他的参数 TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState 和 TIM_OCNIdleState 是
高级定时器 TIM1 和 TIM8 才用到的。 
要实现我们上面提到的场景,方法是: 

TIM_OCInitTypeDef TIM_OCInitStructure; 
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2 
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高 
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //初始化 TIM1 OC1 

4)使能 TIM1。 
在完成以上设置了之后,我们需要使能 TIM1。使能 TIM1 的方法前面已经讲解过: 

TIM_Cmd(TIM1, ENABLE); //使能 TIM1

5)设置 MOE 输出,使能 PWM 输出。 
普通定时器在完成以上设置了之后,就可以输出 PWM 了,但是高级定时器,我们还需要
使能刹车和死区寄存器(TIM1_BDTR)的 MOE 位,以使能整个 OCx(即 PWM)输出。库函
数的设置函数为: 

 TIM_CtrlPWMOutputs(TIM1,ENABLE); // MOE 主输出使能 

6)修改 TIM1_CCR1 来控制占空比。 
最后,在经过以上设置之后,PWM 其实已经开始输出了,只是其占空比和频率都是固定
的,而我们通过修改 TIM1_CCR1 则可以控制 CH1 的输出占空比。继而控制 DS0 的亮度。 
在库函数中,修改 TIM1_CCR1 占空比的函数是: 

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1); 

理所当然,对于其他通道,分别有一个函数名字,函数格式为 TIM_SetComparex(x=1,2,3,4)。 
通过以上 6 个步骤,我们就可以控制 TIM1 的 CH1 输出 PWM 波了。

三、PWM的输出实验

工程文件如下:

 test.c的文件如下:

#include "sys.h"
#include "usart.h"		
#include "delay.h"	
#include "led.h"   
#include "timer.h" 

int main(void)
{			
 	u16 led0pwmval=0;    
	u8 dir=1;	
	Stm32_Clock_Init(9); 
	delay_init(72);	     
	uart_init(72,9600);  
	LED_Init();		  	
	TIM1_PWM_Init(899,0); 
   	while(1)
	{
 		delay_ms(10);	 
		if(dir)led0pwmval++;
		else led0pwmval--;	 
 		if(led0pwmval>300)dir=0;
		if(led0pwmval==0)dir=1;	   					 
		LED0_PWM_VAL=led0pwmval;	   
	} 
}

led.c文件如下:

#include "sys.h"   
#include "led.h"

void LED_Init(void)
{
	RCC->APB2ENR|=1<<2;   	   	 
	RCC->APB2ENR|=1<<5;    	   	 
	GPIOA->CRH&=0XFFFFFFF0; 
	GPIOA->CRH|=0X00000003;   	 
    GPIOA->ODR|=1<<8;      
											  
	GPIOD->CRL&=0XFFFFF0FF;
	GPIOD->CRL|=0X00000300;
	GPIOD->ODR|=1<<2;     
}

timer.c文件如下:

#include "timer.h"
#include "led.h"

void TIM3_IRQHandler(void)
{ 		    		  			    
	if(TIM3->SR&0X0001)
	{
		LED1=!LED1;			    				   				     	    	
	}				   
	TIM3->SR&=~(1<<0);	    
}

void TIM3_Int_Init(u16 arr,u16 psc)
{
	RCC->APB1ENR|=1<<1;	  
 	TIM3->ARR=arr;  	
	TIM3->PSC=psc;  	
	TIM3->DIER|=1<<0;  			
	TIM3->CR1|=0x01;    
  	MY_NVIC_Init(1,3,TIM3_IRQn,2);									 
}

void TIM1_PWM_Init(u16 arr,u16 psc)
{		 					 
	RCC->APB2ENR|=1<<11; 	   
	GPIOA->CRH&=0XFFFFFFF0;
	GPIOA->CRH|=0X0000000B;	 
	
	TIM1->ARR=arr;			
	TIM1->PSC=psc;			
	TIM1->CCMR1|=7<<4;  		 
	TIM1->CCMR1|=1<<3; 		 
 	TIM1->CCER|=1<<0;   	   
	TIM1->BDTR|=1<<15;   		   

	TIM1->CR1=0x0080;   	
	TIM1->CR1|=0x01;    										  
}  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGAI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值