0% found this document useful (0 votes)
20 views

Code VXL LAB1

This document contains Atmega324 assembly code for controlling an LCD display. It includes functions to initialize the LCD, move the cursor, send strings and commands to the LCD. The code sets up port A pins to interface with the LCD for data, control signals like RS, RW, EN. It initializes the LCD, displays a welcome message on two lines and then enters an infinite loop.
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views

Code VXL LAB1

This document contains Atmega324 assembly code for controlling an LCD display. It includes functions to initialize the LCD, move the cursor, send strings and commands to the LCD. The code sets up port A pins to interface with the LCD for data, control signals like RS, RW, EN. It initializes the LCD, displays a welcome message on two lines and then enters an infinite loop.
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 20

Lab1_1

1..include "m324padef.inc" ;Thu vien atmega324


.org 0x0000 ;Bat dau tai dia chi 0x0000
ldi r16, 0xff ;
out ddra, r16 ;Cho porta la output
out portd, r16 ;Bat dien tro keo len cho portd
ldi r16, 0x00 ;
out ddrd, r16 ;Cho portd la input
loop: ;Label loop
in r17, pind ;Doc input portd luu vao r17
com r17; dao bit
out porta, r17 ;Dua gia tr tren r17 ra porta
rjmp loop ;Lap lai chuong trinh

2.. .include "m324padef.inc";Thu vien atmega324


.org 0x0000 ;Bat dau tai dia chi 0x0000
ldi r16, 0xff ;
out ddra, r16 ;Cho porta la output
out portd, r16 ;Bat dien tro keo len cho portb
ldi r16, 0x00 ;
out ddrd, r16 ;Cho portd la input
ldi r18, 5 ;
loop: ;Label loop
in r17, pind ;Doc input portd luu vao r17
com r17; dao bit
add r17,r18 ;Cong r17 them 5
out porta, r17 ;Dua gia tr tren r17 ra porta
rjmp loop ;Lap lai chuong trinh

3....include "m324padef.inc";Thu vien atmega324


.org 0x0000 ;Bat dau tai dia chi 0x0000
ldi r16, 0xff ;
out ddra, r16 ;Cho porta la output
out portd, r16 ;Bat dien tro keo len cho portb
ldi r16, 0x00 ;
out ddrd, r16 ;Cho portd la input
loop: ;Label loop
in r17, pind ;Doc input portd luu vao r17
com r17;dao bit
ldi r18, 0x0f ;
and r18,r17 ;Lay 2 nibble thap
ldi r19, 0xf0 ;
and r19,r17 ;Lay 2 nibble cao
swap r19
mul r18,r19 ;Nhan lai ket qua luu o r1:r0
out porta, r0 ;Dua gia tr tren r17 ra porta
rjmp loop ;Lap lai chuong trinh
4... .include "m324padef.inc";Thu vien atmega324
.org 0x0000 ;Bat dau tai dia chi 0x0000
ldi r16, 0xff ;
out ddra, r16 ;Cho porta la output
out portd, r16 ;Bat dien tro keo len cho portb
ldi r16, 0x00 ;
out ddrd, r16 ;Cho portb la input
ldi r20, 0xf0
loop: ;Label loop
in r17, pind ;Doc input portb luu vao r17
com r17; dao bit
ldi r18, 0x0f ;
and r18,r17 ;Lay 2 nibble thap
sbrc r17,3 ;Neu bit so 3 cua r17 la 0 thi bo qua lenh duoi
or r18,r20 ;Chuyen r18 ve so co dau

ldi r19,0xf0 ;
and r19,r17 ;Lay 2 nibble cao
swap r19 ;Doi 2 nibble trong r19 cho nhau
sbrc r17,7 ;Neu bit so 7 cua r17 la 0 thi bo qua lenh duoi
or r19,r20 ;Chuyen r18 ve so co dau

muls r18,r19 ;Nhan lai ket qua luu o r1:r0


out porta, r0 ;Dua gia tr tren r17 ra porta
rjmp loop ;Lap lai chuong trinh
5...include "m324padef.inc";Thu vien atmega324
.org 0x0000 ;Bat dau tai dia chi 0x0000
cbi ddra,0 ;cho porta0 la input
sbi porta,0 ;dien tro keo len
sbi ddra,1 ;cho porta1 la output

