找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7965|回復: 0
打印 上一主題 下一主題
收起左側

使用GPIO口模擬PWM輸出

[復制鏈接]
跳轉到指定樓層
樓主
ID:105323 發(fā)表于 2016-2-21 15:44 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
       最近再做一個帶藍牙接口的血壓計項目,項目中使用了STM32F10364引腳的MCU,在硬件設計中,因為外設較多,導致每個通用定時器至少有兩個PWM輸出引腳被占用,現(xiàn)在要控制RGB燈,只能用一個普通IO引腳模擬PWM輸出。
相關的硬件電路設置如下:
  GPIOA1------------------------------RGBBLUE燈
  GPIOB1------------------------------RGBGREEN燈
  GPIOD2------------------------------RGBRED燈
RGB燈采用了共陽極電路,所以在PWM的輸出急性設置時,將極性設置為高電平,定時器的初始化如下圖所示:
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 );
//定時器2和3中斷使能
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_ITConfig(TIM3,TIM_IT_Update |TIM_IT_CC2, ENABLE);
}
      輸出極性為高電平的意思就是說,假如說占空比為20%,那么他表示,低電平占整個周期20%的時間,反之如果設置極性為低電平,那么表示高電平占用整個周期的20%。
如何用GPIOD2模擬PWM波形呢? 關鍵的地方就是同時必須使用定時器中斷


   如下圖所示:在使能某個PWM中斷的同時,使能定時器中斷,這樣定時器在T1時刻產生溢出中斷,PWM在t1+t2時刻產生比較中斷。在產生溢出中斷時,將GPIO引腳置為高電平,在產生比較中斷時,將引腳置為低電平。例程如下圖所示:
void TIM3_IRQHandler( void )
{
      if(TIM3->SR & TIM_SR_CC2IF )
     {//產生溢出中斷
          if( effectFlag & BREATH_FLAG_D2  )
         {
              GPIOD->BRR =GPIO_Pin_2;//引腳置為低電平
          }
          // Clearthe pending Bit
         TIM3->SR = ~TIM_SR_CC2IF;
      }
      if(TIM3->SR & TIM_SR_UIF )
     {//產生比較中斷
           // Clear the pending Bit
          TIM3->SR = ~TIM_SR_UIF;
          if(GPIOD2_FLAG& effectFlag )

           {
              // 灝嗗紩鑴氱疆涓洪珮鐢靛鉤
              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;
}
}
}

      這種做法是在資源不足的情況下使用的,在將占空比設置為0或者設置為100%時,定時器的溢出中斷和PWM的比較中斷重合,這個時候,用GPIOD2驅動led,就會發(fā)現(xiàn)led燈都是亮點,因為中斷重合,在將占空比設置為0時,定時器的溢出中斷進不去,所以無法將引腳置為低電平,所以燈一直是亮點。處理的方法時,判斷當發(fā)現(xiàn)占空比為0時,?直接將GPIOD2引腳置為高電平,同時使effectFlag的GPIOD2_FLAG位為0.

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

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表