STM32F103 使用TIM3產生四路PWM


STM32F103 使用TIM3產生四路PWM 

程序如下:

/*******************************************************************************
* 程序說明         : 思路PWM波生成函數
* 函數功能         : 使用TIM3的PWM功能生成思路PWM,
* 輸    入         : 無
* 輸    出         : 四路PWM,通過GPIO引腳復用,對TIM3的四個輸出通道引腳重映射為PC6、PC7、PC8、PC9
*******************************************************************************/





#include"stm32f10x.h"




void RCC_Cfg(void);
void GPIO_Cfg(void);
void TIM_Cfg(void);
void NVIC_Cfg(void);
void delay_ms(u32 i);
void PWM_Cfg(float dutyfactor1,float dutyfactor2,float dutyfactor3,float dutyfactor4);
 
int main()
{
    u8 flag = 1;
      float ooo=0.5;
    RCC_Cfg();
    NVIC_Cfg();
    GPIO_Cfg();
    TIM_Cfg();
    
    //開啟定時器2
    TIM_Cmd(TIM3,ENABLE);
    
      //呼吸燈
    while(1){
            PWM_Cfg(ooo,10,50+0.5*ooo,200-2*ooo);
            
            if(flag == 1)
            {
                  ooo=ooo+0.002;
            }
            if(flag == 0)
            {
                  ooo=ooo-0.002;
            }
            if(ooo>100){
                  flag = 0;
            }
            if(ooo<0.5)
            {
                 flag = 1; 
            }
                  
      }         
}

void GPIO_Cfg(void)
{
    
    GPIO_InitTypeDef GPIO_InitStructure;
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
      
       //全部映射,將TIM3_CH2映射到PB5
       //根據STM32中文參考手冊2010中第第119頁可知:
       //當沒有重映射時,TIM3的四個通道CH1,CH2,CH3,CH4分別對應PA6,PA7,PB0,PB1
       //當部分重映射時,TIM3的四個通道CH1,CH2,CH3,CH4分別對應PB4,PB5,PB0,PB1
       //當完全重映射時,TIM3的四個通道CH1,CH2,CH3,CH4分別對應PC6,PC7,PC8,PC9
       //也即是說,完全重映射之后,四個通道的PWM輸出引腳分別為PC6,PC7,PC8,PC9,我們用到了通道1和通道2,所以對應引腳為PC6,PC7,PC8,PC9,我們用到了通道1和通道2,所以對應引腳為
       GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
      
       //部分重映射的參數
       //GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
    
      
    //設置PC6、PC7、PC8、PC9為復用輸出,輸出4路PWM
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
    GPIO_Init(GPIOC,&GPIO_InitStructure);
    
     

}



void TIM_Cfg(void)
{
     //定義結構體
     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

       //重新將Timer設置為缺省值
       TIM_DeInit(TIM3);
       //采用內部時鍾給TIM2提供時鍾源
       TIM_InternalClockConfig(TIM3);
     
     //預分頻系數為0,即不進行預分頻,此時TIMER的頻率為72MHzre.TIM_Prescaler =0;
       TIM_TimeBaseStructure.TIM_Prescaler = 0;
     //設置計數溢出大小,每計20000個數就產生一個更新事件
       TIM_TimeBaseStructure.TIM_Period = 7200 - 1;
       //設置時鍾分割
       TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
       //設置計數器模式為向上計數模式
       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
       
       //將配置應用到TIM2中
       TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
       //清除溢出中斷標志
       //TIM_ClearFlag(TIM2, TIM_FLAG_Update);
       //禁止ARR預裝載緩沖器
       //TIM_ARRPreloadConfig(TIM2, DISABLE);
       //開啟TIM2的中斷
       //TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
    
}



/*******************************************************************************
* 函 數 名         : PWM波產生配置函數
* 函數功能         : PWM_Cfg
* 輸    入         : dutyfactor 占空比數值,大小從0.014到100
* 輸    出         : 無
*******************************************************************************/
void PWM_Cfg(float dutyfactor1,float dutyfactor2,float dutyfactor3,float dutyfactor4)
{
    TIM_OCInitTypeDef TIM_OCInitStructure;
      //設置缺省值
      TIM_OCStructInit(&TIM_OCInitStructure);
      
      //TIM3的CH1輸出
    TIM_OCInitStructure.TIM_OCMode       = TIM_OCMode_PWM1; //設置是PWM模式還是比較模式 
    TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable; //比較輸出使能,使能PWM輸出到端口
    TIM_OCInitStructure.TIM_OCPolarity   = TIM_OCPolarity_High; //設置極性是高還是低
      //設置占空比,占空比=(CCRx/ARR)*100%或(TIM_Pulse/TIM_Period)*100%
      TIM_OCInitStructure.TIM_Pulse = dutyfactor1 * 7200 / 100;
      TIM_OC1Init(TIM3, &TIM_OCInitStructure);
      
      
      //TIM3的CH2輸出
      TIM_OCInitStructure.TIM_OCMode       = TIM_OCMode_PWM1; //設置是PWM模式還是比較模式 
    TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable; //比較輸出使能,使能PWM輸出到端口
    TIM_OCInitStructure.TIM_OCPolarity   = TIM_OCPolarity_High; //設置極性是高還是低
      //設置占空比,占空比=(CCRx/ARR)*100%或(TIM_Pulse/TIM_Period)*100%
      TIM_OCInitStructure.TIM_Pulse = dutyfactor2 * 7200 / 100;
      TIM_OC2Init(TIM3, &TIM_OCInitStructure);
      
   
      //TIM3的CH3輸出
      TIM_OCInitStructure.TIM_OCMode       = TIM_OCMode_PWM1; //設置是PWM模式還是比較模式 
    TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable; //比較輸出使能,使能PWM輸出到端口
    TIM_OCInitStructure.TIM_OCPolarity   = TIM_OCPolarity_High; //設置極性是高還是低
      //設置占空比,占空比=(CCRx/ARR)*100%或(TIM_Pulse/TIM_Period)*100%
      TIM_OCInitStructure.TIM_Pulse = dutyfactor3 * 7200 / 100;
      TIM_OC3Init(TIM3, &TIM_OCInitStructure);
      
      
      //TIM3的CH4輸出
      TIM_OCInitStructure.TIM_OCMode       = TIM_OCMode_PWM1; //設置是PWM模式還是比較模式 
    TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable; //比較輸出使能,使能PWM輸出到端口
    TIM_OCInitStructure.TIM_OCPolarity   = TIM_OCPolarity_High; //設置極性是高還是低
      //設置占空比,占空比=(CCRx/ARR)*100%或(TIM_Pulse/TIM_Period)*100%
      TIM_OCInitStructure.TIM_Pulse = dutyfactor4 * 7200 / 100;
      TIM_OC4Init(TIM3, &TIM_OCInitStructure);
      
      
      
      
      //使能輸出狀態
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
      
    //設置TIM3的PWM輸出為使能
      TIM_CtrlPWMOutputs(TIM3,ENABLE);
}


