最近在弄STM8S,依照網上的實驗教程調試PWM程序,總是沒有輸出,有沒有人用過這個全程,好像是風馳的教程
STM8的C語言編程(14)-- PWM
在單片機應用系統中,也常常會用到PWM信號輸出,例如電機轉速的控制,F在很多高檔的單片機也都集成了PWM功能模塊,方便用戶的應用。 對于PWM信號,主要涉及到兩個概念,一個就是PWM信號的周期或頻率,另一個就是PWM信號的占空比。例如一個頻率為1KHZ,占空比為30%,有效信號為1的PWM信號,在用示波器測量時,就是高電平的時間為300uS,低電平的時間為700uS的周期波形。 在單片機中實現PWM信號的功能模塊,實際上就是帶比較器的計數器模塊。首先該計數器循環計數,例如從0到N,那么這個N就決定了PWM的周期,PWM周期=(N+1)*計數器時鐘的周期。在計數器模塊中一定還有一個比較器,比較器有2個輸入,一個就是計數器的當前值,另一個是可以設置的數,這個數來自一個比較寄存器。當計數器的值小于比較寄存器的值時,輸出為1(可以設置為0),當計數器的值大于或等于比較寄存器的值時,輸出為0(也可設置為1,與前面對應)。 了解了這個基本原理后,我們就可以使用STM8單片機中的PWM模塊了。下面的實驗程序首先將定時器2的通道2設置成PWM輸出方式,然后通過設置自動裝載寄存器TIM2_CCR2,決定PWM信號的周期。在程序的主循環中,循環修改占空比,先是從0逐漸遞增到128,然后再從128遞減到0。 當把下面的程序在ST的三合一板上運行時,可以看到發光二極管LD1逐漸變亮,然后又逐漸變暗,就這樣循環往復。如果用示波器看,可以看到驅動LD1的信號波形的占空比從0變到50%,然后又從50%變到0。 同樣還是利用ST的開發工具,生成一個C語言程序的框架,然后修改其中的main.c,修改后的代碼如下。
// 程序描述:用PWM輸出驅動LED
#include"STM8S207C_S.h"
voidCLK_Init(void); voidTIM_Init(void);
// 函數功能:延時函數 // 輸入參數:ms -- 要延時的毫秒數,這里假設CPU的主頻為2MHZ // 輸出參數:無 // 返 回 值:無 // 備 注:無 voidDelayMS(unsigned int ms) { unsigned char i; while(ms != 0) { for(i=0;i<250;i++) { } for(i=0;i<75;i++) { } ms--; } }
// 函數功能:初始化時鐘 // 輸入參數:無 // 輸出參數:無 // 返 回 值:無 // 備 注:無 voidCLK_Init() { CLK_CKDIVR = 0x11; // 10:fHSI = fHSI RC output/ 4 // = 16MHZ / 4 =4MHZ // 001: fCPU=fMASTER/2. = 2MHZ }
// 函數功能:初始化定時器2的通道2,用于控制LED的亮度 // 輸入參數:無 // 輸出參數:無 // 返 回 值:無 // 備 注:無 voidTIM_Init() { TIM2_CCMR2 = TIM2_CCMR2 | 0x70;// Output modePWM2. //通道2被設置成比較輸出方式 // OC2M = 111,為PWM模式2, // 向上計數時,若計數器小于比較值,為無效電平 // 即當計數器在0到比較值時,輸出為1,否則為0 TIM2_CCER1 = TIM2_CCER1 | 0x30;// CC polarity low,enable PWMoutput */ // CC2P = 1,低電平為有效電平 // CC2E = 1,開啟輸出引腳
//初始化自動裝載寄存器,決定PWM方波的頻率,Fpwm=4000000/256=15625HZ TIM2_ARRH = 0; TIM2_ARRL = 0xFF;
//初始化比較寄存器,決定PWM方波的占空比 TIM2_CCR2H = 0; TIM2_CCR2L = 0;
// 初始化時鐘分頻器為1,即計數器的時鐘頻率為Fmaster=4MHZ TIM2_PSCR = 0; // 啟動計數 TIM2_CR1 = TIM2_CR1 | 0x01; }
main() { unsigned char i;
CLK_Init(); // 初始化時鐘 TIM_Init(); // 初始化定時器
while(1) // 進入無限循環 { // 下面的循環將占空比逐漸從0遞增到50% for(i=0;i<128;i++) { TIM2_CCR2H = 0; TIM2_CCR2L = i; DelayMS(5); }
// 下面的循環將占空比逐漸從50%遞減到0 for(i=128;i>0;i--) { TIM2_CCR2H = 0; TIM2_CCR2L = i; DelayMS(5); } } } //========================================
//上面這個實例老是調不通,不知道為什么??
//========================================
由于上面的例子總是調試不好,就換了個例子,但也是調不通,不知道是不是我哪里弄錯了在輸出模式下,該寄存器的值與 CNT 的值比較,根據比較結果產生相應動作。利用這點,我們通過修改這個寄存器的值,就可以控制 PWM 的輸出脈寬了。 #include "iostm8s207rb.h" void CLK_Init(void); void TIM2_PWM2_Init(void); void delay_ms(int value); main() { unsigned char i; CLK_Init(); // 初始化時鐘 TIM2_PWM2_Init(); // 初始化定時器的PWM功能 while(1) // 進入無限循環 { // 下面的循環將占空比逐漸從0遞增到50% for(i=0;i<100;i++) { TIM2_CCR2H = 0; TIM2_CCR2L = i; delay_ms(10); } // 下面的循環將占空比逐漸從50%遞減到0 for(i=100;i>0;i--) { TIM2_CCR2H = 0; TIM2_CCR2L = i; delay_ms(10); } } } // 函數功能:初始化定時器2的通道2,用于控制LED的亮度 void TIM2_PWM2_Init() { TIM2_CCMR2 = TIM2_CCMR2 | 0x70;// Output mode PWM2. // 通道2被設置成比較輸出方式 // OC2M = 111,為PWM模式2, // 向上計數時,若計數器小于比較值,為無效電平 // 即當計數器在0到比較值時,輸出為1,否則為0 TIM2_CCER1 = TIM2_CCER1 | 0x10;// CC polarity low,enable PWM output // CC2P = 0,高電平為有效電平 // CC2E = 1,開啟輸出引腳 //初始化自動裝載寄存器,決定PWM方波的頻率,Fpwm=4000000/200=20KHZ TIM2_ARRH = 0; TIM2_ARRL = 0xC8; //200 //初始化比較寄存器,決定PWM方波的占空比 TIM2_CCR2H = 0; TIM2_CCR2L = 0; // 初始化時鐘分頻器為4,即計數器的時鐘頻率為Fmaster=16MHZ,CK_CNT = 4M TIM2_PSCR = 2; // 啟動計數 TIM2_CR1 = TIM2_CR1 | 0x01; } void CLK_Init() { CLK_CKDIVR =0x00; //16M主頻 } /* ******************************************** 簡單延時程序 ******************************************** */ void delay_ms(int value) { int i,j; if(value < 1) value = 1; for(i=0;i!=value;++i) for(j=0;j!=5000;++j); } //===================================
//上面這個例子也是沒有調好
//====================================
|