millioneer
04.01.2005, 21:59
Hallo,
ich wollte gern ein 16x2 LCD-Display mit meinem ATTiny26 im 8bit-Modus ansteuern. Der Tiny26 hat zwei 8bit-Ports, PORTA verwende ich für den Datenbus, die drei Steuerbits kommen vom PORTB. Taktung ist 16 Mhz.
Das Problem ist nur, mit dem LCD passiert rein garnichts, nicht mal ein zucken.
Ich hab schon zwei verschiedene LCD's ausprobiert ein 16x2 und ein 40x4, beide von Reichelt.
Das 40x4 wird komplett dunkel, das 16x2 bleibt komplett hell. An einem gekauften Mega8-Board funktionieren aber beide.
Laut Datenblatt vom HD44780 muss man eine Initialisierung machen, das hab ich aber schon in den verschiedensten Varianten probiert, null Ergebnis.
Es gibt eine Initialisierung für den Problemfall, daß der Power-On Fehlschlug und der normale Init, falls man nur paar Einstellungen ändern will, beides aber ohne Reaktion.
Im Internet findet man ein ganze Menge von derartigen Schaltungen, aber ich kann kein entscheidenen Unterschied entdecken.
Habt ihr vielleicht schonmal ein LCD angeschlossen und da ähnliche Probleme gehabt und eine Lösung gefunden???
Hier mal mein Quellcode für WinAVR (gcc):
#include <avr/io.h>
#include <avr/delay.h>
// Steuerbits bei PortB
#define LCD_RS 3 //Pin für RS
#define LCD_RW 6 //Pin für Read/Write
#define LCD_E 1 //Pin für Enable
#define wait500ns _delay_loop_1(3)
#define wait1us _delay_loop_1(5)
void avr_init(void);
void LCD_Clear (void);
void LCD_Command (char Data);
void LCD_Data (char Data);
void LCD_Init (void);
void waitms(char ms);
void waitms2(int ms);
void waitus(char us);
void waitus2(int us);
int main(void)
{
avr_init();
LCD_Init();
while(1)
{
LCD_Clear();
waitms2(1000);
LCD_Data('a');
LCD_Data('b');
LCD_Data('c');
waitms2(1000);
}
return 0;
}
void avr_init(void)
{
// Initialize device here.
DDRB = 255;
PORTB=0;
DDRA = 255;
PORTA=0;
}
void LCD_Clear (void)
{
LCD_Command (1); //Clear Display
waitms(160);
LCD_Command (0x80); //Set DD-Ram Adresse = 0
}
void LCD_Command (char Data)
{
cbi(PORTB,LCD_RS); //RS = 0 Steuerregister
cbi(PORTB,LCD_RW); //Zum Schreiben RW-Pin = Low
sbi(PORTB,LCD_E);
PORTA = Data;
wait500ns;
cbi(PORTB,LCD_E);
wait500ns;
waitus(50);
}
void LCD_Data (char Data)
{
sbi(PORTB,LCD_RS); //RS = 1 Datenregister
cbi(PORTB,LCD_RW); //Zum Schreiben RW-Pin = Low
sbi(PORTB,LCD_E);
PORTA = Data;
wait500ns;
cbi(PORTB,LCD_E);
wait500ns;
waitus(50);
}
void LCD_Init (void)
{
waitms2(30);
// --- Variante 1 ---
/*LCD_Command (0%00110000); // init
waitms2(5);
LCD_Command (0%00110000); // init
waitus2(150);
LCD_Command (0%00110000); // init
waitms2(5);
// -----------
LCD_Command (0%00111000); // init
waitus2(150);
LCD_Command (0%00001000); // display off
waitus2(150);
LCD_Command (0%00000001); // display clear
waitus2(150);
LCD_Command (0%00000110); // increment cursor
waitus(150);
// -----------
LCD_Command (0%00001111); // disp on, curs on, blink on
waitus2(150);
LCD_Command (0%10000000); //Set DD-Ram Adresse = 0
waitus2(150);*/
// --- Variante 2 ---
LCD_Command(0%00111000); // 8bit, 2line
LCD_Command(0%00001111); // disp on, curs on, blink on
LCD_Command(0%00000001); // clear
waitms(160);
LCD_Command(0%00000110); // increment cursor
// --- Variante 3 ---
/*LCD_Command(0%00110100);
LCD_Command(0%00001001);
LCD_Command(0%00110000);
LCD_Command(0%00001111);
LCD_Command(0%00000001);
waitms(160);
LCD_Command(0%00000110);*/
}
void waitms(char ms)
{
for (;ms>0;ms--)
{
_delay_loop_2(4000); // 1 = 4 cycles
}
}
void waitms2(int ms)
{
for (;ms>0;ms--)
{
_delay_loop_2(4000); // 1 = 4 cycles
}
}
void waitus(char us)
{
for (;us>0;us--)
{
_delay_loop_1(4); // 1 = 4 cycles
}
}
void waitus2(int us)
{
for (;us>0;us--)
{
_delay_loop_1(4); // 1 = 4 cycles -> 16 cycles
}
}
ich wollte gern ein 16x2 LCD-Display mit meinem ATTiny26 im 8bit-Modus ansteuern. Der Tiny26 hat zwei 8bit-Ports, PORTA verwende ich für den Datenbus, die drei Steuerbits kommen vom PORTB. Taktung ist 16 Mhz.
Das Problem ist nur, mit dem LCD passiert rein garnichts, nicht mal ein zucken.
Ich hab schon zwei verschiedene LCD's ausprobiert ein 16x2 und ein 40x4, beide von Reichelt.
Das 40x4 wird komplett dunkel, das 16x2 bleibt komplett hell. An einem gekauften Mega8-Board funktionieren aber beide.
Laut Datenblatt vom HD44780 muss man eine Initialisierung machen, das hab ich aber schon in den verschiedensten Varianten probiert, null Ergebnis.
Es gibt eine Initialisierung für den Problemfall, daß der Power-On Fehlschlug und der normale Init, falls man nur paar Einstellungen ändern will, beides aber ohne Reaktion.
Im Internet findet man ein ganze Menge von derartigen Schaltungen, aber ich kann kein entscheidenen Unterschied entdecken.
Habt ihr vielleicht schonmal ein LCD angeschlossen und da ähnliche Probleme gehabt und eine Lösung gefunden???
Hier mal mein Quellcode für WinAVR (gcc):
#include <avr/io.h>
#include <avr/delay.h>
// Steuerbits bei PortB
#define LCD_RS 3 //Pin für RS
#define LCD_RW 6 //Pin für Read/Write
#define LCD_E 1 //Pin für Enable
#define wait500ns _delay_loop_1(3)
#define wait1us _delay_loop_1(5)
void avr_init(void);
void LCD_Clear (void);
void LCD_Command (char Data);
void LCD_Data (char Data);
void LCD_Init (void);
void waitms(char ms);
void waitms2(int ms);
void waitus(char us);
void waitus2(int us);
int main(void)
{
avr_init();
LCD_Init();
while(1)
{
LCD_Clear();
waitms2(1000);
LCD_Data('a');
LCD_Data('b');
LCD_Data('c');
waitms2(1000);
}
return 0;
}
void avr_init(void)
{
// Initialize device here.
DDRB = 255;
PORTB=0;
DDRA = 255;
PORTA=0;
}
void LCD_Clear (void)
{
LCD_Command (1); //Clear Display
waitms(160);
LCD_Command (0x80); //Set DD-Ram Adresse = 0
}
void LCD_Command (char Data)
{
cbi(PORTB,LCD_RS); //RS = 0 Steuerregister
cbi(PORTB,LCD_RW); //Zum Schreiben RW-Pin = Low
sbi(PORTB,LCD_E);
PORTA = Data;
wait500ns;
cbi(PORTB,LCD_E);
wait500ns;
waitus(50);
}
void LCD_Data (char Data)
{
sbi(PORTB,LCD_RS); //RS = 1 Datenregister
cbi(PORTB,LCD_RW); //Zum Schreiben RW-Pin = Low
sbi(PORTB,LCD_E);
PORTA = Data;
wait500ns;
cbi(PORTB,LCD_E);
wait500ns;
waitus(50);
}
void LCD_Init (void)
{
waitms2(30);
// --- Variante 1 ---
/*LCD_Command (0%00110000); // init
waitms2(5);
LCD_Command (0%00110000); // init
waitus2(150);
LCD_Command (0%00110000); // init
waitms2(5);
// -----------
LCD_Command (0%00111000); // init
waitus2(150);
LCD_Command (0%00001000); // display off
waitus2(150);
LCD_Command (0%00000001); // display clear
waitus2(150);
LCD_Command (0%00000110); // increment cursor
waitus(150);
// -----------
LCD_Command (0%00001111); // disp on, curs on, blink on
waitus2(150);
LCD_Command (0%10000000); //Set DD-Ram Adresse = 0
waitus2(150);*/
// --- Variante 2 ---
LCD_Command(0%00111000); // 8bit, 2line
LCD_Command(0%00001111); // disp on, curs on, blink on
LCD_Command(0%00000001); // clear
waitms(160);
LCD_Command(0%00000110); // increment cursor
// --- Variante 3 ---
/*LCD_Command(0%00110100);
LCD_Command(0%00001001);
LCD_Command(0%00110000);
LCD_Command(0%00001111);
LCD_Command(0%00000001);
waitms(160);
LCD_Command(0%00000110);*/
}
void waitms(char ms)
{
for (;ms>0;ms--)
{
_delay_loop_2(4000); // 1 = 4 cycles
}
}
void waitms2(int ms)
{
for (;ms>0;ms--)
{
_delay_loop_2(4000); // 1 = 4 cycles
}
}
void waitus(char us)
{
for (;us>0;us--)
{
_delay_loop_1(4); // 1 = 4 cycles
}
}
void waitus2(int us)
{
for (;us>0;us--)
{
_delay_loop_1(4); // 1 = 4 cycles -> 16 cycles
}
}