天天看點

STM32 PWM源碼分析 一、LED初始化二、TIM3時鐘初始化三、主函數 四、整體代碼分析

1.實驗器材:

    STM32F103c8

2.實驗目的:

    學習定時器的PWM功能

3.硬體資源:

  •     DS0(連接配接在PB5)
  •     定時器3(TIM3),使用TIM3的通道2(CH2),開啟部分重映射,将TIM3_CH2輸出到PB5.  進而實作PWM輸出控制DS0亮度.

4.實驗現象:

    本實驗,DS0由暗到亮,再由亮到暗,再由暗到亮,依次循環.

 一、LED初始化

代碼分析:

1.聲明GPIO _Initure:

GPIO_InitTypeDef GPIO_Initure
           

2.初始化GPIOB、GPIOE的時鐘:

__HAL_RCC_GPIOB_CLK_ENABLE();

__HAL_RCC_GPIOB_CLK_ENABLE();
           

3.對GPIOB和GPIOE進行配置

GPIO_Initure.Pin=GPIO_PIN_5; 				//PB5
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  	//推挽輸出
GPIO_Initure.Pull=GPIO_PULLUP;          	//上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH;    	 	//高速
           

4.調用GPIO初始化函數,進行初始化:

HAL_GPIO_Init(GPIOB,&GPIO_Initure);
           

5.GPIOE也類似進行初始化,GPIOE和GPIOB的配置是一樣的。

GPIO_Initure.Pin=GPIO_PIN_5; 				//PE5
HAL_GPIO_Init(GPIOE,&GPIO_Initure);
           

6.設定GPIOB和GPIOE的預設狀态

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);	//PB5置1,預設初始化後燈滅
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET);	//PE5置1,預設初始化
           

LED_Init整體代碼:

void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;

    __HAL_RCC_GPIOB_CLK_ENABLE();           	//開啟GPIOB時鐘
	__HAL_RCC_GPIOE_CLK_ENABLE();           	//開啟GPIOE時鐘
	
    GPIO_Initure.Pin=GPIO_PIN_5; 				//PB5
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  	//推挽輸出
    GPIO_Initure.Pull=GPIO_PULLUP;          	//上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;    	 	//高速
    HAL_GPIO_Init(GPIOB,&GPIO_Initure);

	GPIO_Initure.Pin=GPIO_PIN_5; 				//PE5
	HAL_GPIO_Init(GPIOE,&GPIO_Initure);
	
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);	//PB5置1,預設初始化後燈滅
    HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET);	//PE5置1,預設初始化後燈滅
}
           

二、TIM3時鐘初始化

1.配置定時器TIM3的句柄和TIM3通道2的句柄

TIM_HandleTypeDef 	TIM3_Handler;      	//定時器句柄 
TIM_OC_InitTypeDef 	TIM3_CH2Handler;		//定時器3通道2句柄
           

2.通用定時器3中斷初始化函數

  • arr:自動裝載值
  • psc:時鐘預分頻數
  • CounterMode:控制模式
  • ClockDivsion分頻模式
//arr:自動重裝值。
//psc:時鐘預分頻數
//定時器溢出時間計算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定時器工作頻率,機關:Mhz
//這裡使用的是定時器3!
void TIM3_Init(u16 arr,u16 psc)
{  
    TIM3_Handler.Instance=TIM3;                          //通用定時器3
    TIM3_Handler.Init.Prescaler=psc;                     //分頻系數
    TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上計數器
    TIM3_Handler.Init.Period=arr;                        //自動裝載值
    TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//時鐘分頻因子
    HAL_TIM_Base_Init(&TIM3_Handler);
    
    HAL_TIM_Base_Start_IT(&TIM3_Handler); //使能定時器3和定時器3更新中斷:TIM_IT_UPDATE   
}
           

3.PWM的部分初始化函數

1.配置TIM3的基本特性:Prescaler,CounterMode,Period,ClockDivision

2.調用PWM的初始化函數:HAL_TIM_PWM_Init()

2.PWM的模式OCMode為:TIM_OCMODE_PWM1

3.設定比較值 來确定占空比:TIM3_CH2Handler.Pulse=arr/2; 