loop:
cbi porta,1 ;Led off
sbis pina,0 ;Neu sw dang nha thi bo qua lenh duoi
sbi porta,1 ;Led on
rcall delay_50ms ;Delay de on dinh
rjmp loop ;Vong lap loop

delay_50ms: ;255x(255x6+1+1+2)x125ns = 49ms


ldi r16,255 ;1 mc
l1: ldi r17,255 ;1 mc
l2: dec r17 ;1 mc
nop ;1 mc
nop ;1 mc
nop ;1 mc
brne l2 ;2/1 mc
dec r16 ;1 mc
brne l1 ;2/1 mc
ret ;4 mc

lab1_2

2._b .include"m324PAdef.inc"
.org 00
ldi r16,0x01
out DDRA, r16
start:
sbi PORTA,PINA0
call delay05ms
cbi PORTA, PINA0
call delay05ms
rjmp start
delay05ms: ;4*4*250
ldi r16,4
l1: ldi r17,250
l2: nop
dec r17
brne l2
dec r16
brne l1
ret
delay10ms:
ldi r18,20
l10: call delay05ms
dec r18
brne l10
ret
delay100ms:
ldi r18,200
l100: call delay05ms
dec r18
brne l100
ret
delay1s: ;8*250
ldi r18,8
l1000: ldi r19,250
l2000: call delay05ms
dec r19
brne l2000
dec r18
brne l1000
ret

2_c .include "m324PAdef.inc"


.org 00
ldi r16,0x01
out DDRA, r16
start:
sbi PORTA,PINA0
call delay1s ;4MC
cbi PORTA, PINA0
call delay1s ;4MC
rjmp start
delay05ms: ;4*4*250
ldi r16,4
l1: ldi r17,250
l2: nop
dec r17
brne l2
dec r16
brne l1
ret
delay1s: ;8*250
ldi r18,8
l1000: ldi r19,250
l2000: call delay05ms
dec r19
brne l2000
dec r18
brne l1000
ret

3.include "m324padef.inc" ; Include Atmega324pa definitions


.def shiftData = r20 ; Define the shift data register
.equ clearSignalPort = PORTB ; Set clear signal port to PORTB
.equ clearSignalPin = 3 ; Set clear signal pin to pin 0 of PORTB
.equ shiftClockPort = PORTB ; Set shift clock port to PORTB
.equ shiftClockPin = 2 ; Set shift clock pin to pin 1 of PORTB
.equ latchPort = PORTB ; Set latch port to PORTB
.equ latchPin = 1 ; Set latch pin to pin 0 of PORTB
.equ shiftDataPort = PORTB ; Set shift data port to PORTB
.equ shiftDataPin = 0 ; Set shift data pin to pin 3 of PORTB
call initport
main:
ldi r22,0x00 ;Data xuat ra led
call dieukhienled
rjmp main
dieukhienled:
ldi r21, 8 ;Vong lap led sang dan
loop1:
call Delay500ms
sec ;Cho bit C bang 1
ror r22 ;Dich bit qua phai voi bit C
add shiftData,r22 ;Dua vao shiftdata
call cleardata
call shiftoutdata
dec r21
brne loop1
ldi r21, 8 ;Vong lap led tat dan
loop2:
call Delay500ms
clc ;Cho bit C bang 0
rol r22 ;;Dich bit qua trai voi bit C
add shiftData,r22 ;Dua vao shiftdata
call cleardata
call shiftoutdata
dec r21
brne loop2
ret
delay05ms: ;4*4*250
ldi r16,4
l1: ldi r17,250
l2: nop
dec r17
brne l2
dec r16
brne l1
ret
Delay500ms:
ldi r18,4
l1000: ldi r19,250
l2000: call delay05ms
dec r19
brne l2000
dec r18
brne l1000
ret
stop:
jmp stop ; Initialize ports as outputs
initport:
ldi r24,(1<<clearSignalPin)|(1<<shiftClockPin)|(1<<latchPin)|(1<<shiftDataPin)
out DDRB, r24 ; Set DDRB to output
ret
cleardata:
cbi clearSignalPort, clearSignalPin ; Set clear signal pin to low ; Wait for a
short time
sbi clearSignalPort, clearSignalPin ; Set clear signal pin to high
ret ; Shift out data
shiftoutdata:
cbi shiftClockPort, shiftClockPin ;
ldi r18, 8 ; Shift 8 bits
shiftloop:
sbrc shiftData, 7 ; Check if the MSB of shiftData is 1
sbi shiftDataPort, shiftDataPin ; Set shift data pin to high
sbi shiftClockPort, shiftClockPin ; Set shift clock pin to high
lsl shiftData ; Shift left
cbi shiftClockPort, shiftClockPin ; Set shift clock pin to low
cbi shiftDataPort, shiftDataPin ; Set shift data pin to low
dec r18
brne shiftloop ; Latch data
sbi latchPort, latchPin ; Set latch pin to high
cbi latchPort, latchPin ; Set latch pin to low
ret

