--- title: Pulse-width modulation(PWM) ... Introduction ============ 又稱pulse-duration modulation(PDM),是將類比信號轉為脈波的一種技術。 為何需要PWM?雖然類比電壓可直接用來控制,但類比電路控制信號容易隨時間漂移,功耗大。 .. image:: /pwm.png 如圖所示,PWM 電路主要功能是將輸入電壓的振幅轉換成脈衝寬度。一般轉換後脈波的週期固定,脈波的占空比(duty cycle)會依類比信號的大小而改變,可用來控制燈泡亮度、馬達轉速等等,脈波寬度越大燈泡亮度越亮、馬達轉速越快。 Implementation ============== PWM需要透過Timer來實現,STM32的Timer可分為以下幾種 - 基本定時器(TIM6 和 TIM7) - 高級控制定時器(TIM1 和 TIM8) - 通用定時器(TIMx):具有測量輸入信號的脈衝長度、產生輸出波形和PWM的功能。 - clock來源 : 內部clock(CK_INT)、外部clock模式1(TIx)、外部clock模式2(ETR)、內部觸發輸入(ITRx)。 - CK_INT -> AHB Prescaler(/1、2、...、512) -> APB1 Prescaler(/1、2、4、8、16) or APB2 Prescaler(/1、2、4、8、16)。 - Time Base Configuration : .. image:: /up mode.bmp ----------- .. image:: /down mode.bmp ----------- .. image:: /center aligned.jpg - TIM_ClockDivision - 採樣頻率基準,當連續採樣到N個有效電平時,才當作一次有效電平。 - TIM_Prescaler - 將TIMxCLK除以(TIM_Prescaler+1) - TIM_CounterMode - 選擇計數模式 - TIM_Period - TIMx_ARR,counter 週期 - 輸出脈波週期 = (TIM_Period+1) * (TIM_Prescaler+1) * (TIM_ClockDivision+1) / TIMxCLK - PWM configuration - TIM_OCMode - PWM模式 - PWM 1 Mode : 在向上計數,TIMx_CNTTIMx_CCRx時,輸出為0,否則輸出為1。 - PWM 2 Mode : 在向上計數,TIMx_CNTTIMx_CCRx時,輸出為1,否則輸出為0。 - TIM_Pulse - TIMx_CCRx,脈衝寬度 - TIM_OCPolarity - 設置輸出極性,例如:TIM_OCPolarity_High PWM輸出關閉時默認為低電位。 以LED為例: .. image:: /timer.png TIM_Prescaler = 499,TIM_ClockDivision=0,TIMxCLK=84MHz 輸出脈波週期 = (TIM_Period+1) * (TIM_Prescaler+1) * (TIM_ClockDivision+1) / TIMxCLK = (1999+1) * (499+1) * (0+1)/84000000 ≒ 0.012 s 0.012 s 遠小於人眼視覺暫留的時間(0.1~0.4s),因此上圖的PWM 2 duty cycle(75%)>PWM 1 duty cycle(25%),PWM 2 Mode看起來會比PWM 1 Mode亮。 ----------- Code_section ============= //====set pin enable======== RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE ); //開啟Pin腳 D B E提供使用 RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM4 | RCC_APB1Periph_TIM3, ENABLE ); //開啟Timer - GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4); - GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4); - GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_TIM4); - GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_TIM4); - /* GPIOA Configuration: CH1 (PB4) and CH2 (PB5) */ //設定PB4 5為輸出模式 提供模擬中斷來源 - GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 ; - GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_OUT; //輸出信號模式 - GPIO_InitStructure2.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure2.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_Init(GPIOB, &GPIO_InitStructure2); - /* GPIOA Configuration: (PA2) and (PA3) */ //設定PA2 3為輸入模式 提供接收中斷來源 - GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 ; - GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_IN; - GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure2.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure2.GPIO_PuPd = GPIO_PuPd_DOWN ; - GPIO_Init(GPIOA, &GPIO_InitStructure2); - // Setup Blue & Green LED on STM32-Discovery Board to use PWM. / //PD與LED3456相連實作PWM - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Alt Function - Push Pull - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init( GPIOD, &GPIO_InitStructure ); //====Interrupt set section============== - //==清空中斷標誌== - EXTI_ClearITPendingBit(EXTI_Line2); - EXTI_ClearITPendingBit(EXTI_Line3); - //==選擇中斷PIN腳 A2 A3====== - SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource2); - SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource3); - //== - EXTI_InitStructure.EXTI_Line = EXTI_Line2 ; //選擇中斷線路2 - EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //設置為中斷請求,非事件請求 - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling //設置中斷觸發方式為 下降沿觸發 - EXTI_InitStructure.EXTI_LineCmd = ENABLE; //外部中斷enable - EXTI_Init(&EXTI_InitStructure); - EXTI_GenerateSWInterrupt(EXTI_Line2); - EXTI_InitStructure.EXTI_Line = EXTI_Line3 ; //選擇中斷線路3 - EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设設置為中斷請求,非事件請求 - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //設置中斷觸發方式為 下降沿觸發 - EXTI_InitStructure.EXTI_LineCmd = ENABLE; //外部中斷enable - EXTI_Init(&EXTI_InitStructure); - EXTI_GenerateSWInterrupt(EXTI_Line3); - //===給予中斷分組與優先權的設定=== - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //選擇中斷分組2 - NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn ; //選擇中斷通道2 - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶占式中斷優先級設置為0 - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應式中斷優先級設置為0 - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //enable中断 - NVIC_Init(&NVIC_InitStructure); //======================================= //