Created
February 15, 2013 02:31
-
-
Save ilovejs/4958165 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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