Sida 1 av 1
LCD Probelm Med Microchip C18
Postat: 5 juni 2010, 08:41:40
av Jörgen H
Hej har problem med min LCD funtion.
Jag försöker med en MikroC liknande funktion
"lcd_out(Rad,Position,"TEXT")"
Rad 1,2,3 fungerar som dom ska,
men skriver jag "123456789"
till rad 4 ser det ut så här.
------------------------
| |
|56789 |
| 4|
|123 |
------------------------
Skriver 123 på rad 4 hoppar till rad 3 och fortsätter,
Varför??
Skriver jag utan att flytta cursor
så fungerar hela LCDn.
Annväner PIC 18F4550 och 4 raders LCD Från Kjell.com
Borde kanske nämna att jag inte är någon expert
har programmerat PIC i 1 år som hobby.
Så här ser min LCD kod ut:
Kod: Markera allt
#define LCD_RS LATAbits.LATA5
#define LCD_EN LATAbits.LATA4
#define LCD_D7 LATAbits.LATA3
#define LCD_D6 LATAbits.LATA2
#define LCD_D5 LATAbits.LATA1
#define LCD_D4 LATAbits.LATA0
void LCD_STROBE(void){
LCD_EN = 1;
Delay10TCYx(1); // 5uS
LCD_EN = 0;
}
void lcd_write(unsigned char c){
LCD_D4 = ( ( c >> 4 ) & 0x01 );
LCD_D5 = ( ( c >> 5 ) & 0x01 );
LCD_D6 = ( ( c >> 6 ) & 0x01 );
LCD_D7 = ( ( c >> 7 ) & 0x01 );
Delay100TCYx(1); // 54uS
LCD_STROBE();
LCD_D4 = ( c & 0x01 );
LCD_D5 = ( ( c >> 1 ) & 0x01 );
LCD_D6 = ( ( c >> 2 ) & 0x01 );
LCD_D7 = ( ( c >> 3 ) & 0x01 );
Delay100TCYx(1); // 54uS
LCD_STROBE();
}
void lcd_out(unsigned char r,unsigned char p,const rom char *f){
LCD_RS = 0;
switch(r){
case 1:lcd_write(0x80+p);break; // Rad 1 + Position
case 2:lcd_write(0xA8+p);break; // Rad 2 + Position
case 3:lcd_write(0x94+p);break; // Rad 3 + Position
case 4:lcd_write(0xBC+p);break; // Rad 4 + Position
default: break;
}
LCD_RS = 1;
while(*f)lcd_write(*f++);
}
void lcd_clear(void){
LCD_RS = 0;
lcd_write(0x01);
Delay100TCYx(40); // 2ms
}
void LCD_Init(void){
LCD_RS = 0;
LCD_EN = 0;
Delay1KTCYx(30); // 15mS
LCD_D4 = 1;
LCD_D5 = 1;
LCD_D6 = 0;
LCD_D7 = 0;
LCD_STROBE();
Delay100TCYx(100); // 5mS
LCD_STROBE();
Delay100TCYx(10); // 0,5mS
LCD_STROBE();
Delay100TCYx(10); // 0,5mS
LCD_D4 = 0;
LCD_D5 = 1;
LCD_D6 = 0;
LCD_D7 = 0;
LCD_STROBE();
lcd_write(0x28); // Function set: (4Bit Mode,Display Lines=1,Character Font=0)
lcd_write(0x0C); // Display on/off control: (Display On, Cursor OFF, Cursor Blink OFF)
lcd_clear(); // Clear screen
lcd_write(0x06); // Entry Mode set:(Cursor moves to the right)
}
//****************************************************************************************
void main(void){
PIC_Init();
LCD_Init();
while(1==1){
lcd_clear();
Delay10KTCYx(200);
lcd_out(4,0,"123456789");
Delay10KTCYx(200);
}
}
Är det något galet med koden??
Tack för ett bra forum!!
Re: LCD Probelm Med Microchip C18
Postat: 5 juni 2010, 09:34:01
av bos
Min erfarenhet av LCD i 4-bitsläge är att det ibland inte är 100% säkert att LCD:n blir initialiserad korrekt. Lösningen jag använt är att skicka samma initialiseringskommando flera gånger i rad för att säkerställa att den hamnar i 4-bitläge.
Jag har inget datablad till hands och orkar inte googla åt dig, men jag är inte säker på vad din "manuella" skrivning före lcd_write(0x28); gör i slutet på koden. Om 0x28 är din initialiseringssträng som kommentaren säger så upprepa den raden 4-5 gånger och testa om det hjälper.
Re: LCD Probelm Med Microchip C18
Postat: 5 juni 2010, 10:41:38
av Jörgen H
bos
Har testat ditt förslag utan resultat .
Initiering enligt Wikin här på forumet.
Här är det datablad jag har hittat:
http://www.datasheetpro.com/572146_down ... sheet.html
Får testa mer i kväll när jag har tid!
Tack för snabba svar
Re: LCD Probelm Med Microchip C18
Postat: 5 juni 2010, 10:45:56
av Porto
Angående problem med 4-bitarsläge:
Vid 4-bitarsläge så måste man först initiera den som 8-bitars TVÅ gånger. Orsaken är den att om man startar om programmet så finns risken att displayen dels är i 4-bitarsläge, dels att den har hamnat i osynk på grund av att man startade om mitt i en överföring där bara de första 4-bitarna är skickade. Kommandot för 8-bitarsläge är likadant i både 4/8-bitarsläget, enda skillnaden är att om displayen är för stunden i 4-bitarsläge så väntar den på att den andra delen av överföringen skall komma. Därav behöver man initiera den två gånger som 8-bitars innan man byter till 4-bitar.
Re: LCD Probelm Med Microchip C18
Postat: 5 juni 2010, 14:05:11
av sodjan
Eftersom siffrorna faktiskt kommer ut på LCD'n så tror jag inte
att det är strul med 8/4 bitars mode. Snarare att du har strulat
till adresseringen. Eller timing problem. Eller något annat...

