本帖最后由 kkhkbb 于 2018-3-15 09:12 編輯
一、 概述 1、 PWM簡介 PWM即脈沖寬度調(diào)制,是一種模擬控制方式,其根據(jù)相應(yīng)載荷的變化來調(diào)制晶體管基極或MOS管柵極的偏置,來實現(xiàn)晶體管或MOS管導通時間的改變,從而實現(xiàn)開關(guān)穩(wěn)壓電源輸出的改變。這種方式能使電源的輸出電壓在工作條件變化時保持恒定,是利用微處理器的數(shù)字信號對模擬電路進行控制的一種非常有效的技術(shù)。 PWM的主要應(yīng)用:在STM32中如調(diào)節(jié)屏幕亮度、音調(diào)等應(yīng)用都可以通過PWM控制占空比進行實現(xiàn)。下面我們會為大家舉例介紹如何利用PWM控制LED的亮暗,以實現(xiàn)呼吸燈的效果。 2、PWM的工作原理 脈寬調(diào)制基本原理:其控制方式就是對電路開關(guān)器件的通斷進行控制,使輸出端得到一系列幅值相等的脈沖,用這些脈沖來代替正弦波或所需要的波形。也就是在輸出波形的半個周期中產(chǎn)生多個脈沖,使各脈沖的等值電壓為正弦波形,所獲得的輸出平滑且低次諧波少。按一定的規(guī)則對各脈沖的寬度進行調(diào)制,即可改變電路輸出電壓的大小,也可改變輸出頻率。 (1)脈寬調(diào)制原理 脈寬調(diào)制調(diào)制模式可以生產(chǎn)一個由TIMx_ARR寄存器確定頻率,由TIMx_CCRx確定占空比的信號。如下圖所示:  圖8_0脈寬調(diào)制原理示意圖 圖中可知0到t2為一個周期時間,而占空比由CCRx值決定。一個周期時間可以由以下公式計算: 其中:ARR為重新裝載值;PSC為預分頻系數(shù);TCLK為定時器時鐘頻率。如本次實驗中TCLk為84M,選擇ARR為499,PSC為83,其一個周期為0.5ms。 (2)脈寬調(diào)制原理 PWM主要工作過程如下:
 圖8_1 PWM工作過程示意圖 PWM工作步驟解析: a. CCR1捕獲比較值寄存器設(shè)置比較值,將其與當前值寄存器的值比較,要說明的是修改TIM_CCMR1寄存器的OC1M[2:0]位可控制 PWM模式,方法如下: - 110:PWM模式1——向上計數(shù)時,一旦TIMx_CNT<TIMx_CCR1時通道1為有效電平,否則為無效電平;在向下計數(shù)時,一旦TIMx_CNT>TIMx_CCR1時通道1為無效電平(OC1REF=0),否則有效電平(OC1REF=1)。
