Hallo allemaal,

Ik heb problemen met een lcd driver die ik heb geschreven. De initialisatie gaat goed, alleen lukt het me niet om karakters op het display te vertonen. Het enige wat verschijnt zijn niet de karakters die ik naar het display stuur. Waarschijnlijk komen die waarden niet goed aan oid.

Ik maak gebruik van de SDCC compiler op een PIC18f2480, en het display is 4*40 groot. Dus er zijn 2 controllers aanwezig. Voor debugging heb ik de initialisatie alleen op 1 controller gedaan.

de driver in bestand lcddriver.c is hier te vinden: http://www.uploadarchief.net/files/download/lcddriver.c

en dit is mijn main file.


/* ----------------------------------------------------------------------- */
/* Template source file generated by piklab */
#include "pic16/pic18f2480.h"

#define led_tris	TRISAbits.TRISA1
#define led_pin		PORTAbits.RA1

#include "lcddriver.c"

/* ----------------------------------------------------------------------- */
/* Configuration bits: adapt to your setup and needs */
code char at __CONFIG1H CONFIG1H = _OSC_IRCIO67_1H & _FCMEN_OFF_1H & _IESO_OFF_1H;
code char at __CONFIG2L CONFIG2L = _PWRT_OFF_2L & _BOREN_OFF_2L;
code char at __CONFIG2H CONFIG2H = _WDT_OFF_2H;
code char at __CONFIG3H CONFIG3H = _PBADEN_OFF_3H & _LPT1OSC_OFF_3H & _MCLRE_OFF_3H;
code char at __CONFIG4L CONFIG4L = _STVREN_OFF_4L & _LVP_ON_4L & _BBSIZ_1024_4L & _XINST_OFF_4L & _DEBUG_OFF_4L;
code char at __CONFIG5L CONFIG5L = _CP0_OFF_5L & _CP1_OFF_5L;
code char at __CONFIG5H CONFIG5H = _CPB_OFF_5H & _CPD_OFF_5H;
code char at __CONFIG6L CONFIG6L = _WRT0_OFF_6L & _WRT1_OFF_6L;
code char at __CONFIG6H CONFIG6H = _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H;
code char at __CONFIG7L CONFIG7L = _EBTR0_OFF_7L & _EBTR1_OFF_7L;
code char at __CONFIG7H CONFIG7H = _EBTRB_OFF_7H;

void init()	// set microchip settings.
{
	OSCCONbits.IRCF0 = 1;	// set internal oscillator to 8 Mhz
	OSCCONbits.IRCF1 = 1;	//
	OSCCONbits.IRCF2 = 1;	//
	
	led_tris = 0;
	led_pin = 1;

	
	LCD_init(); // run LCD initialisation routine.
}

void main() 
{
	init();	
	
	
	WriteLCD( "hello world" );	
}

Ik heb geen idee waar de fout zit. Ik heb al tijden mn programma getweakt en gekeken wat er beter werkt en wat niet. Maar ik zit vast? Kunnen jullie mij misschien helpen?

Alvast bedankt...

Dexter

[Bericht gewijzigd door Henry S. op (0%)]

ik heb er zelf ook nog niet heel veel kaas van gegeten.
Maar misschien stuur je je tekst te snel na de init..
en/of dien je eerst een Clear commando te geven ofzo?

In de initialisatie routine wordt er na elke instructie gewacht totdat het display klaar is. (de busyTest functie in lcddriver.c)
Dus in principe wordt de schrijf routine niet te snel na de initialisatie aangeroepen.

In de initialisatie routine wordt ook een clear commando aangeroepen.

edit:

Ik heb even een foto gemaakt van wat het programma nu doet. Misschien hebben jullie er wat aan.
http://www.uploadarchief.net/files/download/foto0119.jpg

Het programma is ook verdacht instabiel. Ik weet niet waar het aan kan liggen. Ik heb er nu heel veel lege for loopjes in gezet zodat het wat tijd krijgt. Maar het lijkt niet te werken.

BTW. ik heb het display in 4 bits mode aangesloten.

[Bericht gewijzigd door Henry S. op (21%)]

4 bit of 8 bit mode ? pull ups up je lijnen gezet ?
bit bang je dat spul ? i je data stabiel vooraleer je CS toggelt ?

Ik zie dat je een union gebruikt in putByte() om de bits uit het byte te lezen!
Advies: Nooit doen.
Waarom: Compiler afhankelijk gedrag, is niet gedefinieerd in de C-standaard.

Het kan goed zijn dat de bits in omgekeerde volgorde uit de union gehaald worden waardoor je bitjes geswapt zijn.
(Voorbeeld Dus bit 0 wordt 7, 1->6,... 7->0.)

Ik weet niet wat het nu wordt!

Gebruik beter de volgende constructie:


Oud:
	DB7 = tmp.bit._7;
	DB6 = tmp.bit._6;
	DB5 = tmp.bit._5;
	DB4 = tmp.bit._4;
Wordt:
	DB7 = ((unsigned char)byte & 0x80) >> 7;
	DB6 = ((unsigned char)byte & 0x40) >> 6;
	DB5 = ((unsigned char)byte & 0x20) >> 5;
	DB4 = ((unsigned char)byte & 0x10) >> 4;

Ik weet niet of je de gecompileerde assembly ergens kunt zien, dan kun je ook beoordelen wat de compiler nu echt doet.

@free electron:
Bitbangen?, wat bedoel je daarmee. Pullups zal ik nog even checken.

@henri62:
Ik heb de putbyte functie goed getest. En ik weet zeker dat de volgorde niet wordt omgedraaid.

Ik heb er net pullups op gezet. alleen is het probleem nog niet opgelost. De situatie is nog exact hetzelfde.

