STM32定時(shí)器TIM和PWM的輸出
STM32一共有8個(gè)都為16位的定時(shí)器。其中TIM6、TIM7是基本定時(shí)器;TIM2、TIM3、TIM4、TIM5是通用定時(shí)器;TIM1和TIM8是高級(jí)定時(shí)器。這些定時(shí)器使STM32具有定時(shí)、信號(hào)的頻率測(cè)量、信號(hào)的PWM測(cè)量、PWM輸出、三相6步電機(jī)控制及編碼器接口等功能,都是專(zhuān)門(mén)為工控領(lǐng)域量身訂做的。
基本定時(shí)器:具備最基本的定時(shí)功能,下面是它的結(jié)構(gòu):
啟動(dòng)代碼:
void TIM2_Configuration(void)
{基本定時(shí)器TIM2的定時(shí)配置的結(jié)構(gòu)體(包含定時(shí)器配置的所有元素例如:TIM_Period = 計(jì)數(shù)值)
TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
設(shè)置TIM2_CLK為72MHZ (即TIM2外設(shè)掛在APB1上,把它的時(shí)鐘打開(kāi)。)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
設(shè)置計(jì)數(shù)值位1000
TIM_TimeBaseStructure.TIM_Period=1000;
將TIM2_CLK為72MHZ 除以72 = 1MHZ為定時(shí)器的計(jì)數(shù)頻率
TIM_TimeBaseStructure.TIM_Prescaler= 71;
這個(gè)TIM_ClockDivision是設(shè)置時(shí)鐘分割,這里不分割還是1MHZ的計(jì)數(shù)頻率
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
設(shè)置為向上計(jì)數(shù)模式;(計(jì)數(shù)模式有向上,向下,中央對(duì)齊1,中央對(duì)齊2,中央對(duì)齊3)
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
將配置好的設(shè)置放進(jìn)stm32f10x-tim.c的庫(kù)文件中
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
清除標(biāo)志位
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
使能TIM2中斷
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
使能TIM2外設(shè)
TIM_Cmd(TIM2, ENABLE);
}
通用定時(shí)器:就比基本定時(shí)器復(fù)雜得多了。除了基本的定時(shí),它主要用在測(cè)量輸入脈沖的頻率、脈沖寬與輸出PWM脈沖的場(chǎng)合,還具有編碼器的接口。
如何生成PWM脈沖
通用定時(shí)器可以利用GPIO引腳進(jìn)行脈沖輸出,在配置為比較輸出、PWM輸出功能時(shí),捕獲/比較寄存器TIMx_CCR被用作比較功能,下面把它簡(jiǎn)稱(chēng)為比較寄存器。
這里直接舉例說(shuō)明定時(shí)器的PWM輸出工作過(guò)程:若配置脈沖計(jì)數(shù)器TIMx_CNT為向上計(jì)數(shù),而重載寄存器TIMx_ARR被配置為N,即TIMx_CNT的當(dāng)前計(jì)數(shù)值數(shù)值X在TIMxCLK時(shí)鐘源的驅(qū)動(dòng)下不斷累加,當(dāng)TIMx_CNT的數(shù)值X大于N時(shí),會(huì)重置TIMx_CNT數(shù)值為0重新計(jì)數(shù)。
而在TIMxCNT計(jì)數(shù)的同時(shí),TIMxCNT的計(jì)數(shù)值X會(huì)與比較寄存器TIMx_CCR預(yù)先存儲(chǔ)了的數(shù)值A(chǔ)進(jìn)行比較,當(dāng)脈沖計(jì)數(shù)器TIMx_CNT的數(shù)值X小于比較寄存器TIMx_CCR的值A(chǔ)時(shí),輸出高電平(或低電平),相反地,當(dāng)脈沖計(jì)數(shù)器的數(shù)值X大于或等于比較寄存器的值A(chǔ)時(shí),輸出低電平(或高電平)。
如此循環(huán),得到的輸出脈沖周期就為重載寄存器TIMx_ARR存儲(chǔ)的數(shù)值(N+1)乘以觸發(fā)脈沖的時(shí)鐘周期,其脈沖寬度則為比較寄存器TIMx_CCR的值A(chǔ)乘以觸發(fā)脈沖的時(shí)鐘周期,即輸出PWM的占空比為 A/(N+1)。
如果不想看的可以直接看我標(biāo)注的紅色字體,就大體可以理解。
具體代碼:
void TIM3_GPIO_Config(void)
{配置TIM3復(fù)用輸出PWM的IO
GPIO_InitTypeDef GPIO_InitStructure;
打開(kāi)TIM3的時(shí)鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
打開(kāi)GPIOA和GPIOB的時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
配置PA6.PA7的工作模式
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
配置PB0.PB1的工作模式
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 | GPIO_Pin_1;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void TIM3_Mode_Config(void)
{
TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;//初始化TIM3的時(shí)間基數(shù)單位
TIM_OCInitTypeDefTIM_OCInitStructure;//初始化TIM3的外設(shè)
u16 CCR1_Val = 500;
u16 CCR2_Val = 375;
u16 CCR3_Val = 250;
u16 CCR4_Val = 125;//PWM信號(hào)電平跳變值(即計(jì)數(shù)到這個(gè)數(shù)值以后都是低電平之前都是高電平)
TIM3的時(shí)間基數(shù)單位設(shè)置(如計(jì)數(shù)終止值:999,從0開(kāi)始 ;計(jì)數(shù)方式:向上計(jì)數(shù))
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM3的外設(shè)的設(shè)置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//TIM脈沖寬度調(diào)制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//這個(gè)暫時(shí)不知道,stm32固件庫(kù)里沒(méi)有搜到。應(yīng)該是定時(shí)器輸出聲明使能的意思
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;//設(shè)置了待裝入捕獲比較寄存器的脈沖值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//TIM輸出比較極性高
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能或者失能TIMx在CCR1上的預(yù)裝載寄存器
下面3路PWM輸出和上面的一樣不再解說(shuō)
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);//使能TIM3重載寄存器ARR
TIM_Cmd(TIM3, ENABLE);//使能TIM3
}
程序達(dá)到的4路PWM的效果:
可以看到明顯占空比不同的4路pwm波。
這一節(jié)終于講完,個(gè)人覺(jué)得敲一遍代碼學(xué)起來(lái)還是蠻容易懂的。希望看到的人也能搞懂。
最后補(bǔ)充一點(diǎn)pwm具體能干什么?特別是對(duì)廣大電子DIY愛(ài)好者的應(yīng)用:
智能小車(chē)的電機(jī)控制:我們可以利用pwm來(lái)控制我們的智能小車(chē)的車(chē)速;
機(jī)器人:給“機(jī)器人關(guān)節(jié)”舵機(jī)周期一定(我以前玩過(guò)具體多少毫秒忘記了)pwm波就可以控制舵機(jī)的轉(zhuǎn)動(dòng)角度了;
呼吸燈:輸入不同的pwm波就可以達(dá)到明暗漸明漸暗的效果。