[請益] 8051 microsecond級 delay 的問題

看板ASM作者 (朽唯)時間11年前 (2013/06/27 18:01), 編輯推噓7(7019)
留言26則, 5人參與, 最新討論串1/1
各位好, 小弟最近在寫一支自動控制的工作程式。 需要讓步進馬達可以高轉速運作 因此希望每一步之間的delay可以用100μs為單位控制 MCU 新唐W78E516DDG (8052) 振盪器 30MHz Keil C 電路運作正常 方式1是用一般的timer0中斷 #define tv 248 //用2.5GS/s 示波器量 1ms時 timer0值為2481 #define TH (65536 - tv)/256; #define TL (65536 - tv)%256; int x1ms; void delay100us(int count1) { x1ms = count1; IE = 0x92; //timer0為計時中斷 timer1為uart中斷 TMOD = 0x21; //timer0為計時中斷 timer1為uart中斷 TH0 = TH; TL0 = TL; TR0 = 1; while(x1ms != 0); } void T0_int(void) interrupt 1 { TR0 =0; x1ms-- ; TH0 = TH; TL0 = TL; TR0 =1; } 信號測量程式 void timertest(int delaytime) //透過uart給定delaytime { while(1) { P2 = 0xff; delay100us(delaytime); P2 = 0x00; delay100us(delaytime); } } 這樣timertest(1); 跑出來延遲大約是384 μs, OK,雖然差滿多的,那我調整一下tv參數應該就可以了吧 調整到tv = 150 跑出來為360 μs左右...這樣其他指令也跑太久了吧@@" 再來問題就更大了,我把tv值調得更小 函數timertest()就無法運作 .........也就是最低只能到360μs 也試過把timer0改成mode0 結果相同,完全不知道原因在哪裡... 理論上不是0~65536嗎.. 因為中斷搞不定,我改用跑迴圈的方法: void delayL(int t) //延遲tx1ms 副程式 { int i = 0; while(i != t) { i++; } } Keil C編譯的結果如下: 79: int i = 0; C:0x125D 8B4C MOV 0x4C,R3 C:0x125F 8A4D MOV 0x4D,R2 C:0x1261 894E MOV 0x4E,R1 80: while(i != t) 81: { 82: i++; C:0x1263 BF0116 CJNE R7,#0x01,C:127C 83: } C:0x1266 7F80 MOV R7,#P0(0x80) C:0x1268 7E00 MOV R6,#0x00 C:0x126A 12162A LCALL write_inst(C:162A) 84: } 結果 timertest(1); 跑了542 μs....................這不科學 也試過for迴圈的寫法,差異不大。 想請教: 1.為何tv參數不能更小?或是寫法哪裡有問題@@? 2.delayL 迴圈寫法 跑一圈花的時間也太長了吧...why...我以為頂多幾十μs 3.想要有100 μs的delay函數 不知道要從哪邊下手呢。 *先不考慮timertest(1)和timertest(10)的差異。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 42.70.50.235

06/27 18:13, , 1F
可以去看一下進出中斷的ASM碼
06/27 18:13, 1F

06/27 18:38, , 2F
看了一下 T0_int的函數也只有30行左右@@應該也不用上百
06/27 18:38, 2F

06/27 18:38, , 3F
微秒
06/27 18:38, 3F
Hi All: 後來我在計時中斷時關閉UART中斷,tv參數就可以小到100以下了 void delay100us(int count1) //計時設定副程式 { x1ms = count1; IE = 0x82; TMOD = 0x01; TH0 = TH; TL0 = TL; TR0 = 1; while(x1ms != 0); IE = 0x92; //打開UART中斷 TMOD = 0x21; } delayL我另外開一個單純的project就正常了...應該也是UART設定的問題.... ※ 編輯: shaoweei 來自: 42.70.50.235 (06/27 19:11)

06/30 00:14, , 4F
要設定timer除數要用算的不應用量的. 你要100uS(=10KHz)
06/30 00:14, 4F

06/30 00:15, , 5F
所以從XTAL要除3000, 所以timer要除250
06/30 00:15, 5F

06/30 00:18, , 6F
既然timer只需除250, 用mode2(auto reload)比較好
06/30 00:18, 6F

06/30 00:19, , 7F
另建議是把stpm的控制直接放在timer isr內作掉就好
06/30 00:19, 7F

06/30 02:51, , 8F
他的問題只在於忘記把TIMER的PR提高而已啦 XD
06/30 02:51, 8F

06/30 03:09, , 9F
建議可以換 1T的相容產品 .
06/30 03:09, 9F

06/30 05:41, , 10F
@Lion21 UART 跟TIMER ISR優先權不解決用0.5T/133MHZ
06/30 05:41, 10F

06/30 05:41, , 11F
也是無法解決時間會飄的問題....
06/30 05:41, 11F

06/30 20:49, , 12F
光改timer isr priority沒用, 因為在stpm兩個steps間
06/30 20:49, 12F

06/30 20:49, , 13F
uart interrupt還是會發生
06/30 20:49, 13F

06/30 22:24, , 14F
TIME優先下在TIMER時不會發生UART,在UART會發生TIMER
06/30 22:24, 14F

06/30 22:24, , 15F
所以TIMER只要扣除ISR進入的時間就可以穩定執行了。
06/30 22:24, 15F

06/30 22:25, , 16F
反過來,TIMER內會有UART或UART跟TIMER競爭TIMER就會飄
06/30 22:25, 16F

07/01 01:38, , 17F
原來如此 受教了>< ~~~~~~
07/01 01:38, 17F

07/02 00:18, , 18F
光改timer int priority沒用, 以原po的 timertest()來說
07/02 00:18, 18F

07/02 00:20, , 19F
P2=0xFF與P2=0x00間還是會發生uart int, 造成P2信號輸出
07/02 00:20, 19F

07/02 00:20, , 20F
時間受影響
07/02 00:20, 20F

07/02 00:23, , 21F
事實上把timer int設高priority只有保證timer isr
07/02 00:23, 21F

07/02 00:24, , 22F
不會受到uart的干擾, 所以要把需要精準計時的動作放到
07/02 00:24, 22F

07/02 00:24, , 23F
ISR內做
07/02 00:24, 23F

07/02 00:51, , 24F
上一段的說法不夠正確... 不過原po的程式只改timer int
07/02 00:51, 24F

07/02 00:51, , 25F
priority不夠是肯定的
07/02 00:51, 25F

07/03 20:28, , 26F
多謝k大指點 我再試試把要用的程式一起包到ISR裡面@@
07/03 20:28, 26F
文章代碼(AID): #1Hp0rUQM (ASM)