PDA

Επιστροφή στο Forum : lcd 16x2



spas
21-08-05, 20:57
Γεια σας.Εχω βρει αυτον τον κώδικα ο οποίος περνά σειριακά του χαρακτήρες που γράφω σε μία lcd οθόνη 16χ2.Όμως υπάρχει ένα πρόβλημα καθώς δεν τα περνά σωστά.Συγκεκριμένα γράφει πρωτα τους 16 χαρακτήρες της 1ης γραμμής και μετά για 24 πατηματα πλήκτρων δεν γράφει τίποτα.Μετά γράφει τους 16 χαρακτήρες της 2ης γραμμής και τέλος για 24 πατηματα πλήκτρων δεν γράφει τίποτα.Και γίνεται συνέχεια το ίδιο.Ο κώδικας όμως πρέπει να είναι ημιτελής καθώς για τα labels LCD_Line1,LCD_Line2,LCD_Line1w και LCD_Line2w δεν υπάρχουν άλματα για να πάνε εκεί.Μήπως ξέρει κάποιος σε ποια σημεία του κώδικα θα μπούν αυτά τα άλματα; Αυτά και συγγνώμη αν σας κούρασα


LIST p=16F628 ;tell assembler what chip we are using
include "P16F628.inc" ;include the defaults for the chip
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x3D18 ;sets the configuration settings (oscillator type etc.)




cblock 0x20 ;start of general purpose registers
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
templcd ;temp store for 4 bit mode
templcd2
lcdtmp
Xmit_Byte ;holds byte to xmit
Rcv_Byte ;holds received byte
Bit_Cntr ;bit counter for RS232
Delay_Count ;delay loop counter
endc

LCD_PORT Equ PORTA
LCD_TRIS Equ TRISA
LCD_RS Equ 0x04 ;LCD handshake lines
LCD_RW Equ 0x06
LCD_E Equ 0x07
SER_PORT Equ PORTB
SER_TRIS Equ TRISB
SER_IN Equ 0x07
SER_OUT Equ 0x06



org 0x0000

Start movlw 0x07
movwf CMCON ;turn comparators off (make it like a 16F84)

Initialise clrf count
clrf PORTA
clrf PORTB
call SER_INIT ;initialise serial port
call LCD_Init
Loop call Rcv_RS232
call LCD_Char
goto Loop


;Serial routines

SER_INIT
BSF STATUS, RP0 ;select bank 1
BCF SER_TRIS, SER_OUT ;set B6 as an output
BSF SER_TRIS, SER_IN ;set B7 as an input
BCF STATUS, RP0 ;select bank 0
BSF SER_PORT, SER_OUT ;set SER_OUT high
RETURN

XMIT_RS232 MOVWF Xmit_Byte ;move W to Xmit_Byte
MOVLW 0x08 ;set 8 bits out
MOVWF Bit_Cntr
BCF SER_PORT, SER_OUT
CALL Bit_Delay
Ser_Loop RRF Xmit_Byte , f ;send one bit
BTFSS STATUS , C
BCF SER_PORT, SER_OUT
BTFSC STATUS , C
BSF SER_PORT, SER_OUT
CALL Bit_Delay
DECFSZ Bit_Cntr , f ;test if all done
GOTO Ser_Loop
BSF SER_PORT, SER_OUT
CALL Bit_Delay
RETURN

Rcv_RS232 BTFSC SER_PORT, SER_IN ;wait for start bit
GOTO Rcv_RS232
CALL Start_Delay ;do half bit time delay
BTFSC SER_PORT, SER_IN ;check still in start bit
GOTO Rcv_RS232
MOVLW 0x08 ;set up to read 8 bits
MOVWF Bit_Cntr
CLRF Rcv_Byte
Next_RcvBit CALL Bit_Delay
BTFSS SER_PORT, SER_IN
BCF STATUS , C
BTFSC SER_PORT, SER_IN
BSF STATUS , C
RRF Rcv_Byte , f
DECFSZ Bit_Cntr , f ;test if all done
GOTO Next_RcvBit
CALL Bit_Delay
MOVF Rcv_Byte, W
RETURN

Start_Delay MOVLW 0x0C
MOVWF Delay_Count
Start_Wait NOP
DECFSZ Delay_Count , f
GOTO Start_Wait
RETURN

