Initiera HD44780, AtMega16, 4-bit, lyckas inte...
Postat: 23 februari 2006, 19:15:22
Jag försöker initiera en 20x4 LCD med en HD44780-kontroller till min AtMega16. Det finns bara en HD44780-krets på LCDn trots att den har 4 rader. Databladet till HD44780 finns här.
(Jag har redan tidigare disskuterat detta i "optokomponenter", men tråden blev lång och ohanterlig så jag gör ett nytt försök här. Stort tack till alla som har svarat där!:))
Pinnarna är kopplade så här:

(Det till vänster är min 32,768kHz-kristall för tidtagning.)
Sen har jag kopplat det till mitt STK500 på port B.

Det här är min kod:

Resultatet ser ut så här. Två svarta rader.
Jag har testat delay-funktionen genom att blinka dioder i exakt en Hz, ½ Hz osv och det funkar perfekt. En delay(1) ger således en fördröjning på lite under en tusendel.
Jag har testat att min write_lcd-funktion fungerar dels genom att kolla i debuggern och genom att mäta på pinnarna efter att jag kallat funktionen. T.ex. resulterar write_lcd(0x03) i att D7-D4 är 0011 när jag mäter på LCDn. På samma sätt har jag testat min toggle_E-funktion och att sätta RS.
Jag har även testat att dunka på en prescaler på timern för att fördröja allt ytterligare. Har till och med lagt på så mkt fördröjning att man kan följa initieringsprocessen genom att sätta en PORTA=LCD när portA är kopplat till lysdioder.
Vad är det som är galet? Konrasten funkar ju eftersom jag ser svarta rutor. Jag har även testat att löda på en likadan kontakt på en 16x2-LCD med samma resultat.
Alla tips mottages. Just nu har hela mitt projekt avstannat bara för att jag inte lyckas med nåt så trivialt som att initiera en LCD.
(Jag har redan tidigare disskuterat detta i "optokomponenter", men tråden blev lång och ohanterlig så jag gör ett nytt försök här. Stort tack till alla som har svarat där!:))
Pinnarna är kopplade så här:
Kod: Markera allt
D7 D6 D5 D4 D3 D2 D1 D0 E R/W RS Vee Vcc GND
| | | | | | | | | | | | | |
P3 P2 P1 P0 GNDGNGNDGND P4 GND P5 GND Vtg GND

(Det till vänster är min 32,768kHz-kristall för tidtagning.)
Sen har jag kopplat det till mitt STK500 på port B.

Det här är min kod:
Kod: Markera allt
#include <avr/io.h>
void init_clock(void);
void delay(unsigned long int del);
void write_lcd(unsigned char byte);
void write_char(unsigned char byte);
void toggle_E(void);
void init_lcd(void);
#define LCD PORTB // Port som LCDn sitter på
#define LCD_DDRX DDRB
// Sätter igång timer2 i asynkront läge med 32,768-kristall
void init_clock(void) {
ASSR|=0x08; //async mode
TCCR2|=0x01; //clear timer no prescaler
TIFR=0x40; //start timer
}
// 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
}
}
//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_E(); // toggla E
}
//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
}
void toggle_E(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; // Alla pinnar på lcd till 0
delay(25); // Vänta lite med initieringen
// initiera LCDn
write_lcd(0x03); // 8-bitläge
delay(6);
write_lcd(0x03); // 8-bitläge
delay(2);
write_lcd(0x03); // 8-bitläge
delay(1);
write_lcd(0x02); // 4-bitläge
delay(1);
write_lcd(0x02); // 2 rader, 5x8-tecken
delay(1);
write_lcd(0x08);
delay(1);
write_lcd(0x00); // display off
delay(1);
write_lcd(0x08);
delay(1);
write_lcd(0x00); // display clear
delay(1);
write_lcd(0x01);
delay(1);
write_lcd(0x00); // increment
delay(1);
write_lcd(0x06);
delay(1);
}
int main(void) // main program starts
{
DDRA=0xFF; // PortA till utgång för felsökning med lysdioder
init_clock(); // Starta timern
init_lcd(); // Initiera lcd:n
LCD|=0x20; // RS =1 för att skicka data
write_char(0x4C); // Skriv ett L
write_char(0x43); // Skriv ett C
write_char(0x44); // Skriv ett D
while(1) {}
}

Resultatet ser ut så här. Två svarta rader.
Jag har testat delay-funktionen genom att blinka dioder i exakt en Hz, ½ Hz osv och det funkar perfekt. En delay(1) ger således en fördröjning på lite under en tusendel.
Jag har testat att min write_lcd-funktion fungerar dels genom att kolla i debuggern och genom att mäta på pinnarna efter att jag kallat funktionen. T.ex. resulterar write_lcd(0x03) i att D7-D4 är 0011 när jag mäter på LCDn. På samma sätt har jag testat min toggle_E-funktion och att sätta RS.
Jag har även testat att dunka på en prescaler på timern för att fördröja allt ytterligare. Har till och med lagt på så mkt fördröjning att man kan följa initieringsprocessen genom att sätta en PORTA=LCD när portA är kopplat till lysdioder.
Vad är det som är galet? Konrasten funkar ju eftersom jag ser svarta rutor. Jag har även testat att löda på en likadan kontakt på en 16x2-LCD med samma resultat.
Alla tips mottages. Just nu har hela mitt projekt avstannat bara för att jag inte lyckas med nåt så trivialt som att initiera en LCD.
