【實驗?zāi)康摹?/p>
輸出7路占空比不同的PWM信號是各個版本ST庫必備的例子。本實驗的主要目的不是表現(xiàn)ST芯片PWM功能的強大,而是要完成輸出的精確計算。
【實驗內(nèi)容】
輸出7路PWM信號,并用示波器測量輸出。
【實驗原理】
1、時基單元初始化
TIM1和TIM8使用內(nèi)部時鐘時,時鐘由APB2提供。但是定時器的時鐘并不是直接由APB2提供,而是來自于輸入為APB2的一個倍頻器。當(dāng)APB2的與分頻系數(shù)為1時,這個倍頻器不起作用,定時器時鐘頻率等于APB2時鐘。當(dāng)APB2預(yù)分頻系數(shù)為其他時這個倍頻器起作用。定時器的輸入頻率等于APB2的2倍。本實驗中,APB2時鐘被設(shè)置成了84M是對系統(tǒng)時鐘進行2分頻。因此定時器的輸入時鐘是84M×2 = 168M = SYSCLK。(PS:這個倍頻我在ST的手冊上邊沒有找到,是網(wǎng)上搜索得到的結(jié)果,與實際結(jié)果對比是正確的)
TIM_Prescaler 為預(yù)分頻值,為0時分頻系數(shù)為1.
TIM_Period 為每個周期計數(shù)值,從0開始計數(shù)所以其值應(yīng)為計數(shù)次數(shù)減去1。
TIM_RepetitionCounter是F4新增的一個東西,只有高級定時器TIM1和TIM8有效,對應(yīng)寄存器RCR。意思就是每TIM_RepetitionCounter+1個技術(shù)周期產(chǎn)生一次中斷。
我定義的時基如下,將產(chǎn)生頻率為20K的即使基準(zhǔn):
TimerPeriod = (SystemCoreClock / 20000 ) - 1;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
//時基初始化
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //死區(qū)控制用。
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數(shù)器方向
TIM_TimeBaseInitStructure.TIM_Prescaler = 0; //Timer clock = sysclock /(TIM_Prescaler+1) = 168M
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInitStructure.TIM_Period = TimerPeriod - 1; //Period = (TIM counter clock / TIM output clock) - 1 = 20K
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);
2、計時輸出
ccr1、2、3、4為各個技術(shù)周期的TIM_Pulse。即每當(dāng)計數(shù)到這些個值的時候,PWM波形就會反轉(zhuǎn)。
ccr1 = TimerPeriod / 2; //占空比1/2 = 50%
ccr2 = TimerPeriod / 3; //占空比1/3 = 33%
ccr3 = TimerPeriod / 4; //占空比1/4 = 25%
ccr4 = TimerPeriod / 5; //占空比1/5 = 20%
定義輸出部分:
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = ccr1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;//輸出同相,TIM_OCNPolarity_High時輸出反相
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;TIM_OC1Init(TIM1,&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ccr2;
TIM_OC2Init(TIM1,&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ccr3;
TIM_OC3Init(TIM1,&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ccr4;
TIM_OC4Init(TIM1,&TIM_OCInitStructure);TIM_Cmd(TIM1,ENABLE);
TIM_CtrlPWMOutputs(TIM1,ENABLE);
3、到這里就完成了定時器的配置,下邊是GPIO引腳的配置
使用GPIOE的8、9、10、11、12、13、14引腳進行PWM輸出。配置如下:
void TIM1_GPIO_Config(void)
{
//PE 8 9 10 11 12 13 14輸出
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11
| GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_TIM1);
}
輸出波形圖:
同相輸出時候:
OC1/OC1N
OC2/OC2N
OC3/OC3/N
OC4
反相輸出
OC1/OC1N
OC2/OC2N
OC3/OC3/N
OC4
完整的應(yīng)用代碼:
使用時只主要兩行即可
//主函數(shù)調(diào)用
TIM1_GPIO_Config();
Tim1_Config();
//定時器輸出引腳初始化
void TIM1_GPIO_Config(void)
{
//PE 8 9 10 11 12 13 14輸出
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11
| GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_TIM1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_TIM1);
}
//TIM1做PWM輸出
void Tim1_Config(void)
{
TimerPeriod = (SystemCoreClock / 20000 ) - 1;
ccr1 = TimerPeriod / 2; //占空比1/2 = 50%
ccr2 = TimerPeriod / 3; //占空比1/3 = 33%
ccr3 = TimerPeriod / 4; //占空比1/4 = 25%
ccr4 = TimerPeriod / 5; //占空比1/5 = 20%
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
//時基初始化
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //死區(qū)控制用。
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數(shù)器方向
TIM_TimeBaseInitStructure.TIM_Prescaler = 0; //Timer clock = sysclock /(TIM_Prescaler+1) = 168M
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInitStructure.TIM_Period = TimerPeriod - 1; //Period = (TIM counter clock / TIM output clock) - 1 = 20K
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = ccr1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(TIM1,&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ccr2;
TIM_OC2Init(TIM1,&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ccr3;
TIM_OC3Init(TIM1,&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ccr4;
TIM_OC4Init(TIM1,&TIM_OCInitStructure);
TIM_Cmd(TIM1,ENABLE);
TIM_CtrlPWMOutputs(TIM1,ENABLE);
}