PWM的應(yīng)用可以說非常廣泛,控制電機(jī)速度、燈光亮度、通信調(diào)制等眾多領(lǐng)域。
PWM的問題小伙伴問的比較多,最近也在用PWM,這里就分享一下關(guān)于PWM的一些內(nèi)容。
什么是PWM?
PWM: Pulse Width Modulation,脈沖寬度調(diào)制。
網(wǎng)上的解釋很多,通過下圖,你就能直觀的理解PWM,其實(shí)就是高低電平組成的脈沖信號。
通過改變其中頻率(脈沖周期)、占空比,就能應(yīng)用在很多場合。
PWM常見輸出方式
通過上面描述,PWM就是一個(gè)IO口以不同的時(shí)間周期輸出高、低電平。
1.新手 (菜鳥) 級別
while循環(huán)中,阻塞延時(shí),控制IO口高低輸出:
while(1)
{
IO口高電平
Delay阻塞延時(shí)
IO口低電平
Delay阻塞延時(shí)
}
阻塞延時(shí)可以是:軟件模擬延時(shí),定時(shí)器阻塞延時(shí)等。
2.入門 (初級) 級別
while循環(huán)中,非阻賽延時(shí),控制IO口高低輸出:
while(1)
{
IO口高電平
Delay非阻塞延時(shí)
IO口低電平
Delay非阻塞延時(shí)
}
非阻賽延時(shí)可以是:定時(shí)器標(biāo)識(shí)檢測、RTOS(系統(tǒng))延時(shí)等。
3.熟悉 (中級) 級別
定時(shí)器中斷控制IO高低電平輸出:
定時(shí)器中斷配置 ——> 啟動(dòng)定時(shí)器 ——> 響應(yīng)中斷,控制IO高低電平···
4.熟練 (中級+) 級別
定時(shí)器PWM硬件控制輸出:
配置PWM對應(yīng)的IO,以及定時(shí)器PWM輸出 ——> 啟動(dòng)PWM自動(dòng)輸出···
void AppTask(void *p_arg)
{
PWM_TIM_Configuration();
PWM_Output(頻率, 占空比);
while(1)
{
//自己的應(yīng)用代碼
}
}
比較:
上面幾種PWM輸出方式,前面三種都會(huì)CPU干預(yù)PWM的輸出,也就是會(huì)占用CPU資源,特別是前面兩種方式,不僅占用CPU,誤差還比較大。
使用第三種中斷方式,如果頻率比較高,CPU消耗的也比較嚴(yán)重。這種情況適合于沒有硬件PWM輸出的單片機(jī)。
第四種就是單片機(jī)自帶硬件PWM輸出功能,只需要簡單配置就可以自動(dòng)輸出PWM波形,無需CPU干預(yù)。
硬件輸出PWM例子
這里以大家熟悉的STM32F1為例:為大家簡單分享一下硬件定時(shí)器輸出PWM波形。
PWM定時(shí)器相關(guān)宏定義:
//定時(shí)器計(jì)數(shù)時(shí)鐘(1M次/秒)
#define PWM_COUNTER_CLOCK 1000000
//預(yù)分頻值(與系統(tǒng)時(shí)鐘、計(jì)數(shù)值有關(guān))
#define PWM_PRESCALER_VALUE (SystemCoreClock/PWM_COUNTER_CLOCK - 1)
**PWM配置:
**
/**
* @brief 定時(shí)器PWM輸出配置
* @param 無
* @retval 無
*/
void PWM_TIM_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* 時(shí)鐘配置 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* 引腳配置 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 時(shí)基配置 */
TIM_TimeBaseStructure.TIM_Prescaler = PWM_PRESCALER_VALUE; //預(yù)分頻值
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計(jì)數(shù)
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; //定時(shí)周期(暫定值)
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //分頻因子
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* PWM模式配置 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //輸出PWM1模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能輸出
TIM_OCInitStructure.TIM_Pulse = 0; //脈寬值(暫定值)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性(TIM_OC1對應(yīng)通道1)
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
}
PWM輸出函數(shù)接口:
/**
* @brief 輸出PWM
* @param Frequency:頻率
Dutycycle:占空比
* @retval 無
*/
void PWM_Output(uint32_t Frequency, uint32_t Dutycycle)
{
uint32_t tim_period;
uint32_t tim_pulse;
tim_period = PWM_COUNTER_CLOCK/Frequency - 1; //計(jì)算出計(jì)數(shù)周期(決定輸出的頻率)
tim_pulse = (tim_period + 1)*Dutycycle / 100; //計(jì)算出脈寬值(決定PWM占空比)
TIM_Cmd(TIM2, DISABLE); //失能TIM
TIM_SetCounter(TIM2, 0); //計(jì)數(shù)清零
TIM_SetAutoreload(TIM2, tim_period); //更改頻率
TIM_SetCompare1(TIM2, tim_pulse); //更改占空比(TIM_SetCompare1對應(yīng)通道1)
TIM_Cmd(TIM2, ENABLE); //使能TIM
}
初始化配置,調(diào)用函數(shù)接口,直接就輸出PWM波形了:
void AppTask(void *p_arg)
{
PWM_TIM_Configuration();
PWM_Output(1000, 20);
while(1)
{
//自己的應(yīng)用代碼
}
}
輸出PWM波形:
說明:
本例使用的是STM32標(biāo)準(zhǔn)外設(shè)庫,如果要深入理解其中原理,還是建議使用標(biāo)準(zhǔn)外設(shè)庫。
當(dāng)然,如果想要快速使用PWM這個(gè)功能,不想理解其原理,可以直接使用STM32CubeMX配置生成代碼:
配置注意事項(xiàng)
想要更加精確控制,并更加滿足應(yīng)用層的需求,就需要自己一步一步深入了解原理。
下面說幾點(diǎn)常見的問題吧。
1.引腳映射
如果你使用的引腳需要映射,就需要配置對應(yīng)的參數(shù)。
比如:STM32F1使用PB11(需要查看數(shù)據(jù)手冊):
需要增加對應(yīng)的“映射”代碼:
//復(fù)用功能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//定時(shí)器(PWM)引腳映射
GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);
2.頻率和占空比精度
如果使用32位定時(shí)器的話,頻率范圍更寬、精度也可以達(dá)到更高。比如:頻率:0.01Hz、 占空比0.01%等。
如果是16位的話,其中的參數(shù)都不能超過16位(65535):
#define PWM_COUNTER_CLOCK 1000000
#define PWM_PRESCALER_VALUE (SystemCoreClock/PWM_COUNTER_CLOCK - 1)
tim_period = PWM_COUNTER_CLOCK/Frequency - 1; //計(jì)算出計(jì)數(shù)周期(決定輸出的頻率)
tim_pulse = (tim_period + 1)*Dutycycle / 100; //計(jì)算出脈寬值(決定PWM占空比)
具體可根據(jù)自己情況進(jìn)行配置,比如PWM(定時(shí)器)計(jì)數(shù)時(shí)鐘、分頻值等。
實(shí)際應(yīng)用代碼,建議增加各個(gè)參數(shù)的判斷,以防越界(這里為了方便理解,就寫的比較簡單)。
3.更多
STM32都有硬件PWM輸出功能,但不同的系列,其配置可能略有一些差異,簡單參考官方例程以及手冊。
現(xiàn)在大部分單片機(jī)都自帶有硬件PWM輸出功能,硬件的好處就是不用CPU干預(yù)。如果沒有,可以嘗試上面說的定時(shí)器中斷的方式。
-
IO
+關(guān)注
關(guān)注
0文章
454瀏覽量
39242 -
PWM
+關(guān)注
關(guān)注
114文章
5196瀏覽量
214405 -
通信調(diào)制器
+關(guān)注
關(guān)注
0文章
2瀏覽量
5275 -
電機(jī)速度控制
+關(guān)注
關(guān)注
0文章
10瀏覽量
1421
發(fā)布評論請先 登錄
相關(guān)推薦
評論