
The schematic below is used in the several following examples:
Apart from components necessary for the operation of the microcontroller such as oscillator with capacitors and the simplest reset circuit, there are also several LEDs and one push button. These are used to indicate the operation of the program.
All LEDs are polarized in such a way that they are activated by driving a microcontroller pin low (logic 0).
;************************************************************************
;* PROGRAM NAME : Delay.ASM
;* DESCRIPTION: Program turns on/off LED on the pin P1.0
;* Software delay is used (Delay).
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(DELAY.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ;Reset vector
ORG 100H
XRESET: MOV SP,#STACK_START ;Define Stack pointer
MOV P1,#0FFh ;All pins are configured as inputs
LOOP:
CPL P1.0 ;Pin P1.0 state is inverted
LCALL Delay ;Time delay
SJMP LOOP
Delay:
MOV R2,#20 ;500 ms time delay
F02: MOV R1,#50 ;25 ms
F01: MOV R0,#230
DJNZ R0,$
DJNZ R1,F01
DJNZ R2,F02
END ;End of program
;************************************************************************
;* PROGRAM NAME : WatchDog.ASM
;* DESCRIPTION : After watch-dog reset, program increments number in
;* register R3 and shows it on port P1 in binary format.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(WATCHDOG.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
WMCON DATA 96H
WDTEN EQU 00000001B ; Watch-dog timer is enabled
PERIOD EQU 11000000B ; Nominal Watch-dog period is set to be 1024ms
;RESET VECTOR
CSEG AT 0
JMP XRESET ; Reset vector
CSEG
ORG 100H
XRESET: ORL WMCON,#PERIOD ; Define Watch-dog period
ORL WMCON,#WDTEN ; Watch-dog timer is enabled
MOV A,R3 ; R3 is moved to port 1
MOV P1,A
INC R3 ; Register R3 is incremented by 1
LAB: SJMP LAB ; Wait for watch-dog reset
END ; End of program
;************************************************************************
;* PROGRAM NAME : Tim0Mod1.ASM
;* DESCRIPTION: Program rotates "0" on port 1. Timer T0 in mode 1 is
;* used
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(TIM0MOD1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DECLARATION OF VARIABLES
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 00BH
JMP TIM0_ISR ; Timer T0 reset vector
ORG 100H
XRESET: MOV SP,#STACK_START ; Define Stack pointer
MOV TMOD,#01H ; MOD1 is selected
MOV A,#0FFH
MOV P1,#0FFH
SETB TR0 ; Timer T0 is enabled
MOV IE,#082H ; Interrupt enabled
CLR C
LOOP1: SJMP LOOP1 ; Remain here
TIM0_ISR: RRC A ; Rotate accumulator A through Carry flag
MOV P1,A ; Contents of accumulator A is moved to PORT1
RETI ; Return from interrupt
END ; End of program
;************************************************************************
;* PROGRAM NAME : Split.ASM
;* DESCRIPTION: Timer TL0 rotates bit on port P1, while TL1 determines
;* the rotation direction. Both timers operate in mode
;* 3. Logic zero (0) on output P3.2 disables rotation on port P1.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(SPLIT.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DECLARATION OF VARIABLES
BSEG AT 0
;DECLARATION OF BIT-VARIABLES
SEMAPHORE: DBIT 8
DIRECTION BIT SEMAPHORE
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 00BH
JMP TIM0_ISR ; Timer T0 reset vector
ORG 01BH
JMP TIM1_ISR ; Timer T1 reset vector
ORG 100H
XRESET: MOV SP,#STACK_START ; Define Stack pointer
MOV TMOD,#00001011B ; Define MOD3
MOV A,#0FFH
MOV P1,#0FFH
MOV R0,#30D
SETB TR0 ; TL0 is turned on
SETB TR1 ; TL1 is turned on
MOV IE,#08AH ; Interrupt enabled
CLR C
CLR DIRECTION ; Rotate to the right
LOOP1: SJMP LOOP1 ; Remain here
TIM0_ISR:
DJNZ R0,LAB3 ; Slow down rotation by 256 times
JB DIRECTION,LAB1
RRC A ; Rotate contents of Accumulator to the right through
; Carry flag
SJMP LAB2
LAB1: RLC A ; Rotate contents of Accumulator to the left through
; Carry flag
LAB2: MOV P1,A ; Contents of Accumulator is moved to port P1
LAB3: RETI ; Return from interrupt
TIM1_ISR:
DJNZ R1,LAB4 ; Slow down direction of rotation by 256 times
DJNZ R2,LAB4 ; When time expires, change rotation direction
CPL SMER
MOV R2,#30D
LAB4: RETI
END ; End of program
;************************************************************************
;* PROGRAM NAME : Tim0Tim1.ASM
;* DESCRIPTION: Timer TO rotates bit on port P1 while Timer1
;* changes rotation direction. Both timers are configured to operate in mode 1.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(TIM0TIM1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DECLARATION OF VARIABLES
BSEG AT 0
;DECLARATION OF BIT-VARIABLES
SEMAPHORE: DBIT 8
DIRECTION BIT SEMAPHORE
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 00BH ; Timer 0 Reset vector
JMP TIM0_ISR
ORG 01BH ; Timer 1 Reset vector
JMP TIM1_ISR
ORG 100H
XRESET: MOV SP,#STACK_START ; Define Stack pointer
MOV TMOD,#11H ; Select MOD1 for both timers
MOV A,#0FFH
MOV P1,#0FFH
MOV R0,#30D ; R0 is initialized
SETB TR0 ; TIMER0 is turned on
SETB TR1 ; TIMER1 is turned on
MOV IE,#08AH ; Timer0 and Timer1 Interrupt enabled
CLR C
CLR DIRECTION ; Rotate to the right
LOOP1: SJMP LOOP1 ; Remain here
TIM0_ISR:
JB DIRECTION,LAB1
RRC A ; Rotate contents of accumulator to the right through
; Carry flag
SJMP LAB2
LAB1: RLC A ; Rotate contents of Accumulator to the left through
; Carry flag
LAB2: MOV P1,A ; Contents of Accumulator is moved to port P1
RETI ; Return from interrupt
TIM1_ISR:
DJNZ R0,LAB3 ; When time expires, change rotation direction
CPL DIRECTION
MOV R0,#30D ; Initialize R0
LAB3:
RETI
END ; End of program
;************************************************************************
;* PROGRAM NAME : Timer2.ASM
;* DESCRIPTION: Program rotates log. "0" on port P3. Timer2 determines
;* the speed of rotation and operates in auto-reload mode
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(TIMER2.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DEFINITION OF VARIABLES
T2MOD DATA 0C9H
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 02BH ; Timer T2 Reset vector
JMP TIM2_ISR
ORG 100H
XRESET: MOV SP,#STACK_START ; Define Stack pointer
MOV A,#0FFH
MOV P3,#0FFH
MOV RCAP2L,#0FH ; Prepare 16-bit auto-reload mode
MOV RCAP2L,#01H
CLR CAP2 ; Enable 16-bit auto-reload mod
SETB EXEN2 ; Pin P1.1 reset is enabled
SETB TR2 ; Enable Timer T2
MOV IE,#0A0H ; Interrupt is enabled
CLR C
LOOP1: SJMP LOOP1 ; Remain here
TIM2_ISR: RRC A ; Rotate contents of Accumulator to the right through
; Carry flag
MOV P3,A ; Move the contents of Accumulator A to PORT3
CLR TF2 ; Clear timer T2 flag TF2
CLR EXF2 ; Clear timer T2 flag EXF2
RETI ; Return from interrupt
END ; End of program
;************************************************************************
;* PROGRAM NAME : Int.ASM
;* DESCRIPTION : Program counts interrupts INT0 generated by appearance of high-to-low
;* transition signal on pin P3.2 Result appears on port P0. Interrupts INT1 are also
;* counted up at the same time. They are generated byappearing high-to-low transition
;* signal on pin P3. The result appears on port P1.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(INT.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 003H ; Interrupt routine address for INT0
JMP Isr_Int0
ORG 013H ; Interrupt routine address for INT1
JMP Isr_Int1
ORG 100H
XRESET:
MOV TCON,#00000101B ; Interrupt INT0 is generated by appearing
; high-to-low transition signal on pin P3.2
; Interrupt INT0 is generated by appearing
; high-to-low transition signal on pin P3.3
MOV IE,#10000101B ; Interrupt enabled
MOV R0,#00H ; Counter starting value
MOV R1,#00H
MOV P0,#00H ; Reset port P0
MOV P1,#00H ; Reset port P1
LOOP: SJMP LOOP ; Remain here
Isr_Int0:
INC R0 ; Increment value of interrupt INT0 counter
MOV P0,R0
RETI
Isr_Int1:
INC R1 ; Increment value of interrupt INT1 counter
MOV P1,R1
RETI
END ; End of program
;************************************************************************
;* PROGRAM NAME : 7Seg1.ASM
;* DESCRIPTION: Program displays number "3" on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
XRESET: MOV SP,#STACK_START ; Define Stack pointer
MOV P1,#0 ; Turn off all segments on displays
MOV P3,#20h ; Activate display D4
LOOP:
MOV A,#03 ; Send number “3” to display
LCALL Disp ; Perform appropriate masking for the number
MOV P1,A
SJMP LOOP
Disp: ; Subroutine for displaying digits
INC A
MOVC A,@A+PC
RET
DB 3FH ; Digit 0 mask
DB 06H ; Digit 1 mask
DB 5BH ; Digit 2 mask
DB 4FH ; Digit 3 mask
DB 66H ; Digit 4 mask
DB 6DH ; Digit 5 mask
DB 7DH ; Digit 6 mask
DB 07H ; Digit 7 mask
DB 7FH ; Digit 8 mask
DB 6FH ; Digit 9 mask
END ; End of program
;************************************************************************
;* PROGRAM NAME: 7Seg2.ASM
;* DESCRIPTION: Program writes numbers 0-9 on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG2.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
XRESET: MOV SP,#STACK_START ; Define Stack pointer
MOV R3,#0 ; Counter initial value
MOV P1,#0 ; Turn off all display segments
MOV P3,#20h ; Activate display D4
LOOP:
MOV A,R3
LCALL Disp ; Perform appropriate masking for number in
; Accumulator
MOV P1,A
INC R3 ; Increment number in register by 1
CJNE R3,#10,L2 ; Check whether the number 10 is in R3
MOV R3,#0 ; If it is, reset counter
L2:
MOV R2,#20 ; 500 mS time delay
F02: MOV R1,#50 ; 25 mS
F01: MOV R0,#230
DJNZ R0,$
DJNZ R1,F01
DJNZ R2,F02
SJMP LOOP
Disp: ; Subroutine for writing digits
INC A
MOVC A,@A+PC
RET
DB 3FH ; Digit 0 mask
DB 06H ; Digit 1 mask
DB 5BH ; Digit 2 mask
DB 4FH ; Digit 3 mask
DB 66H ; Digit 4 mask
DB 6DH ; Digit 5 mask
DB 7DH ; Digit 6 mask
DB 07H ; Digit 7 mask
DB 7FH ; Digit 8 mask
DB 6FH ; Digit 9 mask
END ; End of program
;************************************************************************
;* PROGRAM NAME: 7Seg3.ASM
;* DESCRIPTION: Program displays number "23" on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG3.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
XRESET: MOV SP,#STACK_START ; Define Stack pointer
LOOP: MOV P1,#0 ; Turn off all display segments
MOV P3,#20h ; Activate display D4
MOV A,#03 ; Write digit 3 on display D4
LCALL Disp ; Find appropriate mask for that digit
MOV P1,A ; Put the mask on the port
MOV P1,#0 ; Turn off all dislay segments
MOV P3,#10h ; Activate display D3
MOV A,#02 ; Write digit 2 on display D3
LCALL Disp ; Find mask for that digit
MOV P1,A ; Put the mask on the port
SJMP LOOP ; Return to the label LOOP
Disp: ; Subroutine for writing digits
INC A
MOVC A,@A+PC
RET
DB 3FH ; Digit 0 mask
DB 06H ; Digit 1 mask
DB 5BH ; Digit 2 mask
DB 4FH ; Digit 3 mask
DB 66H ; Digit 4 mask
DB 6DH ; Digit 5 mask
DB 7DH ; Digit 6 mask
DB 07H ; Digit 7 mask
DB 7FH ; Digit 8 mask
DB 6FH ; Digit 9 mask
END ; End of program
;************************************************************************
;* PROGRAM NAME : 7Seg5.ASM
;* DESCRIPTION : Program displays number"1234" on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG5.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
XRESET: MOV SP,#STACK_START ; Define Stack pointer
LOOP: MOV P1,#0 ; Turn off all display segments
MOV P3,#20h ; Activate display D4
MOV A,#04 ; Write digit 4 on display D4
LCALL Disp ; Find mask for that digit
MOV P1,A ; Put the mask on the port
MOV P1,#0 ; Turn off all display segments
MOV P3,#10h ; Activate display D3
MOV A,#03 ; Write digit 3 on display D3
LCALL Disp ; Find mask for that digit
MOV P1,A ; Put the mask on the port
MOV P1,#0 ; Turn off all display segments
MOV P3,#08h ; Activate display D2
MOV A,#02 ; Write digit 2 on display D2
LCALL Disp ; Find mask for that digit
MOV P1,A ; Put the mask on the port
MOV P1,#0 ; Turn off all display segments
MOV P3,#04h ; Activate display D1
MOV A,#01 ; Write digit 1 on display D1
LCALL Disp ; Find mask for that digit
MOV P1,A ; Put the mask on the port
SJMP LOOP ; Return to the lable LOOP
Disp: ; Subroutine for writing digits
INC A
MOVC A,@A+PC
RET
DB 3FH ; Digit 0 mask
DB 06H ; Digit 1 mask
DB 5BH ; Digit 2 mask
DB 4FH ; Digit 3 mask
DB 66H ; Digit 4 mask
DB 6DH ; Digit 5 mask
DB 7DH ; Digit 6 mask
DB 07H ; Digit 7 mask
DB 7FH ; Digit 8 mask
DB 6FH ; Digit 9 mask
END ; End of program
;************************************************************************
;* PROGRAM NAME : 7Seg4.ASM
;* DESCRIPTION: Program displays numbers 0-99 on 7-segment LED displays
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG4.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
XRESET: MOV SP,#STACK_START ; Define Stack pointer
MOV R2,#0 ; Counter starting value
MOV R3,#0
MOV R4,#0
LOOP: INC R4 ;Wait for display to be "refreshed" for 100 times
CJNE R4,#20d,LAB1 ;before incrementing the counter
MOV R4,#0
MOV P1,#0 ; Turn off all display segments
INC R2 ; Increment Register containing units by 1
CJNE R2,#10d,LAB1
MOV R2,#0 ; Reset units
INC R3 ; Increment Register with tens by 1
CJNE R3,#10d,LAB1 ;
MOV R3,#0 ; Reset tens
LAB1:
MOV P3,#20h ; Activate display D4
MOV A,R2 ; Copy Register containing units to A
LCALL Disp ; Call mask for that digit
MOV P1,A ; Write units on display D4
LCALL Delay ; 25ms delay
MOV P1,#0 ; Turn off all display segments
MOV P3,#10h ; Activate display D3
MOV A,R3 ; Copy Register contaning tens to A
LCALL Disp ; Call mask for that digit
MOV P1,A ; Write tens on display D3
LCALL Delay ; 25ms delay
SJMP LOOP
Delay:
MOV R1,#50 ; 5 ms delay
F01: MOV R0,#250
DJNZ R0,$
DJNZ R1,F01
RET
Disp: ; Subroutine for displaying digits
INC A
MOVC A,@A+PC
RET
DB 3FH ; Digit 0 mask
DB 06H ; Digit 1 mask
DB 5BH ; Digit 2 mask
DB 4FH ; Digit 3 mask
DB 66H ; Digit 4 mask
DB 6DH ; Digit 5 mask
DB 7DH ; Digit 6 mask
DB 07H ; Digit 7 mask
DB 7FH ; Digit 8 mask
DB 6FH ; Digit 9 mask
END ; End of program
;************************************************************************
;* PROGRAM NAME: EEProm1.ASM
;* DESCRIPTION: Programming EEPROM at address 0000hex and displaying message
;* on LED display.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(EEPROM1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
WMCON DATA 96H
EEMEN EQU 00001000B ; Access to internal EEPROM is enabled
EEMWE EQU 00010000B ; Write to EEPROM is enabled
TEMP DATA 030H ; Define Auxiliary register
THE END EQU 071H ; Display "F"
ERROR EQU 033H ; Display "E"
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
XRESET: MOV IE,#00 ; All interrupts are disabled
MOV SP,#STACK_START
MOV DPTR,#0000H ; Choose location address in EEPROM
ORL WMCON,#EEMEN ; Access to EEPROM is enabled
ORL WMCON,#EEMWE ; Write to EEPROM is enabled
MOV TEMP,#23H ; Number written to EEPROM is moved to
MOV A,TEMP ; register TEMP and Accumulator
MOVX @DPTR,A ; Write byte to EEPROM
CALL DELAY ; 10ms delay
MOVX A,@DPTR ; Read the same location and compare to TEMP,
CJNE A,TEMP,ERROR ; If they don't match, jump to label ERROR
MOV A,#KRAJ ; Display F (correct)
MOV P1,A
XRL WMCON,#EEMWE ; Write to EEPROM is disabled
XRL WMCON,#EEMEN ; Access to EEPROM is disabled
LOOP1: SJMP LOOP1 ; Remain here
ERROR: MOV A,#ERROR ; Display E (error)
MOV P1,A
LOOP2: SJMP LOOP2
DELAY: MOV A,#0AH ; Delay
MOV R3,A
LOOP3: NOP
LOOP4: DJNZ B,LOOP4
LOOP5: DJNZ B,LOOP5
DJNZ R3,LOOP3
RET
END ; End of program
;************************************************************************
;* PROGRAM NAME : UartR.ASM
;* DESCRIPTION: Each data received from PC via UART appears on the port
;* P1.
;*
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(UARTR.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 023H ; Starting address of UART interrupt routine
JMP IR_SER
ORG 100H
XRESET: MOV IE,#00 ; All interrupts are disabled
MOV SP,#STACK_START ; Initialization of Stack pointer
MOV TMOD,#20H ; Timer1 in mode2
MOV TH1,#0FDH ; 9600 baud rate at the frequency of
; 11.0592MHz
MOV SCON,#50H ; Receiving enabled, 8-bit UART
MOV IE,#10010000B ; UART interrupt enabled
CLR TI ; Clear transmit flag
CLR RI ; Clear receive flag
SETB TR1 ; Start Timer1
LOOP: SJMP LOOP ; Remain here
IR_SER: JNB RI,OUTPUT ; If any data is received,
; move it to the port
MOV A,SBUF ; P1
MOV P1,A
CLR RI ; Clear receive flag
OUTPUT RETI
END ; End of program
;************************************************************************
;* PROGRAM NAME : UartS.ASM
;* DESCRIPTION: Sends values 0-255 to PC.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(UARTS.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
XRESET: MOV IE,#00 ; All interrupts are disabled
MOV SP,#STACK_START ; Initialization of Stack pointer
MOV TMOD,#20H ; Timer1 in mode 2
MOV TH1,#0FDH ; 9600 baud rate at the frequency of
; 11.0592MHz
MOV SCON,#40H ; 8-bit UART
CLR TI ; Clear transmit bit
CLR RI ; Clear receive flag
MOV R3,#00H ; Reset caunter
SETB TR1 ; Start Timer 1
START: MOV SBUF,R3 ; Move number from counter to a PC
LOOP1: JNB TI,LOOP1 ; Wait here until byte transmission is
; complete
CLR TI ; Clear transmit bit
INC R3 ; Increment the counter value by 1
CJNE R3,#00H,START ; If 255 bytes are not sent return to the
; label START
LOOP: SJMP LOOP ; Remain here
END ; End of program
*************************************************************************
;* PROGRAM NAME : Lcd.ASM
;* DESCRIPRTION : Program for testing LCD display. 4-bit communication
;* is used. Program does not check BUSY flag but uses program delay
;* between 2 commands. PORT1 is used for connection
;* to the microcontroller.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(LCD.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;Stack
DSEG AT 0E0h
Stack_Start: DS 020h
Start_address EQU 0000h
;Reset vectors
CSEG AT 0
ORG Start_address
JMP Inic
ORG Start_address+100h
MOV IE,#00 ; All interrupts are disabled
MOV SP,#Stack_Start
Inic: CALL LCD_inic ; Initialize LCD
;*************************************************
;* MAIN PROGRAM
;*************************************************
START: MOV A,#80h ; Next character will appear on the first
CALL LCD_status ; location in the first line of LCD display.
MOV A,#'M' ; Display character ‘M’.
CALL LCD_putc ; Call subroutine for character transmission.
MOV A,#'i' ; Display character ‘i’.
CALL LCD_putc
MOV A,#'k' ; Display character ‘k’.
CALL LCD_putc
MOV A,#'r' ; Display character ‘r’.
CALL LCD_putc
MOV A,#'o' ; Display character ‘o’.
CALL LCD_putc
MOV A,#'e' ; Display character ‘e’.
CALL LCD_putc
MOV A,#'l' ; Display character ‘l’.
CALL LCD_putc
MOV A,#'e' ; Display character ‘e’.
CALL LCD_putc
MOV A,#'k' ; Display character ‘k’.
CALL LCD_putc
MOV A,#'t' ; Display character ‘t’.
CALL LCD_putc
MOV A,#'r' ; Display character ‘r’.
CALL LCD_putc
MOV A,#'o' ; Display character ‘o’.
CALL LCD_putc
MOV A,#'n' ; Display character ‘n’.
CALL LCD_putc
MOV A,#'i' ; Display character ‘i’.
CALL LCD_putc
MOV A,#'k' ; Display character ‘k’.
CALL LCD_putc
MOV A,#'a' ; Display character ‘a’.
CALL LCD_putc
MOV A,#0c0h ; Next character will appear on the first
CALL LCD_status ; location in the second line of LCD display.
MOV A,#'R' ; Display character ‘R’.
CALL LCD_putc ; Call subroutine for character transmission.
MOV A,#'a' ; Display character ‘a’.
CALL LCD_putc
MOV A,#'z' ; Display character ‘z’.
CALL LCD_putc
MOV A,#'v' ; Display character ‘v’.
CALL LCD_putc
MOV A,#'o' ; Display character ‘o’.
CALL LCD_putc
MOV A,#'j' ; Display character ‘j’.
CALL LCD_putc
MOV A,#'n' ; Display character ‘n’.
CALL LCD_putc
MOV A,#'i' ; Display character ‘i’.
CALL LCD_putc
MOV A,#' ' ; Display character ‘ ’.
CALL LCD_putc
MOV A,#'s' ; Display character ‘s’.
CALL LCD_putc
MOV A,#'i' ; Display character ‘i’.
CALL LCD_putc
MOV A,#'s' ; Display character ‘s’.
CALL LCD_putc
MOV A,#'t' ; Display character ‘t’.
CALL LCD_putc
MOV A,#'e' ; Display character ‘e’.
CALL LCD_putc
MOV A,#'m' ; Display character ‘m’.
CALL LCD_putc
MOV A,#'i' ; Display character ‘i’.
CALL LCD_putc
MOV R0,#20d ; Wait time (20x10ms)
CALL Delay_10ms ;
MOV DPTR,#LCD_DB ; Clear display
MOV A,#6d ;
CALL LCD_inic_status ;
MOV R0,#10d ; Wait time(10x10ms)
CALL Delay_10ms
JMP START
;*********************************************
;* Subroutine for wait time (T= r0 x 10ms)
;*********************************************
Delay_10ms: MOV R5,00h ; 1+(1+(1+2*r7+2)*r6+2)*r5 approximately
MOV R6,#100d ; (if r7>10)
MOV R7,#100d ; 2*r5*r6*r7
DJNZ R7,$ ; $ indicates current instruction.
DJNZ R6,$-4
DJNZ R5,$-6
RET
;**************************************************************************************
;* SUBROUTINE: LCD_inic
;* DESCRIPTION: Subroutine for LCD initialization.
;*
;* (is used with 4-bit interface, under condition that pins DB4-7 on LCD
;* are connected to pins PX.4-7 on microcontroller’s ports, i.e. four higher
;* bits on the port are used).
;*
;* NOTE: It is necessary to define port pins for controlling LCD operation:
;* LCD_enable, LCD_read_write, LCD_reg_select,similar to port for connection to LCD.
;* It is also necessary to define addresses for the first character in each
;* line.
;**************************************************************************************
LCD_enable BIT P1.3 ; Bit for activating pin E on LCD.
LCD_read_write BIT P1.1 ; Bit for activating pin RW on LCD.
LCD_reg_select BIT P1.2 ; Bit for activating pin RS on LCD.
LCD_port SET P1 ; Port for connection to LCD.
Busy BIT P1.7 ; Port pin on which Busy flag appears.
LCD_Start_I_red EQU 00h ; Address of the first message character
; in the first line of LCD display.
LCD_Start_II_red EQU 40h ; Address of the first message character
; in the second line of LCD display.
LCD_DB: DB 00111100b ; 0 -8b, 2/1 lines, 5x10/5x7 format
DB 00101100b ; 1 -4b, 2/1 lines, 5x10/5x7 format
DB 00011000b ; 2 -Display/cursor shift, right/left
DB 00001100b ; 3 -Display ON, cursor OFF, cursor blink off
DB 00000110b ; 4 -Increment mode, display shift off
DB 00000010b ; 5 -Display/cursor home
DB 00000001b ; 6 -Clear display
DB 00001000b ; 7 -Display OFF, cursor OFF, cursor blink off
LCD_inic: ;*****************************************
MOV DPTR,#LCD_DB
MOV A,#00d ; Triple initialization in 8-bit
CALL LCD_inic_status_8 ; mode is performed at the beginning
MOV A,#00d ; (in case of slow increment of
CALL LCD_inic_status_8 ; power supply when the power supply is on
MOV A,#00d
lcall LCD_inic_status_8
MOV A,#1d ; Change from 8-bit into
CALL LCD_inic_status_8 ; 4-bit mode
MOV A,#1d
CALL LCD_inic_status
MOV A,#3d ; As from this point the program executes in
;4-bit mode
CALL LCD_inic_status
MOV A,#6d
CALL LCD_inic_status
MOV A,#4d
CALL LCD_inic_status
RET
LCD_inic_status_8:
;******************************************
PUSH B
MOVC A,@A+DPTR
CLR LCD_reg_select ; RS=0 - Write command
CLR LCD_read_write ; R/W=0 - Write data on LCD
MOV B,LCD_port ; Lower 4 bits from LCD port are memorized
ORL B,#11110000b
ORL A,#00001111b
ANL A,B
MOV LCD_port,A ; Data is moved from A to LCD port
SETB LCD_enable ; high-to-low transition signal
; is generated on the LCD's EN pin
CLR LCD_enable
MOV B,#255d ; Time delay in case of improper reset
DJNZ B,$ ; during initialization
DJNZ B,$
DJNZ B,$
POP B
RET
LCD_inic_status:
;****************************************************************************
MOVC A,@A+DPTR
CALL LCD_status
RET
;****************************************************************************
;* SUBROUTINE: LCD_status
;* DESCRIPTION: Subroutine for defining LCD status.
;****************************************************************************
LCD_status: PUSH B
MOV B,#255d
DJNZ B,$
DJNZ B,$
DJNZ B,$
CLR LCD_reg_select ; RS=O: Command is sent to LCD
CALL LCD_port_out
SWAP A ; Nibles are swapped in accumulator
DJNZ B,$
DJNZ B,$
DJNZ B,$
CLR LCD_reg_select ; RS=0: Command is sent to LCD
CALL LCD_port_out
POP B
RET
;****************************************************************************
;* SUBROUTINE: LCD_putc
;* DESCRIPTION: Sending character to be displayed on LCD.
;****************************************************************************
LCD_putc: PUSH B
MOV B,#255d
DJNZ B,$
SETB LCD_reg_select ; RS=1: Character is sent to LCD
CALL LCD_port_out
SWAP A ; Nibles are swapped in accumulator
DJNZ B,$
SETB LCD_reg_select ; RS=1: Character is sent to LCD
CALL LCD_port_out
POP B
RET
;****************************************************************************
;* SUBROUTINE: LCD_port_out
;* DESCRIPTION: Sending commands or characters on LCD display
;****************************************************************************
LCD_port_out: PUSH ACC
PUSH B
MOV B,LCD_port ; Lower 4 bits of LCD port are memorized
ORL B,#11110000b
ORL A,#00001111b
ANL A,B
MOV LCD_port,A ; Data is copied from A to LCD port
SETB LCD_enable ; high-to-low transition signal
; is generated on the LCD's EN pin
CLR LCD_enable
POP B
POP ACC
RET
END ; End of program
;************************************************************************
;* SUBROUTINE NAME : BinDec.ASM
;* DESCRIPTION : Content of accumulator is converted into three decimal digits
;************************************************************************
BINDEC: MOV B,#10d ; Store decimal number 10 in B
DIV AB ; A:B. Remainder remains in B
MOV R3,B ; Move units to register R3
MOV B,#10d ; Store decimal number 10 in B
DIV AB ; A:B. Remainder remains in B
MOV R2,B ; Move tens to register R2
MOV B,#10d ; Store decimal number 10 in B
DIV AB ; A:B. Remainder remains in B
MOV A,B ; Move hundreds to accumulator
RET ; Return to the main program