- 111:PWM模式2——在向上計數(shù)時,一旦TIMx_CNT<TIMx_CCR1時通道1為無效電平,否則為有效電平;在向下計數(shù)時,一旦TIMx_CNT>TIMx_CCR1時通道1為有效電平,否則為無效電平。
b. 經(jīng)過輸出控制器后,得到OC1ref電平還要經(jīng)過一個選擇,其由TIMx_CCRE寄存器的CC1P位控制:輸入/捕獲1輸出極性。0:高 電平有效。1:低電平有效 c. 選擇完成后經(jīng)過輸出電路來輸出,輸出電路由TIM_xCCRE寄存器的CC1E位控制。 控制方式為0:關(guān)閉 1:打開。 二、 實驗原理 STM32的定時器有PWM功能,iCore3的三個LED都連接在定時器的輸出接口上,可以通過定時器的PWM輸出控制LED的亮度,從而實現(xiàn)呼吸燈的功能。硬件連接示意圖如下圖所示:  圖8_2 驅(qū)動示意圖 三、源代碼 1、主函數(shù) - /*
- * Name : main
- * Description : ---
- * Author : ysloveivy.
- *
- * History
- * --------------------
- * Rev : 0.00
- * Date : 11/21/2015
- *
- * create.
- * --------------------
- */
- int main(void)
- {
- int i;
- int brightness = 99;
- pwm.initialize();
- float temp = 0.0;
- int data = 0;
- //紅色LED燈循環(huán)由亮變暗,由暗變亮
- while(1){
- for(i = 0;i < 1000000;i++);
- brightness ++;
- if(brightness == 100){
- brightness = 0;
- }
- temp = sin(PI / 99.0 * brightness) * 0.5 + 0.5;
- temp *= 499;
- data = (int)temp;
- pwm.set_compare(data);
- }
- }
復制代碼2.PWM初始化 以下是TIM8初始化及PWM設(shè)置程序: - /*
- * Name : initialize
- * Description : ---
- * Author : ysloveivy.
- *
- * History
- * -------------------
- * Rev : 0.00
- * Date : 11/21/2015
- *
- * create.
- * -------------------
- */
- static int initialize(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE); //開啟TIM8定時器的時鐘
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOI, ENABLE); //開啟GPIOI的時鐘
- GPIO_PinAFConfig(GPIOI,GPIO_PinSource5,GPIO_AF_TIM8); //PI5復用為TIM8
- //GPIO初始化設(shè)置
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //模式設(shè)為復用
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //復用推挽輸出
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_Init(GPIOI,&GPIO_InitStructure);
- //TIM8初始化
- TIM_TimeBaseStructure.TIM_Prescaler = 83; //設(shè)置預分頻值
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計數(shù)模式
- TIM_TimeBaseStructure.TIM_Period = 499; //自動重裝載值
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
- //設(shè)置時鐘分割
- TIM_TimeBaseInit(TIM8,&TIM_TimeBaseStructure);
- //TIM8 CH1 LED_RED
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //設(shè)置為PWM模式2
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
- TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //互補輸出使能
- TIM_OCInitStructure.TIM_Pulse = 0; //設(shè)置待裝入捕獲比較寄存器的脈沖值
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //當定時器的值小于脈沖值時,輸出低電平
- TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
- TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
- TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
- TIM_OC1Init(TIM8, &TIM_OCInitStructure);
- TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable); //使能輸出比較預裝載
- TIM_ARRPreloadConfig(TIM8,ENABLE); //使能TIM8自動重裝載的預裝載寄存器允許位
- TIM_Cmd(TIM8, ENABLE); //TIM8使能
- TIM_CtrlPWMOutputs(TIM8, ENABLE); //使能主輸出
- return 0;
- }
復制代碼3.修改占空比函數(shù) - static int set_compare(int temp)
- {
- TIM_SetCompare1(TIM8,temp); //修改占空比
- return 0;
- }
復制代碼4.小知識 在上面程序中有一段函數(shù)為: GPIO_PinAFConfig(GPIOI,GPIO_PinSource5,GPIO_AF_TIM8); 它的功能是將PI5復用為TIM8_CH1,初學者可能會問了為什么PI5可以復用為TIM8_CH1,其他引角可不可以。這就要借助該芯片的數(shù)據(jù)手冊了,芯片上眾多引角他們往往帶有自己特殊的使命,如以下從數(shù)據(jù)手冊上的截屏:  圖8_3 芯片引腳功能示意圖 其在數(shù)據(jù)手冊的Pinouts and pin description——STM32F40xxx pin and ball definitions目錄下。前面六列為該芯片手冊包含的芯片類型,接下來第七列是引腳的名稱,第八列是引腳類型如可以輸入輸出的I/O口,第八列中有FT標識的引腳表示能承受5V電壓,第九列是注釋,第十列為可復用功能如PI5要復用為TIM8_CH1功能則可通過剛剛介紹的函數(shù)實現(xiàn),第十一列為可重映射功能。 四、 實驗現(xiàn)象: iCore3 雙核心板紅色LED燈亮度從亮到暗,然后從暗到亮。 五、 代碼包下載鏈接
|