Bit_Delay MOVLW 0x18
MOVWF Delay_Count
Bit_Wait NOP
DECFSZ Delay_Count , f
GOTO Bit_Wait
RETURN




;LCD routines

;Initialise LCD
LCD_Init call LCD_Busy ;wait for LCD to settle

movlw 0x20 ;Set 4 bit mode
call LCD_Cmd

movlw 0x28 ;Set display shift
call LCD_Cmd

movlw 0x06 ;Set display character mode
call LCD_Cmd

movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd ;Set cursor off

call LCD_Clr ;clear display

retlw 0x00

; command set routine
LCD_Cmd movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high

movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call LCD_Busy
retlw 0x00

LCD_CharD addlw 0x30 ;add 0x30 to convert to ASCII
LCD_Char movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high

movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call LCD_Busy
retlw 0x00

LCD_Line1 movlw 0x80 ;move to 1st row, first column
call LCD_Cmd
retlw 0x00

LCD_Line2 movlw 0xc0 ;move to 2nd row, first column
call LCD_Cmd
retlw 0x00

LCD_Line1W addlw 0x80 ;move to 1st row, column W
call LCD_Cmd
retlw 0x00

LCD_Line2W addlw 0xc0 ;move to 2nd row, column W
call LCD_Cmd
retlw 0x00

LCD_CurOn movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00

LCD_CurOff movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00

LCD_Clr movlw 0x01 ;Clear display
call LCD_Cmd
retlw 0x00

Pulse_e bsf LCD_PORT, LCD_E
nop
bcf LCD_PORT, LCD_E
retlw 0x00

LCD_Busy
bsf STATUS, RP0 ;set bank 1
movlw 0x0f ;set Port for input
movwf LCD_TRIS
bcf STATUS, RP0 ;set bank 0
bcf LCD_PORT, LCD_RS ;set LCD for command mode
bsf LCD_PORT, LCD_RW ;setup to read busy flag
bsf LCD_PORT, LCD_E
swapf LCD_PORT, w ;read upper nibble (busy flag)
bcf LCD_PORT, LCD_E
movwf templcd2
bsf LCD_PORT, LCD_E ;dummy read of lower nibble
bcf LCD_PORT, LCD_E
btfsc templcd2, 7 ;check busy flag, high = busy
goto LCD_Busy ;if busy check again
bcf LCD_PORT, LCD_RW
bsf STATUS, RP0 ;set bank 1
movlw 0x00 ;set Port for output
movwf LCD_TRIS
bcf STATUS, RP0 ;set bank 0
return

;end of LCD routines


;Delay routines

Long_Delay
call Delay255
call Delay255
call Delay255
call Delay255
return

Delay255 movlw 0xff ;delay 255 mS
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay10 movlw d'10' ;delay 10mS
goto d0
Delay1 movlw d'1' ;delay 1mS
goto d0
Delay5 movlw 0x05 ;delay 5.000 ms (4 MHz clock)
d0 movwf count1
d1 movlw 0xC7
movwf counta
movlw 0x01
movwf countb
Delay_0 decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0

decfsz count1 ,f
goto d1
retlw 0x00

;end of Delay routines


end

gsmaster
22-08-05, 00:20
Η πραγματικότητα είναι ότι αυτά που εσύ στέλνεις δεν χάνονται κάπου αλλά γράφονται στις μή ορατές θέσης της οθόνης αφού κάθε γραμμή αποτελείται από 40 χαρακτήρες, ενώ μόνο οι 16 πρώτοι εμφανίζονται. Για να εμφανίσεις και τους υπόλοιπους μπορείς να χρήσιμοποιήσεις την εντολή shift display η οποία όμως δεν βλέπω να υπάρχει κάπου στον κώδικα.

Για να πηγαίνει στην δεύτερη γραμμή όταν γεμίσει η πρώτη, πρέπει να μετράει πόσους χαρακτήρες έχει εμφανίσει, για να ξέρει όταν φτάσει το 16 να πάει στην δεύτερη γραμμή. Ο κώδικας που δίνεις παραπάνω, δεν κάνει κάτι τέτοιο, αφού το μόνο που κάνει είναι ότι παίρνει από την σειριακή, να το δίνει στην οθόνη.


