Skip to content

Instantly share code, notes, and snippets.

@ilovejs
Created February 15, 2013 02:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ilovejs/4958165 to your computer and use it in GitHub Desktop.
Save ilovejs/4958165 to your computer and use it in GitHub Desktop.
; It is assumed that the following connections on the board are made:
; LCD D0-D7 -> PD0-PD7
; LCD BE-RS -> PA0-PA3
; These ports can be changed if required by replacing all references to the ports with a
; different port. This means replacing occurences of DDRx, PORTx and PINx.
.include "m64def.inc"
.def temp =r16
.def data =r17
.def del_lo = r18
.def del_hi = r19
.def counter=r20
.def counter2=r21
.def counter3=r22
.def ledval = r23
.def one = r30
.def two = r25
.def three = r26
.def four = r27
;LCD protocol control bits
.equ LCD_RS = 3
.equ LCD_RW = 1
.equ LCD_E = 2
;LCD functions
.equ LCD_FUNC_SET = 0b00110000
.equ LCD_DISP_OFF = 0b00001000
.equ LCD_DISP_CLR = 0b00000001
.equ LCD_DISP_ON = 0b00001100
.equ LCD_ENTRY_SET = 0b00000100
.equ LCD_ADDR_SET = 0b10000000
;LCD function bits and constants
.equ LCD_BF = 7
.equ LCD_N = 3
.equ LCD_F = 2
.equ LCD_ID = 1
.equ LCD_S = 0
.equ LCD_C = 1
.equ LCD_B = 0
.equ LCD_LINE1 = 0
.equ LCD_LINE2 = 0x40
.MACRO Clear
ldi r28, low(@0) ; Load the low byte of label @0
ldi r29, high(@0) ; Load the high byte of label @0
clr temp
st y, temp
st -y, temp ; Initialize the two-byte integer at @0 to 0
.ENDMACRO
.dseg
SecondCounter:
.byte 2 ; Two-byte second counter
TempCounter:
.byte 2 ; Temporary counter, used to determine
; if one second has passed
.cseg
.org 0
jmp RESET
jmp Default ; IRQ0 Handler
jmp Default ; IRQ1 Handler
jmp Default ; IRQ2 Handler
jmp Default ; IRQ3 Handler
jmp Default ; IRQ4 Handler
jmp Default ; IRQ5 Handler
jmp Default ; IRQ6 Handler
jmp Default ; IRQ7 Handler
jmp Default ; Timer2 Compare Handler
jmp Default ; Timer2 Overflow Handler
jmp Default ; Timer1 Capture Handler
jmp Default ; Timer1 CompareA Handler
jmp Default ; Timer1 CompareB Handler
jmp Default ; Timer1 Overflow Handler
jmp Default ; Timer0 Compare Handler
jmp Timer0 ; Timer0 Overflow Handler
DEFAULT: reti ; No handling for this interrupt
RESET: ldi temp, high(RAMEND) ; Initialize stack pointer
out SPH, temp
ldi temp, low(RAMEND)
out SPL, temp
rcall lcd_init ; Insert further initialization code here
rjmp main
;Function lcd_write_com: Write a command to the LCD. The data reg stores the value to be written.
lcd_write_com:
out PORTD, data ; set the data port's value up
clr temp
out PORTA, temp ; RS = 0, RW = 0 for a command write
nop ; delay to meet timing (Set up time)
sbi PORTA, LCD_E ; turn on the enable pin
nop ; delay to meet timing (Enable pulse width)
nop
nop
cbi PORTA, LCD_E ; turn off the enable pin
nop ; delay to meet timing (Enable cycle time)
nop
nop
ret
;Function lcd_write_data: Write a character to the LCD. The data reg stores the value to be written.
lcd_write_data:
out PORTD, data ; set the data port's value up
ldi temp, 1 << LCD_RS
out PORTA, temp ; RS = 1, RW = 0 for a data write
nop ; delay to meet timing (Set up time)
sbi PORTA, LCD_E ; turn on the enable pin
nop ; delay to meet timing (Enable pulse width)
nop
nop
cbi PORTA, LCD_E ; turn off the enable pin
nop ; delay to meet timing (Enable cycle time)
nop
nop
ret
;Function lcd_wait_busy: Read the LCD busy flag until it reads as not busy.
lcd_wait_busy:
clr temp
out DDRD, temp ; Make PORTD be an input port for now
out PORTD, temp
ldi temp, 1 << LCD_RW
out PORTA, temp ; RS = 0, RW = 1 for a command port read
busy_loop:
nop ; delay to meet timing (Set up time / Enable cycle time)
sbi PORTA, LCD_E ; turn on the enable pin
nop ; delay to meet timing (Data delay time)
nop
nop
in temp, PIND ; read value from LCD
cbi PORTA, LCD_E ; turn off the enable pin
sbrc temp, LCD_BF ; if the busy flag is set
rjmp busy_loop ; repeat command read
clr temp ; else
out PORTA, temp ; turn off read mode,
ser temp
out DDRD, temp ; make PORTD an output port again
ret ; and return
; Function delay: Pass a number in registers r18:r19 to indicate how many microseconds
; must be delayed. Actual delay will be slightly greater (~1.08us*r18:r19).
; r18:r19 are altered in this function.
; Code is omitted
delay:
ldi r20,1
ldi r21,0
sub del_lo , r20
sbc del_hi , r21
cp del_lo, r21
cpc del_hi, r21
brne delay
ret
;Function lcd_init Initialisation function for LCD.
lcd_init:
ser temp
out DDRD, temp ; PORTD, the data port is usually all otuputs
out DDRA, temp ; PORTA, the control port is always all outputs
ldi del_lo, low(15000) ;15000)
ldi del_hi, high(15000)
rcall delay ; delay for > 15ms
; Function set command with N = 1 and F = 0
ldi data, LCD_FUNC_SET | (1 << LCD_N)
rcall lcd_write_com ; 1st Function set command with 2 lines and 5*7 font
ldi del_lo, low(4100)
ldi del_hi, high(4100)
rcall delay ; delay for > 4.1ms
rcall lcd_write_com ; 2nd Function set command with 2 lines and 5*7 font
ldi del_lo, low(100)
ldi del_hi, high(100)
rcall delay ; delay for > 100us
rcall lcd_write_com ; 3rd Function set command with 2 lines and 5*7 font
rcall lcd_write_com ; Final Function set command with 2 lines and 5*7 font
rcall lcd_wait_busy ; Wait until the LCD is ready
ldi data, LCD_DISP_OFF
rcall lcd_write_com ; Turn Display off
rcall lcd_wait_busy ; Wait until the LCD is ready
ldi data, LCD_DISP_CLR
rcall lcd_write_com ; Clear Display
rcall lcd_wait_busy ; Wait until the LCD is ready
; Entry set command with I/D = 1 and S = 0
ldi data, LCD_ENTRY_SET | (1 << LCD_ID)
rcall lcd_write_com ; Set Entry mode: Increment = yes and Shift = no
rcall lcd_wait_busy ; Wait until the LCD is ready
; Display on command with C = 0 and B = 1
ldi data, LCD_DISP_ON | (1 << LCD_C)
rcall lcd_write_com ; Trun Display on with a cursor that doesn't blink
ret
Timer0: ; Prologue starts.
push r29 ; Save all conflict registers in the prologue.
push r28
in r24, SREG
push r24 ; Prologue ends.
/**** a counter for 3597 is needed to get one second-- Three counters are used in this example **************/
; 3597 (1 interrupt 278microseconds therefore 3597 interrupts needed for 1 sec)
cpi counter, 97 ; counting for 97
brne notsecond
cpi counter2, 35 ; counting for 35
brne secondloop ; jumping into count 100
cpi ledval,0 ; compare the current ledval for zero
breq setFF ; if it is zero jump to set it to FF
ldi ledval,0 ; if the current ledval is not zero set it to 0
rjmp outmot ; jump to out put value
setFF: ldi ledval,255 ; set the ledval to FF
outmot: ldi counter,0 ; clearing the counter values after counting 3597 interrupts which gives us one second
ldi counter2,0
ldi counter3,0
;out PORTD,ledval ; sending the ledval to port
rcall lcd_init
mov data,one
rcall lcd_wait_busy
rcall lcd_write_data
mov data,two
rcall lcd_wait_busy
rcall lcd_write_data
ldi data, ':'
rcall lcd_wait_busy
rcall lcd_write_data
mov data,three
rcall lcd_wait_busy
rcall lcd_write_data
mov data,four
rcall lcd_wait_busy
rcall lcd_write_data
inc four ; increment character
cpi four, '9'+1 ; compare with first character > '9'
brlo skip3 ; if character is now greater than '9'
inc three
ldi four, '0'
skip3:
cpi three, '6' ; compare with first character > '9'
brlo skip2 ; if character is now greater than '9'
inc two
ldi three, '0'
skip2:
cpi two, '9'+1 ; compare with first character > '9'
brlo skip1 ; if character is now greater than '9'
inc one
ldi two, '0'
skip1:
rjmp exit ; go to exit
notsecond: inc counter ; if it is not a second, increment the counter
rjmp exit
secondloop: inc counter3 ; counting 100 for every 35 times := 35*100 := 3500
cpi counter3,100
brne exit
inc counter2
ldi counter3,0
exit:
pop r24 ; Epilogue starts;
out SREG, r24 ; Restore all conflict registers from the stack.
pop r28
pop r29
reti ; Return from the interrupt.
;*****************************************************************************************
; Everything below here can be replaced. This is some sample code to show it all working.
;*****************************************************************************************
; Function main: Test the LCD by writing some characters to the screen. Desired output is:
; Hello World!
; 123456789012
main:
Clear TempCounter ; Initialize the temporary counter to 0
Clear SecondCounter ; Initialize the second counter to 0
ldi one,'0'
ldi two,'0'
ldi three,'0'
ldi four,'0'
ldi temp, 0b00000010
out TCCR0, temp ; Prescaling value=8? 256*8/7.3728
ldi temp, 1<<TOIE0 ; =278 microseconds
out TIMSK, temp ; T/C0 interrupt enable
sei ; Enable global interrupt
end: rjmp end ; loop forever
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment