2011-06-25 130 views
1

我想實現裸機手臂環境(LPC1768)/ GCC一微秒的延遲。我已經看到了使用SysTimer產生一箇中斷是那麼做一些C計數,這是用來作爲時基LPC1768/ARM的Cortex-M3微秒的延遲

https://bitbucket.org/jpc/lpc1768/src/dea43fb213ff/main.c

然而,在12MHz的系統時鐘我不認爲你將在實例非常好地適應微秒延遲。基本上,處理器將花費所有時間來處理中斷。

是否可以查詢SYSTICK_GetCurrentValue的價值在一個循環,並確定有多少蜱微秒去救助循環一旦蜱的數量超過了計算出的數字?

我寧可不使用這種單獨的硬件定時器(但會在沒有其他選擇)

+1

它需要多準確?你可以用nops做一個循環,並且爲你的硬件進行校準,即找出每次迭代有多少個週期並計算迭代次數。 –

+1

注意12MHz是(通常是)晶振頻率,它被時鐘電路乘以得到實際的處理器時鐘頻率。 LPC1768可以高達100MHz的頻率運行。 –

回答

3

首先中斷,您可以輪詢定時器,沒有必要與中斷矯枉過正。是這些例子使用中斷的原因,但這並不意味着這是使用計時器的唯一方法。

蓋伊Sirton的回答是合理的,但我更喜歡彙編,我可以精確控制它的時鐘週期(只要有在途中沒有得到中斷或其他物品)。計時器通常是,雖然作爲代碼更加輕便一點(改變處理器的時鐘頻率更容易,你必須重新調整環,具有定時,有時候你需要做的是改變初始化代碼使用不同的預分頻器,或者改變尋找計算的計數的那一行),並且允許系統中的中斷和這樣的事情。

在這種情況下,雖然你說的是12MHz的,和一微秒,也就是12條指令是嗎?放入12個小餅。或分支的一些彙編與像10個空指令或8,不管它出來,以彌補在兩個分支管道沖洗。定時器和中斷將耗費超過12個指令週期的開銷。即使在循環中輪詢計時器也會變得渺茫。計數循環將工作太,你需要,雖然和調整理解分支的成本爲:

delay_one_ms: 
mov r0,#3 
wait: 
sub r0,#1 @cortex-m3 means thumb/thumb2 and gas complains about subs. 
bne wait 
nop @might need some nops to tune the loop accurately 
nop 
bx lr 

調用此函數,是什麼在使用GPIO循環3000萬次領導或UART輸出和秒錶和看到眨眼間隔30秒。

ldr r4,=uart_tx_register_address 
mov r5,#0x55 
again: 
ldr r6,=24000000 
str r5,[r4] 
top: 
bl delay_one_ms 
sub r6,#1 
bne top 
str r5,[r4] 
b again 

實際上因爲我假定每個分支2個時鐘中,測試環具有3個時鐘,延遲被假定爲是一個總的12個時鐘每循環,使15個時鐘,30秒30000000微秒,理想3000萬個循環,但我需要十二分之一的迴路數來補償。如果您的示波器的時基有些準確,或者至少與您想要的這種延遲一樣準確,那麼這會更容易。

我沒有研究過ARM的支費自己否則我會對此作出評論。這可能是兩三個鍾。所以mov是1,sub是一個循環次數的一倍,這個循環可以說是循環次數的兩倍。兩個分支到這裏來回兩個。 5+(3個*循環)+的NOP = 12。 (3 *循環)+ nops = 7循環是2並且nops是1,是嗎?我覺得串起了許多的NOP一起要容易得多:

delay_one_ms: 
    nop 
    nop 
    nop 
    nop 
    nop 
    nop 
    nop 
    nop 
    bx lr 

您可能需要暫時燒幾個指令禁止中斷,如果你使用它們。如果你正在尋找「至少」一微秒,那麼不要擔心它。

+0

如果我有機會,今天我會放棄這一點。我確實有一個體面的範圍,所以我會用gpio來衡量。 – user815719

4

的一個方法是使用一個循環來創建的延遲,類似如下所示。你需要校準你的因素。更通用的方法是根據一些已知的時基來計算啓動時的因子。不需要爲這種事情

#define CAL_FACTOR (100) 

void delay (uint32_t interval) 
{ 
    uint32_t iterations = interval/CAL_FACTOR; 

    for(int i=0; i<iterations; ++i) 
    { 
    __asm__ volatile // gcc-ish syntax, don't know what compiler is used 
    (
     "nop\n\t" 
     "nop\n\t" 
     ::: 
    ); 
    } 
} 
+1

這是一個很好的/典型的裸機編程方法。但是,使用arm cpu,即使仔細校準,也期望得到準確的時間。如果您需要延遲'約'1us,這是一個好方法。 – zdav

+2

Cortex-M3用戶指南說:「NOP什麼都不做,NOP不一定是一個耗時的NOP,處理器可能會在它到達執行階段之前將其從流水線中移除。」這足以嚇跑我使用NOP延遲。 – goertzenator

3

你可以在ARM處理器內部使用SYSTICK。只需對它進行編程即可計算每個1uS,或者如果您擁有足夠的時鐘速度,則執行該操作,並執行循環,直到延遲值到期。 像這樣:

void WaitUs(int us) { 

    unsigned int cnt; 

    while(us-- >0) { 
     cnt = STK_VAL; // get systick counter, ticking each 500nS 
     while((STK_VAL-cnt) < 2); // repeat till 2 ticks 
    } 
} 

請記住,這是一個例子,你需要調整它除其他事項外反翻車。