Sida 1 av 3
Initiera HD4478, Atmega16 funkar inte?
Postat: 22 februari 2006, 12:42:46
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) { }
}
Postat: 22 februari 2006, 12:55:53
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.
Postat: 22 februari 2006, 13:38:25
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....
Postat: 22 februari 2006, 13:49:24
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?
Postat: 22 februari 2006, 14:08:03
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?
Postat: 22 februari 2006, 14:15:40
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?
Postat: 22 februari 2006, 14:34:31
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.
Postat: 22 februari 2006, 14:39:25
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.
Postat: 22 februari 2006, 14:47:39
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.
Postat: 22 februari 2006, 15:48:19
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.
Postat: 22 februari 2006, 15:54:13
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?
Postat: 22 februari 2006, 15:54:17
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.
Postat: 22 februari 2006, 15:59:10
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?
Postat: 22 februari 2006, 16:10:04
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...

Postat: 22 februari 2006, 18:33:11
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...
