使用STM32定時器進(jìn)行PWM的配置有以下幾個步驟,以下是參考例差可以作為歷程參考。
/******************************************************************************************************************************
*使用PWM來實(shí)現(xiàn)對電機(jī)的控制,實(shí)現(xiàn)開環(huán)的速度控制
*
*使用四個直流電機(jī) motor1: motor2:
* motor3: motor4:
*
cnt = 0 對應(yīng)占空比0
TIM3:(部分重映像)
CH1:PB4
CH2:PB5
CH3:PB0
CH4:PB1
TIM4:
CH1:PB6
CH2:PB7
CH3:PB8
CH4:PB9
*******************************************************************************************************************************/
void TIM_PWM_Init(void)
{
//設(shè)置變量
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//使能時鐘
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3 | RCC_APB1Periph_TIM4 , ENABLE);
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig( GPIO_PartialRemap_TIM3 , ENABLE);//使定時器TIM4進(jìn)行部分重映像操作
//GPIO_PinRemapConfig(GPIO_Remap_TIM4,ENABLE);
TIM_TimeBaseStructure.TIM_Period = 899;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseInit(TIM3 , &TIM_TimeBaseStructure);
TIM_TimeBaseInit(TIM4 , &TIM_TimeBaseStructure);
//端口復(fù)用
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//PB4:TIM3_CH1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC1Init(TIM3 , &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3 , TIM_OCPreload_Enable);
//PB5:TIM3_CH2
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 450;
TIM_OC2Init(TIM3 , &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3 , TIM_OCPreload_Enable);
//PB0:TIM3_CH3
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC3Init(TIM3 , &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM3 , TIM_OCPreload_Enable);
//PB1:TIM3_CH4
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC4Init(TIM3 , &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3 , TIM_OCPreload_Enable);
//
//PB6:TIM4_CH1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 900;
TIM_OC1Init(TIM4 , &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM4 , TIM_OCPreload_Enable);
//PB7:TIM4_CH2
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 900;
TIM_OC2Init(TIM4 , &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM4 , TIM_OCPreload_Enable);
//PB8:TIM4_CH3
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC3Init(TIM4 , &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM4 , TIM_OCPreload_Enable);
//PB9:TIM4_CH4
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 900;
TIM_OC4Init(TIM4 , &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM4 , TIM_OCPreload_Enable);
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM4, ENABLE);
}
在上述PWM初始化函數(shù)中使用定時器TIM3和TIM4來輸出PWM波,其中為了更好的應(yīng)用IO口的布局等等TIM3進(jìn)行了部分重映像的操作,這意味著部分引腳可以使用重映像的操作使之擁有另外的功能,即讓TIM4本來該復(fù)用的引腳重映像到了其他引腳上。這個時候我們就需要查找相關(guān)的參考手冊來對比引腳關(guān)系。如我使用的STM32F103。
通過表格我們就可以知道我想要使用PB4和PB5作為PWM的輸出引腳,所以對TIM3使用了部分重映像的功能,實(shí)現(xiàn)這個功能的代碼是:
GPIO_PinRemapConfig( GPIO_PartialRemap_TIM3 , ENABLE);//使定時器TIM3進(jìn)行部分重映像操作
? ?? 這里有一個值得注意的地方,若是其他的功能引腳需要復(fù)用IO口,同樣也是需要相同的方法來對該外設(shè)進(jìn)行部分重映像或完全重映像(若是沒有重映象則不需要),而需要重映像對象則可以在庫函數(shù)中找到。如我需要使用PD8和PD9作為USART3的TXD和RXD引腳則需要完全重映像USART3:
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3, ENABLE ); /* 使能USART1,GPIOA時鐘 */
GPIO_PinRemapConfig(GPIO_FullRemap_USART3,ENABLE); //完全重映像USART3,使用PD8和PD9作為USART3的TXD和RXD引腳
除了重映像的問題其余就是以下幾個步驟:
(1)使能時鐘????????
(2)配置GPIO口? pin、speed、mode等,其中mode需選擇為GPIO_Mode_AF_PP復(fù)用輸出。
(3)配置基本的定時器參數(shù),
typedef struct
{
uint16_t TIM_Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock.
This parameter can be a number between 0x0000 and 0xFFFF */
uint16_t TIM_CounterMode; /*!< Specifies the counter mode.
This parameter can be a value of @ref TIM_Counter_Mode */
uint16_t TIM_Period; /*!< Specifies the period value to be loaded into the active
Auto-Reload Register at the next update event.
This parameter must be a number between 0x0000 and 0xFFFF. */
uint16_t TIM_ClockDivision; /*!< Specifies the clock division.
This parameter can be a value of @ref TIM_Clock_Division_CKD */
uint8_t TIM_RepetitionCounter; /*!< Specifies the repetition counter value. Each time the RCR downcounter
reaches zero, an update event is generated and counting restarts
from the RCR value (N).
This means in PWM mode that (N+1) corresponds to:
- the number of PWM periods in edge-aligned mode
- the number of half PWM period in center-aligned mode
This parameter must be a number between 0x00 and 0xFF.
@note This parameter is valid only for TIM1 and TIM8. */
} TIM_TimeBaseInitTypeDef;
TIM_Prescaler:定時器分頻系數(shù)psc,對時鐘頻率進(jìn)行分頻;
TIM_CounterMode:計(jì)數(shù)模式,向上計(jì)數(shù)或是向下計(jì)數(shù)
TIM_Period:時鐘周期
TIM_ClockDivision:時鐘分頻。(設(shè)置為0即可)
(4)配置定時器的輸出參數(shù):
//PB4:TIM3_CH1 TIM3通道1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM1輸出模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 0;//cnt捕獲值,和占空比有關(guān)
TIM_OC1Init(TIM3 , &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3 , TIM_OCPreload_Enable);
PWM的占空比為n = pul/arr
PWM的周期計(jì)算為 T = psc/72M(f103的時鐘頻率)*arr 如arr=1000,psc=7200,arr=1000則可計(jì)算PWM周期為T=7200/72000000*1000=0.1s f=1/T=10HZ
(5)使能TIM定時器文章來源:http://www.zghlxwxcb.cn/news/detail-732734.html
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM4, ENABLE);
TIM_Cmd(TIM2, ENABLE);
這就是初始化PWM的整個流程,希望可以幫助到你。文章來源地址http://www.zghlxwxcb.cn/news/detail-732734.html
到了這里,關(guān)于基于STM32配置PWM的輸出和相關(guān)GPIO口的配置(有關(guān)重映像問題解答)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!