[PWM 設定步驟]
要編寫 PWM 程式,可按照如下步驟進行設定:(1) 設定 GPIO 及 Timer 的 RCC 時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能TIM3時鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE); //使能 GPIOB 時鐘和 AFIO 複用時鐘(2) GPIO 設為復用推輓輸出,並將 TIM3 重映射
定義一個 GPIO_InitTypeDef 類型的結構體
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); //TIM3部分重映射 TIM3_CH2->PB5 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //複用推輓輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; //配置輸出速率 GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB相關 GPIO 相關設定說明,請參考:STM32筆記(17):按鍵控制-使用 GPIO 讀取。
(3) 設定定時器:設定重裝載值 ARR 與分頻係數 PSC 等
定義一個 TIM_TimeBaseInitTypeDef 類型的結構體
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //定義TIMx定時器結構體 TIM_TimeBaseStructure.TIM_Period = arr; //設置自動重裝載暫存器週期的值 arr = value - 1 TIM_TimeBaseStructure.TIM_Prescaler = psc; //設置預分頻值 psc = value - 1 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設置時鐘分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //初始化 TIM3 PWM 週期(4) 初始化外設 OC2 比較參數,並進行預載暫存器
//初始化TIM3 Channel2 PWM模式 TIM_OCInitTypeDef TIM_OCInitStructure; //定義結構體 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時器模式:TIM脈衝寬度調製模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //Enable 比較輸出 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高 TIM_OCInitStructure.TIM_Pulse = 0; TIM_OC2Init(TIM3, &TIM_OCInitStructure); //初始化外設 TIM3 OC2 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //啟動 TIM3 在 CCR2 預載暫存器(5) 啟用定時器
TIM_Cmd(TIM3, ENABLE); //啟動定时器 TIM3(6)在主函數中不斷改變比較值 CCRx,達到不同的占空比效果
TIM_SetCompare2(TIM3,pwmValue); //通道2, 改變比較值CCRx依照上述幾個步驟,就可完成定 PWM 的控制,以下就用一個定時器進行 PWM 的實做,透過改變 CCR 值讓 LED 出現明暗的變化,好像在呼吸一樣,並將 CCR 比較值顯示在 OLED 上。
[材料]
- STM32F103C8T6 主板 x 1
- OLED SSD1306 顯示器 x 1
- STLINK V2 模擬下載器 x 1
- LED x 1
- 麵包板 x 1
- 連接線 x N 條
[接線與電路圖]
LED 的負極接地,另一腳接在 STM32F103x PB5,與 SSD1306 連接的方式如下:STM32F103x | SSD1306 OLED |
---|---|
3.3v | VDD |
GND | GND |
B8 | SCK/SCL |
B9 | SDA |
[程式]
主程式一開始先對 OLED 進行初始化,進入迴圈循環後就改變 CCR 值,等中斷產生,主程式 main.c 如下:#include "stm32f10x.h" #include "delay.h" #include "sys.h" #include "oled.h" #include "bmp.h" #include "pwm.h" //主函數 int main(void) { u16 pwmValue = 1; u8 dir = 1; delay_init(); //延時函數初始化 OLED_Init(); //初始化OLED OLED_Clear(0); //清除螢幕 OLED_ShowString(2, 2, "Count:",16); PWM_Init(99, 7199); while(1) { OLED_ShowNum(60, 2, pwmValue,3, 16); delay_ms(30); if(dir) pwmValue++; //從暗到亮 else pwmValue--; //從亮到暗 if(pwmValue >= 100) dir = 0; if(pwmValue <= 1) dir = 1; TIM_SetCompare2(TIM3,pwmValue); //通道2, 改變比較值CCRx } }pwm.c 程式如下:
#include "pwm.h" void PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; //定義GPIO結構體 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //定義TIMx定時器結構體 TIM_OCInitTypeDef TIM_OCInitStructure; //定義定時器脈寬調製結構體 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能TIM3時鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);//使能GPIOB時鐘和AFIO複用時鐘 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); //TIM3部分重映射 TIM3_CH2->PB5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //複用推輓輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; //配置輸出速率 GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化GPIOB TIM_TimeBaseStructure.TIM_Period = arr; //設置自動重裝載暫存器週期的值 arr=value-1 TIM_TimeBaseStructure.TIM_Prescaler = psc; //設置預分頻值 psc=value-1 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設置時鐘分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //初始化TIMx時間基數 //初始化TIM3 Channel2 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時器模式:TIM脈衝寬度調製模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能比較輸出 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高 TIM_OCInitStructure.TIM_Pulse = 0; TIM_OC2Init(TIM3,&TIM_OCInitStructure); //根據T指定的參數初始化外設TIM3 OC2 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIM3在CCR2上的預裝載暫存器 TIM_Cmd(TIM3, ENABLE); //使能TIM3 }pwm.h 程式如下:
#ifndef __PWM_H_ #define __PWM_H_ #include "stm32f10x.h" void PWM_Init(u16 arr,u16 psc); #endif完整的程式請參考 Github:8.Breathing light with PWM
您好,請問可以教學如何使用stm32做PI控制嗎
回覆刪除請問, 所謂的控制PI,是讓PI接周邊裝置,如馬達等,讓STM32遠端控制 PI 啟動馬達嗎?或請描述一下情境?
刪除張貼留言