STM32F1输出16路PWM工程介绍(基于寄存器)

注:需要工程库的加我qq:468001647
PWM在控制中应用十分广泛,从单电机控制,到舵机控制,再到机械臂控制都广泛运用到PWM。但是如果直接在工程里面向调用一路PWM这会是一件很麻烦的事,工程师应该把更多的精力放在算法的研究和产品的调试上,而并非琢磨单片机最基本额定控制,况且如果直接使用寄存器或者ST提供的官方库会让工程变得很乱,不利于后期开发。在此,我建立了一个工程库,这个库可以支持STM32F1系列输出16路PWM。
下面事对此工程的详细讲解。
首先我们来看一段PWM的输出,以PWM1为例,在此之前我先给大家看一下PWM引脚的分布,如下图:
在这里插入图片描述
那我们就以PWM1的通道1为例先作一个讲解:
废话不多说,上代码:

			RCC->APB2ENR|=1<<11; 	//TIM1时钟使能   
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 			
			GPIOA->CRH&=0XFFFFFFF0;	//PA8清除之前的设置
			GPIOA->CRH|=0X0000000B;	//复用功能输出 
			
			TIM1->ARR=arr_init;			//设定计数器自动重装值 
			TIM1->PSC=psc_init;			//预分频器设置
			
			TIM1->CCMR1|=6<<4;  	//CH1 PWM1模式		 
			TIM1->CCMR1|=1<<3; 		//CH1预装载使能	 
			TIM1->CCER|=1<<0;   	//OC1 输出使能	   
				TIM1->BDTR|=1<<15;   	//MOE 主输出使能	   
			
			TIM1->CR1=0x0080;   	//ARPE使能 
			TIM1->CR1|=0x01;    	//使能定时器1
			
			TIM1->CCR1 =PWM_VAL;

这个是一段PWM初始化代码,我们逐块分析:

RCC->APB2ENR|=1<<11; 首先要说的是,启用PWM1的通道1前必须要去使能改PWM的时钟,我们使用的PWM1通道1对应的时钟是TIM1,我们这个时候需要查找中文参考手册,看截图:
在这里插入图片描述
可以清晰地看见,想要启用TIM1必须要将RCC_APB2ENR寄存器地11位置1,这样才能使能!
好,我们激活了TIM1剩下来就要使能它地输出引脚,这里是PA8,那么第二行到第三行我就不多做介绍,值得注意地是,这里引脚必须设置为复用功能输出。

TIM1->ARR=arr_init; //设定计数器自动重装值
TIM1->PSC=psc_init; //预分频器设置
这两句相比是PWM这一块最让人头大的部分,我初学的时候也费了很大的功夫才把这块弄明白,我在这里也简单地说一下原理吧!
在这里插入图片描述
ARR指的是自动重装载值,PSC指的是预分频值
我们知道F103基本都是72MHZ的主频,那么如上图就是一个周期里面的一段波形,我们把一个单位时间里面分成PSC个段落,就像上图里面一个个尖波一样(一个尖波就是一个段落,一个单位时间里面就有个PSC个这样的周期)。ARR就是每个段落里面都会达到一个峰值,这个峰值就是ARR;
这两个值设置方式就是:TIM1->ARR=arr_init; TIM1->PSC=psc_init;
当然这里有个公式需要特别注意:频率=72000 000/( (ARR+1)(PSC+1) )*

之后我们讲一下PWM两种模式:PWM1和PWM2模式:
PWM1模式:图上的CCRx就是需要你设置的一个值(这个之后讲),同一个段落里面,当计数到CCRx之前是是高电平,但是一旦计数到CCRx时,之后就会变成低电平,但这个段落结束之后就会到下一个段落,它又会变成高电平知道下一个CCRx的出现,以此反复。
PWM2模式:与PWM1模式相反,同一个段落里面,到CCRx之前位低电平,之后为高电平!
那么设置该模式有一个专属的寄存器:TIMx_CCMR1! 在这里插入图片描述
我们可以看到,
使能PWM1,模式这样写:TIM1->CCMR1|=6<<4; // PWM1模式
使能PWM2,模式这样写:TIM1->CCMR1|=7<<4; //PWM2模式