lab1_3:
1....include "m324padef.inc" ; Include Atmega324pa definitions
.org 0x0000 ; interrupt vector table
rjmp reset_handler ; reset
;******************************* Program ID *********************************
.org INT_VECTORS_SIZE
dong1:
.db "TN VXL-AVR",0
dong2:
.db "Nhom: XX",0
reset_handler:
call LCD_Init
; display the first line of information
ldi ZH, high(dong1) ; point to the information that is to be displayed
ldi ZL, low(dong1)
call LCD_Send_String
ldi r16,1
ldi r17,0
call LCD_Move_Cursor
ldi ZH, high(dong2) ; point to the information that is to be displayed
ldi ZL, low(dong2)
call LCD_Send_String
start:
rjmp start

;init the LCD


;LCD_D7..LCD_D4 connect to PA7..PA4
;LCD_RS connect to PA0
;LCD_RW connect to PA1
;LCD_EN connect to PA2
.equ LCDPORT = PORTA ; Set signal port reg to PORTA
.equ LCDPORTDIR = DDRA ; Set signal port dir reg to PORTA
.equ LCDPORTPIN = PINA ; Set clear signal port pin reg to PORTA
.equ LCD_RS = PINA0
.equ LCD_RW = PINA1
.equ LCD_EN = PINA2
.equ LCD_D7 = PINA7
.equ LCD_D6 = PINA6
.equ LCD_D5 = PINA5
.equ LCD_D4 = PINA4
LCD_Init:
; Set up data direction register for Port A
ldi r16, 0b11110111 ; set PA7-PA4 as outputs, PA2-PA0 as output
out LCDPORTDIR, r16
; Wait for LCD to power up
call DELAY_10MS
call DELAY_10MS
; Send initialization sequence
ldi r16, 0x02 ; Function Set: 4-bit interface
call LCD_Send_Command
ldi r16, 0x28 ; Function Set: enable 5x7 mode for chars
call LCD_Send_Command
ldi r16, 0x0E ; Display Control: Display OFF, Cursor ON
call LCD_Send_Command
ldi r16, 0x01 ; Clear Display
call LCD_Send_Command
ldi r16, 0x80 ; Clear Display
call LCD_Send_Command
ret

; Function to move the cursor to a specific position on the LCD


; Assumes that the LCD is already initialized
; Input: Row number in R16 (0-based), Column number in R17 (0-based)
LCD_Move_Cursor:
cpi r16,0 ;check if first row
brne LCD_Move_Cursor_Second
andi r17, 0x0F
ori r17,0x80
mov r16,r17
; Send command to LCD
call LCD_Send_Command
ret
LCD_Move_Cursor_Second:
cpi r16,1 ;check if second row
brne LCD_Move_Cursor_Exit ;else exit
andi r17, 0x0F
ori r17,0xC0
mov r16,r17
; Send command to LCD
call LCD_Send_Command
LCD_Move_Cursor_Exit:
; Return from function
ret
; Subroutine to send string to LCD
;address of the string on ZH-ZL
;string end with Null
.def LCDData = r16
LCD_Send_String:
push ZH ; preserve pointer registers
push ZL
push LCDData
; fix up the pointers for use with the 'lpm' instruction
lsl ZL ; shift the pointer one bit left for the lpm instruction
rol ZH
; write the string of characters
LCD_Send_String_01:
lpm LCDData, Z+ ; get a character
cpi LCDData, 0 ; check for end of string
breq LCD_Send_String_02 ; done
; arrive here if this is a valid character
call LCD_Send_Data ; display the character
rjmp LCD_Send_String_01 ; not done, send another character
; arrive here when all characters in the message have been sent to the LCD module
LCD_Send_String_02:
pop LCDData
pop ZL ; restore pointer registers
pop ZH
ret

