|
最近再做一個(gè)帶藍(lán)牙接口的血壓計(jì)項(xiàng)目,項(xiàng)目中使用了STM32F10364引腳的MCU,在硬件設(shè)計(jì)中,因?yàn)橥庠O(shè)較多,導(dǎo)致每個(gè)通用定時(shí)器至少有兩個(gè)PWM輸出引腳被占用,現(xiàn)在要控制RGB燈,只能用一個(gè)普通IO引腳模擬PWM輸出。
相關(guān)的硬件電路設(shè)置如下:
GPIOA1------------------------------RGBBLUE燈
GPIOB1------------------------------RGBGREEN燈
GPIOD2------------------------------RGBRED燈
RGB燈采用了共陽極電路,所以在PWM的輸出急性設(shè)置時(shí),將極性設(shè)置為高電平,定時(shí)器的初始化如下圖所示:
void initLedTimer( void ){
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_DeInit( TIM2 );
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure );
TIM_TimeBaseStructure.TIM_Period =TIMER_PERIOD;
TIM_TimeBaseStructure.TIM_Prescaler =TIMER_PRESCALER;
TIM_TimeBaseStructure.TIM_ClockDivision= TIM_CKD_DIV1; // 不分頻
TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
TIM_OCStructInit(&TIM_OCInitStructure );
TIM_OCInitStructure.TIM_OCMode =TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState =TIM_OutputState_Disable;
TIM_OCInitStructure.TIM_Pulse =DEFAULT_DUTY_CYCLE;
TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_High;
//
TIM_OC1Init(TIM2,&TIM_OCInitStructure);
//
TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable);
//
TIM_OC2Init(TIM2,&TIM_OCInitStructure);
//
TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);
//
TIM_OC3Init(TIM3,&TIM_OCInitStructure);
//
TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);
//
TIM_OC4Init(TIM3,&TIM_OCInitStructure);
//
TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
//
TIM_OCStructInit(&TIM_OCInitStructure );
TIM_OCInitStructure.TIM_OCMode =TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_Pulse =DEFAULT_DUTY_CYCLE;
//
TIM_OC2Init(TIM3,&TIM_OCInitStructure);
//
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
// ARR重裝載使能
TIM_ARRPreloadConfig(TIM2,ENABLE);
TIM_ARRPreloadConfig(TIM3,ENABLE);
//
TIM_ClearITPendingBit( TIM2,TIM_IT_Update );
TIM_ClearITPendingBit( TIM3,TIM_IT_Update | TIM_IT_CC2 );
//定時(shí)器2和3中斷使能
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_ITConfig(TIM3,TIM_IT_Update |TIM_IT_CC2, ENABLE);
}
輸出極性為高電平的意思就是說,假如說占空比為20%,那么他表示,低電平占整個(gè)周期20%的時(shí)間,反之如果設(shè)置極性為低電平,那么表示高電平占用整個(gè)周期的20%。
如何用GPIOD2模擬PWM波形呢? 關(guān)鍵的地方就是同時(shí)必須使用定時(shí)器中斷
如下圖所示:在使能某個(gè)PWM中斷的同時(shí),使能定時(shí)器中斷,這樣定時(shí)器在T1時(shí)刻產(chǎn)生溢出中斷,PWM在t1+t2時(shí)刻產(chǎn)生比較中斷。在產(chǎn)生溢出中斷時(shí),將GPIO引腳置為高電平,在產(chǎn)生比較中斷時(shí),將引腳置為低電平。例程如下圖所示:
void TIM3_IRQHandler( void )
{
if(TIM3->SR & TIM_SR_CC2IF )
{//產(chǎn)生溢出中斷
if( effectFlag & BREATH_FLAG_D2 )
{
GPIOD->BRR =GPIO_Pin_2;//引腳置為低電平
}
// Clearthe pending Bit
TIM3->SR = ~TIM_SR_CC2IF;
}
if(TIM3->SR & TIM_SR_UIF )
{//產(chǎn)生比較中斷
// Clear the pending Bit
TIM3->SR = ~TIM_SR_UIF;
if(GPIOD2_FLAG& effectFlag )
{
// 灝嗗紩鑴氱疆涓洪珮鐢?shù)邈^
GPIOD->BRR =GPIO_Pin_2;
}
//濡傛灉timer3 涓嶅啀浣跨敤,鍒欏叧闂?
if( 0 == ( TIM3->CCER & (TIM_CCER_CC3E | TIM_CCER_CC4E | TIM_CCER_CC2E ) ) ){
// 鍏抽棴timer3
TIM3->CR1 &= ~TIM_CR1_CEN;
// 鍏抽棴鏃墮挓
RCC->APB1ENR &=~RCC_APB1RSTR_TIM3RST;
}
}
}
這種做法是在資源不足的情況下使用的,在將占空比設(shè)置為0或者設(shè)置為100%時(shí),定時(shí)器的溢出中斷和PWM的比較中斷重合,這個(gè)時(shí)候,用GPIOD2驅(qū)動(dòng)led,就會(huì)發(fā)現(xiàn)led燈都是亮點(diǎn),因?yàn)橹袛嘀睾,在將占空比設(shè)置為0時(shí),定時(shí)器的溢出中斷進(jìn)不去,所以無法將引腳置為低電平,所以燈一直是亮點(diǎn)。處理的方法時(shí),判斷當(dāng)發(fā)現(xiàn)占空比為0時(shí),?直接將GPIOD2引腳置為高電平,同時(shí)使effectFlag的GPIOD2_FLAG位為0.
|
|