找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 7965|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

使用GPIO口模擬PWM輸出

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:105323 發(fā)表于 2016-2-21 15:44 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
       最近再做一個(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.

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表