# 實驗一:計數器 **其他筆記連結:** * [單晶片系統實驗器材準備](https://hackmd.io/@zjewp/8051) * [X8051 組譯器使用說明](https://hackmd.io/@zjewp/x8051_assemble) * [ALL-100 燒錄器使用教學](https://hackmd.io/@zjewp/all-100) ## 實驗簡介 使用 Port 1 實現計數器功能,編寫程式使數值每秒加一,並輸出到 P1.0 至 P1.7 所接的 LED。 (P1.7 為暫存器 P1 的 highest bit,P1.0 為 lowest bit) ## AT89S52 的腳位定義 ![pindef](https://hackmd.io/_uploads/HJVolmfpT.png) ## 電路圖 ![circuit](https://hackmd.io/_uploads/HJixFibpa.jpg) ## 範例程式 ```= ORG 0000H ; 告知接下來的指令將被置於 0000H CLR A ; 清除暫存器 A LOOP: MOV P1, A ; 將暫存器 A 的內容複製到 P1 INC A ; 將暫存器 A 的值加一 ACALL DELAY ; 呼叫 subroutine "DELAY" AJMP LOOP ; 跳至 label "LOOP" 處 ; Delay routine ; 暫存器只有 8 bits 大小,注意放入的數值不要超過 255 DELAY: MOV R5, #NUM1 ; 1 machine cycle DL0: MOV R6, #NUM2 ; 1 cycle DL1: MOV R7, #NUM3 ; 1 cycle DL2: DJNZ R7, DL2 ; 2 cycle DJNZ R6, DL1 ; 2 cycle DJNZ R5, DL0 ; 2 cycle RET ; 2 cycle END ``` ## DELAY routine 說明 此 subroutine 的作用是呼叫後延遲 X 秒,才繼續執行下一條指令。 一個 machine cycle 佔 12 個 clock,而 12 除以 OSC 的頻率 12 MHz,得出結果為 10 的負六次方秒,即 1 微秒。 * 1 machine cycle = 1 µs DJNZ 指令需要兩個 machine cycle 執行,目標是延遲一秒的話,讓 2 * (NUM1 * NUM2 * NUM3) 的積為一百萬即可。 **Execution count** ```= DELAY: MOV R5, #NUM1 ; 1 DL0: MOV R6, #NUM2 ; 1 * NUM1 DL1: MOV R7, #NUM3 ; 1 * NUM1 * NUM2 DL2: DJNZ R7, DL2 ; 2 * NUM1 * NUM2 * NUM3 DJNZ R6, DL1 ; 2 * NUM1 * NUM2 DJNZ R5, DL0 ; 2 * NUM1 RET ; 2 * 1 END ``` **以 C 語言來描述暫存器內容變化** ```=c for (int r5 = NUM1; r5 > 0; r5--) for (int r6 = NUM2; r6 > 0; r6--) for (int r7 = NUM3; r7 > 0; r7--) ```