### 8051 Microcontroller Assembly Language Programming The 8051 is an 8-bit microcontroller. Its architecture includes CPU, RAM, ROM, I/O ports, timers, and serial communication. Assembly language provides direct control over hardware. ### Addressing Modes How the operand's location is specified. - **Immediate Addressing:** Operand is part of the instruction. `MOV A, #55H` (Move hex value 55 into Accumulator A) - **Direct Addressing:** Operand's address is specified directly in the instruction. `MOV A, 30H` (Move content of RAM location 30H into A) - **Register Addressing:** Operand is in one of the 8051's registers (R0-R7). `MOV A, R0` (Move content of R0 into A) - **Register Indirect Addressing:** Operand's address is in R0 or R1. `MOV A, @R0` (Move content of RAM address pointed by R0 into A) - **Indexed Addressing:** Used for accessing data tables in program memory. `MOVC A, @A+DPTR` (Move code byte from address A+DPTR into A) ### 8051 Instruction Set Summary Instructions are categorized by function. - **Data Transfer:** `MOV`, `MOVC`, `MOVX`, `PUSH`, `POP`, `XCH` - **Arithmetic:** `ADD`, `ADDC`, `SUBB`, `INC`, `DEC`, `MUL`, `DIV`, `DA A` - **Logical:** `ANL`, `ORL`, `XRL`, `CLR`, `CPL`, `RL`, `RLC`, `RR`, `RRC`, `SWAP` - **Boolean:** `CLR C`, `SETB C`, `CPL C`, `ANL C, bit`, `ORL C, bit` - **Branching:** `LJMP`, `SJMP`, `AJMP`, `JMP @A+DPTR`, `CALL`, `LCALL`, `ACALL`, `RET`, `RETI`, `JZ`, `JNZ`, `JC`, `JNC`, `JB`, `JNB`, `JBC`, `DJNZ`, `CJNE` ### Assembler Directives Commands for the assembler, not executed by the CPU. - **ORG (Origin):** Sets the starting address for the code segment. `ORG 0000H` - **END:** Marks the end of the source file. - **EQU (Equate):** Assigns a symbolic name to a constant. `COUNT EQU 20H` - **DB (Define Byte):** Defines byte-sized data. `MYDATA: DB 'HELLO', 0DH, 0AH` - **DW (Define Word):** Defines word-sized data (16-bit). - **DS (Define Space):** Reserves space in RAM. `BUFFER: DS 10H` (Reserves 16 bytes for BUFFER) ### Data Movement / Copy Operations - **MOV destination, source:** Most common, copies byte data. `MOV A, R0` (Register to Accumulator) `MOV P1, A` (Accumulator to Port 1) `MOV R2, #10H` (Immediate to Register) - **MOVC A, @A+DPTR:** Move Code byte (from program memory). - **MOVX A, @DPTR:** Move External data byte (from external RAM). - **PUSH direct:** Pushes a byte onto the stack. `PUSH 30H` (Pushes content of RAM 30H onto stack) - **POP direct:** Pops a byte from the stack. `POP 30H` (Pops from stack into RAM 30H) ### Block Transfer, Data Swap / Exchange - **Block Transfer:** Achieved using loops with `MOV` and pointer increments. ```assembly MOV R0, #SOURCE_ADDR MOV R1, #DEST_ADDR MOV R7, #LENGTH LOOP_BLK: MOV A, @R0 MOV @R1, A INC R0 INC R1 DJNZ R7, LOOP_BLK ``` - **XCH A, byte:** Exchanges content of Accumulator with a byte. `XCH A, R0` (Exchange A with R0) `XCH A, 30H` (Exchange A with RAM 30H) - **XCHD A, @Ri:** Exchanges the low-order nibble (4 bits) of A with the low-order nibble of the memory location pointed to by Ri (R0 or R1). `XCHD A, @R0` - **SWAP A:** Swaps the upper and lower nibbles within the Accumulator. `SWAP A` (e.g., if A=3CH, after SWAP A=C3H) ### Arithmetic Operations - **ADD A, source:** Adds source to Accumulator. `ADD A, R0` - **ADDC A, source:** Adds source and Carry flag to Accumulator. `ADDC A, #05H` - **SUBB A, source:** Subtracts source and Borrow (Carry) flag from Accumulator. `SUBB A, 30H` - **INC byte:** Increments a byte by 1. `INC A`, `INC R0`, `INC 30H`, `INC DPTR` (DPTR is 16-bit) - **DEC byte:** Decrements a byte by 1. `DEC A`, `DEC R1` - **MUL AB:** Multiplies A by B (unsigned 8-bit values). Result is 16-bit, stored in B (high byte) and A (low byte). - **DIV AB:** Divides A by B (unsigned 8-bit values). Result: A = Quotient, B = Remainder. - **DA A (Decimal Adjust Accumulator):** Adjusts A for BCD addition. ### Logical Operations - **ANL destination, source:** Logical AND. `ANL A, #0FH` (Mask lower nibble) `ANL P1, A` - **ORL destination, source:** Logical OR. `ORL A, #80H` (Set MSB) - **XRL destination, source:** Logical XOR. `XRL A, #FFH` (Toggle all bits) - **CLR A / CLR C:** Clear Accumulator / Clear Carry flag. - **CPL A / CPL C:** Complement Accumulator / Complement Carry flag. - **RL A (Rotate Left):** - **RLC A (Rotate Left through Carry):** - **RR A (Rotate Right):** - **RRC A (Rotate Right through Carry):** ### Stack Operations The 8051 stack grows upwards. SP (Stack Pointer) points to the last occupied byte. - **PUSH direct:** Increments SP, then copies content of `direct` address to `(SP)`. `PUSH 05H` (Pushes R5 onto stack) - **POP direct:** Copies content of `(SP)` to `direct` address, then decrements SP. `POP 05H` (Pops from stack into R5) ### Loops, Condition Evaluation, Decision Making - **DJNZ (Decrement and Jump if Not Zero):** `DJNZ R7, LABEL` (Decrements R7, if R7 != 0, jumps to LABEL) `DJNZ 30H, LABEL` (Decrements content of RAM 30H, if not 0, jumps) - **JZ (Jump if Zero):** Jumps if Accumulator is zero. `JZ LABEL` - **JNZ (Jump if Not Zero):** Jumps if Accumulator is not zero. `JNZ LABEL` - **JC (Jump if Carry):** Jumps if Carry flag is set (C=1). - **JNC (Jump if No Carry):** Jumps if Carry flag is clear (C=0). - **JB bit, target (Jump if Bit is Set):** `JB P1.0, LED_ON` - **JNB bit, target (Jump if Bit is Not Set):** - **JBC bit, target (Jump if Bit is Set and Clear Bit):** Jumps if bit is set, and then clears the bit. - **CJNE destination, source, relative_offset (Compare and Jump if Not Equal):** `CJNE A, #50H, NOT_50` (Compares A with #50H, if not equal, jumps) `CJNE R0, 30H, NOT_EQUAL` ### Call, Return, Jumps - **Jumps (Unconditional):** - `SJMP relative_offset` (Short Jump, -128 to +127 bytes) - `LJMP address` (Long Jump, 16-bit address) - `AJMP address` (Absolute Jump, 11-bit address, within 2KB page) - `JMP @A+DPTR` (Indirect Jump, used for jump tables) - **Calls (Subroutine):** Pushes PC onto stack, then jumps to subroutine. - `LCALL address` (Long Call, 16-bit address) - `ACALL address` (Absolute Call, 11-bit address, within 2KB page) - **RET (Return from Subroutine):** Pops PC from stack, returns to caller. - **RETI (Return from Interrupt):** Pops PC and PSW (Program Status Word) from stack, enables interrupts. ### I/O Port Structure and Programming The 8051 has four 8-bit I/O ports: P0, P1, P2, P3. - All ports are bi-directional. - **P0:** Open-drain, requires external pull-ups for output, also serves as multiplexed Address/Data bus in external memory access. - **P1:** Internal pull-ups, general purpose I/O. - **P2:** Internal pull-ups, also serves as high-order Address bus in external memory access. - **P3:** Internal pull-ups, general purpose I/O, but also serves as alternate functions (Serial Rx/Tx, Interrupts, Timers). **Programming Example (Toggle P1.0):** ```assembly ORG 0000H START: SETB P1.0 ; Set P1.0 (LED OFF if active low) ACALL DELAY CLR P1.0 ; Clear P1.0 (LED ON if active low) ACALL DELAY SJMP START DELAY: MOV R7, #200 DLY_LOOP: MOV R6, #250 DJNZ R6, $ ; Inner loop for delay DJNZ R7, DLY_LOOP ; Outer loop for delay RET END ``` ### Interrupts The 8051 has 5 interrupt sources: 1. **External Interrupt 0 (INT0):** P3.2 2. **Timer 0 Overflow (TF0)** 3. **External Interrupt 1 (INT1):** P3.3 4. **Timer 1 Overflow (TF1)** 5. **Serial Port (RI or TI)** **Interrupt Registers:** - **IE (Interrupt Enable):** - `EA` (Enable All, global enable/disable) - `ET2`, `ES`, `ET1`, `EX1`, `ET0`, `EX0` (Individual enables) - **IP (Interrupt Priority):** Sets high/low priority for each interrupt. **Interrupt Service Routine (ISR):** - Starts at fixed vector addresses. - Must end with `RETI`. **Example (External Interrupt 0):** ```assembly ORG 0000H LJMP MAIN ORG 0003H ; Vector address for INT0 LJMP EXT_INT0_ISR ORG 0030H MAIN: MOV SP, #7FH ; Initialize Stack Pointer SETB EX0 ; Enable External Interrupt 0 SETB EA ; Enable Global Interrupts SETB IT0 ; Set INT0 to falling edge triggered (0=level, 1=edge) SJMP $ ; Infinite loop EXT_INT0_ISR: CPL P1.0 ; Toggle P1.0 on interrupt RETI END ``` ### Timer/Counter The 8051 has two 16-bit Timer/Counters: T0 and T1. - Can be used as: - **Timer:** Counts machine cycles. - **Counter:** Counts external events on T0 (P3.4) or T1 (P3.5) pins. **Registers:** - **TMOD (Timer Mode Control):** - `GATE`, `C/T`, `M1`, `M0` for T1 and T0. - `C/T=0` for Timer, `C/T=1` for Counter. - `M1 M0` determine mode (0, 1, 2, 3). - **TCON (Timer Control):** - `TF1`, `TR1`, `TF0`, `TR0` (Timer Overflow Flags, Run Control bits) - `IE1`, `IT1`, `IE0`, `IT0` (External Interrupt Flags, Type Control bits) - **TH0/TL0, TH1/TL1:** High/Low bytes of Timer 0 and Timer 1. **Timer Modes (M1 M0):** - **Mode 0 (13-bit):** THx (8-bit) and TLx (5-bit). - **Mode 1 (16-bit):** THx (8-bit) and TLx (8-bit). - **Mode 2 (8-bit Auto-Reload):** TLx counts, THx holds reload value. - **Mode 3 (Split Timer):** T0 becomes two 8-bit timers, T1 stops or uses T0's overflow. **Example (Timer 0 Mode 1):** ```assembly ORG 0000H LJMP MAIN ORG 000BH ; Vector address for Timer 0 overflow LJMP T0_ISR ORG 0030H MAIN: MOV SP, #7FH MOV TMOD, #01H ; Timer 0, Mode 1 (16-bit timer) MOV TH0, #HIGH(-50000) ; Load initial value for 50ms delay (approx) MOV TL0, #LOW(-50000) SETB ET0 ; Enable Timer 0 interrupt SETB EA ; Enable Global interrupts SETB TR0 ; Start Timer 0 SJMP $ ; Infinite loop T0_ISR: CLR TR0 ; Stop Timer 0 CPL P1.0 ; Toggle P1.0 MOV TH0, #HIGH(-50000) ; Reload timer value MOV TL0, #LOW(-50000) SETB TR0 ; Restart Timer 0 RETI END ``` ### Serial Port and Programming The 8051 has a built-in UART for serial communication. - **Registers:** - **SCON (Serial Control):** - `SM0`, `SM1` (Mode selection) - `SM2`, `REN`, `TB8`, `RB8`, `TI`, `RI` (Flags and control) - **SBUF (Serial Buffer):** Data register for transmit/receive. - **PCON (Power Control):** `SMOD` (Double baud rate). **Serial Port Modes (SM0 SM1):** - **Mode 0:** Shift Register. - **Mode 1:** 8-bit UART, variable baud rate. - **Mode 2:** 9-bit UART, fixed baud rate (typically crystal/32 or /64). - **Mode 3:** 9-bit UART, variable baud rate. **Baud Rate Generation (Mode 1, 3):** - Typically uses Timer 1 in Mode 2 (8-bit auto-reload). - Baud Rate = (2^SMOD / 32) * (Oscillator Freq / (12 * (256 - TH1))) **Example (Transmit 'A' repeatedly, 9600 baud, 11.0592MHz crystal):** ```assembly ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV SP, #7FH MOV TMOD, #20H ; Timer 1, Mode 2 (8-bit auto-reload) MOV TH1, #0FDH ; Reload value for 9600 baud (11.0592MHz, SMOD=0) MOV SCON, #50H ; Serial Mode 1 (8-bit UART), REN=0 SETB TR1 ; Start Timer 1 CLR TI ; Clear Transmit Interrupt flag CLR RI ; Clear Receive Interrupt flag TX_LOOP: MOV SBUF, #'A' ; Load 'A' into SBUF for transmission WAIT_TX: JNB TI, WAIT_TX ; Wait until TI flag is set (transmission complete) CLR TI ; Clear TI flag for next transmission ACALL DELAY_BETWEEN_CHARS SJMP TX_LOOP DELAY_BETWEEN_CHARS: MOV R7, #100 DJNZ R7, $ RET END ```