logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

LCD, assembler i 89s51. Dlaczego kod do obsługi LCD nie działa?

Raflles 03 Sie 2006 15:45 2308 2
  • #1 2876713
    Raflles
    Poziom 14  
    Posty: 93
    Pomógł: 4
    Witam !! Wiem, że temat ten był już niejednokrotnie wałkowany tu na forum, ale ja już mam dosyć, 3 dni siedzenia nad jednym i tym samym trochę męczy i zniechęca. Poniżej zamieściłem kod mojego programu obsługi LCD i prosiłbym, aby ktoś powiedział mi dlaczego on nie chce działać. Inicjalizację robiłem na podstawie algorytmu z książki "Mikrokontrolery 8051 w praktyce" dla 4 - bitowej magistrali.

    
    ;Obsluga wyswietlacza
    
    Data_LCD EQU P2
    EN EQU P2.3
    RW EQU P2.2
    RS EQU P2.1
    LED EQU P1.0
    
    lcall LCD_INIT
    lcall LCD_CLR
    
    mov A,#'X'
    lcall WYSW_ZNAK
    
    Blink:
    
    cpl LED
    loop2:
    djnz R5,$
    djnz R6,loop2
    
    ljmp blink
    
    WYSW_ZNAK:
    
    setb RS
    clr RW
    lcall LCD_ZAPIS
    lcall Readbusy
    
    ret
    
    LCD_ZAPIS:
    
    push ACC
    orl Data_LCD,#0F0h
    orl A,#0Fh
    anl Data_LCD,A
    setb En
    mov R3,#5d
    lcall Delay_ms
    clr En
    
    pop ACC
    swap A 
    orl Data_LCD,#0F0h
    orl A,#0Fh
    anl Data_LCD,A
    setb En
    mov R3,#5d
    lcall Delay_ms
    clr En
    
    ret
    
    LCD_CLR:
    
    clr RS
    clr RW
    setb En
    
    orl Data_LCD,#0F0h
    anl Data_LCD,#0Fh
    
    clr En
    mov R3,#5d
    lcall Delay_ms
    setb En
    
    lcall Readbusy
    
    ret
    
    LCD_INIT:
    
    clr RS
    clr RW
    setb En
    
    mov R3,#50d             ;czeka 50 ms
    lcall Delay_ms          ;
    
    anl Data_LCD,#3Fh       ;wpisuje do portu 3Fh
    clr En                  ;zapisuje wartosc 3 do wyswietlacza (8-bit)
    mov R3,#5d              ;czeka 5 ms
    lcall Delay_ms          ;
    setb En                 
    mov R3,#10d             ;czeka 10 ms
    lcall Delay_ms
    clr En                  ;zapisuje 3 do wyswietlacza (8-bit)
    mov R3,#5d              ;czeka 5 ms
    lcall Delay_ms          
    setb En                 
    mov R3,#1d              ;czeka 1 ms
    lcall Delay_ms
    clr En                  ;zapisuje 3 do wyswietlacza (8-bit)
    mov R3,#5d
    lcall Delay_ms
    
    setb En
    clr RS
    clr RW
    
    orl Data_LCD,#0F0h
    anl Data_LCD,#2Fh
    
    clr En                  ;wpisanie do LCD 2 (4-bit)
    mov R3,#5d
    lcall Delay_ms
    setb En
    
    lcall Readbusy
    
    clr En                  ;Function set (4-bit) 
    mov R3,#5d              ;
    lcall Delay_ms          ;
    setb En                 ;
    mov R3,#5d              ;
    lcall Delay_ms          ;
    orl Data_LCD,#0F0h      ;Function set N=1-dwie linie
    anl Data_LCD,#8Fh       ;F=0-znaki 5x7 punktow
    
    clr En                  ;wpisanie do LCD
    mov R3,#5d
    lcall Delay_ms
    setb En
    
    lcall Readbusy 
    
    orl Data_LCD,#0F0h      ;Display ON/OFF
    anl Data_LCD,#0Fh       ;
    
    clr En                  ;wpisanie do LCD
    mov R3,#5d
    lcall Delay_ms
    setb En
    
    lcall Readbusy
    
    orl Data_LCD,#0F0h      ;Display ON/OFF
    anl Data_LCD,#8Fh       ;
    
    clr En                  ;wpisanie do LCD
    mov R3,#5d
    lcall Delay_ms
    setb En
    
    lcall Readbusy
    
    orl Data_LCD,#0F0h      ;
    anl Data_LCD,#0Fh       ;
    
    clr En                  ;wpisanie do LCD
    mov R3,#5d
    lcall Delay_ms
    setb En
    
    lcall Readbusy
    
    orl Data_LCD,#0F0h      ;
    anl Data_LCD,#1Fh       ;
    
    clr En                  ;wpisanie do LCD
    mov R3,#5d
    lcall Delay_ms
    setb En
    
    lcall Readbusy
    
    orl Data_LCD,#0F0h      ;Entry mode set
    anl Data_LCD,#0Fh       ;
    
    clr En                  ;wpisanie do LCD
    mov R3,#5d
    lcall Delay_ms
    setb En
    
    lcall Readbusy
    
    orl Data_LCD,#0F0h
    anl Data_LCD,#6Fh
    
    clr En                  ;wpisanie do LCD
    mov R3,#5d
    lcall Delay_ms
    setb En
    
    lcall Readbusy
    
    ret
    
    ReadBusy:
    
    clr RS
    setb RW
    orl Data_LCD,#0F0h
    Busy:
    setb En
    mov A,Data_LCD
    clr En
    JB ACC.7,Busy
    clr RW
    
    ret
    
    Delay_ms:
    
    mov R1,#45d
    mov R2,#10d
    Loop:
    DJNZ R1,$;trwa 0,0001 sekundy przy zegarze 11,0592MHz
    DJNZ R2,loop; calosc trwa w przyblizeniu 1 ms
    DJNZ R3,loop; w zaleznosci od zawartosci rejestru R3
    
    ret
    
    end
  • #2 2876755
    Zaquadnik
    Poziom 27  
    Posty: 998
    Pomógł: 103
    Ocena: 25
    Jak wysyłasz jakąkolwiek daną do LCD w trybie 4-ro bitowym, to musisz napierw wysłać starszy półbajt, potem młodszy. Zrób tak:
    
    LCD_ZAPIS:
    
    swap ACC
    push ACC
    orl Data_LCD,#0F0h
    orl A,#0Fh
    anl Data_LCD,A
    setb En
    mov R3,#5d
    lcall Delay_ms
    clr En
    
    pop ACC
    swap A
    orl Data_LCD,#0F0h
    orl A,#0Fh
    anl Data_LCD,A
    setb En
    mov R3,#5d
    lcall Delay_ms
    clr En
    
    ret 
    


    Co do samej inicjalizacji możesz spojrzeć na to, co ja robiłem, z tym, że ja nie czytam busy flag.
    
    RS equ P1.2
    E equ P1.3
    DB4 equ P1.4
    DB5 equ P1.5
    DB6 equ P1.6
    DB7 equ P1.7
    
    LCDinit:
    	mov A,#3Ch
    	lcall Pauza
    	
    	mov P1,#00h
    	clr RS
    	clr E
    	orl P1,#30h
    	setb E
    	clr E
    	mov A,#14h
    	lcall Pauza
    	
    	anl P1,#0Fh
    	orl P1,#30h
    	setb E
    	clr E
    	mov A,#01h
    	lcall Pauza
    		
    	anl P1,#0Fh
    	orl P1,#30h
    	setb E
    	clr E
    	mov A,#01h
    	lcall Pauza
    
    	anl P1,#0Fh
    	orl P1,#20h
    	setb E
    	clr E
    	mov A,#01h
    	lcall Pauza
    	
    	anl P1,#0Fh
    	orl P1,#20h
    	setb E
    	clr E
    	anl P1,#0Fh
    	orl P1,#80h
    	setb E
    	clr E
    	mov A,#01h
    	lcall Pauza
    
    	anl P1,#0Fh
    	orl P1,#00h
    	setb E
    	clr E
    	anl P1,#0Fh
    	orl P1,#60h
    	setb E
    	clr E
    	mov A,#01h
    	lcall Pauza
    	
    	anl P1,#0Fh
    	orl P1,#00h
    	setb E
    	clr E
    	anl P1,#0Fh
    	orl P1,#0E0h
    	setb E
    	clr E
    	mov A,#01h
    	lcall Pauza
    	
    	anl P1,#0Fh
    	orl P1,#00h
    	setb E
    	clr E
    	anl P1,#0Fh
    	orl P1,#30h
    	setb E
    	clr E
    	mov A,#01h
    	lcall Pauza
    
    	ret
    			
    Pauza:	
      Petla:
      	mov B,#07Bh	;2 cykle
      	djnz B,$	;2 cykle
      	djnz ACC,Petla	;2 cykle
      	ret
    
    


    Pozdrawiam :)
  • #3 2907262
    Raflles
    Poziom 14  
    Posty: 93
    Pomógł: 4
    Witam !!

    Problem rozwiązany. Powodem była między innymi zła kolejność ustawiania sygnałów sterujących wyświetlacza. Poniżej zamieszczam działający program. Temat zamykam.

    
    ;Obsluga wyswietlacza
    
    Data_LCD EQU P2
    EN EQU P2.3
    RW EQU P2.2
    RS EQU P2.1
    LED EQU P1.0
    
    lcall LCD_INIT
    lcall LCD_ON
    
    mov R5,#13d
    clr A
    WYSW_NAPIS:
    lcall Znak
    lcall WYSW_ZNAK
    lcall Readbusy
    djnz R5,WYSW_NAPIS
    
    Blink:
    
    cpl LED
    loop2:
    djnz R5,$
    djnz R6,loop2
    
    ljmp blink
    
    ZNAK:
    inc A
    movc A,@A+PC
    ret
    DB 'Mikroprocesor'
    
    
    WYSW_ZNAK:
    
    setb RS
    clr RW
    lcall LCD_ZAPIS
    
    ret
    
    LCD_ODCZYT:
    
    orl Data_LCD,#0F0h
    setb En
    mov A,Data_LCD
    clr En
    anl A,#0F0h
    push ACC
    setb En
    mov A,Data_LCD
    clr En
    anl A,#0F0h
    swap A
    mov R7,A
    pop ACC
    orl A,R7
    
    ret
    
    LCD_ZAPIS:
    
    push ACC
    orl Data_LCD,#0F0h
    orl A,#0Fh
    anl Data_LCD,A
    setb En
    clr En
    
    pop ACC
    swap A 
    orl Data_LCD,#0F0h
    orl A,#0Fh
    anl Data_LCD,A
    setb En
    clr En
    
    ret
    
    LCD_ON:
    
    clr RS
    clr RW
    
    orl Data_LCD,#0F0h
    anl Data_LCD,#0Fh
    
    setb En
    clr En
    lcall Readbusy
    orl Data_LCD,#0F0h
    anl Data_LCD,#0FFh
    setb En
    clr En
    lcall Readbusy
    
    ret
    
    LCD_INIT:
    
    clr RS
    clr RW
    
    mov R3,#10d             ;czeka 50 ms
    lcall Delay_ms          ;
    
    anl Data_LCD,#3Fh       ;wpisuje do portu 3Fh
    setb En
    clr En                  ;zapisuje wartosc 3 do wyswietlacza (8-bit)
    mov R3,#10d              ;czeka 5 ms
    lcall Delay_ms          ;
    setb En                 
    clr En                  ;zapisuje 3 do wyswietlacza (8-bit)
    mov R3,#5d              ;czeka 5 ms
    lcall Delay_ms          
    setb En                 
    clr En                  ;zapisuje 3 do wyswietlacza (8-bit)
    mov R3,#1d
    lcall Delay_ms
    
    
    clr RS
    clr RW
    
    orl Data_LCD,#0F0h
    anl Data_LCD,#2Fh
    
    setb En
    clr En                  ;wpisanie do LCD 2 (4-bit)
    lcall Readbusy
    setb En
    clr En                  ;Function set (4-bit) 
    lcall Readbusy
    
    orl Data_LCD,#0F0h      ;Function set N=1-dwie linie
    anl Data_LCD,#8Fh       ;F=0-znaki 5x7 punktow
    
    
    setb En                 ;        
    clr En                  ;wpisanie do LCD
    lcall Readbusy
    
    orl Data_LCD,#0F0h      ;Display ON/OFF
    anl Data_LCD,#0Fh       ;
    setb En
    clr En                  ;wpisanie do LCD
    lcall Readbusy
    
    orl Data_LCD,#0F0h      ;Display ON/OFF
    anl Data_LCD,#8Fh       ;
    setb En
    clr En                  ;wpisanie do LCD
    lcall Readbusy
    
    orl Data_LCD,#0F0h      ;
    anl Data_LCD,#0Fh       ;
    
    setb En
    clr En                  ;wpisanie do LCD
    lcall Readbusy
    
    orl Data_LCD,#0F0h      ;
    anl Data_LCD,#1Fh       ;
    
    setb En
    clr En                  ;wpisanie do LCD
    lcall Readbusy
    
    
    orl Data_LCD,#0F0h      ;Entry mode set
    anl Data_LCD,#0Fh       ;
    setb En
    clr En                  ;wpisanie do LCD
    lcall Readbusy
    
    
    orl Data_LCD,#0F0h
    anl Data_LCD,#6Fh
    setb En
    clr En                  ;wpisanie do LCD
    lcall Readbusy
    
    ret
    
    ReadBusy:
    
    clr RS
    setb RW
    lcall LCD_ODCZYT
    jb ACC.7,Readbusy
    clr RW
    
    ret
    
    Delay_ms:
    
    mov R1,#45d
    mov R2,#10d
    Loop:
    DJNZ R1,$;trwa 0,0001 sekundy przy zegarze 11,0592MHz
    DJNZ R2,loop; calosc trwa w przyblizeniu 1 ms
    DJNZ R3,loop; w zaleznosci od zawartosci rejestru R3
    
    ret
    
    end
    
    


    PS. Fragment programu pod etykietą Blink jest po to, żeby było wiadomo że wszystkie procedury związane z wyświetlaczem zostały wykonane. Polecam ten sposób sprawdzania programu, bo może się wyświetlić napis, ale procesor może stanąć w którymś miejscu.

    Pozdrawiam !! [/code]
REKLAMA