; Subroutine to send command to LCD


;Command code in r16
;LCD_D7..LCD_D4 connect to PA7..PA4
;LCD_RS connect to PA0
;LCD_RW connect to PA1
;LCD_EN connect to PA2
LCD_Send_Command:
push r17
call LCD_wait_busy ; check if LCD is busy
mov r17,r16 ;save the command
; Set RS low to select command register
; Set RW low to write to LCD
andi r17,0xF0
; Send command to LCD
out LCDPORT, r17
nop
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
swap r16
andi r16,0xF0
; Send command to LCD
out LCDPORT, r16
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
pop r17
ret

LCD_Send_Data:
push r17
call LCD_wait_busy ;check if LCD is busy
mov r17,r16 ;save the command
; Set RS high to select data register
; Set RW low to write to LCD
andi r17,0xF0
ori r17,0x01
; Send data to LCD
out LCDPORT, r17
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
cbi LCDPORT, LCD_EN
; Delay for command execution
;send the lower nibble
nop
swap r16
andi r16,0xF0
; Set RS high to select data register
; Set RW low to write to LCD
andi r16,0xF0
ori r16,0x01
; Send command to LCD
out LCDPORT, r16
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
cbi LCDPORT, LCD_EN
pop r17
ret

LCD_wait_busy:
push r16
ldi r16, 0b00000111 ; set PA7-PA4 as input, PA2-PA0 as output
out LCDPORTDIR, r16
ldi r16,0b11110010 ; set RS=0, RW=1 for read the busy flag
out LCDPORT, r16
nop
LCD_wait_busy_loop:
sbi LCDPORT, LCD_EN
nop
nop
in r16, LCDPORTPIN
cbi LCDPORT, LCD_EN
nop
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
nop
andi r16,0x80
cpi r16,0x80
breq LCD_wait_busy_loop
ldi r16, 0b11110111 ; set PA7-PA4 as output, PA2-PA0 as output
out LCDPORTDIR, r16
ldi r16,0b00000000 ; set RS=0, RW=1 for read the busy flag
out LCDPORT, r16
pop r16
ret
DELAY_10MS: ;
push r16
push r17
ldi r16,106
l1:
ldi r17,250
;1MC
;1MC
l2: dec r17 ;1MC
brne l2 ;2/1MC
dec r16
;1MC
brne l1
pop r17
pop r16
ret
;2/1MC
;4MC

2... b.include "m324padef.inc" ; Include Atmega324pa definitions


.org 0x0000 ; interrupt vector table
;******************************* Program ID *********************************
.def solanBam = r24
ldi solanBam, 0

call LCD_Init
call SW_Init
call BARLED_Init
start:
call checkSWnoDB
call disp_BL
call disp_LCD
rjmp start

;////////////////////////LCD DISP///////////////////////
.org INT_VECTORS_SIZE
dong1:
.db "So Lan Bam:",0
disp_LCD:
push r16
push r17
push r18
push solanBam
; display the first line of information
ldi r16,0
ldi r17,0
call LCD_Move_Cursor
ldi ZH, high(dong1) ; point to the information that is to be displayed
ldi ZL, low(dong1)
call LCD_Send_String
ldi r16,1
ldi r17,0
call LCD_Move_Cursor

ldi r17,0
ldi r18,0
hangtram:
cpi solanBam,100
brsh lonhontram
hangchuc:
cpi solanBam,10
brsh lonhonchuc
rjmp inraLCD
lonhonchuc:
subi solanBam,10
inc r17
rjmp hangchuc
lonhontram:
subi solanBam,100
inc r18
rjmp hangtram

inraLCD:
ldi r16,48
add r16,r18
call LCD_Send_Data
ldi r16,48
add r16,r17
call LCD_Send_Data
ldi r16,48
add r16,solanBam
call LCD_Send_Data

pop solanBam
pop r18
pop r17
pop r16
ret

;////////////////////////SW/////////////////////////////
SW_Init:
cbi ddrd, 0
sbi portd, 0
ret