Loop call Rcv_RS232 ;Διάβασε από την σειριακή
call LCD_Char ;Εμφάνιστε αυτό που διάβασες στην οθόνη
goto Loop ;Ξανακάνε το ίδιο από την αρχή


Πρέπει να μπεί ένας μετρητής ο οποίος να μετράει κάθε φορά που στέλνεται χαρακτήρας στην οθόνη και όταν φτάσει το 16 να αλλάξει γραμμή...

spas
22-08-05, 01:38
Ευχαριστώ.Η μετατροπή που έκανα στον κώδικα είναι αυτή:


cblock 0x20 ;start of general purpose registers
countlcd
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
templcd ;temp store for 4 bit mode
templcd2
lcdtmp
Xmit_Byte ;holds byte to xmit
Rcv_Byte ;holds received byte
Bit_Cntr ;bit counter for RS232
Delay_Count ;delay loop counter
endc

......

Initialise clrf count
clrf PORTA
clrf PORTB
call SER_INIT ;initialise serial port
call LCD_Init
movlw 0x16
movwf countlcd
Loop call Rcv_RS232
call LCD_Char
decfsz countlcd,f
goto $+2
call lcd_line2
goto Loop
.....

LCD_Line2 movlw 0xc0 ;move to 2nd row, first column
call LCD_Cmd
movlw 0x16
movwf countlcd
retlw 0x00
Επειδή δεν ξέρω πολλά από προγραμματισμό, μπορείς να μου πεις αν είναι σωστά αυτά που έκανα.Επίσης μπορείς να μου πεις καμμιά ιδέα πως να επιστρέψω στην 1η γραμμή ;

gsmaster
22-08-05, 01:59
Σωστότατο είναι, ακριβώς αυτό είχα στο μυαλό μου. ΑΛΛΑ όταν μηδενησει ο countlcd θα ξεκινήσει να παίρνει τιμές απο 255 και θα μειώνεται. όταν ξαναφτάσει πάλι 0 θα ξαναπάει στην αρχή της δεύτερης γραμμής.

Τι προτείνω:


Loop1 call Rcv_RS232 ;diavase apo tin seiriaki
call LCD_Char ;steile stin lcd
decfsz countlcd,f ;meiwse ton countlcd kata 1
goto Loop1 ;an=/=0, ksanasteile stin prwti grammi
call lcd_line2 ;an=0 pigaine stin deyteri grammi
movlw 0x16 ;vale pali to 16 ston countlcd
movwf countlcd ;ston countlcd
goto Loop2 ;kai pigaine sto loop2

Loop2 call Rcv_RS232 ;diavase apo tin seiriaki
call LCD_Char ;steile stin lcd
decfsz countlcd,f ;meiwse ton countlcd kata 1
goto Loop2 ;an=/=0, ksanasteile stin deyteri grammi
call lcd_line1 ;an=0 pigaine stin prwti grammi
movlw 0x16 ;vale pali to 16 ston countlcd
movwf countlcd ;ston countlcd
goto Loop1 ;kai pigaine sto loop1




Κάνεις δύο ίδια loop τα οποία όταν η μία γραμμή γεμίζει σε στέλνει στην άλλη. το loop1 για την πρώτη γραμμή και το loop2 για την δεύτερη γραμμή. όταν ξαναπηγαίνεις στην πρώτη γραμμή αν θές βάζεις και μια εντολή για να καθαρίσεις την οθόνη από το προηγούμενο κείμενο. ;)

ΥΓ κατέβασε και αυτό (http://www.hlektronika.gr/pafiledb/pafiledb.php?action=file&id=33) θα σε βοηθήσει να κατανοήσεις την λειτουργία αυτών των οθονών.

ΥΓ2 καλό θα ήταν αν όλα αυτά που έγραψα παραπάνω δουλέψουν να δοκιμάσεις να το κάνεις να στέλνεις εσύ σε ποιά διεύθυσνη να γράψει τον χαρακτήρα. Αλήθεια απο την πλευρά του pc έφτιαξες κάποιο πρόγραμμα, ή με το κλασσικό hyper terminal?

_ab
26-08-05, 20:29
Αγαπητε μου φιλε που χρησιμοποιεις αυτο το αρχειο σε τι κατασκευη????