这样PWM模式使能完成,下面就是预装载使能、输出使能和总使能,特别的:只有TIM1这个高级定时器需要使能MOE,既TIM1->BDTR|=1<<15; !!!
下面是完整的使能过程
TIM1->CCMR1|=1<<3; //CH1预装载使能
TIM1->CCER|=1<<0; //OC1 输出使能
TIM1->BDTR|=1<<15; //MOE 主输出使能

这里的参考手册上的内容我就不一一展示了,有兴趣可以参考,懒的话可以直接调用!
不过值得一提的是如果通道变了的话就必须改变位移的位数,这个读者可以参考手册,下面我会给出其他情况的代码!

下面就是ARPE的使能,和上面的一样,可以直接调用,正常情况下配置不会出特别大的变化。

		TIM1->CR1=0x0080;   	//ARPE使能 
		TIM1->CR1|=0x01;    	//使能定时器1

最后是初始化CCR1的值(如下语句,直接调用,讲解参照上面):
TIM1->CCR1 =PWM_VAL;
这样PWM初始化就语句就完成了!!

那么如果需要在main.c文件中改变PWM的占空比的话就直接给TIM1->CCR1 赋值!!!

那么,这里说一下我的编程习惯:
1、我习惯PWM1
2、我正常将PSC赋值为0,ARR赋值为7199,为什么???这样频率F=72 000 000/( (7199+1)*(0+1) )=1 0000,即一分钟分成10000份,这样方便而且精度很高!
下面就是我写的PWM库:


#include "pwm.h"
/*
此库可以支持的PWM引脚通道对照表:
通道名       对应引脚		复用引脚
PWM1_CH1     PA8			PE9    
PWM1_CH2	 PA9			PE11
PWM1_CH3	 PA10			PE13
PWM1_CH4	 PA11			PE14

PWM2_CH1     PA0            PA15
PWM2_CH2	 PA1			PB3
PWM2_CH3	 PA2			PB10
PWM2_CH4	 PA3			PB11

PWM3_CH1 	 PA6			PB4
PWM3_CH2	 PA7			PB5
PWM3_CH3	 PB0			PC8
PWM4_CH4	 PB1			PC9

PWM4_CH1	 PB6			PD12
PWM4_CH2	 PB7			PD13
PWM4_CH3	 PB8			PD14
PWM4_CH4	 PB9			PD15
*/

#define arr_init 7199     //频率=72000 000/( (7199+1)*(0+1) ),每秒10000次
#define psc_init 0