void NVIC_Cfg(void)
{    
    //定義結構體
    NVIC_InitTypeDef NVIC_InitStructure;
    
    //選擇中斷分組1
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    
    //選擇TIM2的中斷通道
      NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;      
      //搶占式中斷優先級設置為0
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
      //響應式中斷優先級設置為0
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
      //使能中斷
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    
    NVIC_Init(&NVIC_InitStructure);
}



void RCC_Cfg(void)
{
     //定義錯誤狀態變量
       ErrorStatus HSEStartUpStatus;

       //將RCC寄存器重新設置為默認值
       RCC_DeInit();

       //打開外部高速時鍾晶振
       RCC_HSEConfig(RCC_HSE_ON);

       //等待外部高速時鍾晶振工作
       HSEStartUpStatus = RCC_WaitForHSEStartUp();

       if(HSEStartUpStatus == SUCCESS)
       {
             //設置AHB時鍾(HCLK)為系統時鍾
              RCC_HCLKConfig(RCC_SYSCLK_Div1);

              //設置高速AHB時鍾(APB2)為HCLK時鍾
              RCC_PCLK2Config(RCC_HCLK_Div1);

              //設置低速AHB時鍾(APB1)為HCLK的2分頻
              RCC_PCLK1Config(RCC_HCLK_Div2);
          
              //設置FLASH代碼延時
              FLASH_SetLatency(FLASH_Latency_2);

              //使能預取指緩存
              FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

              //設置PLL時鍾,為HSE的9倍頻 8MHz * 9 = 72MHz
              RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

              //使能PLL
              RCC_PLLCmd(ENABLE);

              //等待PLL准備就緒
              while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

              //設置PLL為系統時鍾源
              RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

              //判斷PLL是否是系統時鍾
              while(RCC_GetSYSCLKSource() != 0x08);
              
       }
       
       //允許TIM2的時鍾
       RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
       
       //允許GPIO的時鍾
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE);

}

void TIM2_IRQHandler(void)
{
    u16 aa=10;
    if(TIM_GetFlagStatus(TIM2,TIM_IT_Update)!=RESET)
    {
        //清除TIM2的中斷待處理位
            TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);
        
        
        TIM_Cmd(TIM2,DISABLE);
            //通過循環讓燈閃爍
        while (aa){
            GPIO_SetBits(GPIOC,GPIO_Pin_3);
            delay_ms(10);
            GPIO_ResetBits(GPIOC,GPIO_Pin_3);
            delay_ms(10);
            aa--;
        }
    //使燈的狀態為滅
    GPIO_SetBits(GPIOC,GPIO_Pin_3);
    TIM_Cmd(TIM2,ENABLE);
    }        
}

void delay_ms(u32 i)
{
    u32 temp;
    SysTick->LOAD=9000*i;      //設置重裝數值, 72MHZ時
    SysTick->CTRL=0X01;        //使能,減到零是無動作,采用外部時鍾源
    SysTick->VAL=0;            //清零計數器
    do
    {
        temp=SysTick->CTRL;       //讀取當前倒計數值
    }
    while((temp&0x01)&&(!(temp&(1<<16))));    //等待時間到達
    SysTick->CTRL=0;    //關閉計數器
    SysTick->VAL=0;        //清空計數器
}

 

在產生PWM時,如果輸出引腳已經被使用,就要對引腳進行重映射,閱讀《STM32中文參考手冊2010》第119頁可知:

對TIM3而言:

1、當沒有重映射時,TIM3的四個通道CH1,CH2,CH3,CH4分別對應PA6,PA7,PB0,PB1
2、當部分重映射時,TIM3的四個通道CH1,CH2,CH3,CH4分別對應PB4,PB5,PB0,PB1
3、當完全重映射時,TIM3的四個通道CH1,CH2,CH3,CH4分別對應PC6,PC7,PC8,PC9

為了整齊,我們選擇完全重映射,使用的函數是:

GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);

如果想使用部分映射,參數用GPIO_PartialRemap_TIM3:

GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM