JESCAB 
Produkter Tjänster Info Leveransvillkor Kontakt
 Snabb länkar:


HD44780

 

 

 

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.

 om1625

 

;**********************************************************************
;   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

 


Denna sida senast uppdaterad 26-Jan-2013