Det första jag skulle göra är att lägga in en rejäl delay (flera sekunder)
mellan varje skrivning till LCD'n. Dels så ser du om det är timing problem, dels
så kan du faktiskt hinna med att mäta (t.ex med ett oscilloskop) på signalerna.
Men för övrigt så är det väl bara att felsöka, eller hur ?

Det första är t.e att hårdkoda det du tror att du gör mot LCD'n och
se om *det* fungerar. Om det *gör* det, så har du fel i dina rutiner.
Om det *inte* fungerar så är det fel i din förståelse av hur LCD'n fungerar.
Jag tycker att din "lcd_write" ser lite onödigt stökig ut. Jag hade kört 4-bitars
mode med SWAPF och ANDF/ORF (vilket det nu blir) mot LATA istället
för de där 4 shiften.
Vad gör "c >> 4" ? Shiftar 4 steg ?
I så fall blir det väl 28 SHIFT och 7 AND operationer för varje anrop av "lcd_write" (?).
Re: LCD Probelm Med Microchip C18
Postat: 5 juni 2010, 16:51:24
av bos
> Vad gör "c >> 4" ? Shiftar 4 steg ?
Ja.
Håller helt med sodjan om att lcd_write() är onödigt bökig och ett rent slöseri med instruktioner, men om målet är att "få det att funka" så duger den förstås.
Re: LCD Probelm Med Microchip C18
Postat: 5 juni 2010, 23:24:32
av sodjan
> men om målet är att "få det att funka" så duger den förstås.
Right. Men nu så fungerar det ju inte. Och då så försvårar den
sannolikt felsökningen som den ser ut nu. Hur som helst med det,
det som behövs är enbart gammal hederlig felsökning, inget annat...

