Initiera HD4478, Atmega16 funkar inte?

Lysdioder, Optiska sensorer, Fiberoptik, Displayer, Lasrar, Optiska kopplare
Användarvisningsbild
gunne
Inlägg: 2088
Blev medlem: 17 juni 2004, 15:00:31
Ort: sthlm
Kontakt:

Initiera HD4478, Atmega16 funkar inte?

Inlägg av gunne »

Jag försöker att använda en 40x4-LCD till en Atmega16 i 4-pinnarsläge. LCDn har beteckningen LM044L och har såklart ett HD4478-chip. När jag har kopplat in den syns två svarta rader vilket jag har förstått betyder att den väntar på initiering. Jag tycker att jag har skrivit initieringsrutinen rätt, men det verkar inte funka. Jag har mätt på pinnarna när jag skickar min akommandon för att se att det stämmer, och det gör det. Vad kan va fel?

Info om HD4478 finn här och här om det behövs...

Kod: Markera allt

#include <avr/io.h>

#define LCD_DDRX DDRA
#define LCD PORTA		// Port som LCDn sitter på

void init_lcd(void) {

	LCD_DDRX=0xFF;	// LCD-porten som utgång
	LCD=0x00;		//Allt till 0
	delay(25);		// Vänta lite med initieringen

	// initiera skiten
	write_lcd(0x30);
	delay(6);
	write_lcd(0x30);
	delay(6);
	write_lcd(0x30);
	delay(6);
	write_lcd(0x38);
	delay(6);
	write_lcd(0x08);
	delay(6);
	write_lcd(0x01);
	delay(6);
	write_lcd(0x06);

}

//Skriver ut en byte till LCDn
void write_lcd(unsigned char byte) {


	LCD&=0xF0;		// Nollställ D7-D4
	LCD|=byte>>4;	// Lägg ut översta 4 bitarna

	LCD|=0x10;		// Sätt E till 1
	delay(1);		// Fördröj x tusendelar
	LCD&=~0x10;		// Sätt E till 0

	LCD&=0xF0;		// Nollställ D7-D4
	LCD|=byte&0x0F;	// Lägg ut nedersta 4 bitarna

	LCD|=0x10;		// Sätt E till 1
	delay(1);		// Fördröj x tusendelar
	LCD&=~0x10;		// Sätt E till 0
}

// Fördröjer med _del_ tusendelar av en sekund. För exakt en sekund använd del = 1024
void delay(unsigned long int del){
unsigned long int i=0;
unsigned char wait=0;
	for(i=0;i<del;i++) {
		wait=TCNT2+31;
		while(wait!=TCNT2) {}	//Vänta på klockan	
	}
}

// Sätter igång timer2 i asynkront läge
void init_clock(void) {
	ASSR|=0x08;	//async mode
	TCCR2|=0x01;	//clear timer no prescaler
	TIFR=0x40;	//start timer
}


int main(void)
{
	init_clock();
	init_lcd();

	LCD|=0x20;	// RS=1;

	write_lcd(0xF0);          // Skriv ett tecken

	while(1) {	} 
} 

Användarvisningsbild
JimmyAndersson
Inlägg: 26483
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Testa att köra med längre fördröjning mellan varje initierings-kommando. Prova även att vänta lite till innan initieringen. Bara för att testa...

Nu har du ju visserligen problem med initieringen, men jag hittar inte var du sedan stänger på displayen?

edit: Du måste ju även sätta E-pinnen hög en kort stund och sedan låg, mellan varje initierings-rad. Det var ett tag sedan jag programmerade C, så du kanske har med det i koden, men jag hittar det inte.

En liten liten parantes: Detta är ju ett programmeringsrelaterat problem, så tråden kanske hade passat bättre i Mikroprocessor-delen.
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

Om man kollar här så ser man att skicka först
0011 och sedan vänta minst 5ms och sedan 0011 igen....

Men som du gör nu skickar du ut 0011 och litet ögonblik senare ut 0000 där har du ett fel....
Användarvisningsbild
gunne
Inlägg: 2088
Blev medlem: 17 juni 2004, 15:00:31
Ort: sthlm
Kontakt:

Inlägg av gunne »

