概述:stm32的每個引腳都有其自帶的特殊功能,有定時器輸出功能的引腳可以輸出pwm。如果沒有的也可以io口模拟輸出,如果非要較真的話,理論上可以算是每個引腳都能輸出PWM,但一般我們都使用帶定時器輸出功能的io。此文章來詳述使用stm32F051R8T6型号單片機,帶有定時器輸出功能的引腳來輸出pwm波形,同理其他型号的單片機也可實作。并同時來控制直流電機轉速,本文以adda公司生産的AD0212DB-G50直流風扇為例講述。
1.硬體條件
保證單片機輸出IO可以支援定時器功能。我闆子上連接配接風扇的引腳為PC9,根據單片機手冊PC9引腳帶有定時器功能
同理如下圖的幾個引腳都可以
再次就不一一列舉了,在是用不同型号的單片機時,參考單片機手冊。
2.stm32固件庫
上圖分别是stm32定時器相關的庫函數,和相關調用的定時器驅動子函數,使用者自己定義。
軟硬體條件都準備好了,接下來就是pwm所需的相關配置。
1.首先是輸出管腳的IO口設定,PWM輸出,自然會采用到IO口作為輸出端口,在STM32F051系列中,IO端口可以複用為TIM定時器輸出通道。
采用PC9的複用功能AF1作為TIM3定時器的第4通道輸出。
2.設定定時器的參數,配置出頻率為17.57 KHz的PWM波
考慮time定時器的時鐘頻率。如果我們設定分頻數為0,也就是說time定時器等于系統時鐘,system_stm32f0xx.c中已經把系統頻率設定在48MHZ,在startup_stm32f0xx.s中,首先運作了systemInit函數,是以可以确定time定時器運作在48MHZ。
定時器産生的PWM的頻率可以按照下面的公式進行計算:
預定标的值TIM1_Period = (time定時器頻率 / pwm的頻率) - 1
預定标的值實際上就是定時器運作多少次算一個PWM周期,這個在設定pwm頻率中重要的參數。
配置完整代碼如下:
/*==============================================================================
函數名 : Fan_PWMConfigInit
功能 : 風扇控制引腳輸出pwm控制風扇轉速
輸入參數說明: 無
傳回值說明 : 無
------------------------------------------------------------------------------*/
void Fan_PWMConfigInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
s32 TimerPeriod, Channel1Pulse;
/* 使能GPIO時鐘 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
/* 配置GPIO管腳參數設定*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* GPIO管腳複用設定*/
GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_1);
/*計算預定标 的值,也就是多少個時鐘計數為一個周期*/
TimerPeriod = (SystemCoreClock / 17570 ) - 1;
/*計算CCR1 跳轉值 在占空比為50%時*/
Channel1Pulse = (u16)(((u32)5 * (TimerPeriod - 1)) / 10);
/* TIM3 時鐘使能 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Time 定時基礎設定*/
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
/* Time 定時設定為上升沿計算模式*/
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* 頻道1的PWM 模式設定 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
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_OCInitStructure.TIM_Pulse = Channel1Pulse;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
/* TIM3 電腦使能*/
TIM_Cmd(TIM3, ENABLE);
/* TIM3 主輸出使能 */
TIM_CtrlPWMOutputs(TIM3, ENABLE);
}
在需要改變風扇轉速時,隻需要改變占空比即可。
/* 風扇控制 */
static s32 CmdFanCtrl (TCmdTbl *cmdtp, s32 argc, s8 *argv[])
{
u8 byCmd;
s32 Channel1Pulse;
if (argc < 2)
return -1;
byCmd = strtoul(argv[1], NULL, 0);
switch(byCmd){
case 1:
Channel1Pulse = (u16)(((u32)875 * 2730) / 1000);
break;
case 2:
Channel1Pulse = (u16)(((u32)75 * 2730) / 100);
break;
case 3:
Channel1Pulse = (u16)(((u32)625 * 2730) / 1000);
break;
case 4:
Channel1Pulse = (u16)(((u32)5 * 2730) / 10);
break;
case 5:
Channel1Pulse = (u16)(((u32)375 * 2730) / 1000);
break;
case 6:
Channel1Pulse = (u16)(((u32)25 * 2730) / 100);
break;
case 7:
Channel1Pulse = (u16)(((u32)125 * 2730) / 1000);
break;
case 8:
Channel1Pulse = (u16)(((u32)1 * 2730) / 100);
break;
}
TIM_SetCompare4(TIM3, Channel1Pulse);
return 0;
}
TIM_SetCompare4(TIM3, Channel1Pulse);該函數是改變對應TIM定時器對應通道占空比的函數,其中的2370是根據系統時間計算出來。使用不同的定時器和通道,可在stm32f0xx_tim.c中查找不同的庫函數。
下面是輸出的pwm波形