如何用雙定時(shí)器控制單片機(jī)輸出固定的數(shù)量的PWM脈沖?
[導(dǎo)讀]關(guān)注「Linux大陸」,星標(biāo)公眾號(hào),一起進(jìn)步!最近在逛21ic論壇,看到幾個(gè)帖子都在咨詢?nèi)绾慰刂茊纹瑱C(jī)輸出固定的數(shù)量的PWM脈沖,用于控制電機(jī)的轉(zhuǎn)停,剛好前兩天本人也需要該功能做測(cè)試,我是輸出PWM給伺服電機(jī)驅(qū)動(dòng)器,驅(qū)動(dòng)器以位置模式工作,收到脈沖就控制電機(jī)轉(zhuǎn)動(dòng),如果需要精確控制電...
關(guān)注「Linux大陸」,星標(biāo)公眾號(hào),一起進(jìn)步!
最近在逛21ic論壇,看到幾個(gè)帖子都在咨詢?nèi)绾?a href="/tags/控制" target="_blank">控制單片機(jī)輸出固定的數(shù)量的PWM脈沖,用于控制電機(jī)的轉(zhuǎn)停,剛好前兩天本人也需要該功能做測(cè)試,我是輸出PWM給伺服電機(jī)驅(qū)動(dòng)器,驅(qū)動(dòng)器以位置模式工作,收到脈沖就控制電機(jī)轉(zhuǎn)動(dòng),如果需要精確控制電機(jī)轉(zhuǎn)過(guò)的角度,就需要給驅(qū)動(dòng)器輸入固定數(shù)量的脈沖。于是我便用STM32F031的雙定時(shí)器實(shí)現(xiàn)了該功能,下文便詳細(xì)描述。
我在進(jìn)行代碼編譯之前也在網(wǎng)絡(luò)上搜索過(guò)相應(yīng)的方法,總結(jié)起來(lái)一共五個(gè)方法:
1、單脈沖法,需要一個(gè)脈沖中斷一次,中斷次數(shù)多,影響效率2、一個(gè)定時(shí)器輸出PWM,另一定時(shí)器使用輸入捕獲進(jìn)行中斷計(jì)數(shù),與方法1一樣,同樣需要頻繁的中斷3、用主從定時(shí)器門控方式,比較繁瑣4、用一個(gè)定時(shí)器(從)作為另一個(gè)定時(shí)器(主)的外部時(shí)鐘觸發(fā)源5、高級(jí)定時(shí)器T1、T8的重復(fù)計(jì)數(shù)方式,RCR計(jì)數(shù)中斷,看手冊(cè)好像這種方式最簡(jiǎn)單,能滿足一部分人要求,缺點(diǎn)是寄存器只有8位,最多實(shí)現(xiàn)255個(gè)脈沖計(jì)數(shù)輸出。
我在最初時(shí)使用了第2和方法,該方法對(duì)于我來(lái)說(shuō)你叫簡(jiǎn)單,后來(lái)在寫這篇文章時(shí)選擇了第4個(gè)方法,總結(jié)起來(lái)還是4比較靠譜,但是這里的第2方法也描述一下,便于大家選擇。
方法2:
因?yàn)闂l件限制,干脆說(shuō)為了省事,我在原來(lái)用于其他功能的板子上進(jìn)行測(cè)試,因?yàn)橹婚_放了PB3和PB4,所以這里只好用TIM2和TIM3進(jìn)行測(cè)試。
TIM2用于產(chǎn)生PWM脈沖輸出,在輸出給驅(qū)動(dòng)器的同時(shí)將該脈沖也接到PB4,也就是TIM3的輸入口,這樣TIM3也能接收到TIM2發(fā)出的脈沖,TIM3只需要配置為輸入捕獲,并開啟中斷,便可以在每次脈沖到來(lái)進(jìn)入中斷,在TIM3的中斷中去計(jì)數(shù),達(dá)到需要的脈沖數(shù)便關(guān)閉TIM2便可。
首先依舊是初始化端口:
先貼一下time.h文件:
因?yàn)槲业臅r(shí)鐘初始化是單獨(dú)定義的,所以這里未進(jìn)行時(shí)鐘的初始化,在參考的我的代碼時(shí)需注意:
最近在逛21ic論壇,看到幾個(gè)帖子都在咨詢?nèi)绾?a href="/tags/控制" target="_blank">控制單片機(jī)輸出固定的數(shù)量的PWM脈沖,用于控制電機(jī)的轉(zhuǎn)停,剛好前兩天本人也需要該功能做測(cè)試,我是輸出PWM給伺服電機(jī)驅(qū)動(dòng)器,驅(qū)動(dòng)器以位置模式工作,收到脈沖就控制電機(jī)轉(zhuǎn)動(dòng),如果需要精確控制電機(jī)轉(zhuǎn)過(guò)的角度,就需要給驅(qū)動(dòng)器輸入固定數(shù)量的脈沖。于是我便用STM32F031的雙定時(shí)器實(shí)現(xiàn)了該功能,下文便詳細(xì)描述。
我在進(jìn)行代碼編譯之前也在網(wǎng)絡(luò)上搜索過(guò)相應(yīng)的方法,總結(jié)起來(lái)一共五個(gè)方法:
1、單脈沖法,需要一個(gè)脈沖中斷一次,中斷次數(shù)多,影響效率2、一個(gè)定時(shí)器輸出PWM,另一定時(shí)器使用輸入捕獲進(jìn)行中斷計(jì)數(shù),與方法1一樣,同樣需要頻繁的中斷3、用主從定時(shí)器門控方式,比較繁瑣4、用一個(gè)定時(shí)器(從)作為另一個(gè)定時(shí)器(主)的外部時(shí)鐘觸發(fā)源5、高級(jí)定時(shí)器T1、T8的重復(fù)計(jì)數(shù)方式,RCR計(jì)數(shù)中斷,看手冊(cè)好像這種方式最簡(jiǎn)單,能滿足一部分人要求,缺點(diǎn)是寄存器只有8位,最多實(shí)現(xiàn)255個(gè)脈沖計(jì)數(shù)輸出。
我在最初時(shí)使用了第2和方法,該方法對(duì)于我來(lái)說(shuō)你叫簡(jiǎn)單,后來(lái)在寫這篇文章時(shí)選擇了第4個(gè)方法,總結(jié)起來(lái)還是4比較靠譜,但是這里的第2方法也描述一下,便于大家選擇。
方法2:
因?yàn)闂l件限制,干脆說(shuō)為了省事,我在原來(lái)用于其他功能的板子上進(jìn)行測(cè)試,因?yàn)橹婚_放了PB3和PB4,所以這里只好用TIM2和TIM3進(jìn)行測(cè)試。
TIM2用于產(chǎn)生PWM脈沖輸出,在輸出給驅(qū)動(dòng)器的同時(shí)將該脈沖也接到PB4,也就是TIM3的輸入口,這樣TIM3也能接收到TIM2發(fā)出的脈沖,TIM3只需要配置為輸入捕獲,并開啟中斷,便可以在每次脈沖到來(lái)進(jìn)入中斷,在TIM3的中斷中去計(jì)數(shù),達(dá)到需要的脈沖數(shù)便關(guān)閉TIM2便可。
首先依舊是初始化端口:
先貼一下time.h文件:
/* 定義防止遞歸包含 ----------------------------------------------------------*/#ifndef _TIMER_H#define _TIMER_H
/* 包含的頭文件 --------------------------------------------------------------*/#include "stm32f0xx.h"
/* 宏定義 --------------------------------------------------------------------*/#define TIM6_COUNTER_CLOCK 1000000 //計(jì)數(shù)時(shí)鐘(1M次/秒) //預(yù)分頻值#define TIM6_PRESCALER_VALUE (SystemCoreClock/TIM6_COUNTER_CLOCK - 1)#define TIM6_PERIOD_TIMING (10 - 1) //定時(shí)周期(相對(duì)于計(jì)數(shù)時(shí)鐘:1周期 = 1計(jì)數(shù)時(shí)鐘)
#define TIM2_COUNTER_CLOCK 24000000 //計(jì)數(shù)時(shí)鐘(24M次/秒) //預(yù)分頻值#define TIM2_PRESCALER_VALUE (SystemCoreClock/TIM2_COUNTER_CLOCK - 1)
/* 函數(shù)申明 ------------------------------------------------------------------*/void Systick_Init(void);void Delay_ms(__IO uint32_t nTime);void TimingDelay_Decrement(void);void Delay(uint32_t temp);void delay_us(uint32_t nus);void delay_init();
void TIMER_Initializes(void);
void TIMDelay_N10us(uint16_t Times);void TIMDelay_Nms(uint16_t Times);void TIMDelay_Ns(uint16_t Times);
void TIMER_PWM_GPIO_Configuration(void);void TIM2_CH2_PWM(uint32_t Freq, uint16_t Dutycycle);void TIMER_IC_Configuration(void);
#endif /* _TIMER_H */因?yàn)槲业臅r(shí)鐘初始化是單獨(dú)定義的,所以這里未進(jìn)行時(shí)鐘的初始化,在參考的我的代碼時(shí)需注意:
void TIMER_PWM_GPIO_Configuration(void){ GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //TIM2引腳 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //復(fù)用模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //高速輸出 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推完輸出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOB, 




