welcom ! Handel home

2014年6月24日 星期二

ST32 PWM note

STM32----3----PWM 
[ ST32 PWM form Timer ]
TIM6 and TIM7 不能產生 PWM
TIM1 and TIM8 高級計數器 各可以同時產生 7 PWM
TIM2,3,4,5 普通計時器 各可以同時產生 4 PWM
ST32  最多可以同時產生 30PWM(2x7 + 4x4 )

[ PWM Reg ]
TIMx_CCMR1 ..2, (捕獲/比較 mode Reg)
TIMx_CCER     (捕獲/比較 enable Reg)
TIMx_CCR1..4   (捕獲/比較 working Reg)

TIMx_CCMR1 => CH1,CH2
TIMx_CCMR2 => CH3,CH4


 void PWM_Configuration(void)//PWM初始化函數 
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; //計時器初始化結構   
    TIM_OCInitTypeDef        TIM_OCInitStructure;   //通道輸出初始化結構   
    GPIO_InitTypeDef         GPIO_InitStructure;    //輸出通道的GPIO管腳結構  

    //(1)TIM3初始化,時間基部分
    TIM_TimeBaseStructure.TIM_Period =999;              //週期0~999   
    TIM_TimeBaseStructure.TIM_Prescaler = 71;           //時鐘分頻   
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;    //時鐘分割
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //模式   
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);     //基本初始化   
    //TIM_ITConfig(TIM3, TIM_IT_CC4, ENABLE);   //打開中斷,中斷需要這行代碼   

    //(2)TIM3通道初始化 ,CCP部分
    TIM_OCStructInit(& TIM_OCInitStructure);                             //默認參數
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                    //工作狀態
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;        //設定為輸出,需要PWM輸出才需要這行代碼
    TIM_OCInitStructure.TIM_Pulse =250 ;                                 //占空長度
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;            //高電平       
    TIM_OC4Init(TIM3, &TIM_OCInitStructure);                             //通道初始化
    
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                //工作狀態
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;        //設定為輸出,需要PWM輸出才需要這行代碼
    TIM_OCInitStructure.TIM_Pulse =500 ;                                 //占空長度
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;   //高電平   
    TIM_OC3Init(TIM3, &TIM_OCInitStructure);                                  //通道初始化   
    
    //TIM_OC3Init(TIM3, &TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                    //工作狀態
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;        //設定為輸出,需要PWM輸出才需要這行代碼
    TIM_OCInitStructure.TIM_Pulse =750 ;                                 //占空長度
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;            //高電平   
    TIM_OC2Init(TIM3, &TIM_OCInitStructure)
        
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                    //工作狀態
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;        //設定為輸出,需要PWM輸出才需要這行代碼
    TIM_OCInitStructure.TIM_Pulse =900 ;                                 //占空長度
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;            //高電平   
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    
    TIM_Cmd(TIM3, ENABLE);                   //使能TIM3,到此在TIM中已配置完成,下面開始配置GPIO

    //(3)PWM輸出通道初始化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;//選擇PC    
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管腳頻率為50MHZ    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //模式為推挽輸出    
    GPIO_Init(GPIOC, &GPIO_InitStructure);   //初始化GPIOA寄存器   
    GPIO_PinRemapConfig(GPIO_FullRemap_TIM3 , ENABLE);

}


===================================================================
[Ext2:  啟動PWM 範例 5 個步驟]

//Step1.啟動TIM1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

//Step2. PA.8口設置為TIM1的OC1輸出口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//Step3.使能TIM1的輸出比較匹配中斷
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