4.選擇TIM3的通道2來作為PWM的産生。

//arr:自動重裝值。
//psc:時鐘預分頻數
//定時器溢出時間計算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定時器工作頻率,機關:Mhz
void TIM3_PWM_Init(u16 arr,u16 psc)
{  
    TIM3_Handler.Instance=TIM3;          	//定時器3
    TIM3_Handler.Init.Prescaler=psc;       //定時器分頻
    TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;//向上計數模式
    TIM3_Handler.Init.Period=arr;          //自動重裝載值
    TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_PWM_Init(&TIM3_Handler);       //初始化PWM
    
    TIM3_CH2Handler.OCMode=TIM_OCMODE_PWM1; //模式選擇PWM1
    TIM3_CH2Handler.Pulse=arr/2;            //設定比較值,此值用來确定占空比,預設比較值為自動重裝載值的一半,即占空比為50%
    TIM3_CH2Handler.OCPolarity=TIM_OCPOLARITY_LOW; //輸出比較極性為低 
    HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH2Handler,TIM_CHANNEL_2);//配置TIM3通道2
	
    HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_2);//開啟PWM通道2
	 	   
}
           

4.定時器的底層驅動(時鐘使能、引腳配置)

PS:該函數會被HAL_TIM_PWM_Init()調用

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
	GPIO_InitTypeDef GPIO_Initure;
	
    if(htim->Instance==TIM3)
	{
		__HAL_RCC_TIM3_CLK_ENABLE();			//使能定時器3
		__HAL_AFIO_REMAP_TIM3_PARTIAL();		//TIM3通道引腳部分重映射使能
		__HAL_RCC_GPIOB_CLK_ENABLE();			//開啟GPIOB時鐘
		
		GPIO_Initure.Pin=GPIO_PIN_5;           	//PB5
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;  	//複用推挽輸出
		GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
		GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
		HAL_GPIO_Init(GPIOB,&GPIO_Initure); 	
	}
}
           

5.設定TIM3通道2的比較值

void TIM_SetTIM3Compare2(u32 compare)
{
	TIM3->CCR2=compare; 
}
           

6.定時器中斷服務函數

void TIM3_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&TIM3_Handler);
}
           

7.定時器回調函數,由定時器中斷服務函數調用

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim==(&TIM3_Handler))
    {
//        LED1=!LED1;        //LED1反轉
    }
}
           

三、主函數

1.初始化HAL庫

2.設定時鐘

3.初始化delay函數

4.初始化序列槽、LED燈

5.TIM3的PWM的初始化

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

int main(void)
{
	u8 dir=1;
    u16 led0pwmval=0; 
	
    HAL_Init();                    	 	//初始化HAL庫    
    Stm32_Clock_Init(RCC_PLL_MUL9);   	//設定時鐘,72M
	delay_init(72);               		//初始化延時函數
	uart_init(115200);					//初始化序列槽
	LED_Init();							//初始化LED	
	KEY_Init();							//初始化按鍵
    TIM3_PWM_Init(500-1,72-1);       	//72M/72=1M的計數頻率,自動重裝載為500,那麼PWM頻率為1M/500=2kHZ
    while(1)
    {
		delay_ms(10);	 	
		if(dir)led0pwmval++;				//dir==1 led0pwmval遞增
		else led0pwmval--;					//dir==0 led0pwmval遞減 
		if(led0pwmval>300)dir=0;			//led0pwmval到達300後,方向為遞減
		if(led0pwmval==0)dir=1;				//led0pwmval遞減到0後,方向改為遞增
		TIM_SetTIM3Compare2(led0pwmval);	//修改比較值,修改占空比
    }
}
           

 四、整體代碼分析

1.主函數代碼執行流程:

STM32 PWM源碼分析 一、LED初始化二、TIM3時鐘初始化三、主函數 四、整體代碼分析

2.GPIO的屬性:

STM32 PWM源碼分析 一、LED初始化二、TIM3時鐘初始化三、主函數 四、整體代碼分析

3.定時器TIM3和PWM

STM32 PWM源碼分析 一、LED初始化二、TIM3時鐘初始化三、主函數 四、整體代碼分析

繼續閱讀