Sida 2 av 3
Postat: 22 februari 2006, 18:44:23
av JimmyAndersson
Vill du visa både den fungerande och den icke-fungerande koden?
Ett bra tips är att jämföra koderna.
Har själv haft en hel del liknande problem så jag vet hur det kan vara..
edit: Var det hela koden du visade i första inlägget?
Postat: 22 februari 2006, 19:55:51
av Porto
HD44780 kan bara hantera 80st tecken, som om det är en 40*4 lcd så sitter det 2st HD44780 chip på displayen, med varsin enable ingång. Så det är egentligen 2st 40*2 displayer på samma glasbit, som måste initieras var för sig. Du kan ju kolla ett datablad från elfa på en 40*4 för anslutningarna.
http://www.elfa.se/pdf/75/07551328.pdf
http://www.elfa.se/pdf/75/07555147.pdf
Fast enligt databladet så tycks det vara en 20*4 tecken display?
I såfall så är det egentligen en 40*2 kapad på mitten så att rad 3 och 4 egentligen är slutet på rad 1 och 2, så den måste initieras som en display med dubbla rader.
Postat: 22 februari 2006, 20:02:04
av gunne
Jag har gått i dom tankegångarna oxå, men det sitter bara ett HD44780A00-chip på baksidan och sen några andra chip. Och så finns det bara 14 pinnar precis som det ska...
Kanske är nåt special? Jag skulle kunna testa att trycka dit en 16x2-lcd imorn för att se om koden funkar.
Postat: 22 februari 2006, 20:52:38
av Porto
> write_lcd(0x30);
Du tycks ställa in displayen för 8-bit med 4-bit kommandon.
Man kan anta att displayen är i 8-bit mode eller 4-bit om man starta om processorn men inte bryter strömmen till lcd:n. Så man får först ställa om displayen till 8-bit med för displayen både 4-bits och 8-bits kommandon.
Så något sådant för att initiera en display med 2 rader i 4-bit mode:
RS=0 (kommando)
R/W=0 (skriv)
Enable=0
Uppstart paus 100ms typ
(pulsa enable nedan=kort paus, enable låg till hög | kort paus | enable hög till låg | kort paus)
Ställer om till 8-bit överföring (om man initierar displayen 2 ggr)
00110000B ;DL=1 N=0 F=0 : 8 bit , 1 line , 5*7 dots
Skicka de högsta 4 bitarna med bara en enable signal - 8-bit kommando
pulsa enable
paus >40us
Samma igen - om displayen redan var i 4-bit mode - skickar även låga data delen!
00110000B ;DL=1 N=0 F=0 : 8 bit , 1 line , 5*7 dots
Skicka de högsta 4 bitarna med bara en enable signal - 8-bit kommando
pulsa enable
paus >40us
Ställer om till 4-bit överföring (via 8-bit kommando)
00100000B ; DL=0 N=0 F=0 : 4 bit , 1 line , 5*7 dots
Skicka de högsta 4 bitarna med bara en enable signal - 8-bit kommando
pulsa enable
paus >40us
Sänder samma igen - nu i 4-bit mode - vid föregående 8-bit instruktion fick man ju inte med D0-D3
00101000B ; DL=0 N=1 F=0 : 4 bit , 2 lines , 5*7 dots
höga delen, pulsa enable
låga delen, pulsa enable
paus >40us
00001100B ; D=1 C=0 B=0, display on, cursor/flash off
höga delen, pulsa enable
låga delen, pulsa enable
paus >40us
00000110B ; I/D=1 S=0 : increment w. display shift
höga delen, pulsa enable
låga delen, pulsa enable
paus >40us
00000001B ; reset Display
höga delen, pulsa enable
låga delen, pulsa enable
paus >2ms
Det måste även vara en kort paus mellan att (RS,R/W), data och enable pinnarna ändras.
Postat: 23 februari 2006, 09:16:01
av gunne
Jag hade ätit knark när jag skrev första inlägget. Det är en 20x4 och inte en 40x4 lcd. Men det spelar nog mindre roll.
Menar du att jag ska ställa in den till 8-bit läge först, och sen ställa om den? Måste man göra det? Har inte sett den varianten i nån guide jag läst... Hajjar inte riktigt trots att det var ett detaljerat och bra svar.
Jag ska testa att göra exakt som du skrev när jag kommer till labbet så får vi se om det funkar.
Postat: 23 februari 2006, 09:35:04
av frejo
Följer man bara databladet brukar det aldrig vara nå problem, har initierat från AVR i både 4- och 8-bitars läge.

E behöver inte gå hög före datalinorna, jag brukar göra en strobe funktion som sätter E hög och sen låg igen, dvs för sätter jag mina datalinor sen kallar jag på Strobe. Vill man göra det snyggt kollar man busyflag innan man gör något fast det är inte nödvändigt, ett delay på 5-10ms efter att E gått låg brukar räcka för att den ska hinna klart med sina interna grejer innan man gör något nytt.

