# 實驗一:計數器
**其他筆記連結:**
* [單晶片系統實驗器材準備](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 的腳位定義

## 電路圖

## 範例程式
```=
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--)
```