checkSW:
rcall debounce
brts else
waitSW:
rcall debounce
brts pressed
rjmp waitSW
pressed:
inc solanBam
ret
else:
rjmp checkSW

debounce:
sbic pind,0 ;bit is clear=button is pressed
rjmp bitSet
call DELAY_10MS
sbic pind,0 ;button still pressed?
rjmp bitSet
set
ret
bitSet:
clt
ret

checkSWnoDB:
sbic pind,0
rjmp else1
waitSW1:
sbic pind,0
rjmp pressed1
rjmp waitSW1
pressed1:
inc solanBam
ret
else1:
rjmp checkSWnoDB
;////////////////////////BARLED//////////////////////////
BARLED_Init:
ldi r16,0xff
out ddrb,r16
ret
disp_BL:
out portb,solanBam
ret
;////////////////////////LCD/////////////////////////////
;init the LCD
;LCD_D7..LCD_D4 connect to PA7..PA4
;LCD_RS connect to PA0
;LCD_RW connect to PA1
;LCD_EN connect to PA2
.equ LCDPORT = PORTA ; Set signal port reg to PORTA
.equ LCDPORTDIR = DDRA ; Set signal port dir reg to PORTA
.equ LCDPORTPIN = PINA ; Set clear signal port pin reg to PORTA
.equ LCD_RS = PINA0
.equ LCD_RW = PINA1
.equ LCD_EN = PINA2
.equ LCD_D7 = PINA7
.equ LCD_D6 = PINA6
.equ LCD_D5 = PINA5
.equ LCD_D4 = PINA4
LCD_Init:
; Set up data direction register for Port A
ldi r16, 0b11110111 ; set PA7-PA4 as outputs, PA2-PA0 as output
out LCDPORTDIR, r16
; Wait for LCD to power up
call DELAY_10MS
call DELAY_10MS
; Send initialization sequence
ldi r16, 0x02 ; Function Set: 4-bit interface
call LCD_Send_Command
ldi r16, 0x28 ; Function Set: enable 5x7 mode for chars
call LCD_Send_Command
ldi r16, 0x0E ; Display Control: Display OFF, Cursor ON
call LCD_Send_Command
ldi r16, 0x01 ; Clear Display
call LCD_Send_Command
ldi r16, 0x80 ; Clear Display
call LCD_Send_Command
ret

; Function to move the cursor to a specific position on the LCD


; Assumes that the LCD is already initialized
; Input: Row number in R16 (0-based), Column number in R17 (0-based)
LCD_Move_Cursor:
cpi r16,0 ;check if first row
brne LCD_Move_Cursor_Second
andi r17, 0x0F
ori r17,0x80
mov r16,r17
; Send command to LCD
call LCD_Send_Command
ret
LCD_Move_Cursor_Second:
cpi r16,1 ;check if second row
brne LCD_Move_Cursor_Exit ;else exit
andi r17, 0x0F
ori r17,0xC0
mov r16,r17
; Send command to LCD
call LCD_Send_Command
LCD_Move_Cursor_Exit:
; Return from function
ret
; Subroutine to send string to LCD
;address of the string on ZH-ZL
;string end with Null
.def LCDData = r16
LCD_Send_String:
push ZH ; preserve pointer registers
push ZL
push LCDData
; fix up the pointers for use with the 'lpm' instruction
lsl ZL ; shift the pointer one bit left for the lpm instruction
rol ZH
; write the string of characters
LCD_Send_String_01:
lpm LCDData, Z+ ; get a character
cpi LCDData, 0 ; check for end of string
breq LCD_Send_String_02 ; done
; arrive here if this is a valid character
call LCD_Send_Data ; display the character
rjmp LCD_Send_String_01 ; not done, send another character
; arrive here when all characters in the message have been sent to the LCD module
LCD_Send_String_02:
pop LCDData
pop ZL ; restore pointer registers
pop ZH
ret

; Subroutine to send command to LCD