//Step4. TIM模組設置
void TIM_Configuration(void)
{
    TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;


    //TIM1基本計數器設置
    TIM_BaseInitStructure.TIM_Period = 0xffff;           //這裡必須是65535 ( TIMx_ARR)
    TIM_BaseInitStructure.TIM_Prescaler = 71;          //預分頻71,即72分頻,得1M (TIMx_PSC)
    TIM_BaseInitStructure.TIM_ClockDivision = 0;
    TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_BaseInitStructure.TIM_RepetitionCounter = 0;              
    TIM_TimeBaseInit(TIM1, &TIM_BaseInitStructure);

    //TIM1_OC1模組設置
    TIM_OCStructInit(& TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;  //管腳輸出模式:翻轉
    TIM_OCInitStructure.TIM_Pulse = 2000;                                     //翻轉週期:2000個脈衝
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   //使能TIM1_CH1通道
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //輸出為正邏輯
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);                        //寫入配置

    //清中斷
    TIM_ClearFlag(TIM1, TIM_FLAG_CC1);

    //TIM1中斷源設置,開啟相應通道的捕捉比較中斷
    TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);

    //TIM1開啟
    TIM_Cmd(TIM1, ENABLE);

    //通道輸出使能
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
}

//Step5.TIM1 中斷服務副程式
void TIM1_CC_IRQHandler(void)
{
    u16 capture;
    if(TIM_GetITStatus(TIM1, TIM_IT_CC1) == SET)
    {
        TIM_ClearITPendingBit(TIM1, TIM_IT_CC1 );
        capture = TIM_GetCapture1(TIM1);
        TIM_SetCompare1(TIM1, capture + 2000);
        //這裡解釋下:
        //將TIM1_CCR1的值增加2000,使得下一個TIM事件也需要2000個脈衝,
        //另一種方式是清零脈衝計數器
        //TIM_SetCounter(TIM2,0x0000);
    }
}

=====================================================
[ ext3 PWM drive demo code ]

/*
這個是STM32的PWM輸出模式,STM32的TIM1模組是增強型的計時器模組,天生就是為電機控制而生,可以產生3組6路PWM,同時每組2路PWM為互補,並可以帶有死區,可以用來驅動H橋。

下面的代碼,是利用TIM1模組的1、2通道產生一共4路PWM的代碼例子,
類似代碼也可以參考ST的固件庫中相應exampleC語言:TIM1模組產生PWM,帶死區
*/

//Step1.開啟TIM和相應埠時鐘//啟動GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|\RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,\ENABLE);

//啟動AFIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//啟動TIM1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);

//Step2.GPIO做相應設置,為AF輸出//PA.8/9口設置為TIM1的OC1輸出口
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);

//PB.13/14口設置為TIM1_CH1N和TIM1_CH2N輸出口
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);

//Step3.TIM模組初始化
voidTIM_Configuration(void){
TIM_TimeBaseInitTypeDefTIM_BaseInitStructure;
TIM_OCInitTypeDefTIM_OCInitStructure;
TIM_BDTRInitTypeDefTIM_BDTRInitStructure;

//TIM1基本計數器設置(設置PWM頻率)//頻率=TIM1_CLK/(ARR+1)
TIM_BaseInitStructure.TIM_Period=1000-1;
TIM_BaseInitStructure.TIM_Prescaler=72-1;
TIM_BaseInitStructure.TIM_ClockDivision=0;
TIM_BaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_BaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM1,&TIM_BaseInitStructure);

//啟用ARR的影子寄存器(直到產生更新事件才更改設置)
TIM_ARRPreloadConfig(TIM1,ENABLE);

//TIM1_OC1模組設置(設置1通道占空比)
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_Pulse=120;
TIM_OC1Init(TIM1,&TIM_OCInitStructure);

//啟用CCR1寄存器的影子寄存器(直到產生更新事件才更改設置)
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);

//TIM2_OC2模組設置(設置2通道占空比)
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse=680;
TIM_OC2Init(TIM1,&TIM_OCInitStructure);

//啟用CCR2寄存器的影子寄存器(直到產生更新事件才更改設置)
TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);

//死區設置
TIM_BDTRInitStructure.TIM_OSSRState=TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState=TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel=TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime=0x90;//這裡調整死區大小0-0xff
TIM_BDTRInitStructure.TIM_Break=TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity=TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);

//TIM1開啟
TIM_Cmd(TIM1,ENABLE);

//TIM1_OC通道輸出PWM(一定要加)
TIM_CtrlPWMOutputs(TIM1,ENABLE);

}
//其實,PWM模組還可以有很多花樣可以玩,比方在異常時(如CPU時鐘有問題),可以緊急關閉輸出,以免發生電路燒毀等嚴重事故。

沒有留言: