Robofun 機器人論壇

 找回密碼
 申請會員
搜索
熱搜: 活動 交友 discuz
12
返回列表 發新帖
樓主: ffffff2641
打印 上一主題 下一主題

roboot >>>>S-O-S

[複製鏈接]
21#
發表於 2007-8-12 14:28:55 | 顯示全部樓層
我的意見2:
你的中斷計時方法用起上來有點怪:
T0_INT:    ;只用到一個計時中斷
PUSH A
PUSH PSW
CLR TR0
MOV TH0,#>(65536-40) ;設定TIMER0在每40us中斷一次,if use12Mhz crystal
MOV TL0,#<(65536-40)
;INC  CUT  ;CUT還搞不懂
SETB TR0
CLR TR0
POP PSW
POP A
RETI

紅色部份我覺得是不需要的,搞不好會不會是一個 dead loop。
22#
發表於 2007-8-12 14:33:16 | 顯示全部樓層
我的意見3:
C1:
SETB P1.1 ;R0=41H
MOV R7, #13 ;每一格"H"的時間,視需要微調
ACALL DEL_H ;1ms
ACALL PWM_WIDTH
CLR P1.1

這個 del_H 用 13 會較接近 1ms (@ 12MHz)
因我計算你原設計的計械週期(machine cycle) 是 74 x 10 = 740 mc = 740 us (@ 12 MHz)
23#
發表於 2007-8-12 14:46:05 | 顯示全部樓層
最後這個不知是否錯誤,只是對用 timer 作中斷計時是 很怪的用法。
PWM_WIDTH:
          MOV COUNT,@R0
LOOP1:
       SETB TR0 ; 開啟T0計數器
        JNB TF0,$
       CLR TR0 ;關閉T0計數器
       DJNZ COUNT,LOOP1 ;將PWM的值乘以40us         
       CLR TR0 ;這行有點多餘=.=
       MOV CUT,#0 ;因為T0中斷給兩個副程式使用,所以CUT累加在此須清除         
        MOV PWM,@R0 ;將R0的值交給DEL_L去取LOW的時間
        INC R0 ;找下一個PWM的位置
RET

用 timer 作中斷計時本意是要讓 cpu 有空去處理其它事務。計時的任務便交  timer 去負責,時間到了才通知 cpu 接手處理的。
JNB TFO.$ 是檢查 timer 有否 overflow
這裡 cpu 並沒有空著,而是不斷檢查 timer 有否 overflow。其實是重複了 timer 的任務。
在真正 overflow 時,很有可能是先 做了 T0_INT 的部份,然後才執行 JNB TFO.$ 這一句 。如果在 T0_INT 返回時把 overflow 的 flag 給 clear 了,搞不好也有機會造成 dead loop 的。
其實這樣倒不如交由 cpu 自己做計時吧。

[ 本帖最後由 irobot 於 2007-8-12 14:49 編輯 ]
24#
發表於 2007-8-12 20:15:35 | 顯示全部樓層
Zirok大大:
開于于第52帖提到的可能錯誤,終於有時間翻查了 manual 。確定會導致錯誤了。
http://www.atmel.com/dyn/resources/prod_documents/DOC4316.PDF  (用搜尋找 timer 0 的段落)
你看這個:
2.11.5 Interrupt
Each timer handles one interrupt source; that is the timer overflow flag TF0 or TF1. This
flag is set every time an overflow occurs. Flags are cleared when vectoring to the timer
interrupt routine
.
它說當 timer0 溢位(overflow) 時,TF0=1。 程序流程 導向 中斷程序(timer interrupt routine)時,會清空 TF0 的旗標,即 TF0=0。
按這順序
PWM_WIDTH:
          MOV COUNT,@R0
LOOP1:
       SETB TR0 ; 開啟T0計數器
        JNB TF0,$
       CLR TR0 ;關閉T0計數器
當開始計時後發生溢位,程序流程 會先指向 中斷程序, 並清空 TF0 的旗標,即 TF0=0。當返回下句時 JNB TF0,$
,它可能永遠也測不到溢位的,做成無限循環。程式其它部份若是用以上的寫法皆有問題,你要更改啊!!

解決辦法也很簡單,你用 timer 也不過是想做 40us 的延時。乾脆用 NOP (no operation) 這個指令吧。執行它 cpu 什麼也不會做,但會消耗 1 個 機械週期 (machine cycle) 的時間。 在頻率 12MHz 時剛好是 1us 。就用 40 個 NOP 便可以了,比你原先的計時方法更準確。
PWM_WIDTH:
          MOV COUNT,@R0
LOOP1:
       NOP       ;每個 nop 延時 1us
       NOP
       NOP
       ....共 四十 個

       NOP
       NOP
       DJNZ COUNT,LOOP1 ;將PWM的值乘以40us         
       MOV CUT,#0 ;因為T0中斷給兩個副程式使用,所以CUT累加在此須清除         
        MOV PWM,@R0 ;將R0的值交給DEL_L去取LOW的時間
        INC R0 ;找下一個PWM的位置
RET

[ 本帖最後由 irobot 於 2007-8-12 20:43 編輯 ]
25#
發表於 2007-8-12 20:26:27 | 顯示全部樓層
CPL PWM
ADD A,PWM
這2句的功能就是做 ( A - PWM -1 ) 啊。

