На ATmega16, на асме, код коцаный перекоцаный:
CODE
.include "m16def.inc"
.equ LCD_RS = 5
.equ LCD_E = 7
.def temp = r16
.def argument= r17 ;argument for calling subroutines
.def return = r18 ;return value from subroutines
.CSEG
.org 0
jmp RESET ; Reset
jmp EXT_INT1
reti
jmp EXT_INT1
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
RESET:
clr r16
out GICR, r16 ;Disable external interrupt
out DDRA, r16 ;All in
out DDRB, r16
out DDRC, r16
out DDRD, r16
out PORTA, r16 ; All Tri-state
out PORTB, r16
out PORTC, r16
out PORTD, r16
ldi r16, 0b00100000
out DDRA, r16 ; ????? out A
ldi r16, 0xFF
out DDRB, r16 ; ????? out B
ldi r16, 0xFF
out DDRC, r16 ; ????? out C
ldi r16, 0b10100000
out DDRD, r16 ; ????? out D
ldi r16, 0x00 ;PORTA5 is RS
out PORTA, r16
ldi r16, 0b00110000
out PORTB, r16
ldi r16, 0x00
out PORTC, r16
ldi r16, 0x00 ;PORTD7 is E
out PORTD, r16
ldi r16, LOW(RAMEND) ;Stack Pointer
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16
ldi r16, 0x00
out SFIOR, r16
ldi r16, 0x0B
out MCUCR, r16
ldi r16, 0x10
out WDTCR, r16
rcall LCD_init
rcall LCD_delay
ldi r16, 0x80
out GICR, r16
;rcall text_out
LOOP:
sei
rjmp LOOP
EXT_INT1:
rcall text_out ;MUST WORK!(((((((((((((((
reti
lcd_command8: ;used for init (we need some 8-bit commands to switch to 4-bit mode!)
;in temp, DDRD ;we need to set the high nibble of DDRD while leaving
;the other bits untouched. Using temp for that.
;sbr temp, 0b11110000 ;set high nibble in temp
;out DDRD, temp ;write value to DDRD again
in temp, PortC ;then get the port value
andi temp, 0x0F
andi argument, 0xF0 ;then clear the low nibble of the argument
;so that no control line bits are overwritten
or temp, argument ;then set the data bits (from the argument) in the
;Port value
out PortC, temp ;and write the port value.
cbi PortA, LCD_RS
sbi PortD, LCD_E ;now strobe E
nop
nop
nop
nop
nop
nop
nop
nop
cbi PortD, LCD_E
;cbi PortA, LCD_RS
ret
lcd_putchar:
push argument ;save the argmuent (it's destroyed in between)
in temp, PortC ;then get the data from PortD
;push temp
andi temp, 0x0F ;clear ALL LCD lines (data and control!)
andi argument, 0xF0 ;we have to write the high nibble of our argument first
;so mask off the low nibble
or temp, argument ;now set the argument bits in the Port value
out PortC, temp ;and write the port value
sbi PortA, LCD_RS ;now take RS high for LCD char data register access
sbi PortD, LCD_E ;strobe Enable
nop
nop
nop
nop
nop
nop
nop
nop
cbi PortD, LCD_E
pop argument ;restore the argument, we need the low nibble now...
andi temp, 0x0F ;clear the data bits of our port value
swap argument ;we want to write the LOW nibble of the argument to
;the LCD data lines, which are the HIGH port nibble!
andi argument, 0xF0 ;clear unused bits in argument
or temp, argument ;and set the required argument bits in the port value
out PortC, temp ;and write the port value
sbi PortA, LCD_RS ;now take RS high for LCD char data register access
sbi PortD, LCD_E ;strobe Enable
nop
nop
nop
nop
nop
nop
nop
nop
cbi PortD, LCD_E
;pop temp
;out PortC, temp
ret
lcd_command: ;same as LCD_putchar, but with RS low!
push argument ;save the argmuent (it's destroyed in between)
in temp, PortC ;then get the data from PortD
andi temp, 0x0F ;clear ALL LCD lines (data and control!)
andi argument, 0xF0 ;we have to write the high nibble of our argument first
;so mask off the low nibble
or temp, argument ;now set the argument bits in the Port value
out PortC, temp ;and write the port value
cbi PortA, LCD_RS ;now take RS high for LCD char data register access
sbi PortD, LCD_E ;strobe Enable
nop
nop
nop
nop
nop
nop
nop
nop
cbi PortD, LCD_E
pop argument ;restore the argument, we need the low nibble now...
andi temp, 0x0F ;clear the data bits of our port value
swap argument ;we want to write the LOW nibble of the argument to
;the LCD data lines, which are the HIGH port nibble!
andi argument, 0xF0 ;clear unused bits in argument
or temp, argument ;and set the required argument bits in the port value
out PortC, temp ;and write the port value
cbi PortA, LCD_RS ;now take RS high for LCD char data register access
sbi PortD, LCD_E ;strobe Enable
nop
nop
nop
nop
nop
nop
nop
nop
cbi PortD, LCD_E
ret
LCD_wait:
ldi r18, 0x03
LCD_wait_l1:
clr r19
LCD_wait_l2:
dec r19
brne LCD_wait_l2
dec r18
brne LCD_wait_l1
ret
LCD_delay:
clr r2
LCD_delay_outer:
clr r3
LCD_delay_inner:
dec r3
brne LCD_delay_inner
dec r2
brne LCD_delay_outer
ret
LCD_init:
rcall LCD_delay ;first, we'll tell the LCD that we want to use it
ldi argument, 0x20 ;in 4-bit mode.
rcall LCD_command8 ;LCD is still in 8-BIT MODE while writing this command!!!
rcall LCD_delay
ldi argument, 0x28 ;NOW: 2 lines, 5*7 font, 4-BIT MODE!
rcall LCD_command ;
rcall LCD_delay
ldi argument, 0x0F ;now proceed as usual: Display on, cursor on, blinking
rcall LCD_command
rcall LCD_delay
ldi argument, 0x01 ;clear display, cursor -> home
rcall LCD_command
rcall LCD_delay
ldi argument, 0x06 ;auto-inc cursor
rcall LCD_command
ret
text_out:
ldi Zl, LOW(2*line1)
ldi Zh, HIGH(2*line1)
text_out_l1:
lpm
adiw Zl, 1
tst r0
breq text_out_l2
mov argument, r0
rcall LCD_putchar
rcall LCD_wait
rjmp text_out_l1
text_out_l2:
ldi argument, 0x80
ori argument, 0x40
rcall LCD_command
rcall LCD_wait
ldi Zl, LOW(2*line2)
ldi Zh, HIGH(2*line2)
text_out_l3:
lpm
adiw Zl, 1
tst r0
breq text_out_l4
mov argument, r0
rcall LCD_putchar
rcall LCD_wait
rjmp text_out_l3
text_out_l4:
ret
line1: .db ' ',' ',' ','G','R','E','A','T','I','N','G','S','!',' ',' ',' ',0
line2: .db ' ',' ',' ','V','I','C','E',' ','C','I','T','Y','!',' ',' ',' ',0
...как тэг кода ставить? не подскажете?