Re: LCD Probelm Med Microchip C18
Postat: 6 juni 2010, 00:20:33
av Jörgen H
OK
jag är ingen expert men "c >> 4" håller väl inte reda på :
#define LCD_D7 LATAbits.LATA0
#define LCD_D6 LATAbits.LATB1
#define LCD_D5 LATAbits.LATC1
#define LCD_D4 LATAbits.LATD0
det va det jag var ute efter!
Inte minsta instruktioner!
Tack för alla svar!
Har redan laborera med olika tider som "sodjan" skrev, men inte med oscilloskop!!
Tiderna är tagna med Stopwath i MPLAB
While(1==1){
lcd_clear();
Delay10KTCYx(200); // 1 Sec
lcd_out(4,0,"123456789");
Delay10KTCYx(200); // 1Sec
}
Det blinkar med 1 sekund på lcdn!!!! (1Sec ON 1Sec OFF)
Kör med INTOSC 8Mhz
Re: LCD Probelm Med Microchip C18
Postat: 6 juni 2010, 00:47:29
av TomasL
Öka tidsfördröjningarna, eftersom du inte använder "busyflaggan" .
ANDa utgångarna istället för alla dessa shiftoprerationer, blir bättre.
Re: LCD Probelm Med Microchip C18
Postat: 6 juni 2010, 00:53:40
av Jörgen H
Denna kod fungerar i MikroC utan problem:
Kod: Markera allt
void main() {
PIC_Init(); // Initialize PIC
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
while(1){
Lcd_Cmd(_LCD_CLEAR);
Delay_Ms(1000); // Clear display
Lcd_Out(4,1,"1234567890");
Delay_Ms(1000);
}
}
Så det borde inte vara LCD:n??
Kör med "Microcip C18 Lite" om det har någon betydelse
Re: LCD Probelm Med Microchip C18
Postat: 6 juni 2010, 11:21:18
av sodjan
> Så det borde inte vara LCD:n??
Det är lite oklart vad du menar med "vara LCD:n".
Om du menar det inte är något fel på LCD'n i sig så
är det med 100% säkerhet inte det.
Självklart är det antingen fel i din kod eller fel i hur du
tror att LCD'n fungerar. Vilket som är mest sannolikt just
nu vet jag inte, men det är enkelt att verifiera av dig.
Re: LCD Probelm Med Microchip C18
Postat: 6 juni 2010, 13:15:54
av dangraf
kopilerar du exakt samma kod i microC som för C18 när du säger att det fungerar för microC?
Om du kör någon from av debugger (realIce eller ICD2) så skulle jag nog stega i koden och se vad som händer. Du skulle även kunna stega i koden i mplabs simulator och titta på vad portarna får för värden.
Re: LCD Probelm Med Microchip C18
Postat: 6 juni 2010, 13:19:14
av sodjan
Jag har inte kollat i detalj, men det är nog lite osannolikt att
Lcd_Out, Lcd_Cmd o.s.v är implementerade (om de ens finns)
på samma sätt i MikroC och C18.
Re: LCD Probelm Med Microchip C18
Postat: 7 juni 2010, 00:20:11
av Jörgen H
Ha
Har löst problemet!
Jag hade strulat till det med "Address counter"
Byte till rad 2 = 40Hex inte decimalt som jag skrev!
Knepigt att LCD skrev på rad 2+4 När (Address countern < 0x40)
å vad man kan strula till det ibland
Tack för alla svar
Här är den fungerande koden om någon e intresserad !
Kod: Markera allt
#define LCD_RS LATAbits.LATA5
#define LCD_EN LATAbits.LATA4
#define LCD_D7 LATAbits.LATA3
#define LCD_D6 LATAbits.LATA2
#define LCD_D5 LATAbits.LATA1
#define LCD_D4 LATAbits.LATA0
void LCD_STROBE(void){
LCD_EN = 1;
Delay10TCYx(1); // 5uS
LCD_EN = 0;
}
void lcd_write(unsigned char c){
LCD_D4 = ( ( c >> 4 ) & 0x01 );
LCD_D5 = ( ( c >> 5 ) & 0x01 );
LCD_D6 = ( ( c >> 6 ) & 0x01 );
LCD_D7 = ( ( c >> 7 ) & 0x01 );
Delay100TCYx(1); // 54uS
LCD_STROBE();
LCD_D4 = ( c & 0x01 );
LCD_D5 = ( ( c >> 1 ) & 0x01 );
LCD_D6 = ( ( c >> 2 ) & 0x01 );
LCD_D7 = ( ( c >> 3 ) & 0x01 );
Delay100TCYx(1); // 54uS
LCD_STROBE();
}
void lcd_out(unsigned char r,unsigned char p,const rom char *f){
LCD_RS = 0;
switch(r){
case 1:lcd_write(0x80+p);break; // Rad 1 + Position
case 2:lcd_write(0xC0+p);break; // Rad 2 + Position
case 3:lcd_write(0x94+p);break; // Rad 3 + Position
case 4:lcd_write(0xD4+p);break; // Rad 4 + Position
default: break;
}
LCD_RS = 1;
while(*f)lcd_write(*f++);
}
void lcd_clear(void){
LCD_RS = 0;
lcd_write(0x01);
Delay100TCYx(40); // 2ms
}
void LCD_Init(void){
LCD_RS = 0;
LCD_EN = 0;
Delay1KTCYx(40); // 20mS
LCD_D4 = 1;
LCD_D5 = 1;
LCD_D6 = 0;
LCD_D7 = 0;
LCD_STROBE();
Delay100TCYx(100); // 5mS
LCD_STROBE();
Delay100TCYx(10); // 0,5mS
LCD_STROBE();
Delay100TCYx(10); // 0,5mS
LCD_D4 = 0;
LCD_D5 = 1;
LCD_D6 = 0;
LCD_D7 = 0;
LCD_STROBE();
lcd_write(0x28); // Function set: (4Bit Mode,Display Lines=1,Character Font=0)
lcd_write(0x0C); // Display on/off control: (Display On, Cursor OFF, Cursor Blink OFF)
lcd_clear(); // Clear screen
lcd_write(0x06); // Entry Mode set:(Cursor moves to the right)
}
//****************************************************************************************
void main(void){
PIC_Init();
LCD_Init();
while(1==1){
lcd_clear();
Delay10KTCYx(200); // Delay 1 Sec
lcd_out(1,1,"1234567890");
Delay10KTCYx(200); // Delay 1 Sec
lcd_out(2,2,"1234567890");
Delay10KTCYx(200); // Delay 1 Sec
lcd_out(3,3,"1234567890");
Delay10KTCYx(200); // Delay 1 Sec
lcd_out(4,4,"1234567890");
Delay10KTCYx(200); // Delay 1 Sec
}
}