Hi, i'm trying to learn some assembly, ive got a assignment from school to control a lcd screen. I've got some sample code that i mostly understand but i can't figure out what the SBI command does.
Using atmega32, with avr studio 4
sbi PortD, LCD_E
At this point PortD = 32, and LCD_E = 0 (decimal)
After the sbi line PortD = 36
I don't see how he changes from 32 to 36.
Atmega instruction info:http://iranmicro.ir/Online/Help/avrasm/index.html?html_sbi.htm
Example i've got from school:
; Some notes on the hardware:
;ATmega8 (clock frequency doesn't matter, tested with 1 MHz to 8 MHz)
; PortD.1 -> LCD RS (register select)
; PortD.2 -> LCD RW (read/write) -enable
; PortD.3 -> LCd E (Enable) -RS
; PortD.4 ... PortD.7 -> LCD data.4 ... data.7
; the other LCd data lines can be left open or tied to ground.
.include "m32def.inc"
.equ LCD_RS = 3
.equ LCD_RW = 0
.equ LCD_E = 2
.def temp = r16
.def argument= r17 ;argument for calling subroutines
.def return = r18 ;return value from subroutines
.org 0
rjmp reset
reset:
ldi temp, low(RAMEND)
out SPL, temp
ldi temp, high(RAMEND)
out SPH, temp
;ser R19
;out DDRA, R19
;LCD after power-up: ("*" means black bar)
;|****************|
;| |
rcall LCD_init
;LCD now:
;|& | (&: cursor, blinking)
;| |
rcall LCD_delay
ldi argument, 'A' ;write 'A' to the LCD char data RAM
rcall LCD_putchar
;|A& |
;| |
rcall LCD_delay
ldi argument, 0x80
;out PORTA, argument
;rcall LCD_putchar ;now let the cursor go to line 0, col 0 (address 0)
rcall LCD_command ;for setting a cursor address, bit 7 of the commands has to be set
;|A | (cursor and A are at the same position!)
;| |
; rcall LCD_delay
; pop argument ;restore the character
; rcall LCD_putchar ;and print it again
; rcall LCD_delay
;pop argument ;restore the character
;rcall LCD_putchar ;and print it again
; rcall LCD_delay
;pop argument ;restore the character
;rcall LCD_putchar ;and print it again
;|AA& | (A has been read from position 0 and has then been written to the next pos.)
;| |
loop: rjmp loop
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, PortD ;then get the port value
cbr temp, 0b11110000 ;and clear the data bits
cbr argument, 0b00001111 ;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 PortD, temp ;and write the port value.
sbi PortD, LCD_E ;now strobe E
nop
nop
nop
cbi PortD, LCD_E
in temp, DDRD ;get DDRD to make the data lines input again
cbr temp, 0b11110000 ;clear data line direction bits
out DDRD, temp ;and write to DDRD
ret
lcd_putchar:
push argument ;save the argmuent (it's destroyed in between)
in temp, DDRD ;get data direction bits
sbr temp, 0b11110000 ;set the data lines to output
out DDRD, temp ;write value to DDRD
in temp, PortD ;then get the data from PortD
cbr temp, 0b11111110 ;clear ALL LCD lines (data and control!)
cbr argument, 0b00001111 ;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 PortD, temp ;and write the port value
sbi PortD, LCD_RS ;now take RS high for LCD char data register access
sbi PortD, LCD_E ;strobe Enable
nop
nop
nop
cbi PortD, LCD_E
pop argument ;restore the argument, we need the low nibble now...
cbr temp, 0b11110000 ;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!
cbr argument, 0b00001111 ;clear unused bits in argument
or temp, argument ;and set the required argument bits in the port value
out PortD, temp ;write data to port
sbi PortD, LCD_RS ;again, set RS
sbi PortD, LCD_E ;strobe Enable
nop
nop
nop
cbi PortD, LCD_E
cbi PortD, LCD_RS
in temp, DDRD
cbr temp, 0b11110000 ;data lines are input again
out DDRD, temp
ret
lcd_command: ;same as LCD_putchar, but with RS low!
push argument
in temp, DDRD
sbr temp, 0b11110000
out DDRD, temp
in temp, PortD
cbr temp, 0b11111110
cbr argument, 0b00001111
or temp, argument
out PortD, temp
sbi PortD, LCD_E
nop
nop
nop
cbi PortD, LCD_E
pop argument
cbr temp, 0b11110000
swap argument
cbr argument, 0b00001111
or temp, argument
out PortD, temp
sbi PortD, LCD_E
nop
nop
nop
cbi PortD, LCD_E
in temp, DDRD
cbr temp, 0b11110000
out DDRD, temp
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:
ldi temp, 0b00001110 ;control lines are output, rest is input
out DDRD, temp
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