[Bericht gewijzigd door Henry S. op (23%)]

Moet eerlijk zeggen dat ik je code een beetje eng vind, rare macro's. Maar, dan zou hij het in theorie nog moeten doen.

Hierr staat code van mij, van mijn HD44780 project met sdcc. Zit dat er wat uart rommel in staat, maar zou het eigenlijk moeten doen. Wel even de pinnen in display.c aanpassen.

1) Heb je gechecked hoe lang de delays in de praktijk zijn, maw worden ze niet weg-geoptimaliseerd door de compiler?
Dit stukje kan dan wel eens erg kort worden:
setE
for (i=0; i<2 ; i++); //wait
clearE

2) Volgens mij moet je het LCD ready signaal pas na de entry mode set gebruiken. (na de putByte(0x2C)?? )

3) Ik heb ook eens soortgelijk probleem gehad met een display. Achteraf bleek de timing tussen de verschillende commando's toch langer te moeten zijn dan wat in het datasheet stond. Vooral de initialisatie is erg langzaam en ik moest minmaal 4.1 mS wachten na de entry mode set voordat het ding ergens op reageerde.
Het was ook een zogenaamd HD compatible display, mooi niet helemaal dus. Ik zou eens proberen tussen alle initialisatie stapjes een delay stoppen om te kijken of het daardoor komt.

@henri62 & RoelA: Bedankt voor jullie hulp.

Het werkt alleen nogsteeds niet. Ik heb jouw code voor een deel gebruikt om mijn code schoner te maken. En alle timings aangepast. Maar helaas, het wil nogsteeds niet werken.

Ik heb de lcddriver.c hier geupload. Mijn main c file is onveranderd gebleven. Wat is dit toch naar.. brr.

Edit:
Het valt me trouwens wel op dat de karakters die op het scherm verschijnen veranderd zijn sinds die foto. Elk karakter beslaat 2 plekken op het scherm. Alsof het lijkt dat hij niet goed in 4 bits mode staat. Maar volgens mij is dat wel zo.

[Bericht gewijzigd door neoel op (24%)]

Juist. Dat doet vermoeden dat je code toch wel juist is, maar er elektrisch iets niet helemaal op orde is.

Geeft hij altijd de zelfde vage output? Zo ja, dan zal er vermoedelijk ergens een pin foutief verbonden zijn met voeding of ground. Zo nee, dan zou het hem wel eens in een onterecht zwevende pin kunnen zitten, een slecht soldeercontact of kabelbreuk (in het bijzonder in je klok-lijn).

Ook gezien je laatste edit: controleer je bekabeling!

Weet je zeker dat de datalijnen juist zijn aangesloten??

Ik net nog even alles gecheckt. En alle datalijnen zijn goed aangesloten. Geen kortsluiting oid. Dus dat is het probleem niet.

Het is wel constant dezelfde output. Hij is alleen veranderd nu ik het programma heb veranderd.

edit:
Zelfs de karakters zijn constant hetzelfde. (ie. bij "hello world" zijn de 3 l'en en o's hetzelfde. Alleen dan in vage tekens.)

Goed. Wat doet de setE / clearE functie precies? In je putByte() roep je ze erg direct achter elkaar aan. Het doet vermoeden dat dit om een soort kloksignaal gaat, al is mijn kennis van LCD-aansturing wat weggezakt, zeker in 4-bit. Het gevolg van deze rappe aanroep is dat de poort / lijn eigenlijk niet de tijd krijgt een nieuwe waarde aan te nemen, of het LCD niet de tijd om deze nieuwe waarde correct waar te nemen. Mocht setE / clearE inderdaad een lijn richting LCD aansturen, raad ik je aan hier eens een korte delay tussen te zetten.

Ook niet heel per ongeluk de bitvolgorde gewisseld in je datalijnen? Dat gebeurt de besten ;-)

Nog een kleine design-hint: schrijf ook de for-loop van je delay routine in assembler. Je weet nooit zeker hoeveel overhead de compiler van een for-loop maakt, en deze is ook nog eens variabel voor het aantal loops.. Er is een prachtige website om delay-routines te genereren voor PIC controllers.

[Bericht gewijzigd door Bert M op (19%)]

de setE en clearE functie setten en clearen de enable bit. Deze macro is gemaakt omdat ik 2 controllers heb. Zodat ik makkelijk kan schakelen tussen de verschillende controllers.

Maar.. Ik heb LCDHome toegevoegd aan de initialisatie functie. En opeens verschijnt er "hello world" op m'n scherm. Ik kan het niet geloven. En al helemaal niet verklaren. Maar ik ben blij dat het werkt.

Bedankt voor jullie hulp.

dan is je init niet goed. je krijgt display niet in 4 bit mode.

wat heb je met de overgebleven pinne gedaan van het dsplay ? via pullups aan voeding hangen ? of laat je die los ?

Oei, ja daar zeg je me wat. Jemig. Ik heb er niks mee gedaan. Maarja, dat werkt natuurlijk niet goed.

Daar ga ik direct wat mee doen. Nog een vraagje. Maakt het uit of ik een pull-down of -up gebruik?, mij lijkt het beter als ze constant 0 zijn.

Pullups gebruiken dat lijkt me het beste, zeker niet aan vcc of gnd hangen. Tijden het lezen in 4 bit mode zouden de pinnen outputs kunnen worden zodat je het display opblaast.

Wat henri62 schrijft is juist.
Maar een HD44780 heeft pull-ups van zichzelf, dus ongebruikte pinnen gewoon los laten hangen (dit moet je ook kunnen meten aan het display, ongebruikte pinnen zullen een hoog niveau moeten hebben).