Det är sant. Men jag har testat att fördröja i det läget. Är det så att man måste sätta E hög, vänta lite, sänka den om SEN vänta ytterligare 5 ms?

Stänger på displayen? Jag initierar den, sen sätter jag RS=1 och skickar ett tecken.

Har även testat att göra alla fördröjningar ~10 ggr längre utan framgång...

Vad annars kan vara fel? Är det någon som har erfarenhet av att använda HD4478 i 4-bitarsläge?
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

Testa att bara skicka 4bitar åt gången...
delvis
0011 vänta minst 5 ms
0011 vänta minst 0.1 ms
0011
osv...

Som det ser ut nu så skickar du

0011
0000
0011
0000
osv...

För står du vad jag menar?
Användarvisningsbild
JimmyAndersson
Inlägg: 26483
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

4-bitarsläge? Men nu kör du ju 8-bitar som du delar på? Kan vara jag som missat varför..


Mellan varje rad ska E bli hög/låg. Såhär:

0x30
vänta lite
E = hög
vänta lite
E = låg
vänta lite

0x030
vänta lite
E = hög
vänta lite
E = låg
vänta lite

osv...


När du initierat "grunden" (dvs det ovan) så måstse du stänga på displayen för att kunna se något. Det gör man med:

1100 (C hex) innebär: Display on, cursor off, blink off.
1000 (8 hex) innebär: Display off, cursor off, blink off.
Resten kan du se i databladet.

Även här ska man sätta E hög/låg. -Det ska man förresten alltid när man matar in något...


Det finns förresten ett mycket bra program (javascript) för att simulera såna här displayer. Det kan köras härifrån eller laddas ner från samma sida. Obs: Det tar en liten stund innan sidan visas.


En fråga bara: Du skriver "HD4478" men dina länkar hänvisar till sidor med HD44780?
Användarvisningsbild
gunne
Inlägg: 2088
Blev medlem: 17 juni 2004, 15:00:31
Ort: sthlm
Kontakt:

Inlägg av gunne »

Det är en HD44780A00.

Jag har nu testat att bara skicka ut fyra bitar åt gången. De vitala delarna av mitt program:

Kod: Markera allt

void init_lcd(void) {

	LCD_DDRX=0xFF;	// LCD-porten som utgång
	LCD=0x00;		//Allt till 0
	delay(25);		// Vänta lite med initieringen
	
	// initiera skiten
	write_lcd(0x03);
	delay(6);
	write_lcd(0x03);
	delay(2);
	write_lcd(0x03);
	delay(1);
	write_lcd(0x02);
	delay(1);
	write_lcd(0x02);
	delay(1);
	write_lcd(0x08);
	delay(1);
	write_lcd(0x00);
	delay(1);
	write_lcd(0x08);
	delay(1);
	write_lcd(0x00);
	delay(1);
	write_lcd(0x01);
	delay(1);
	write_lcd(0x00);
	delay(1);
	write_lcd(0x06);
	delay(1);

	write_lcd(0x0C);	
	delay(1);
	write_lcd(0x08);
}

//Skriver ut en byte till LCDn
void write_char(unsigned char byte) {	
	write_lcd(byte>>4);	// Lägg ut översta 4 bitarna
   delay(1);
	write_lcd(byte);	// Lägg ut nedersta 4 bitarna
}

//Skriver ut en halv byte till LCDn
void write_lcd(unsigned char byte) {
	LCD&=0xF0;		// Nollställ D7-D4
	LCD|=byte&0x0F;	// Lägg ut nedersta 4 bitarna

	delay(1);		// Fördröj x tusendelar
	LCD|=0x10;		// Sätt E till 1
	delay(1);		// Fördröj x tusendelar
	LCD&=~0x10;		// Sätt E till 0
	delay(1);		// Fördröj x tusendelar
}

int main(void) 
{
	DDRB=0xFF;
	PORTB=0xF0;	

	init_clock();
	init_lcd();

	LCD|=0x20;	// RS =1;


	write_char(0x03);	// Skriv en nolla

	while(1) {}
}
La även till dina två kommandon på slutet. Får det inte att funka oavsätt hur lång fördröjning jag lägger in. Tackar för all hjälp förresten! Många bra svar än så länge...

