脈沖寬度調(diào)制 (PWM) 是一種模擬調(diào)制技術(shù),其中脈沖的持續(xù)時間或?qū)挾入S時間而變化。它是一種常用的技術(shù),用于產(chǎn)生具有定義頻率和占空比的連續(xù)脈沖信號。簡而言之,PWM 就是在頻率保持不變的情況下改變脈沖的寬度。
使用 PWM 信號,您可以輕松控制伺服電機的速度或 LED 的亮度。由于通用微控制器只能在其輸出引腳上提供邏輯 1(高)或邏輯 0(低),因此它們無法提供變化的模擬電壓,除非它具有內(nèi)置的數(shù)模轉(zhuǎn)換器 (DAC)或外部連接。在這種情況下,可以對微控制器進行編程以輸出具有不同占空比的脈寬調(diào)制 (PWM) ,然后可以將其轉(zhuǎn)換為不同的模擬電壓。
因此,在本教程中,我們將 LED 與通用 STM8S 微控制器連接,該微控制器使用微控制器生成的 PWM 信號進行控制,我們將使用 STVD 和 Cosmic C 編譯器對微控制器進行編程。在此之前,讓我們了解一些 PWM 信號的基礎(chǔ)知識。
了解 PWM 信號的基礎(chǔ)
您可能聽說過,PWM 代表脈沖寬度調(diào)制。它是一種模擬調(diào)制技術(shù),用于大量不同的應(yīng)用和項目。PWM 信號的圖像如下所示。
您在上面看到的圖像是具有相同ON 時間和OFF 時間的通用方波。現(xiàn)在,假設(shè)方波的總周期為 1 秒,這意味著方波的開啟時間和方波的關(guān)閉時間也是 500 毫秒。因此,如果我們連接一個 LED 并用這個方波給它加電,LED 將在半個周期內(nèi)亮起,在半個周期內(nèi)熄滅??雌饋?LED 以一半的亮度發(fā)光。
在上圖中,您可以看到我們降低了占空比,如果我們考慮相同的 1S 周期,我們的 On-Time 為 250ms,OFF 時間為 750ms?,F(xiàn)在,如果我們連接相同的 LED,我們會觀察到 LED 會因為占空比降低而變得更暗。
STM8S PWM 發(fā)生器電路:硬件設(shè)置和要求
由于我們使用 PWM 控制 LED,因此需要一個 LED 與 STM8S 板連接。由于 STM8S 開發(fā)板上有 LED,因此我將使用它進行演示。我們還需要STM8S開發(fā)板以及ST-LINK編程器。除此之外,我們需要一個 5V 電源為開發(fā)板供電,因為開發(fā)板有一個板載 micro USB 電纜,我們將使用它為開發(fā)板供電。
基于STM8S微控制器的LED調(diào)光器電路圖
為了對電路進行編程,我們將ST-Link V2 編程器連接到 STM8S 開發(fā)板的 3.3V、SWIM 和接地引腳。STM8 微控制器最有趣的地方在于,它只需要一個SWIM 引腳即可對微控制器進行編程。
正如您在上面的示意圖中看到的,測試 LED 連接到開發(fā)板上,并連接到板最左側(cè)的端口 1.4
ST Micro STM8S 微控制器上的 PWM 引腳
STM8S 有 20 個引腳,其中 8 個引腳可以配置為 PWM。下圖顯示了紅色方框中標(biāo)記的 PWM 引腳。這些引腳也是可用于其他功能的 GPIO 引腳。
正如我們在上圖中看到的,標(biāo)記的引腳可以生成 PWM 信號。所以我們將使用板上的其中一個來產(chǎn)生 PWM 信號。但是,啟用 PWM 會禁用其他功能,因此我們需要小心選擇將哪個引腳配置為 PWM。由于我們正在構(gòu)建此電路以進行在線演示,因此我們將使用 PIN D4 生成 PWM 信號。
對 STM8s 微控制器進行編程以生成 PWM 信號
如我們在STM8S 微控制器入門教程中討論的那樣,創(chuàng)建一個工作區(qū)和新項目。您可以添加所有頭文件和源文件,也可以僅添加 gpio、timer2、config 和 stm8s 文件。打開 main.c 文件并開始編寫程序。
確保您已包含如上圖所示的頭文件。打開?main.c?文件并啟動代碼。完整的 main.c 代碼可以在此頁面底部找到,您還可以從那里下載項目文件。代碼解釋如下,如果您對編碼部分感到困惑,也可以參考?SPL 用戶手冊?或本頁底部鏈接的視頻。??
在我們開始編碼過程之前,您需要包含stm8s_gpio.c、stm8s_tim2.c ,并且在源文件夾和頭文件夾中您需要包含stm8s_gpio.h、stm8s_tim2。H。您可以從STM8S103F3P6 SPL GitHub Repository獲取這些頭文件。完成后,我們通過包含所有必需的庫開始我們的代碼,并定義所有必要的變量。對于這個實驗代碼,我們只需要將 PWM 值保存在一個變量中,這就是我們包含一個名為pwm_duty 的變量的原因。
?
#包括“STM8S.h” 有符號的 int pwm_duty = 0;
?
一旦我們聲明了所有的庫和變量,我們需要構(gòu)建我們的延遲函數(shù),因為 cosmic c 編譯器不提供任何預(yù)定義的延遲函數(shù)。我們將使用只需要一個時鐘周期的匯編指令NOP 。而且由于微控制器的內(nèi)核以 2MHz 運行,我們可以很容易地推測延遲。出于這個原因,我們將延遲與兩個 for 循環(huán)結(jié)合起來。這是對 cosmic C 編譯器進行延遲的最簡單、最準(zhǔn)確的方法。
?
void delay_ms (int ms) //函數(shù)定義 { for (int i=0; i<=ms; i++) for (int j=0; j<120; j++) // Nop = Fosc/4 _asm("nop"); //執(zhí)行無操作 //匯編代碼 }
?
接下來,我們將研究我們的主循環(huán)。對于本節(jié),我們需要查看SPL 用戶手冊。我們通過取消初始化 GPIO 引腳和 Timer2 來啟動主函數(shù)。如果 GPIO 或 Timer 之前已用于其他應(yīng)用程序,則應(yīng)在使用它們之前對其進行初始化。這不是強制性的,但這是一個很好的做法。
?
GPIO_DeInit(GPIOD); TIM2_DeInit();
?
接下來,我們必須將引腳聲明為輸出,借助TIM2_OC1Init()函數(shù)設(shè)置 Timer2,并在定時器中使用預(yù)分頻器來實現(xiàn) 4KHz 的 PWM 頻率。我們是在TIM2_TimeBaseInit()函數(shù)的幫助下完成的。完成后,我們在TIM2_Cmd(ENABLE)函數(shù)的幫助下啟用定時器。對于這個項目,我們決定在板上使用 PIN D4,這是一個支持 PWM 的 PIN。
?
GPIO_DeInit(GPIOD); TIM2_DeInit(); GPIO_Init(GPIOD,GPIO_PIN_4,GPIO_MODE_OUT_PP_HIGH_FAST); TIM2_OC1Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 1000, TIM2_OCPOLARITY_HIGH); TIM2_TimeBaseInit(TIM2_PRESCALER_1, 500); TIM2_Cmd(啟用);
?
接下來,我們有我們的無限循環(huán)。在無限循環(huán)中,我們設(shè)置了 for 循環(huán),并啟用了捕獲和比較語句,這將使我們能夠設(shè)置 PWM 通道。
?
而(真){ 對于(pwm_duty = 0;pwm_duty < 1000;pwm_duty += 2){ TIM2_SetCompare1(pwm_duty); 延遲毫秒(10); } 對于(pwm_duty = 1000;pwm_duty > 0;pwm_duty -= 2){ TIM2_SetCompare1(pwm_duty); 延遲毫秒(10); } }
?
上面的代碼負責(zé)產(chǎn)生 PWM 信號,因為在第一個 for 循環(huán)中 PWM 信號會從高電平變?yōu)榈碗娖剑驗橄乱粋€ for 循環(huán),PWM 信號會從低電平變?yōu)楦唠娖讲⒗^續(xù)循環(huán)。
使用 STM8S 生成 PWM 信號
編譯代碼并上傳到你的STM8S開發(fā)板。如果您遇到任何編譯錯誤,請確保您已添加所有頭文件和源文件,如前所述。上傳代碼后,您應(yīng)該會看到引腳 D4 上連接的 LED 的亮度會發(fā)生變化。
#包括“STM8S.h”
有符號的 int pwm_duty = 0;
void delay_ms (int ms) //函數(shù)定義
{
for (int i=0; i<=ms; i++)
for (int j=0; j<120; j++) // Nop = Fosc/4
_asm("nop"); //執(zhí)行無操作 //匯編代碼
}
無效主要(無效)
{
GPIO_DeInit(GPIOD);
TIM2_DeInit();
GPIO_Init(GPIOD,GPIO_PIN_4,GPIO_MODE_OUT_PP_HIGH_FAST);
TIM2_OC1Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 1000,
TIM2_OCPOLARITY_HIGH);
TIM2_TimeBaseInit(TIM2_PRESCALER_1, 500);
TIM2_Cmd(啟用);
而(真){
for(pwm_duty = 0; pwm_duty < 1000; pwm_duty += 2){ // 循環(huán)
TIM2_SetCompare1(pwm_duty); //設(shè)置Timer2的捕獲比較
延遲毫秒(10);//延遲10ms
}
對于(pwm_duty = 1000;pwm_duty > 0;pwm_duty -= 2){
TIM2_SetCompare1(pwm_duty);
延遲毫秒(10);
}
}
}
評論
查看更多