昨天剛寫了篇文章分析定時器pwm輸出初始化,以爲都懂了再用會很簡單,今天使用TIM17就出問題了— 。—
使用TIM17_CH1N對應引腳PB7,因爲之前用的定時器15也是CH1N,就直接把TIM15的初始化搬過來改成TIM17,結果TIM15是有波形輸出,而TIM17沒有任何輸出!!!真是奇怪了。。
void TIM17_PWM_Init(void)
{
uint16_t ChannelPulse = 0,PWM_TimerPeriod;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//引腳初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM17 , ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);//使能GPIOA時鐘和複用功能時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //TIM2二通道PWM波形輸出端口PA1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//設置引腳爲推輓輸出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //設置引腳爲上拉
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設置引腳速度爲50MHZ
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_2);
/*
系統時鐘48mhz,180us,週期10ms,48*1000*10 >65535,要分頻
*/
PWM_TimerPeriod = (unsigned int)( 1000*25 ) - 1;
ChannelPulse = (uint16_t) (((uint32_t) 45 * (PWM_TimerPeriod - 1)) / 100);//佔空比5%
/* Time 定時基礎設置*/
TIM_TimeBaseStructure.TIM_Prescaler = 48-1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; /* Time 定時設置爲上升沿計算模式*/
TIM_TimeBaseStructure.TIM_Period = PWM_TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM17, &TIM_TimeBaseStructure);
TIM_ARRPreloadConfig(TIM17, ENABLE);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM脈衝寬度調製模式1
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;//輸出空閒狀態
TIM_OCInitStructure.TIM_Pulse =ChannelPulse;
TIM_OC1Init(TIM17, &TIM_OCInitStructure); //根據TIM_OCInitStruct中指定的參數初始化外設TIMx
TIM_OC1PreloadConfig(TIM17, TIM_OCPreload_Enable); //使能TIMx在CCR1上的預裝載寄存器
TIM_Cmd(TIM17, ENABLE);
/* TIM1 Main Output Enable */
TIM_CtrlPWMOutputs(TIM17, ENABLE);
}
開始找原因:
先對比T15和T17寄存器值的區別,沒問題,再看手冊,T17的寄存器沒發現問題。。
試試修改參數,將有效脈衝由低改成高等改參數,沒有波形;
T17開中斷,中斷函數加一個輸出引腳的翻轉,量這個引腳是會翻轉,說明定時器計時沒問題;
試試CH1通道輸出pwm有沒有波形,將引腳改爲PB9,輸出有波形!!再將CH1N也加進來,都有波形了!!
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM脈衝寬度調製模式1
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//TIM_OutputState_Enable
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OCInitStructure.TIM_OCPolarity= TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState= TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;//輸出空閒狀態
TIM_OCInitStructure.TIM_Pulse =ChannelPulse; //1200設置待裝入捕獲比較寄存器的脈衝值,取值必須在0x0000~0xFFFF之間,佔空1200/2400
TIM_OC1Init(TIM17, &TIM_OCInitStructure); //根據TIM_OCInitStruct中指定的參數初始化外設TIMx
那就是CH1的參數影響CH1N了,將TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
//TIM_OCInitStructure.TIM_OCPolarity= TIM_OCPolarity_High;隱掉這句,都沒影響,還是有波形,那就差
TIM_OCInitStructure.TIM_OCIdleState= TIM_OCIdleState_Reset;就是這句影響了,將這句隱掉後就跟一開始一樣,CH1N沒有波形!!
那就看看這句到底是怎麼影響的?
對比寄存器變化:
(隱掉TIM_OCIdleState) (未隱掉TIM_OCIdleState)
看TIM_OCIdleState_Reset ((uint16_t)0x0000)定義,並沒有涉及其他位,怎麼會有三位的值變化了,再看是不是不設置的話默認值不是0,仿真調試發現,沒有設置TIM_OCIdleState時默認成了0x0115,也就是CR2|=0X0115,這也就解釋了OIS1 (bit8)CCUS(bit2) CCPC(bit0)位都置1的原因了。
這個默認值0x0115是怎麼來的??(未解決)
繼續查是哪一位影響的:
將CCPC=0後有波形,
CCPC=1時沒有波形。所以這一位導致的沒有輸出,那看看這一位是幹什麼的:
僅在有互補輸出時起作用??(未解決)
TIM_OC1Init函數裏:雖然寫着assert_param檢查參數範圍,但是assert_param沒有起作用,因爲它的宏定義沒有開。所以TIM_OCIdleState的值超範圍了也沒報錯。
另外,TIM_OutputState,TIM_OCPolarity不設置使用默認值的話並不是0,雖然這個值沒有影響。。。
對了,這個問題對TIM15並沒有影響,TIM15的TIM_OCIdleState也是0x0115,但是它能有波形,奇怪不奇怪?
暫時的結論:
初始化設置完整一點,即使互補通道中只用一個通道,還是要將結構體TIM_OCInitStructure裏的參數都附一個值:
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM脈衝寬度調製模式1
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;//
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OCInitStructure.TIM_OCPolarity= TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState= TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;//輸出空閒狀態TIM_OCInitStructure.TIM_Pulse =ChannelPulse;
TIM_OC1Init(TIM17, &TIM_OCInitStructure);