La libreria Neptune per il controllo di display LCD con controller Samsung KS0070B è completata. In fondo a questo articolo è possibile trovare il codice sorgente per gestire il display con la libreria Neptune; è stata utilizzata anche la libreria Chrono per avere i giusti ritardi ed impartire le giuste temporizzazioni.
Analizziamo insieme il codice sorgente. L'esecuzione parte con la routine Coldstart: in essa viene inizializzato il display LCD (LcdInit), pulito lo schermo (LcdClear) e vieme caricata nella zona di buffer del display la scritta che compare nella foto. Alla fine viene invocata la routine LcdRefresh per trasferire i caratteri dal buffer al display. Nella LcdInit vengono mandati i comandi come indicati dal datasheet Samsung.Le routines LcdSendCmd e LcdSendData vengono usate per mandare comandi e dati rispettivamente al display, utilizzando un bus a 4 bit.
Ecco il codice nella sua completezza.
;**************************************************
;
; Prova libreria display LCD TS2020 - 1 KS0070B
;
; Marco Tinari 2012 ;**************************************************
; fissa i parametri di compilazione
processor 16F628a
radix dec
; includi le definizione per il processore
#include P16F628a.inc
; maschera i warnings per la scelta del banco ram
errorlevel -302
; stabilisci i valori per i fuses
__config _XT_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _BODEN_OFF & _LVP_OFF
;definizione dei valori usati
Lcd_EN EQU 0
Lcd_RS EQU 3
Lcd_BIT4 EQU 4
Lcd_BIT5 EQU 5
Lcd_BIT6 EQU 6
Lcd_BIT7 EQU 7
; registri di lavoro
cblock 020H
us_counter : 1
ms_counter : 1
Lcd_Temp : 1
Lcd_Counter : 1
Lcd_Cells : 40
endc
ORG 0H ; vettore di reset
StartUp
GOTO ColdStart
ORG 05H ; inizio On-Chip program memory
ColdStart
CALL LcdInit
CALL LcdClear
MOVLW 'M'
MOVWF Lcd_Cells+0
MOVLW 'o'
MOVWF Lcd_Cells+1
MOVLW 'd'
MOVWF Lcd_Cells+2
MOVLW 'u'
MOVWF Lcd_Cells+3
MOVLW 'l'
MOVWF Lcd_Cells+4
MOVLW 'o'
MOVWF Lcd_Cells+5
MOVLW ' '
MOVWF Lcd_Cells+6
MOVLW 'L'
MOVWF Lcd_Cells+7
MOVLW 'C'
MOVWF Lcd_Cells+8
MOVLW 'D'
MOVWF Lcd_Cells+9
MOVLW ' '
MOVWF Lcd_Cells+10
MOVLW 'v'
MOVWF Lcd_Cells+11
MOVLW 'e'
MOVWF Lcd_Cells+12
MOVLW 'r'
MOVWF Lcd_Cells+13
MOVLW '.'
MOVWF Lcd_Cells+14
MOVLW ' '
MOVWF Lcd_Cells+15
MOVLW '2'
MOVWF Lcd_Cells+16
MOVLW '.'
MOVWF Lcd_Cells+17
MOVLW '0'
MOVWF Lcd_Cells+18
MOVLW 'M'
MOVWF Lcd_Cells+20
MOVLW 'a'
MOVWF Lcd_Cells+21
MOVLW 'r'
MOVWF Lcd_Cells+22
MOVLW 'c'
MOVWF Lcd_Cells+23
MOVLW 'o'
MOVWF Lcd_Cells+24
MOVLW ' '
MOVWF Lcd_Cells+25
MOVLW 'T'
MOVWF Lcd_Cells+26
MOVLW 'i'
MOVWF Lcd_Cells+27
MOVLW 'n'
MOVWF Lcd_Cells+28
MOVLW 'a'
MOVWF Lcd_Cells+29
MOVLW 'r'
MOVWF Lcd_Cells+30
MOVLW 'i'
MOVWF Lcd_Cells+31
MOVLW ' '
MOVWF Lcd_Cells+32
MOVLW '2'
MOVWF Lcd_Cells+33
MOVLW '6'
MOVWF Lcd_Cells+34
MOVLW '/'
MOVWF Lcd_Cells+35
MOVLW '5'
MOVWF Lcd_Cells+36
MOVLW '/'
MOVWF Lcd_Cells+37
MOVLW '1'
MOVWF Lcd_Cells+38
MOVLW '2'
MOVWF Lcd_Cells+39
CALL LcdRefresh
SLEEP
;*****************************************
;* *
;* Libreria CHRONO *
;* subroutines di ritardo per *
;* 16F628A @ 4 MHz *
;* *
;* by Marco Tinari - Roma 12/11/2006 *
;* *
;*****************************************
;ritardo di 50 microsecondi
;compresa la CALL chiamante
Delay50us: MOVLW 14
Entry1 MOVWF us_counter
Delay50us1 DECFSZ us_counter,1
GOTO Delay50us1
NOP
NOP
NOP
RETURN
;ritardo di 101 microsecondi
;compresa la CALL chiamante
Delay101us: MOVLW 30
GOTO Entry1
;ritardo di 500 microsecondi
;compresa la CALL chiamante
Delay500us: MOVLW 163
GOTO Entry1
;ritardo di 1 millisecondo
;compresa la CALL chiamante
Delay1ms: CALL Delay500us
GOTO Delay500us
;ritardo di 50 millisecondi
;compresa la CALL chiamante
Delay50ms: MOVLW 49
Entry2 MOVWF ms_counter
Delay50ms1 CALL Delay1ms
DECFSZ ms_counter,1
GOTO Delay50ms1
CALL Delay500us
MOVLW 112 ; ritarda altri 347 usec
CALL Entry1
NOP ; ulteriore 1 usec
RETURN
;ritardo di 1 decimo di secondo
;compresa la CALL chiamante
Delay1decs: MOVLW 198
MOVWF ms_counter
CALL Delay50ms
CALL Delay500us
CALL Delay50us
NOP
RETURN
;ritardo di 5 decimi di secondo
;più 2+1us per la CALL chiamante e return
Delay5decs: CALL Delay1decs
CALL Delay1decs
CALL Delay1decs
CALL Delay1decs
CALL Delay1decs
RETURN
;ritardo di 1 secondo
;più 4+2+2us per la CALL chiamante e return
Delay1sec: CALL Delay5decs
GOTO Delay5decs
;*****************************************
;* *
;* subroutines controllo lcd *
;* TS2020 - 1 KS0070B *
;* *
;* by Marco Tinari - Roma 26/05/2012 *
;* *
;*****************************************
;**********************************************************************
; Manda il byte in W al display 4 bit per volta
;**********************************************************************
LcdSendByte: MOVWF Lcd_Temp
BCF PORTB,Lcd_BIT4 ;prepara per i primi 4 bit
BCF PORTB,Lcd_BIT5
BCF PORTB,Lcd_BIT6
BCF PORTB,Lcd_BIT7
BTFSC Lcd_Temp,4
BSF PORTB,Lcd_BIT4
BTFSC Lcd_Temp,5
BSF PORTB,Lcd_BIT5
BTFSC Lcd_Temp,6
BSF PORTB,Lcd_BIT6
BTFSC Lcd_Temp,7
BSF PORTB,Lcd_BIT7
BSF PORTB,Lcd_EN ;toggle di 1 ms su EN
CALL Delay1ms
BCF PORTB,Lcd_EN
CALL Delay1ms
BCF PORTB,Lcd_BIT4 ;prepara per i successivi 4 bit
BCF PORTB,Lcd_BIT5
BCF PORTB,Lcd_BIT6
BCF PORTB,Lcd_BIT7
BTFSC Lcd_Temp,0
BSF PORTB,Lcd_BIT4
BTFSC Lcd_Temp,1
BSF PORTB,Lcd_BIT5
BTFSC Lcd_Temp,2
BSF PORTB,Lcd_BIT6
BTFSC Lcd_Temp,3
BSF PORTB,Lcd_BIT7
LcdHalfSend: BSF PORTB,Lcd_EN ;toggle di 1 ms su EN
CALL Delay1ms
BCF PORTB,Lcd_EN
CALL Delay1ms
RETURN
;**********************************************************************
; Manda un carattere visualizzabile a LCD
;**********************************************************************
LcdSendData: BSF PORTB,Lcd_RS
CALL LcdSendByte
CALL Delay1ms
RETURN
;**********************************************************************
; Manda un comando a LCD
;**********************************************************************
LcdSendCmd: BCF PORTB,Lcd_RS
CALL LcdSendByte
CALL Delay1ms
CALL Delay1ms
RETURN
;**********************************************************************
; Inizializzazione di LCD - controller KS0070B
;**********************************************************************
LcdInit: CALL SelectB1 ; seleziona il Bank 1
BCF TRISB,Lcd_EN ; imposta i giusti pin in output
BCF TRISB,Lcd_RS
BCF TRISB,Lcd_BIT4
BCF TRISB,Lcd_BIT5
BCF TRISB,Lcd_BIT6
BCF TRISB,Lcd_BIT7
CALL SelectB0 ; seleziona il Bank 0
BCF PORTB,Lcd_RS
BCF PORTB,Lcd_EN
CALL Delay50ms ; imposta il display
; FUNCTION SET
BCF PORTB,Lcd_BIT4 ; 0 richiesto
BSF PORTB,Lcd_BIT5 ; 1 richiesto
BCF PORTB,Lcd_BIT6 ; 0 richiesto
BCF PORTB,Lcd_BIT7 ; 0 richiesto
CALL LcdHalfSend
CALL LcdHalfSend ; ripeti
BCF PORTB,Lcd_BIT4 ; non considerato
BCF PORTB,Lcd_BIT5 ; non considerato
BSF PORTB,Lcd_BIT6 ; F=1 5x10 dots
BSF PORTB,Lcd_BIT7 ; N=1 2-line mode
CALL LcdHalfSend
CALL Delay50ms
; DISPLAY ON/OFF CONTROL
BCF PORTB,Lcd_BIT4 ; 0 richiesto
BCF PORTB,Lcd_BIT5 ; 0 richiesto
BCF PORTB,Lcd_BIT6 ; 0 richiesto
BCF PORTB,Lcd_BIT7 ; 0 richiesto
CALL LcdHalfSend
BCF PORTB,Lcd_BIT4 ; B=0 blink off
BCF PORTB,Lcd_BIT5 ; C=0 cursor off
BSF PORTB,Lcd_BIT6 ; D=1 display on
BSF PORTB,Lcd_BIT7 ; 1 richiesto
CALL LcdHalfSend
CALL Delay50ms
; CLEAR DISPLAY
BCF PORTB,Lcd_BIT4 ; 0 richiesto
BCF PORTB,Lcd_BIT5 ; 0 richiesto
BCF PORTB,Lcd_BIT6 ; 0 richiesto
BCF PORTB,Lcd_BIT7 ; 0 richiesto
CALL LcdHalfSend
BSF PORTB,Lcd_BIT4 ; 1 richiesto
BCF PORTB,Lcd_BIT5 ; 0 richiesto
BCF PORTB,Lcd_BIT6 ; 0 richiesto
BCF PORTB,Lcd_BIT7 ; 0 richiesto
CALL LcdHalfSend
CALL Delay50ms
; ENTRY MODE SET
BCF PORTB,Lcd_BIT4 ; 0 richiesto
BCF PORTB,Lcd_BIT5 ; 0 richiesto
BCF PORTB,Lcd_BIT6 ; 0 richiesto
BCF PORTB,Lcd_BIT7 ; 0 richiesto
CALL LcdHalfSend
BCF PORTB,Lcd_BIT4 ; SH=0 entire shift off
BSF PORTB,Lcd_BIT5 ; ID=1 increment mode
BSF PORTB,Lcd_BIT6 ; 1 richiesto
BCF PORTB,Lcd_BIT7 ; 0 richiesto
CALL LcdHalfSend
RETURN
;**********************************************************************
; Pulisce il display ed le celle associate in ram
;**********************************************************************
LcdClear: MOVLW 40 ; considera i 40 caratteri
MOVWF Lcd_Counter
MOVLW Lcd_Cells ; punta la prima cella per LCD
MOVWF FSR
MOVLW 020H ; metti 'spazio' in W
LcdClr1 MOVWF INDF ; pulisci la cella
INCF FSR,1 ; avanza di un carattere
DECFSZ Lcd_Counter,1
GOTO LcdClr1
MOVLW 01H ; manda un Clear Display a LCD
GOTO LcdSendCmd
;**********************************************************************
; Visualizza i caratteri presenti nelle 40 celle Lcd_Cells
;**********************************************************************
LcdRefresh: MOVLW 01H ; manda un Clear Display a LCD
CALL LcdSendCmd
MOVLW 20 ; considera i primi 20 caratteri
MOVWF Lcd_Counter
MOVLW Lcd_Cells ; punta la prima cella per LCD
MOVWF FSR
LcdRefr1: MOVF INDF,0 ; leggi il carattere
CALL LcdSendData
INCF FSR,1 ; avanza di un carattere
DECFSZ Lcd_Counter,1
GOTO LcdRefr1 ; ripeti per il primo blocco
MOVLW 0C0H ; spostati sui secondi 8 chars di LCD
CALL LcdSendCmd
MOVLW 20 ; ripeti per il secondo blocco
MOVWF Lcd_Counter
MOVLW Lcd_Cells+20 ; punta la nona cella per LCD
MOVWF FSR
LcdRefr2: MOVF INDF,0 ; leggi il carattere
CALL LcdSendData
INCF FSR,1 ; avanza di un carattere
DECFSZ Lcd_Counter,1
GOTO LcdRefr2 ; ripeti per il secondo blocco
RETURN
SelectB0: bcf STATUS, RP1 ; seleziona il bank 0
bcf STATUS, RP0
return
SelectB1: bcf STATUS, RP1 ; seleziona il bank 1
bsf STATUS, RP0
return
END