PIC, ASM: Problem med kod för LCD-display.
Postat: 28 maj 2009, 21:46:07
Efter den här tråden så gjorde jag om koden helt från början, denna gång i assembler.
Allt är kopplat precis likadant som i förra tråden. Se schema.
De inringade motstånden är bortlödda i debugsyfte. Info om de inritade kondingarna finns i länken högst upp.
Problemet är att displayen verkar initieras korrekt, men jag får inte ut något tecken på den. Displayen är helt tom.
Något av det jag gjort i debug-syfte (inte listat i någon speciell ordning) :
* Ökat delay-tiderna mellan varje instruktion till displayen.
* Jämfört med liknande kod, från t.ex Sodjan. Länk.
* Testat samma LCD-initierings-koder som i Sodjans kod.
* Använt MPLAB SIM och kontrollerat så att rätt data hamnar på porten (PORTB) vid rätt tillfälle och att övrig kod stämmer.
* Kollat delay-rutinerna med oscilloskop och frekvensräknare för att dubbelkolla att delay-tiderna stämmer.
* Lusläst och jämfört med datablad för displayen och den här PDF'en.
* Suttit med MPLAB SIM och matat in datan i en LCD-simulator.
* Bytt ut displayen mot en rad lysdioder för att dubbelkolla att rätt bit hamnar på rätt ställe.
* Tagit många pauser för att få ny energi och tänka bättre.
För att minska risken för copy/paste-fel så klistrar jag in hela koden som den ser ut just nu:
(Alla delay_5ms-rader är bara i debugsyfte. Jag har varierat dem ganska friskt.)
Hoppas ni inte har ett allt för slitet scrollhjul. Ni lär behöva det nu!
Varför blir tabbarna så skeva när man klistrar in här...
Ni behöver förstås inte lusläsa allt, men kika gärna på LCD-initieringen om ni har en stund över.
Allt är kopplat precis likadant som i förra tråden. Se schema.
De inringade motstånden är bortlödda i debugsyfte. Info om de inritade kondingarna finns i länken högst upp.
Problemet är att displayen verkar initieras korrekt, men jag får inte ut något tecken på den. Displayen är helt tom.
Något av det jag gjort i debug-syfte (inte listat i någon speciell ordning) :
* Ökat delay-tiderna mellan varje instruktion till displayen.
* Jämfört med liknande kod, från t.ex Sodjan. Länk.
* Testat samma LCD-initierings-koder som i Sodjans kod.
* Använt MPLAB SIM och kontrollerat så att rätt data hamnar på porten (PORTB) vid rätt tillfälle och att övrig kod stämmer.
* Kollat delay-rutinerna med oscilloskop och frekvensräknare för att dubbelkolla att delay-tiderna stämmer.
* Lusläst och jämfört med datablad för displayen och den här PDF'en.
* Suttit med MPLAB SIM och matat in datan i en LCD-simulator.
* Bytt ut displayen mot en rad lysdioder för att dubbelkolla att rätt bit hamnar på rätt ställe.
* Tagit många pauser för att få ny energi och tänka bättre.
För att minska risken för copy/paste-fel så klistrar jag in hela koden som den ser ut just nu:
(Alla delay_5ms-rader är bara i debugsyfte. Jag har varierat dem ganska friskt.)
Hoppas ni inte har ett allt för slitet scrollhjul. Ni lär behöva det nu!