Edit: På sidan 213 i databladet står något om att ställa in hur många rader man ska ha. Har jag missat det? min display har ju 4 men det är vanligare med 2-raders.
Användarvisningsbild
JimmyAndersson
Inlägg: 26483
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Funderar på denna rad:

LCD&=0xF0; // Nollställ D7-D4

Då nollställer du varje initieringsrad innan den skickas (genom att E blir hög/låg.) Om jag inte missuppfattat något så är det där felet ligger.
Användarvisningsbild
gunne
Inlägg: 2088
Blev medlem: 17 juni 2004, 15:00:31
Ort: sthlm
Kontakt:

Inlägg av gunne »

Som jag har tänkt det så nollar jag pinnarna D7-D4 medans resten av pinnarna har kvar sitt ursprungliga läge. Detta för att kunna lägga ut ettorna på dessa pinnar med ett &.

ex:

Vi vill lägga ut 0011 på D7-D4
LCD är 1010 1100 säger vi.
LCD&=0xF0 gör att LCD blir 1010 0000
LCD|=0000 0011 gör sen att LCD blir 1010 0011

eller?

D7-D4 refererar till pinnarna på LCDn och de är kopplade till pinna 0-4 på avr-porten.
Användarvisningsbild
JimmyAndersson
Inlägg: 26483
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Det blir lite rörigare att göra så, men det borde gå.

Det här med att ställa in hur många rader man har: Det görs i rad nr6: 1000 (i 4-bit-läget).

La däremot märke till en annan sak: Du har RS hög vid initieringen? Den ska vara låg.
Dvs:
RS = låg -> Instruktioner/kommando
RS = hög -> Data. T.ex för att skicka text till displayen.


Sedan är det lite svårare att använda 4-bitars-läget. Har man däremot fått 8-bitarsläget att fungera så är det lite lättare att "få igång" 4-bitarsläget.

edit: Hur har du satt R/W ? Den kan man koppla direkt till jord, så länge man inte behöver läsa något från displayen till processorn.
Användarvisningsbild
gunne
Inlägg: 2088
Blev medlem: 17 juni 2004, 15:00:31
Ort: sthlm
Kontakt:

Inlägg av gunne »

Jag sätter inte RS till 1 förrens efter initieringen. LCD=0x20 gör RS hög.

Betyder 1000 i rad 6 att man har 2 rader?
Användarvisningsbild
Kramer
Inlägg: 16
Blev medlem: 30 oktober 2005, 00:16:35

Inlägg av Kramer »

Om du är intresserad så har jag en nästan färdig drivrutin till den displayen, koden är skriven i C och jag har testat den med Atmega16 och den fungerar. Det enda som inte fungerar är att sätta markören till rätt rad och kolumn, men det kanske du kan fixa själv.
Användarvisningsbild
gunne
Inlägg: 2088
Blev medlem: 17 juni 2004, 15:00:31
Ort: sthlm
Kontakt:

Inlägg av gunne »

Jo, det är jag intresserad av... Har suttit sen klockan 11 i morse och försökt få igång den här skiten. Det e så segt när man verkligen inte kan hajja vad man gjort fel...

maila gärna filen till mej på gunnee[at]m.kth.se om du vill. Är det i 4-bitarsläge?
Användarvisningsbild
Kramer
Inlägg: 16
Blev medlem: 30 oktober 2005, 00:16:35

Inlägg av Kramer »

Jo, det är 4-bitars läge, om du får till positionering av rad och kolumn så får du gärna skicka den koden... :shock:
Användarvisningsbild
gunne
Inlägg: 2088
Blev medlem: 17 juni 2004, 15:00:31
Ort: sthlm
Kontakt:

Inlägg av gunne »

Tackar för koden. Jag SKA dock få min egen att funka. Kan någon föreslå felsökningsmetoder för att luska ut var felet ligger?

Jag har lagt ut olika saker (t.ex. LCD&=0x20) och mätt på pinnarna för att kontrollera att det är rätt. Jag har utökat fördröjningen mellan alla steg utan resultat. Känns bittert när man spenderat en hel dag på att fixa en LCD och inte har sett ett enda tecken... :(
Skriv svar