上一章節(jié)學(xué)習(xí)了PWM生成,剛好買的元器件也都到了。測(cè)試下代碼,完美運(yùn)行。這不又趁著周末,進(jìn)行下一個(gè)環(huán)節(jié)—定時(shí)器編碼器模式。
目的是為下一步PID控制做準(zhǔn)備。
周末學(xué)習(xí)編碼器模式也是一波三折呀,沒人指點(diǎn)真的是寸步難行呀。氣的直咬牙。
說說啥情況:
我用上節(jié)的PWM輸出控制電機(jī)旋轉(zhuǎn),用編碼器采集脈沖,想把這個(gè)脈沖顯示在LCD上,就這個(gè)顯示功能搗鼓了一天多,最后還是沒成功,最后沒辦法了,只能串口打印出來。就在昨天晚上準(zhǔn)備更新博客的時(shí)候想想不能就這么算了,又去調(diào)試了幾下,奇跡出現(xiàn)了,LCD竟然可以顯示了,弄完之后十點(diǎn)多了,就去睡覺了。目前問題還是不確定在哪,之前的代碼修改的也找不到了,晚上回家再試試改成之前的代碼,找找問題的根本原因。
改天單獨(dú)開個(gè)帖子說說吧,今天先學(xué)習(xí)編碼器。
首先需要明白的一點(diǎn)就是為什么要用編碼器模式,而不是直接用輸入捕獲。
最主要的原因就是編碼器采集的是兩個(gè)信號(hào),根據(jù)兩個(gè)信號(hào)的高低電平來判斷是正轉(zhuǎn)還是反轉(zhuǎn),比輸入捕獲用一個(gè)信號(hào)的抗干擾能力強(qiáng)。如果一個(gè)信號(hào)有干擾,而另一個(gè)信號(hào)沒有干擾,則計(jì)數(shù)器不會(huì)計(jì)數(shù),
就像下圖這樣,圖片在中文參考手冊(cè)中找的
圖中紅線標(biāo)注的是毛刺,當(dāng)TI1有干擾的情況下,計(jì)數(shù)器是不會(huì)繼續(xù)向上累加的。如果用輸入捕獲的話,左邊紅色框中有兩個(gè)脈沖,也就是說累加器會(huì)加兩次。這就出現(xiàn)了誤差,本來不該加,他卻加了。
這就是首選編碼器模式的主要原因。知道了他的作用還需要知道原理。
1.理解框圖
上圖是定時(shí)器的框圖,首先我們會(huì)從電機(jī)屁股后面的編碼器引出兩根信號(hào)線接到單片機(jī)的編碼器引腳,如上圖第一個(gè)框內(nèi),接到某定時(shí)器的TIMx_CH1和TIMx_CH2兩個(gè)通道的引腳上。進(jìn)來之后進(jìn)行濾波和邊沿檢測(cè)之后輸出TI1FP1和TI1FP2,之后就直接到2號(hào)框了。2號(hào)框是將TI1FP1和TI1FP2接入編碼器接口,在這里判斷是該向上還是向下計(jì)數(shù),之后來到3號(hào)框,進(jìn)行分頻,最后來到CNT計(jì)數(shù)器進(jìn)行計(jì)數(shù)。我們可以定時(shí)采集CNT里面的值,這樣就能算出電機(jī)的轉(zhuǎn)速和其他一些參數(shù)了。
具體配置一會(huì)看代碼吧。大致了解一下定時(shí)器框圖。
2.理解計(jì)數(shù)方式
框圖明白了,腦海里就明白了編碼器工作的大致原理了。但還需要明白一些細(xì)節(jié)方面的東西。比如它是怎么通過兩路信號(hào)進(jìn)行計(jì)數(shù)的,到底是向上還是向下計(jì)數(shù)等等。
其實(shí)也很簡(jiǎn)單,結(jié)合上面兩張圖片很好理解。簡(jiǎn)單說一下,明白一個(gè)其他都明白了。
首先假定此時(shí)是電機(jī)正轉(zhuǎn),還有一點(diǎn)要知道,編碼器兩個(gè)信號(hào)相差90°的相位角。一個(gè)周期的信號(hào)可以分為0 π/2 π 3/2*π 2π,如上圖,剛好差了π/2。上圖是兩個(gè)通道上下邊沿都檢測(cè)(SMS=’011’) 。
當(dāng)TI1為上升沿時(shí)時(shí),此時(shí)TI2為低電平,對(duì)應(yīng)下面的圖,先看【有效邊沿】,因?yàn)槭强吹腡I1上升沿,所以第一項(xiàng)選擇【僅在TI1計(jì)數(shù)】,之后找對(duì)應(yīng)的【TI1FP1 信號(hào)項(xiàng)】,選擇上升。因?yàn)閳D中TI1是上升沿,對(duì)應(yīng)TI2是低電平,因此在【相對(duì)信號(hào)的電平】那一項(xiàng)應(yīng)該選擇低,對(duì)應(yīng)起來就是向上計(jì)數(shù)。如下圖紅色部分。
理解了TI1上升沿計(jì)數(shù)之后,其他的都一樣了。
到這里,基本上編碼器模式已經(jīng)掌握的差不多了,下面就開始代碼了。
1.PWM輸出
較上一節(jié)講得做了引腳變動(dòng),這次使用定時(shí)器3,PA6引腳作為PWM輸出
具體配置和上一節(jié)差不多,不在啰嗦。
2.編碼器采集
編碼器采集用的是通用定時(shí)器2的PA0,PA1引腳,程序已經(jīng)詳細(xì)的注釋了。講幾個(gè)重要的參數(shù)配置、其中用
注釋的是普通的輸入捕獲模式、
3.編碼器配置中的主要參數(shù)講解
①中斷優(yōu)先級(jí)
不用問,問就是最高優(yōu)先級(jí),再平衡小車系統(tǒng)中,電機(jī)的速度和位置是至關(guān)重要的,而采集編碼器數(shù)據(jù)就是作為計(jì)算速度和位置的重要參數(shù)、
②TIM_TimeBaseStructure.TIM_Period = (359 * 4);
這行代碼是配置自動(dòng)重裝載的值,在這里設(shè)置359 * 4其實(shí)意義不大,因?yàn)槲覀冏龅氖菍?shí)驗(yàn),而且轉(zhuǎn)速不是很快,編碼器一圈才11個(gè)脈沖,因此采樣值很小,滿占空比才到達(dá)50左右,因此該數(shù)值只要大于60就行。網(wǎng)上很多都是一圈300脈沖的那種高精度編碼器,因此該值需要大于在采樣周期能采樣的最大值,再留一些余量就行了。假設(shè)你編碼器1s采樣一次,一次采樣500個(gè)脈沖,而你設(shè)定ARR=400,這肯定是不行的,因此該值應(yīng)該根據(jù)自己的實(shí)際情況進(jìn)行設(shè)定。
③TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
在編碼器模式中,該配置不起作用,正反項(xiàng)計(jì)數(shù)是根據(jù)兩個(gè)信號(hào)的前后順序來決定的,親測(cè)該配置對(duì)計(jì)數(shù)無作用。
④TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
重中之重
這個(gè)函數(shù)明白了就好理解,不要被表象給迷惑到就行。
1.這個(gè)函數(shù)是開啟編碼器模式的,第一個(gè)參數(shù)是選擇定時(shí)器,在這里我們選擇定時(shí)器2;
2.第二個(gè)參數(shù)是選擇計(jì)數(shù)器模式的,進(jìn)入到函數(shù)體中可以找到具體配置的是TIMx_SMCR寄存器中的SMS【2-0】位。具體說明如下:
因此選擇的是編碼器模式3,根據(jù)另一個(gè)信號(hào)的電平來決定怎么計(jì)數(shù),上面在將編碼器計(jì)數(shù)原理的時(shí)候也說過了,向上向下計(jì)數(shù)是要看另一路信號(hào)的電平的。
3.最后兩個(gè)參數(shù)也是最不容易理解的,主要是好多都是根據(jù)字面意思講解,沒有到函數(shù)體中看到底是配置的哪一個(gè)寄存器。當(dāng)你真正的進(jìn)去看函數(shù)體的時(shí)候你就明白了。
這兩個(gè)參數(shù)從下面這張圖中還以為是配置上升沿、下降沿還是雙邊沿檢測(cè)的,其實(shí)不是,
其實(shí)不是這樣,從函數(shù)體中找到這兩個(gè)參數(shù),其實(shí)是配置CCER寄存器中的CC1E、CC1P、CC2E以及CC2P,CC1E和CC2E是使能的,CC1P、CC2P是配置極性的,具體看中文手冊(cè),我也給你截好圖了
反向和不反向的意思就是從0到ARR計(jì)數(shù)還是從ARR到0 計(jì)數(shù)、而該位正是配置這一點(diǎn)的,在一個(gè)TIM_ICPolarity_BothEdge這個(gè)定義并不能在這個(gè)函數(shù)的形參中使用。該函數(shù)只能配置反向和不反向,下圖紅色框中需要注意下。
4.TIM_ICInitStructure.TIM_ICFilter = 10;
這個(gè)是設(shè)定濾波的,設(shè)定0的時(shí)候不是很穩(wěn)。具體參考中文手冊(cè)如下圖:
寫到這里,輸入捕獲的配置基本完后了。下面就是采樣了,我采用系統(tǒng)滴答定時(shí)器進(jìn)行1s采樣一次,這個(gè)值是輸入捕獲1s中采樣的編碼器的值。并把它顯示到屏幕上或者串口打印出來。
int Read_Encoder(u8 TIMX);
這個(gè)函數(shù)參考網(wǎng)上的代碼寫的,把這放到滴答定時(shí)器中斷里。如下圖
之后主函數(shù)一直循環(huán)顯示即可。這個(gè)是顯示在屏幕上的。
int main(void) { char aa[10; delay_init(); //延時(shí)函數(shù)初始化 LCD_Fill(30,130,239,130+16,WHITE); LCD_Init(); //uart_init(115200); //串口初始化為115200 SysTick_Config(SystemCoreClock / 1000);//1ms Advance_TIM_Init(); PWM_Init(); LCD_ShowString(30,50,16,"Show Frequency1",0); while(1) { sprintf(aa,"%d",Frequency1); LCD_ShowString(30,70,16,aa,0); //printf("count = %d\r\n",Frequency1); //delay_ms(10);//每隔1s打印一次編碼器角度,用手去撥動(dòng)編碼器 使其慢速旋轉(zhuǎn) } }基本都是老套路了、
①定義函數(shù)結(jié)構(gòu)體
②使能GPIO時(shí)鐘
③配置GPIO
④配置中斷優(yōu)先級(jí)
⑤使能定時(shí)器時(shí)鐘
⑥配置基本定時(shí)器
⑦配置編碼器模式
⑧初始化輸入捕獲
⑨使能定時(shí)器
最主要的還是理解其中的一些重要的參數(shù),其實(shí)也不難(不過對(duì)于新手確實(shí)難,弄過一遍回過頭才覺得簡(jiǎn)單),進(jìn)入到函數(shù)體中仔細(xì)看看函數(shù),在對(duì)著手冊(cè)看寄存器內(nèi)容說明也就明白啦。
感悟這個(gè)帖子已經(jīng)寫了好幾天了,7月3號(hào)就開始寫,寫到現(xiàn)在才弄完。中間過程很艱苦,不過一旦走出來,滿滿的成就感。
LCD相關(guān)的函數(shù)操作直接找的別人的代碼,我還沒有仔細(xì)研究,先拿來用吧。還是先把項(xiàng)目完成吧,拖得時(shí)間長(zhǎng)了就沒信心了。
一個(gè)人搞軟件有時(shí)候真的是累,不是那種身體勞累,是心累。搞了幾天還沒把一個(gè)問題解決的那種心情,真的是煩躁,恨不得把電腦砸了。他不像干體力活,加把勁就干完了,這種加把勁都不到往哪加。就像這個(gè)lcd顯示采集到的編碼器的值,就這一個(gè)問題弄了兩三天。各種百度,同樣代碼別人就行,到我這就不行了。到目前為止還沒有真正找到答案、-_-||
源碼代碼放到公眾號(hào)了,后續(xù)我會(huì)將之前的代碼也都放到公眾號(hào)上,歡迎小伙伴們交流學(xué)習(xí)哈。關(guān)注公眾號(hào)回復(fù)
“編碼器模式”
獲取源碼。
歡迎光臨 (http://www.torrancerestoration.com/bbs/) | Powered by Discuz! X3.1 |