;Command code in r16
;LCD_D7..LCD_D4 connect to PA7..PA4
;LCD_RS connect to PA0
;LCD_RW connect to PA1
;LCD_EN connect to PA2
LCD_Send_Command:
push r17
call LCD_wait_busy ; check if LCD is busy
mov r17,r16 ;save the command
; Set RS low to select command register
; Set RW low to write to LCD
andi r17,0xF0
; Send command to LCD
out LCDPORT, r17
nop
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
swap r16
andi r16,0xF0
; Send command to LCD
out LCDPORT, r16
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
pop r17
ret

LCD_Send_Data:
push r17
call LCD_wait_busy ;check if LCD is busy
mov r17,r16 ;save the command
; Set RS high to select data register
; Set RW low to write to LCD
andi r17,0xF0
ori r17,0x01
; Send data to LCD
out LCDPORT, r17
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
cbi LCDPORT, LCD_EN
; Delay for command execution
;send the lower nibble
nop
swap r16
andi r16,0xF0
; Set RS high to select data register
; Set RW low to write to LCD
andi r16,0xF0
ori r16,0x01
; Send command to LCD
out LCDPORT, r16
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
cbi LCDPORT, LCD_EN
pop r17
ret

LCD_wait_busy:
push r16
ldi r16, 0b00000111 ; set PA7-PA4 as input, PA2-PA0 as output
out LCDPORTDIR, r16
ldi r16,0b11110010 ; set RS=0, RW=1 for read the busy flag
out LCDPORT, r16
nop
LCD_wait_busy_loop:
sbi LCDPORT, LCD_EN
nop
nop
in r16, LCDPORTPIN
cbi LCDPORT, LCD_EN
nop
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
nop
andi r16,0x80
cpi r16,0x80
breq LCD_wait_busy_loop
ldi r16, 0b11110111 ; set PA7-PA4 as output, PA2-PA0 as output
out LCDPORTDIR, r16
ldi r16,0b00000000 ; set RS=0, RW=1 for read the busy flag
out LCDPORT, r16
pop r16
ret

DELAY_10MS: ;
push r16
push r17
ldi r16,106 ;1MC
l1: ldi r17,250 ;1MC
l2: dec r17 ;1MC
brne l2 ;2/1MC
dec r16 ;1MC
brne l1 ;2/1MC
pop r17
pop r16
ret ;4MC

3.
.include "m324padef.inc" ; Include Atmega324pa definitions
.org 0x0000 ; interrupt vector table
jmp reset ; reset
.org 0x000E ; pin change interrupt vector
rjmp pinchange ; Chuong trinh ngat
;******************************* Program ID *********************************
.def sttphimBam = r24
.org 0x0020
reset:
ldi sttphimBam, 0
call LCD_Init
call SW_Init
call BARLED_Init
call INT_Init

start:
rjmp start

pinchange:
push r16
in r16, PIND
cpi r16, 0xf0
breq pinchange_handler_exit;
call scankey ;scan and shiftout keycode
cpi r24, 0xff
breq pinchange_handler_exit;
call disp_LCD
call disp_BL
pinchange_handler_exit:
pop r16
call SW_Init
reti ; return from interrupt

;////////////////////////LCD DISP///////////////////////
.org INT_VECTORS_SIZE
dong1:
.db "Da bam phim:",0
disp_LCD:
push r16
push r17
push r18
push sttphimBam
; display the first line of information
ldi r16,0
ldi r17,0
call LCD_Move_Cursor
ldi ZH, high(dong1) ; point to the information that is to be displayed
ldi ZL, low(dong1)
call LCD_Send_String
ldi r16,1
ldi r17,0
call LCD_Move_Cursor

ldi r17,0
ldi r18,0
hangtram:
cpi sttphimBam,100
brsh lonhontram
hangchuc:
cpi sttphimBam,10
brsh lonhonchuc
rjmp inraLCD
lonhonchuc:
subi sttphimBam,10
inc r17
rjmp hangchuc
lonhontram:
subi sttphimBam,100
inc r18
rjmp hangtram

inraLCD:
ldi r16,48
add r16,r18
call LCD_Send_Data
ldi r16,48
add r16,r17
call LCD_Send_Data
ldi r16,48
add r16,sttphimBam
call LCD_Send_Data

pop sttphimBam
pop r18
pop r17
pop r16
ret
;////////////////////////INTERUPT PinChange////////////////////
INT_Init:
;PinChange cho PortC 7-4
ldi r16, 0xf0
sts PCMSK3, r16
ldi r16, (1<<PCIE3)
sts PCICR, r16
sei
ret

