Kod för att skriva till en standard HD44780 LCD skriven för PIC16F886. Kan utan större justeringar användas till de flesta nyare PIC16. Koden nedan skriver texten enligt bilden till höger.
Lägg upp ett tomt projekt i MPLAB, skapa en ny, tom ASM fil och klistra in koden. |
|
;**********************************************************************
; Enkelt test av HD44780 LCD display.
; Använder en standard 16x2 LCD.
; För PIC16F886
;
;**********************************************************************
; *
; Filename: HD44780_16F886.asm
; Date: 20070702
; File Version: 1.0
;
; Author: Jan-Erik Söderholm
; Company: Jan-Erik Söderholm Consulting AB
;
;**********************************************************************
;
; Files required: P16F886.INC
; 16F886.LKR
;
;**********************************************************************
;
; Notes:
; Använder intosc på 4 Mhz.
;
; E : RA0
; RS: RA1
; D4-D7 : RA4-RA7
; R/W kopplad till GND (d.v.s ingen läsning av Busy-signalen).
;
;**********************************************************************
;
;
list p=16f886 ; list directive to define processor
#include <p16f886.inc> ; processor specific variable definitions
;
__CONFIG _CONFIG1, _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
__CONFIG _CONFIG2, _WRT_OFF & _BOR21V
;
errorlevel -302
;
#define LCD_E PORTA, 0
#define LCD_RS PORTA, 1
#define LCD_PORT PORTA
;
;
;**********************************************************************
RESET_VECTOR CODE 0x000 ; processor reset vector
goto start ; go to beginning of program
;
;
INT_VECTOR CODE 0x004 ; interrupt vector location
retfie ; Ingen interrupt kod...
;
;
;**********************************************************************
; Macro för att skicka en text till LCD.
;
lcd_text macro text_label
banksel eeadr ; byt till rätt bank...
movlw high text_label ; bit 8-15 av adressen till texten
movwf eeadrh
movlw low text_label ; bit 0-7 av adressen till texten
movwf eeadr
;
; Nu är de två adressregistren laddade med rätt adress.
; Anropa subrutinen för att hämta texten och skriva ut den.
;
call lcd_send_text
banksel porta ; Lämna rutinen i bank 0.
;
endm
;
;**********************************************************************
; Huvudkoden.
; Här hamnar vi vid reset eller power-on (från RESET_VECTOR)
;
;
MAIN CODE
start
;
; Först normal uppstart ej specifik för LCD
;
banksel ansel ; Stäng av alla analoga funktioner
clrf ansel
clrf anselh
banksel trisa ; Alla pinnar utgångar...
clrf trisa
clrf trisb
clrf trisc
;
banksel intcon
clrf intcon
banksel porta ; se till att vi är på bank 0.
;
; Så då var grundinställningen av processorn klar.
; Nu går vi vidare med LCD hanteringen...
;
call lcd_init_hd44780 ; Ställ in LCD'n.
;
; Skriv ut ett par texter på LCD'n...
;
lcd_text lcd_text1
lcd_text lcd_text2
lcd_text lcd_text3
lcd_text lcd_text4
;
loop goto loop ; Gör ingenting....
;
;**********************************************************************
; Subs för HD44780
;
; Nägra temp variabler som används av LCD rutinerna.
; Lägger dom i "shared memory" så slipper vi banksel...
;
LCD_VARS UDATA_SHR
LCD_TMP1 RES 1
LCD_TMP2 RES 1
;
; Slut på variabler, här kommer koden...
;
LCD_CODE CODE
;
lcd_init_hd44780
;
call delay_1s ; Ge LCD'n tid att starta...
bcf LCD_E ; Se till att E och RS är
bcf LCD_RS ; nollade...
;
; Skicka initkoder enligt manual för HD44780.
; För detaljer, se manual för HD44780 eller datablad för en LCD.
;
movlw h'30'
call lcd_send_4_bit
call delay_5ms
movlw h'30'
call lcd_send_4_bit
call delay_5ms
movlw h'30'
call lcd_send_4_bit
call delay_100us
movlw h'20' ; Byt till 4-bitars interface !
;
call lcd_send_4_bit
call delay_100us
;
; Allt härefter sänds som två
; 4-bittars "nibbles". Först
; den höga delen (bit 4-7) sedan
; den låga (bot 0-3).
; Se lcd_send_cmd och lcd_send_data för detaljer.
;
movlw b'00101000' ; Function set
call lcd_send_cmd
movlw b'00010100' ; Display/curs shift
call lcd_send_cmd
movlw b'00001110' ; Display/curs on/off
call lcd_send_cmd
movlw b'00000110' ; Entry mode set
call lcd_send_cmd
movlw b'00000010' ; Display/curs home
call lcd_send_cmd
movlw b'00000001' ; Display clear
call lcd_send_cmd
;
; För detaljer kring varje kommando oven hänvisas till
; manual för HD44780 eller ett datablad för en LCD.
;
return
;
lcd_toggle_E
;
; Toggla E p LCD'n så att data på D4-D7 läses in.
;
banksel lcd_port
bsf lcd_e
nop
bcf lcd_e
nop
return
;
lcd_send_4_bit
; Data i W-reg bit 4-7 överförs till LCD_PORT bit 4-7.
; LCD_PORT bit 0-3 lämnas som de är.
;
banksel lcd_port
movwf lcd_tmp1 ; Spara LCD data...
movlw b'00001111' ; "Mask" för LCD_PORT
andwf lcd_port, w ; Läs av LCD_PORT bit 0-3
iorwf lcd_tmp1, w ; Kombinare med LCD data bit 4-7
movwf lcd_port ; Skriv tillbaka till LCD_PORT.
call lcd_toggle_e ; Och överför till LCD.
return
;
lcd_send_cmd
; Data i W överförs till LCD som ett "kommando".
;
banksel lcd_port
bcf LCD_RS ; RS = "0" för kommando.
call lcd_send_byte ; Skicka
call delay_5ms ; Vänta 5 ms efter ett kommando.
return
;
lcd_send_data
; Data i W överförs till LCD som "data".
;
banksel lcd_port
bsf LCD_RS ; RS = "1" för data
call lcd_send_byte ; Skicka
call delay_100us ; Ge LCD'n tid att bearbeta datat.
return
;
lcd_send_byte
; Data i W överförs till LCD som två 4-bitars bitar.
;
movwf lcd_tmp2 ; Spara W tillfälligt
movlw B'11110000' ; Mask för bit 4-7
andwf lcd_tmp2, w ; Nolla bit 0-3
call lcd_send_4_bit ; Skicka bit 4-7
swapf lcd_tmp2, f ; Byt plats på 0-3 <-> 4-7
movlw B'11110000' ; Mask för bit 4-7 (nu 0-3 !!)
andwf lcd_tmp2, w ; Nolla bit 0-3 (nu 4-7 !!)
call lcd_send_4_bit ; Skicka bit 4-7 (nu 0-3 !!)
return
;
lcd_send_text
; Sänd en fast text till LCD.
; När rutinen anropas ska EEADR och EEADRH vara initierade
; med adressen i flash till text-bufferten. T.ex genom det
; lcd_text macro som finns i detta program.
; Beräkningen av rad/kol -> LCD-pos är just nu anpassad
; till 16x2 LCD'er. Får justeras för att passa andra...
;
; Läs första positionen i texten ("LCD-rad")
;
call read_flash
movwf lcd_tmp1 ; Lagra (radnummer på LCD)
;
; Hämta nästa pos i textraden (pos på LCD raden...)
;
call inc_eeadr
call read_flash
movwf lcd_tmp2 ; Lagra (position på raden på LCD)
;
; Justering av rad/pos väden
;
decf lcd_tmp1, f ; Rad 1-2 => 0-1
bcf status, c
rrf lcd_tmp1, f
rrf lcd_tmp1, f
rrf lcd_tmp1, f ; Nu är lcd_tmp1 h'00' eller h'40'...
decf lcd_tmp2, f ; Pos 1-40 => 0-39
;
; Nu är rad och pos färdiga att addera ihop och skicka till LCD'n...
;
movlw h'80' ; Bas-kommandot för LCD-position.
addwf lcd_tmp1, w ; Lägg till rad (h'00' eller h'40')
addwf lcd_tmp2, w ; Lägg till pos.
call lcd_send_cmd ; Skicka kommandot (i W-reg)
;
; Nu läser vi resten av texten fram till h'00' poch skickar
; till LCD'n.
;
send_text_loop
;
; Läs nästa position ("LCD-text") och skicka.
; Avsluta om datat/tecknet = h'00'
;
call inc_eeadr
call read_flash
btfsc status, z ; Var det h'00' (slut på text) ?
goto send_text_end ; Ja, avsluta.
; Nej, fortsätt...
call lcd_send_data ; Skicka tecken med data i W-reg.
goto send_text_loop ; Om igen...
;
send_text_end
; Slut på text...
;
return
;
read_flash
;
; Läs en byte från flash
; EEADR och EEADRH ska redan vara initierade.
;
banksel eecon1
bsf eecon1, eepgd ; Läs från flash...
bsf eecon1, rd ; Sätt läs-flaggan...
nop ; Vänta på att läsning
nop ; ska gå klart...
banksel eedat
movf eedat, w ; Nu har vi värdet i W-reg.
return
;
; Räkna fram eeadr/eeadrh till nästa position
;
inc_eeadr
banksel eeadr
incf eeadrh, f ; öka först eeadrh
incfsz eeadr, f ; öka eeadr, = 0 ?
decf eeadrh, f ; eeadr <> 0, återställ eeadrh...
return
;
;
;**********************************************************************
; Diverse delay rutiner.
; Alla delay rutiner generade med kodgeneratorn här :
; http://www.piclist.com/techref/piclist/codegen/delay.htm
; OBS generatade för 4 Mhz processorhastighet.
;
DLY_VAR UDATA_SHR
d1 RES 1
d2 RES 1
d3 RES 1
;
;
DLY_CODE CODE
;
delay_1s
movlw 0x08
movwf d1
movlw 0x2F
movwf d2
movlw 0x03
movwf d3
Delay_1s_0
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_1s_0
goto $+1
nop
return
;
delay_5ms
movlw 0xE7
movwf d1
movlw 0x04
movwf d2
Delay_5ms_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_5ms_0
goto $+1
return
;
delay_100us
movlw 0x21
movwf d1
Delay_100us_0
decfsz d1, f
goto Delay_100us_0
return
;
;**********************************************************************
LCD_texts CODE
; Fasta texter för LCDn.
; Två första värderna i varje text är rad (1,2,3 eller 4)
; och position (1-40). Resten är text fram till h'00'.
;
lcd_text1 data d'1', d'1', 'L', 'C', 'D', ' ', 'D', 'E', 'M', 'O', h'00'
lcd_text2 data d'1', d'10', '1', '6', 'F', '8', '8', '6', h'00'
lcd_text3 data d'2', d'4', 'W','W','W','.','J','E','S','C','A','B','.','S','E', h'00'
lcd_text4 data d'2', d'1', '(', 'C', ')', h'00'
;
;**********************************************************************
end