Kod: Markera allt
;****************************************************
Processor PIC18F1320
#include <p18f1320.inc>
;****************************************************
; UV-box - Svart/Silver-modellen.
;
; Relä RB6 Utgång
; Encoder 0 RA4 Ingång
; Encoder 1 RB4 Ingång
; Knapp (5/1) RA3 Ingång
; Knapp (Start/stopp) RB5 Ingång
; LCD RS RA0 Utgång
; LCD E RA1 Utgång
; LCD RW RA2 Utgång
; LCD D4 RB0 Utgång
; LCD D5 RB1 Utgång
; LCD D6 RB2 Utgång
; LCD D7 RB3 Utgång
;
; Använder HSPLL med en kristall på 10MHz = 40MHz.
; LCD med HD44780-kontroller i 4bit-mode.
;
;****************************************************
CONFIG OSC = HSPLL
CONFIG PWRT = ON, BOR = OFF, WDT = OFF, MCLRE= ON
CONFIG STVR = OFF, LVP = OFF, DEBUG = OFF, CP0 = OFF
CONFIG CP1 = OFF, CPB =OFF, CPD = OFF, WRT0 = OFF
CONFIG WRT1 = OFF, WRTB = OFF, WRTC = OFF, WRTD = OFF
CONFIG EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF
errorlevel -302
;****************************************************
; Definiera diverse namn...
; LCD-Display
#define LCD_RS PORTA, 0
#define LCD_E PORTA, 1
#define LCD_RW PORTA, 2
#define LCD_PORT PORTB ; B3 (d7), B2 (d6), B1 (d5), B0 (d4)
; Encoder, knappar och relä
#define encoder_a PORTA, 4
#define encoder_b PORTB, 4
#define knapp_51 PORTA, 3
#define knapp_start PORTB, 5
#define rela PORTB, 6
;****************************************************
encoder_vars udata_acs
knapp res 1 ; Vilken knapp som tryckts ner
; det blir mer här senare..
;****************************************************
Boot CODE h'0000'
goto start
;****************************************************
Int_vect CODE h'0008'
;goto isr_rutin
retfie
;****************************************************
; MACRO
; kommer senare...
;****************************************************
Main CODE
Start
;Generell setup
; Oscillator
bcf OSCCON, IDLEN ;CPU core clocked in Run modes, not in Sleep
bcf OSCCON, SCS1 ;Primary oscillator
bcf OSCCON, SCS0 ;Primary oscillator
; I/O
movlw b'11111000' ;Knapp_51, Encoder_a, MCLR, OSC2, OSC1 som ingångar. Resten utgångar.
movwf TRISA
movlw b'00110000' ;Encoder_b, Knapp_start som ingångar. Resten utgångar.
movwf TRISB
clrf PORTA ;Städat och fint...
clrf PORTB
; Interrupt
bcf INTCON, GIE ;Global interrupt enable bit. <-- OFF för tillfället.
bcf INTCON, PEIE ;Peripheral interrupt enable bit. <-- OFF för tillfället.
bcf INTCON, TMR0IE ;TMR0 Overflow interrupt
bcf INTCON, INT0IE ;INT0 External interrupt
bcf INTCON, RBIE ;RB Port change interrupt <-- OFF för tillfället.
bcf INTCON, TMR0IF ;TMR0 overflow interrupt flag.
bcf INTCON, INT0IF ;INT0 external interrupt flag.
bcf INTCON, RBIF ;RB port change interrupt flag.
setf INTCON2 ;Inga PortB-pullups, external interrupt on rising edge.
bcf INTCON3, INT2IE ;External INT2 interrupt enable bit
bcf INTCON3, INT1IE ;External INT1 interrupt enable bit
bcf INTCON3, INT2IF ;INT2 external interrupt flag
bcf INTCON3, INT1IF ;INT1 external interrupt flag
bcf PIR1, TMR1IF ;TMR1 overflow interrupt flag
bcf PIR2, TMR3IF ;TMR3 overflow interrupt flag
bcf PIE1, ADIE ;A/D converter interrupt disabled
bcf PIE1, RCIE ;EUSART recieve interrupt disabled
bcf PIE1, TXIE ;EUSART transmit interrupt disabled
bcf PIE1, CCP1IE ;CCP1 interrupt disabled
bcf PIE1, TMR2IE ;TMR2 to PR2 match interrupt disabled
bcf PIE1, TMR1IE ;TMR1 overflow interrupt disabled
bcf PIE2, OSCFIE ;Oscillator fail interrupt disabled
bcf PIE2, EEIE ;Data EEPROM/Flash-write interrupt disabled
bcf PIE2, LVDIE ;Low-voltage detect interrupt disabled
bcf PIE2, TMR3IE ;TMR3 overflow interrupt disabled
bcf RCON, IPEN ;Priority levels on interrupt disabled
; Övrigt
bcf WDTCON, SWDTEN ;WDT off
;****************************************************
;****************************************************
;****************************************************
;Övriga grejjer, dvs anrop till sub-rutiner/makron osv.
call sub_lcd_init ;Initiera displayen.
call sub_lcd_test ;Skriver en test-sträng på displayen.
;
loop goto loop ;Om och om igen...
;
;****************************************************
;****************************************************
;****************************************************
;Sub-rutiner
LCD_VARS UDATA_ACS
lcd_cmd_4 RES 1
lcd_cmd RES 1
lcd_data RES 1
lcd_porttest RES 1
LCD_CODE CODE
sub_lcd_test
movlw b'01001000' ;Bokstaven "H".
call sub_lcd_data
return
sub_lcd_test2 ;Bokstaven "H", men den här går direkt till PORTB.
bsf lcd_rs
call delay_5ms
call delay_5ms
bcf PORTB, 3
bsf PORTB, 2
bcf PORTB, 1
bcf PORTB, 0
call sub_lcd_e
call delay_5ms
call delay_5ms
bsf PORTB, 3
bcf PORTB, 2
bcf PORTB, 1
bcf PORTB, 0
call sub_lcd_e
call delay_5ms
call delay_5ms
return
sub_lcd_init
call delay_1s ;1s paus för att ge LCD'n lite tid att komma igång.
bcf lcd_rw ;RW satt i skriv-läge.
bcf lcd_e ;E-pinnen nollad.
bcf lcd_rs ;RS satt i instruktions-läge
; Init-koder
movlw b'00110000'
call sub_lcd_cmd_4
movlw b'00110000'
call sub_lcd_cmd_4
movlw b'00110000'
call sub_lcd_cmd_4
movlw b'00100000'
call sub_lcd_cmd_4
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
;Härifrån skickas högsta nibblen först, därefter den lägsta.
movlw b'00101000' ;Initierar 2 rader b'00101000'
call sub_lcd_cmd
movlw b'00010100' ;Flytta markör åt höger vid tecken, b'00010100'
call sub_lcd_cmd
movlw b'00001110' ;Display on, Markör off, Tecken vid markör blinkar inte. b'00001100'
call sub_lcd_cmd
movlw b'00000110' ;Entry: Öka teckenposition. b'00000110'
call sub_lcd_cmd
movlw b'00000010' ;Display och markör: Home-position. b'00000010'
call sub_lcd_cmd
movlw b'00000001' ;Rensa displayen. b'00000001'
call sub_lcd_cmd
return
sub_lcd_e
bsf lcd_e
call delay_5ms
bcf lcd_e
call delay_5ms
return
sub_lcd_cmd_4
movwf lcd_cmd_4 ;Datan finns i lcd_cmd_4. (t.ex 01100000)
bcf lcd_rs ;Kommando-läge.
swapf lcd_cmd_4, 1 ;Byt plats på bit 7-4 med bit 3-0. Resultatet (t.ex 00000110) i lcd_cmd_4.
bcf lcd_cmd_4, 4
bcf lcd_cmd_4, 5
bcf lcd_cmd_4, 6
bcf lcd_cmd_4, 7
movff lcd_cmd_4, lcd_port ;Placera (t.ex 00001011) i LCD-porten. (B3, B2, B1, B0. Övriga ignoreras)
call sub_lcd_e ;Flippa med e-pinnen.
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
return
sub_lcd_cmd
movwf lcd_cmd ;Datan finns i lcd_cmd. (t.ex 01101011)
bcf lcd_rs ;Kommando-läge.
swapf lcd_cmd, 1 ;Byt plats på bit 7-4 med bit 3-0. Resultatet (t.ex 10110110) i lcd_cmd.
movlw b'00001111' ;Markera 4 lägsta (tidigare högsta) bitarna.
andwf lcd_cmd, 0 ;Kombinera markeringen med datan i lcd_cmd. Resultatet (t.ex 00000110) i W.
movwf lcd_port ;Placera (t.ex 00000110) i LCD-porten. (B3, B2, B1, B0)
call sub_lcd_e ;Flippa med e-pinnen.
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
swapf lcd_cmd, 1 ;Byt plats igen. Resultatet (t.ex 01101011) i lcd_cmd.
bcf lcd_cmd, 4
bcf lcd_cmd, 5
bcf lcd_cmd, 6
bcf lcd_cmd, 7
movff lcd_cmd, lcd_port ;Placera (t.ex 00001011) i LCD-porten. (B3, B2, B1, B0)
call sub_lcd_e ;Flippa med e-pinnen.
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
return
sub_lcd_data
movwf lcd_data ;Datan finns i lcd_data. (t.ex 01101011)
bsf lcd_rs ;Data-läge. (För att skriva tecken på displayen.)
swapf lcd_data, 1 ;Byt plats på bit 7-4 med bit 3-0. Resultatet (t.ex 10110110) i lcd_data.
movlw b'00001111' ;Markera 4 lägsta (tidigare högsta) bitarna.
andwf lcd_data, 0 ;Kombinera markeringen med datan i lcd_data. Resultatet (t.ex 00000110) i W.
movwf lcd_port ;Placera (t.ex 00000110) i LCD-porten. (B3, B2, B1, B0)
call sub_lcd_e ;Flippa med e-pinnen.
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
swapf lcd_data, 1 ;Byt plats igen. Resultatet (t.ex 01101011) i lcd_cmd.
bcf lcd_data, 4
bcf lcd_data, 5
bcf lcd_data, 6
bcf lcd_data, 7
movff lcd_data, lcd_port ;Placera (t.ex 00001011) i LCD-porten. (B3, B2, B1, B0)
call sub_lcd_e ;Flippa med e-pinnen.
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
call delay_5ms
return
;****************************************************
;Delay-rutiner
DLY_VARS UDATA_ACS
d1 RES 1
d2 RES 1
d3 RES 1
DLY_CODE CODE
;Delay 1s (1,00056s)
Delay_1s
movlw 0x5A
movwf d1
movlw 0xCD
movwf d2
movlw 0x16
movwf d3
Delay_1s_0
decfsz d1, f
goto Delay_1s_1
decfsz d2, f
Delay_1s_1
goto Delay_1s_2
decfsz d3, f
Delay_1s_2
goto Delay_1s_0
nop
return
;Delay 5ms. (5,0003ms)
Delay_5ms
movlw 0x07
movwf d1
movlw 0x28
movwf d2
Delay_5ms_0
decfsz d1, f
goto Delay_5ms_1
decfsz d2, f
Delay_5ms_1
goto Delay_5ms_0
nop
nop
return
;Delay 1us.
Delay_1us
nop
nop
nop
nop
nop
nop
nop
nop
return
;****************************************************
end

Ni behöver förstås inte lusläsa allt, men kika gärna på LCD-initieringen om ni har en stund över.