;////////////////////////Matrix SW/////////////////////////////
SW_Init:
ldi r16,0x0f ; PC7-4 input row 3-0, 3-0 output col 3-0
out ddrd, r16
ldi r16,0xf0
out portd,r16 ; Dien tro keo len
ret

scanKey:
push r22
push r23

ldi r22, 0b11110111 ; initial col mask


ldi r23,3 ;scanning col index
ldi r24, 0 ; initial pressed row value
keypad_scan_loop:
out PORTD, r22 ; scan current col
nop ;need to have 1us delay to stablize
sbic PIND, 4 ; check row 0
rjmp keypad_scan_check_col2
call DELAY_1MS
sbic PIND, 4 ; check row 0
rjmp keypad_scan_check_col2
rjmp keypad_scan_found ; row 0 is pressed
keypad_scan_check_col2:
sbic PIND, 5 ; check row 1
rjmp keypad_scan_check_col3
call DELAY_1MS
sbic PIND, 5 ; check row 0
rjmp keypad_scan_check_col3
ldi r24, 1 ; row1 is pressed
rjmp keypad_scan_found
keypad_scan_check_col3:
sbic PIND, 6 ; check row 2
rjmp keypad_scan_check_col4
call DELAY_1MS
sbic PIND, 6 ; check row 0
rjmp keypad_scan_check_col4
ldi r24, 2 ; row 2 is pressed
rjmp keypad_scan_found
keypad_scan_check_col4:
sbic PIND, 7 ; check row 3
rjmp keypad_scan_next_row
call DELAY_1MS
sbic PIND, 7 ; check row 0
rjmp keypad_scan_next_row
ldi r24, 3 ; row 3 is pressed
rjmp keypad_scan_found
keypad_scan_next_row:
; check if all rows have been scanned
cpi r23,0
breq keypad_scan_not_found
; shift row mask to scan next row
ror r22
dec r23 ;increase row index
rjmp keypad_scan_loop
keypad_scan_found:
; combine row and column to get key value (0-15)
;key code = row*4 + col
lsl r24 ; shift row value 4 bits to the left
lsl r24
add r24, r23 ; add row value to column value
rjmp end_scan
keypad_scan_not_found:
ldi r24, 0xFF ; no key pressed
end_scan:
pop r23
pop r22
ret

;////////////////////////BARLED//////////////////////////
BARLED_Init:
ldi r16,0xff
out ddrb,r16
ret
disp_BL:
out portb,sttphimBam
ret
;////////////////////////LCD/////////////////////////////
;init the LCD
;LCD_D7..LCD_D4 connect to PA7..PA4
;LCD_RS connect to PA0
;LCD_RW connect to PA1
;LCD_EN connect to PA2
.equ LCDPORT = PORTA ; Set signal port reg to PORTA
.equ LCDPORTDIR = DDRA ; Set signal port dir reg to PORTA
.equ LCDPORTPIN = PINA ; Set clear signal port pin reg to PORTA
.equ LCD_RS = PINA0
.equ LCD_RW = PINA1
.equ LCD_EN = PINA2
.equ LCD_D7 = PINA7
.equ LCD_D6 = PINA6
.equ LCD_D5 = PINA5
.equ LCD_D4 = PINA4
LCD_Init:
; Set up data direction register for Port A
ldi r16, 0b11110111 ; set PA7-PA4 as outputs, PA2-PA0 as output
out LCDPORTDIR, r16
; Wait for LCD to power up
call DELAY_10MS
call DELAY_10MS
; Send initialization sequence
ldi r16, 0x02 ; Function Set: 4-bit interface
call LCD_Send_Command
ldi r16, 0x28 ; Function Set: enable 5x7 mode for chars
call LCD_Send_Command
ldi r16, 0x0E ; Display Control: Display OFF, Cursor ON
call LCD_Send_Command
ldi r16, 0x01 ; Clear Display
call LCD_Send_Command
ldi r16, 0x80 ; Clear Display
call LCD_Send_Command
ret

; Function to move the cursor to a specific position on the LCD