/*
函数名:PWM初始化函数
参数:一:PWM通道
	 二:初始PWM值
时间:2019.8.14
例:PWM_Init(PWM1_CH1,0);
注:本pwm初始化库,可以控制TIM1~TIM4定时共输出16路定时器
TIM1->CCMR1|=7<<4;  	//CH1 PWM2模式适用于led
*/
void PWM_Init(PWM_Ch n,u16 PWM_VAL)
{
	switch(n)
	{
		case PWM1_CH1://PA8
		{
			RCC->APB2ENR|=1<<11; 	//TIM1时钟使能   
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 			
			GPIOA->CRH&=0XFFFFFFF0;	//PA8清除之前的设置
			GPIOA->CRH|=0X0000000B;	//复用功能输出 
			
			TIM1->ARR=arr_init;			//设定计数器自动重装值 
			TIM1->PSC=psc_init;			//预分频器设置
			
			TIM1->CCMR1|=6<<4;  	//CH1 PWM1模式		 
			TIM1->CCMR1|=1<<3; 		//CH1预装载使能	 
			TIM1->CCER|=1<<0;   	//OC1 输出使能	   
				TIM1->BDTR|=1<<15;   	//MOE 主输出使能	   
			
			TIM1->CR1=0x0080;   	//ARPE使能 
			TIM1->CR1|=0x01;    	//使能定时器1
			
			TIM1->CCR1 =PWM_VAL;
			
			break;
		}
		case PWM1_CH2://PA9
		{
			RCC->APB2ENR|=1<<11; 	//TIM1时钟使能    
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 
			GPIOA->CRH&=0XFFFFFF0F;	//PA9清除之前的设置
			GPIOA->CRH|=0X000000B0;	//复用功能输出 
	
			TIM1->ARR=arr_init;			//设定计数器自动重装值 
			TIM1->PSC=psc_init;			//预分频器设置

			TIM1->CCMR1|=6<<12;//CH2 PWM1模式
			TIM1->CCMR1|=1<<11; //CH2预装载使能 
			TIM1->CCER|=1<<4; //CH2输出使能 
				TIM1->BDTR |= 1<<15;//TIM1必须要这句话才能输出PWM
			
			TIM1->CR1=0x80; //ARPE使能
			TIM1->CR1|=0x01; //使能定时器2 
			 			
			TIM1->CCR2 =PWM_VAL;
			
			break;
		}
		case PWM1_CH3://PA10
		{
			RCC->APB2ENR|=1<<11; 	//TIM1时钟使能
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 			
			GPIOA->CRH&=0XFFFFF0FF;	//PA10清除之前的设置
			GPIOA->CRH|=0X00000B00;	//复用功能输出 
	
			TIM1->ARR=arr_init;			//设定计数器自动重装值 
			TIM1->PSC=psc_init;			//预分频器设置

			TIM1->CCMR2|=6<<4;//CH2 PWM1模式
			TIM1->CCMR2|=1<<3; //CH2预装载使能 
			TIM1->CCER|=1<<8; //CH2输出使能 
				TIM1->BDTR |= 1<<15;//TIM1必须要这句话才能输出PWM
			
			TIM1->CR1=0x80; //ARPE使能
			TIM1->CR1|=0x01; //使能定时器2 
			 
			TIM1->CCR3 =PWM_VAL;
			
			break;
		}
		case PWM1_CH4://PA11
		{
			RCC->APB2ENR|=1<<11; 	//TIM1时钟使能
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 			
			GPIOA->CRH&=0XFFFF0FFF;	//PA10清除之前的设置
			GPIOA->CRH|=0X0000B000;	//复用功能输出 
	
			TIM1->ARR=arr_init;			//设定计数器自动重装值 
			TIM1->PSC=psc_init;			//预分频器设置

			TIM1->CCMR2|=6<<12;//CH2 PWM1模式
			TIM1->CCMR2|=1<<11; //CH2预装载使能 
			TIM1->CCER|=1<<12; //CH2输出使能 
				TIM1->BDTR |= 1<<15;//TIM1必须要这句话才能输出PWM
			
			TIM1->CR1=0x80; //ARPE使能
			TIM1->CR1|=0x01; //使能定时器2 
			 
			TIM1->CCR3 =PWM_VAL;
			
			break;
		}
		
		case PWM2_CH1://PA0
		{
			RCC->APB1ENR|=1; //使能TIM2时钟 
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 
			GPIOA->CRL&=0XFFFFFFF0; //PA 0 复位
			GPIOA->CRL|=0X0000000B; //PA 0 复用输出
		 
			TIM2->ARR=arr_init;//设定计数器自动重装值
			TIM2->PSC=psc_init; //预分频器不分频
			
			TIM2->CCMR1|=6<<4; //CH1 PWM1模式
			TIM2->CCMR1|=1<<3; //CH1预装载使能
			TIM2->CCER|=1<<0; //CH1输出使能
			
			TIM2->CR1=0x80; //ARPE使能
			TIM2->CR1|=0x01; //使能定时器2
			
			TIM2->CCR1 =PWM_VAL;
		}
		case PWM2_CH2://PA1
		{
			RCC->APB1ENR|=1; //使能TIM2时钟 
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 
			GPIOA->CRL&=0XFFFFFF0F; //PA  1复位
			GPIOA->CRL|=0X000000B0; //PA  1复用输出

			TIM2->ARR=arr_init;//设定计数器自动重装值
			TIM2->PSC=psc_init; //预分频器不分频
			
			TIM2->CCMR1|=6<<12;//CH2 PWM1模式
			TIM2->CCMR1|=1<<11; //CH2预装载使能 
			TIM2->CCER|=1<<4; //CH2输出使能 

			TIM2->CR1=0x80; //ARPE使能
			TIM2->CR1|=0x01; //使能定时器2 
			
			TIM2->CCR2 =PWM_VAL;
		}
		case PWM2_CH3://PA2
		{
			RCC->APB1ENR|=1; //使能TIM2时钟 
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 
			GPIOA->CRL&=0XFFFFF0FF;	//PA2清除之前的设置
			GPIOA->CRL|=0X00000B00;	//复用功能输出 
	
			TIM2->ARR=arr_init;			//设定计数器自动重装值 
			TIM2->PSC=psc_init;			//预分频器设置

			TIM2->CCMR2|=6<<4;//CH3 PWM1模式
			TIM2->CCMR2|=1<<3; //CH3预装载使能 
			TIM2->CCER|=1<<8; //CH3输出使能 
			
			TIM2->CR1=0x80; //ARPE使能
			TIM2->CR1|=0x01; //使能定时器2 
			 
			TIM2->CCR3 =PWM_VAL;
			
			break;
		}
		case PWM2_CH4://PA3
		{
			RCC->APB1ENR|=1; //使能TIM2时钟   
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 			
			GPIOA->CRL&=0XFFFF0FFF;	//PA3清除之前的设置
			GPIOA->CRL|=0X0000B000;	//复用功能输出 
	
			TIM2->ARR=arr_init;			//设定计数器自动重装值 
			TIM2->PSC=psc_init;			//预分频器设置

			TIM2->CCMR2|=6<<12;//CH4 PWM1模式
			TIM2->CCMR2|=1<<11; //CH4预装载使能 
			TIM2->CCER|=1<<12; //CH4输出使能 
			
			TIM2->CR1=0x80; //ARPE使能
			TIM2->CR1|=0x01; //使能定时器2 
			 
			TIM2->CCR4 =PWM_VAL;
			
			break;
		}
		
		case PWM3_CH1://PA6
		{
			RCC->APB1ENR|=1<<1; //使能TIM3时钟 
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 
			GPIOA->CRL&=0XF0FFFFFF; //PA6复位
			GPIOA->CRL|=0X0B000000; //PA6 复用输出

			TIM3->ARR=arr_init;//设定计数器自动重装值
			TIM3->PSC=psc_init; //预分频器不分频
			
			TIM3->CCMR1|=6<<4; //CH1 PWM1模式
			TIM3->CCMR1|=1<<3; //CH1预装载使能
			TIM3->CCER|=1<<0; //CH1输出使能
			
			TIM3->CR1=0x80; //ARPE使能
			TIM3->CR1|=0x01; //使能定时器2
			
			TIM3->CCR1 =PWM_VAL;
			
			break;
		}
		case PWM3_CH2://PA7
		{
			RCC->APB1ENR|=1<<1; //使能TIM3时钟 
			RCC->APB2ENR|=1<<2; //GPIOA时钟使能 
			GPIOA->CRL&=0X0FFFFFFF; //PA7 复位
			GPIOA->CRL|=0XB0000000; //PA7 复用输出
		 
			TIM3->ARR=arr_init;//设定计数器自动重装值
			TIM3->PSC=psc_init; //预分频器不分频
			
			TIM3->CCMR1|=6<<12;//CH2 PWM1模式
			TIM3->CCMR1|=1<<11; //CH2预装载使能 
			TIM3->CCER|=1<<4; //CH2输出使能 

			TIM3->CR1=0x80; //ARPE使能
			TIM3->CR1|=0x01; //使能定时器2 
			
			TIM3->CCR2 =PWM_VAL;
			
			break;
		}
		case PWM3_CH3://PB0
		{
			RCC->APB1ENR|=1<<1; //使能TIM3时钟
			RCC->APB2ENR|=1<<3;			
			GPIOB->CRL&=0XFFFFFFF0;	//PB0清除之前的设置
			GPIOB->CRL|=0X0000000B;	//复用功能输出 
	
			TIM3->ARR=arr_init;			//设定计数器自动重装值 
			TIM3->PSC=psc_init;			//预分频器设置

			TIM3->CCMR2|=6<<4;//CH3 PWM1模式
			TIM3->CCMR2|=1<<3; //CH3预装载使能 
			TIM3->CCER|=1<<8; //CH3输出使能 
			
			TIM3->CR1=0x80; //ARPE使能
			TIM3->CR1|=0x01; //使能定时器2 
			 
			TIM3->CCR3 =PWM_VAL;
			
			break;
		}
		case PWM3_CH4://PB1
		{
			RCC->APB1ENR|=1<<1; //使能TIM3时钟 
			RCC->APB2ENR|=1<<3;
			GPIOB->CRL&=0XFFFFFF0F;	//PB1清除之前的设置
			GPIOB->CRL|=0X000000B0;	//复用功能输出 
	
			TIM3->ARR=arr_init;			//设定计数器自动重装值 
			TIM3->PSC=psc_init;			//预分频器设置

			TIM3->CCMR2|=6<<12;//CH4 PWM1模式
			TIM3->CCMR2|=1<<11; //CH4预装载使能 
			TIM3->CCER|=1<<12; //CH4输出使能 
			
			TIM3->CR1=0x80; //ARPE使能
			TIM3->CR1|=0x01; //使能定时器2 
			 
			TIM3->CCR4 =PWM_VAL;
			
			break;
		}
		
		///
		case PWM4_CH1://PB6
		{
			RCC->APB1ENR|=1<<2; //使能TIM4时钟 
			RCC->APB2ENR|=1<<3; //GPIOB时钟使能 
			GPIOB->CRL&=0XF0FFFFFF; //PB6复位
			GPIOB->CRL|=0X0B000000; //PB6 复用输出
		 
			TIM4->ARR=arr_init;//设定计数器自动重装值
			TIM4->PSC=psc_init; //预分频器不分频
			
			TIM4->CCMR1|=6<<4; //CH1 PWM1模式
			TIM4->CCMR1|=1<<3; //CH1预装载使能
			TIM4->CCER|=1<<0; //CH1输出使能
			
			TIM4->CR1=0x80; //ARPE使能
			TIM4->CR1|=0x01; //使能定时器2
			
			TIM4->CCR1 =PWM_VAL;
			
			break;
		}
		case PWM4_CH2://PB7
		{
			RCC->APB1ENR|=1<<2; //使能TIM4时钟 
			RCC->APB2ENR|=1<<3; //GPIOB时钟使能 
			GPIOB->CRL&=0X0FFFFFFF; //PB7复位
			GPIOB->CRL|=0XB0000000; //PB7 复用输出
		 
			TIM4->ARR=arr_init;//设定计数器自动重装值
			TIM4->PSC=psc_init; //预分频器不分频
			
			TIM4->CCMR1|=6<<12;//CH2 PWM1模式
			TIM4->CCMR1|=1<<11; //CH2预装载使能 
			TIM4->CCER|=1<<4; //CH2输出使能 

			TIM4->CR1=0x80; //ARPE使能
			TIM4->CR1|=0x01; //使能定时器2 
			
			TIM4->CCR2 =PWM_VAL;
			
			break;
		}
		case PWM4_CH3://PB8
		{
			RCC->APB1ENR|=1<<2; //使能TIM4时钟 
			RCC->APB2ENR|=1<<3; //GPIOB时钟使能 
			GPIOB->CRH&=0XFFFFFFF0; //PB8复位
			GPIOB->CRH|=0X0000000B; //PB8 复用输出
	
			TIM4->ARR=arr_init;//设定计数器自动重装值
			TIM4->PSC=psc_init; //预分频器不分频

			TIM4->CCMR2|=6<<4;//CH3 PWM1模式
			TIM4->CCMR2|=1<<3; //CH3预装载使能 
			TIM4->CCER|=1<<8; //CH3输出使能 
			
			TIM4->CR1=0x80; //ARPE使能
			TIM4->CR1|=0x01; //使能定时器2 
			 
			TIM4->CCR3 =PWM_VAL;
			
			break;
		}
		case PWM4_CH4://PB9
		{
			RCC->APB1ENR|=1<<2; //使能TIM4时钟 
			RCC->APB2ENR|=1<<3; //GPIOB时钟使能 
			GPIOB->CRH&=0XFFFFFF0F; //PB9复位
			GPIOB->CRH|=0X000000B0; //PB9 复用输出
	
			TIM4->ARR=arr_init;//设定计数器自动重装值
			TIM4->PSC=psc_init; //预分频器不分频

			TIM4->CCMR2|=6<<12;//CH4 PWM1模式
			TIM4->CCMR2|=1<<11; //CH4预装载使能 
			TIM4->CCER|=1<<12; //CH4输出使能 
			
			TIM4->CR1=0x80; //ARPE使能
			TIM4->CR1|=0x01; //使能定时器2 
			 
			TIM4->CCR4 =PWM_VAL;
			
			break;
		}
	}
}
/*
函数名:占空比设置函数
参数:一:PWM通道
	 二:占空比大小(0~10000)
时间:2019.8.14
例:PWM_duty(PWM1_CH1,1000);
*/
void PWM_duty(PWM_Ch n,u16 PWM_DUTY)
{
	float PWM_VAL;

	PWM_VAL=(arr_init*PWM_DUTY/10000.0);
	switch(n)
	{
		case PWM1_CH1://PA8
		{
			TIM1->CCR1 =PWM_VAL;
			break;
		} 
		case PWM1_CH2://PA9
		{
			TIM1->CCR2 =PWM_VAL;
			break;
		} 
		case PWM1_CH3://PA10
		{
			TIM1->CCR3 =PWM_VAL;
			break;
		} 
		case PWM1_CH4://PA11
		{
			TIM1->CCR4 =PWM_VAL;
			break;
		} 
		
		case PWM2_CH1://PA0
		{
			TIM2->CCR1 =PWM_VAL;
			break;
		} 
		case PWM2_CH2://PA1
		{
			TIM2->CCR2 =PWM_VAL;
			break;
		}
		case PWM2_CH3://PA2
		{
			TIM2->CCR3 =PWM_VAL;
			break;
		}
		case PWM2_CH4://PA3
		{
			TIM2->CCR4 =PWM_VAL;
			break;
		}

		case PWM3_CH1://PA6
		{
			TIM3->CCR1 =PWM_VAL;
			break;
		} 
		case PWM3_CH2://PA7
		{
			TIM3->CCR2 =PWM_VAL;
			break;
		} 
		case PWM3_CH3://PB0
		{
			TIM3->CCR3 =PWM_VAL;
			break;
		} 
		case PWM3_CH4://PB1
		{
			TIM3->CCR4 =PWM_VAL;
			break;
		} 
		
		case PWM4_CH1://PB6
		{
			TIM4->CCR1 =PWM_VAL;
			break;
		} 
		case PWM4_CH2://PB7
		{
			TIM4->CCR2 =PWM_VAL;
			break;
		} 
		case PWM4_CH3://PB8
		{
			TIM4->CCR3 =PWM_VAL;
			break;
		} 
		case PWM4_CH4://PB9
		{
			TIM4->CCR4 =PWM_VAL;
			break;
		} 
	}
}