所以 你先做 MOV A,#27H 。就等於計這算術  ==> (27H - PWM -1) = 26H - PWM
意思正好是 (1.5ms - pulse_width ) 了。
你明白麼?
如果還不明白可以在網上找找關於 2進制補碼 (2's complement) 的資料和使用方法。可以學多一樣東西。

PS :其實伺服機訊號是 0.5 至 2.5 ms 較多的。而且你做到 0.3 至 2.7 ms 會更好,差不多所有 servo 你也能控制了。
因已包括 (1 至 2 ms) 在內,你說對嗎?

[ 本帖最後由 irobot 於 2007-8-12 20:47 編輯 ]
26#
發表於 2007-8-13 14:43:41 | 顯示全部樓層
呵呵,不錯的改動 !! 大致上也可以了。
但要留意
       MOV         R4,#28H               ;40次                 
LOOP3:        
        NOP                                     ;每個 nop 延時 1us
        DJNZ       R4,LOOP3            ;R4=0時跳下一行   <=== 每次執行這句要用 2us 啊!!
        DJNZ       COUNT,LOOP2    ;將PWM LOW的值乘以40us         
        CLR        TR0                      ;這行有點多餘=.= 藍色的可以不要
        MOV        CUT,#0        ;因為T0中斷給兩個副程式使用,所以CUT累加在此須清除                 
        RET

所以較準確的寫法是這樣
        MOV COUNT,A
LOOP2:
        MOV         R4, #0AH               ;10次                 
LOOP3:        
        NOP                                     ;每個 nop 延時 1us  (t1)
        NOP                                     ;每個 nop 延時 1us  (t2)
        DJNZ       R4,LOOP3            ;R4=0時跳下一行     (t3) <=== 連這一句計 (t1+t2+t3) 總數是 4us 。
        DJNZ       COUNT,LOOP2    ;將PWM LOW的值乘以40us         
        MOV        CUT,#0        ;因為T0中斷給兩個副程式使用,所以CUT累加在此須清除                 
        RET
27#
發表於 2007-8-13 20:51:32 | 顯示全部樓層
你太跨獎了,你也可以做到的。若要我自己用彙編寫便不行了。這些東西是看時容易做時難。
你在進步中啊!! 不若我再考考你,若把 5 放入 COUNT 內,你猜 它是否真的計時 5 X 40us = 200 us 呢?若不是,又延時了多少呢?
程式碼如下:
        MOV COUNT, #05H
LOOP2:
        MOV         R4, #0AH               ;10次                 
LOOP3:        
        NOP                                     ;每個 nop 延時 1us  (t1)
        NOP                                     ;每個 nop 延時 1us  (t2)
        DJNZ       R4,LOOP3            ;R4=0時跳下一行     (t3) <=== 連這一句計 (t1+t2+t3) 總數是 4us 。
        DJNZ       COUNT,LOOP2    ;將PWM LOW的值乘以40us
28#
發表於 2007-8-13 21:07:35 | 顯示全部樓層
你的目標是要讓伺服機起動,在我看來其實你已經有足夠能力做到了。
只是你剛開始便要同時處理8個伺服機,在你來說是稍稍難了一點。
如果你真的很想起動你的伺服機,可以把要求稍微降低一點。
1.  用你的 8051 點著一盞 LED 燈。
2.  讓這盞 LED 燈閃爍。
3.  準確控制 LED 燈著的時間和熄滅的時間。(例如 1 秒)
     這可訓練你準確用 Looping 計時的技巧。若是用 timer 計時也可以,同樣達到目的。
4,  輸出 1.5 ms High, 18.5 ms Low 這要求很準確的計時。若你做到便可以控制一個伺服機了。
5.  有了基礎,便可陸續加入更多的伺服機了(即你現在做的ssc)。
6.  也可以先嘗試 用 rs232 控制一盞 LED 燈的開關,熟悉一下 rs232 的用法。然後便用來控制一個伺服機。
總括以言,就是盡量把問題簡化。逐個擊破。 然後才做擴展。 不要同時出現太多不熟悉的問題。


[ 本帖最後由 irobot 於 2007-8-13 21:11 編輯 ]
29#
發表於 2007-8-14 18:17:58 | 顯示全部樓層
用 8051 的輸出腳接 led 是可控制它亮著或熄滅的。在未完成你的 ssc 前不妨順著1至4做,能控制一個伺服機也很有意思的。而且較容易成功和有滿足感。
另外答案是 5 x 2us = 10 us ,是多了 10 us 所以這樣的計時方法還不是準確的。
在這裡的誤差是 ( (5x2) / (5x40) ) x 100% = (2/40) x 100% = 5%  (留意是一個固定的誤差值,與 5 無關的)

[ 本帖最後由 irobot 於 2007-8-14 18:24 編輯 ]
您需要登錄後才可以回帖 登錄 | 申請會員

本版積分規則

小黑屋|手機版|Archiver|機器人論壇 from 2005.07

GMT+8, 2024-6-2 07:08 , Processed in 0.197118 second(s), 8 queries , Apc On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表