Notera att även fast det inte står någon delay specifierad i de sista instruktionerna i initieringen tar varje instruktion ändå minst 37uS att utföra, antingen kollar man busy-flag eller så väntar man en lämpligt vald tid, minst 2ms brukar jag ta.
datablad
Postat: 23 februari 2006, 10:32:13
av Porto
gunne:
>Menar du att jag ska ställa in den till 8-bit läge först, och sen ställa om den? Måste man göra det? Har inte sett den varianten i nån guide jag läst... Hajjar inte riktigt trots att det var ett detaljerat och bra svar.
Problemet är att om man startar om processorn utan att bryta strömmen till lcd:n, så vet man inte om displayen är i 4-bit eller 8-bit mode. Har man riktigt tur så är den i 4-bit mode och har precis fått höga delen när processorn startade om, då är risken att lcd:n kommer att vara i osynk och inte vilja fungera som den skall. Om man byter till 8-bits mode vid initieringen och sedan tillbaka till 4-bit så kommer den att hamna i synk igen.
Postat: 23 februari 2006, 11:53:51
av gunne
Frejo, att följa databladet är precis vad jag tycker att jag gör. Nu ser koden ut så här och jag kan inte hitta nåt fel. om jag stegar mej igenom den i debugen kan jag se att den lägger ut data på rätt pinnar. Jag har även gjort allt ~100 ggr långsammare och lagt ut samma data som till lcdn på lysdioderna på stk500 och stegat mej igenom initieringen. Allt verkar stämma...
Kod: Markera allt
#include <avr/io.h>
EDIT: Hade vänt som här fel!
// Pinnarna är kopplade så här:
//
// P0 -> D4
// P1 -> D5
// P2 -> D6
// P3 -> D7
// P4 -> E
// P5 -> RS
//
//
#define LCD_DDRX DDRB
#define LCD PORTB // Port som LCDn sitter på
// 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
}
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
}
}
//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
toggle_enable();
}
void toggle_enable(void) {
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
}
void init_lcd(void) {
LCD_DDRX=0xFF; // LCD-porten som utgång
LCD=0x00; //Allt till 0
delay(100); // 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);
}
int main(void) // main program starts
{
init_clock();
init_lcd();
LCD|=0x20; // RS =1;
write_char(0x03); // Skriv en nolla
while(1) {}
}
Porto: Om jag bryter strömmen till lcdn helt innan jag sätter igång processorn så borde det inte va nå problem?
Postat: 23 februari 2006, 12:28:14
av sodjan
Skriv gärna du inte vad du *tror* att du gör när du "initierar skiten" ???
(Väldigt oproffsig kommentar, för övrigt...)
Det *ser* OK ut, men det blir tusan så mycket enklare att följa
med lite kommentarar. Dela gärna upp varje kommando också, något
i stil med :
Kod: Markera allt
// initiera skiten
write_lcd(0x03); // 8-bit...
delay(6);
write_lcd(0x03); // 8-bit...
delay(2);
write_lcd(0x03); // 8-bit...
delay(1);
write_lcd(0x02); // 4-bit !
delay(1);
write_lcd(0x02); // 2-line...
delay(1);
write_lcd(0x08);
delay(1);
write_lcd(0x00); // All off...
delay(1);
write_lcd(0x08);
delay(1);
write_lcd(0x00); // Clear display...
delay(1);
write_lcd(0x01);
delay(1);
write_lcd(0x00); // Display on, curs underline...
delay(1);
write_lcd(0x06);
delay(1);
Jag tror att jag fick det rätt, men det vore bra om det även stämmer
överens med din bild...
> Om jag bryter strömmen till lcdn helt innan jag sätter igång processorn så borde det inte va nå problem?
Så vitt jag kan se så sätter du modulen i 8-bitars mode tre gånger
så jag tror inte det...
> write_char(0x03); // Skriv en nolla
Är inte "0" = 0x30 ??
Postat: 23 februari 2006, 12:55:33
av Porto
gunne:
> // P0 -> D7
> // P1 -> D6
> // P2 -> D5
> // P3 -> D4
> // P4 -> E
> // P5 -> RS
Borde inte P0 gå till D4, P1 till D5 osv
Sedan som Sodjan skriver så borde "0" bli = 0x30
Postat: 23 februari 2006, 13:06:01
av sodjan
Rätt Porto, missade det... (alltså P0-P4 -> D7-D4)

Postat: 23 februari 2006, 15:12:59
av gunne
Argh. Jag skrev fel på pinnarna. Jag har kopplat det rätt (PO->D4...) Men när jag skrev kommentaren i koden så tänkte jag lite bortom hjärnan.
Sant det där med kommentarerna. Ska försöka bättra mej
Sätter den i 8 bitarsläge tre gånger? Jag skickar precis de kommanona som står i databladet (se frejos inlägg). 0011, 0011, 0011, 0010 osv som det står.
Sant att noll är 0x30, men det spelar ingen som helst roll eftersom jag ändå inte kan skriva ut nåt tecken. Har även testat att skriva ut andra tecken såklart...
Postat: 23 februari 2006, 15:43:25
av Porto
Blir det fortfarande bara svarta rader på displayen?
Har du provat att skruva på kontrasten?
Du har ingen bild på hur du har kopplat?
Postat: 23 februari 2006, 15:50:04
av sodjan
> Sant att noll är 0x30, men det spelar ingen som helst roll eftersom jag
> ändå inte kan skriva ut nåt tecken. Har även testat att skriva ut andra
> tecken såklart...
Tja, om de var lika fel som din "nolla", så spelar det väl en viss roll...
Generellt sätt är det ganska meningslöst att bara säga att du har gjort
något visst, utan att också *VISA* att det stämmer (med kod eller schema).
Allt annat blir bara gissningar att du faktiskt har gjort som du säger...
Postat: 23 februari 2006, 17:19:56
av gunne
Fortfarande ingenting... Jag gör så att jag tar lite foton på hur jag kopplat, kommenterar min kod lite bättre och startar en ny tråd. Det blir så rörigt när man blandar gammal felaktig kod med ny osv.
Bör man starta tråden i mC-forumet istället? Känns som att det är programmeringen som är kärnan i den här frågan...