下面是头文件部分

#ifndef __PWM_H
#define __PWM_H

#include "sys.h"

typedef enum
{
	PWM1_CH1,//TIM1_CH1,
	PWM1_CH2,//TIM1_CH2,
	PWM1_CH3,//TIM1_CH3,
	PWM1_CH4,//TIM1_CH4,
	
	PWM2_CH1,//TIM2_CH1,
	PWM2_CH2,//TIM2_CH2,
	PWM2_CH3,//TIM2_CH3,
	PWM2_CH4,//TIM2_CH4,
	
	PWM3_CH1,//TIM3_CH1,
	PWM3_CH2,//TIM3_CH2,
	PWM3_CH3,//TIM3_CH3,
	PWM3_CH4,//TIM3_CH4,
	
	PWM4_CH1,//TIM4_CH1,
	PWM4_CH2,//TIM4_CH2,
	PWM4_CH3,//TIM4_CH3,
	PWM4_CH4,//TIM4_CH4,
	
//	PWM5_CH1,//TIM5_CH1,
//	PWM5_CH2,//TIM5_CH2,
//	PWM5_CH3,//TIM5_CH3,
//	PWM5_CH4,//TIM5_CH4,
}PWM_Ch;

void PWM_Init(PWM_Ch n,u16 PWM_VAL);
void PWM_duty(PWM_Ch n,u16 PWM_DUTY);

#endif


如果你直接使用这个库,你会觉得真的十分方便,我举个实例:

void main ()
{
PWM_Init(PWM1_CH1,0);//初始化PWM1通道1
while(1)
{
PWM_duty(PWM1_CH1,1000)//将PWM设为1000,最大10000,即10%;
}
}

那么如果大家有什么不明白,或者觉得我上面讲的或是库里面有什么错误,随时可以私信我,奉上我的个人qq:468001647
也十分希望有喜欢单片机技术的同学和我交流,大家一起进步!!!

注:需要工程库的加我qq:468001647

  • 12
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
定时器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 ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值