; Assumes that the LCD is already initialized
; Input: Row number in R16 (0-based), Column number in R17 (0-based)
LCD_Move_Cursor:
cpi r16,0 ;check if first row
brne LCD_Move_Cursor_Second
andi r17, 0x0F
ori r17,0x80
mov r16,r17
; Send command to LCD
call LCD_Send_Command
ret
LCD_Move_Cursor_Second:
cpi r16,1 ;check if second row
brne LCD_Move_Cursor_Exit ;else exit
andi r17, 0x0F
ori r17,0xC0
mov r16,r17
; Send command to LCD
call LCD_Send_Command
LCD_Move_Cursor_Exit:
; Return from function
ret
; Subroutine to send string to LCD
;address of the string on ZH-ZL
;string end with Null
.def LCDData = r16
LCD_Send_String:
push ZH ; preserve pointer registers
push ZL
push LCDData
; fix up the pointers for use with the 'lpm' instruction
lsl ZL ; shift the pointer one bit left for the lpm instruction
rol ZH
; write the string of characters
LCD_Send_String_01:
lpm LCDData, Z+ ; get a character
cpi LCDData, 0 ; check for end of string
breq LCD_Send_String_02 ; done
; arrive here if this is a valid character
call LCD_Send_Data ; display the character
rjmp LCD_Send_String_01 ; not done, send another character
; arrive here when all characters in the message have been sent to the LCD module
LCD_Send_String_02:
pop LCDData
pop ZL ; restore pointer registers
pop ZH
ret

; Subroutine to send command to LCD


;Command code in r16
;LCD_D7..LCD_D4 connect to PA7..PA4
;LCD_RS connect to PA0
;LCD_RW connect to PA1
;LCD_EN connect to PA2
LCD_Send_Command:
push r17
call LCD_wait_busy ; check if LCD is busy
mov r17,r16 ;save the command
; Set RS low to select command register
; Set RW low to write to LCD
andi r17,0xF0
; Send command to LCD
out LCDPORT, r17
nop
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
swap r16
andi r16,0xF0
; Send command to LCD
out LCDPORT, r16
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
pop r17
ret

LCD_Send_Data:
push r17
call LCD_wait_busy ;check if LCD is busy
mov r17,r16 ;save the command
; Set RS high to select data register
; Set RW low to write to LCD
andi r17,0xF0
ori r17,0x01
; Send data to LCD
out LCDPORT, r17
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
cbi LCDPORT, LCD_EN
; Delay for command execution
;send the lower nibble
nop
swap r16
andi r16,0xF0
; Set RS high to select data register
; Set RW low to write to LCD
andi r16,0xF0
ori r16,0x01
; Send command to LCD
out LCDPORT, r16
nop
; Pulse enable pin
sbi LCDPORT, LCD_EN
nop
cbi LCDPORT, LCD_EN
pop r17
ret

LCD_wait_busy:
push r16
ldi r16, 0b00000111 ; set PA7-PA4 as input, PA2-PA0 as output
out LCDPORTDIR, r16
ldi r16,0b11110010 ; set RS=0, RW=1 for read the busy flag
out LCDPORT, r16
nop
LCD_wait_busy_loop:
sbi LCDPORT, LCD_EN
nop
nop
in r16, LCDPORTPIN
cbi LCDPORT, LCD_EN
nop
sbi LCDPORT, LCD_EN
nop
nop
cbi LCDPORT, LCD_EN
nop
andi r16,0x80
cpi r16,0x80
breq LCD_wait_busy_loop
ldi r16, 0b11110111 ; set PA7-PA4 as output, PA2-PA0 as output
out LCDPORTDIR, r16
ldi r16,0b00000000 ; set RS=0, RW=1 for read the busy flag
out LCDPORT, r16
pop r16
ret

DELAY_1MS: ;
push r16
push r17
ldi r16,10 ;1MC
l11: ldi r17,250 ;1MC
l22: dec r17 ;1MC
brne l22 ;2/1MC
dec r16 ;1MC
brne l11 ;2/1MC
pop r17
pop r16
ret ;4MC

DELAY_10MS: ;
push r16
push r17
ldi r16,106 ;1MC
l1: ldi r17,250 ;1MC
l2: dec r17 ;1MC
brne l2 ;2/1MC
dec r16 ;1MC
brne l1 ;2/1MC
pop r17
pop r16
ret ;4MC

You might also like