Forum: Mikrocontroller und Digitale Elektronik Attiny2313 mit HD44780 LCD


von Mr.x (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
ich habe mir vor ein paar Tage ein 4 Zeilen/16 Zeichen LCD mit HD44780 
Controller gekauft und will das jetzt mit einem STK500 + Attiny2313 
betreiben.
Das LCD zeigt beim Start in Zeile 2 und 4 Weisse Balken an. Nach der 
Initialisierung durch den Atmega sind die Balken weg und das Display 
leer. Leider wird mir der im Code vorgegebene Text nicht angezeigt. (Am 
Kontrast schauben bringt auch nichts).

Die LCD Lib ist von Peter Fleury. Die LCD Pinbelegung, der CPU Tankt und 
der 4Bit Mode wurden in der lcd.h angepasst.

Der Controller läuft mit 4MHz und der Flash wird über den ISP Mode 
beschrieben.

Das LCD ist wie Folgt an den Controller angeschlossen:

LCD_DATA0_PIN    -> PB0
LCD_DATA1_PIN    -> PB1
LCD_DATA2_PIN    -> PB2
LCD_DATA3_PIN    -> PB3
LCD_RS_PIN       -> PB4
LCD_RW_PIN       -> PB5
LCD_E_PIN        -> PB6

Wie man sieht soll das ganze im 4-Bit Mode laufen.

p.S.: In der main.c sind soviele Delays, weil ich gedacht habe, dass das 
LCD evtl zu langsam für den Atmega ist und nicht hinterher kommt. Aber 
auch daran scheint es nicht zu hängen.

von J.-u. G. (juwe)


Lesenswert?

Mr.x schrieb:
> LCD_DATA0_PIN    -> PB0
> LCD_DATA1_PIN    -> PB1
> LCD_DATA2_PIN    -> PB2
> LCD_DATA3_PIN    -> PB3
> LCD_RS_PIN       -> PB4
> LCD_RW_PIN       -> PB5
> LCD_E_PIN        -> PB6
>
> Wie man sieht soll das ganze im 4-Bit Mode laufen.

Bei den LCD, die ich bisher hatte, müssen im 4-Bit-Modus die 
LCD-Datenpins 4 bis 7 mit den Datenleitungen des µC verbunden werden.

von Jens G. (jensig)


Lesenswert?

>Bei den LCD, die ich bisher hatte, müssen im 4-Bit-Modus die
>LCD-Datenpins 4 bis 7 mit den Datenleitungen des µC verbunden werden.

Genau:

DB0 to DB3 4 I/O MPU
Four low order bidirectional tristate data bus
pins. Used for data transfer and receive
between the MPU and the HD44780U.
These pins are not used during 4-bit operation.

von Mr.x (Gast)


Lesenswert?

UPS das kommt in der lcd.h nicht rüber.
Habe die Datenpins 4-7 am µC angeschlossen.

von Karl H. (kbuchegg)


Lesenswert?

Mach da mal ein F_CPU davor
1
#define F_CPU 4000000
2
3
#include <stdlib.h>
4
#include <avr/io.h>
5
#include <avr/pgmspace.h>
6
#include <util/delay.h>
7
#include "lcd.h"
8
...

ansonsten stimmen die Zeiten deiner _delay_ms nicht.

Alternativ: schmeiss die _delay_ms am Anfang raus. Nach dem Textausgeben 
ist ok. Du verbrutzels nach dem Einschalten erst mal 3 Sekunden und 3 
Sekunden können lang sein, wenn man auf etwas wartet. Sicher, dass du 
lang genug gewartet hast, ehe sich am LCD was tun sollte?

von USBASP User (Gast)


Lesenswert?

Hallo Herr Moderator,

Das F_CPU kann er sich schenken. Er verwendet die Fleury Library und die 
funktioniert seit Jahren in dieser Form.
In der lcd.h ist folgender Eintrag:

#define XTAL 4000000              /**< clock frequency in Hz, used to 
calculate delay timer */

Das sollte doch reichen, oder?

von Karl H. (kbuchegg)


Lesenswert?

USBASP User schrieb:
> Hallo Herr Moderator,
>
> Das F_CPU kann er sich schenken. Er verwendet die Fleury Library und die
> funktioniert seit Jahren in dieser Form.

Es geht nicht um die Fleury Lib, es geht um
#include <util/delay.h>
und darum, dass seine main() mit ein paar _delay_ms anfängt.

von USBASP User (Gast)


Lesenswert?

delay.h wird hier nicht verwendet. Daher ist F_CPU zwar nicht 
syntaktisch falsch aber überflüssig.

von Karl H. (kbuchegg)


Lesenswert?

USBASP User schrieb:
> delay.h wird hier nicht verwendet. Daher ist F_CPU zwar nicht
> syntaktisch falsch aber überflüssig.

Dann muss ich was an den Augen haben.

1. Posting
main.c
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/pgmspace.h>
4
#include <util/delay.h>
5
#include "lcd.h"
6
7
8
int main(void)
9
{
10
11
  /* initialize display, cursor off */
12
  lcd_init(LCD_DISP_ON);
13
  _delay_ms(1000);
14
  lcd_clrscr();
15
  _delay_ms(1000);
16
  lcd_gotoxy(0,0); 
17
  _delay_ms(1000);
18
    for (;;) {                           /* loop forever */
19
    /* clear display and home cursor */
20
    lcd_puts("TEST");
21
    _delay_ms(1000);
22
  }
23
}

wenn die 4 mal so lang dauern wie vorgesehen, sind das 12 Sekunden bis 
zum ersten mal was geschrieben wird. Da kann man schon mal die Nerven 
verlieren. 12 Sekunden sind lang, wenn man darauf wartet.

Da die Balken verschwinden, wird sein LCD initialisiert.

von Mr.x (Gast)


Angehängte Dateien:

Lesenswert?

Guten Morgen zusammen,
ich habe die Datenleitungen und die RS, RW, E Leitungen mal auf 
verschiedene PORTs gelegt.

#define LCD_PORT         PORTB        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN    0            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    2            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    3            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      PORTD        /**< port for RS line         */
#define LCD_RS_PIN       0            /**< pin  for RS line         */
#define LCD_RW_PORT      PORTD        /**< port for RW line         */
#define LCD_RW_PIN       1            /**< pin  for RW line         */
#define LCD_E_PORT       PORTD        /**< port for Enable line     */
#define LCD_E_PIN        2            /**< pin  for Enable line     */

Außerdem habe ich die _delay_ms(1000) gelöscht. Das LCD bleibt 
dummerweise immernoch leer.

Kann es vielleicht sein, dass die LCDlib nur für LCDs mit 2 Zeilen 
geeignet ist und mit einem 4 Zeilen LCD nicht funktioniert?

von Karl H. (kbuchegg)


Lesenswert?

Schmeiss mal den lcd_clear und den gotoxy raus. Je weniger du im 
Programm hast, was schief gehen kann, desto besser.
1
int main(void)
2
{
3
4
  /* initialize display, cursor off */
5
  lcd_init(LCD_DISP_ON);
6
    for (;;) {                           /* loop forever */
7
    lcd_puts("TEST");
8
    _delay_ms(1000);
9
  }
10
}

von Mr.x (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Schmeiss mal den lcd_clear und den gotoxy raus. Je weniger du im
> Programm hast, was schief gehen kann, desto besser.
>
> int main(void)
> {
>
>   /* initialize display, cursor off */
>   lcd_init(LCD_DISP_ON);
>     for (;;) {                           /* loop forever */
>     lcd_puts("TEST");
>     _delay_ms(1000);
>   }
> }

Funktioniert leider auch nicht.
Ich glaube ja immernoch das LCD ist für den µC zu langsam (LCD arbeitet 
noch die Initialisierung ab und der µC ist schon beim nächsten Befehl).
Kann es sein, dass die Optimierung -Os zuviel weg optimiert?


Die initialisierung funktioniert mitlerweile auch nurnoch bei jedem 
zweiten oder dritten Neustart des µC.


Was mir noch aufgefallen ist:
1. STK500 Start -> Balke weg, LCD leer
2. STK500 Neustart / LCD hängt an einem externen Netzteil und wird nicht 
neugestartet (LCD immernoch leer) -> Nach dem Zweiten Neustart sind die 
Balken wieder da



Was mich TOTAL verwirrt ist, das ganze lief gestern morgen mal kurz. Bis 
ich das STK500 neu gestartet habe, danach war das LCD wieder leer. Ich 
habe gedacht, der Flash vom µC wo das Programm drauf war hat sich evtl 
verabschiedet und habe code unverändert wieder auf das Controller 
geschoben, aber dann ging nichtsmehr.. :(

von Karl H. (kbuchegg)


Lesenswert?

Mr.x schrieb:
> Karl Heinz Buchegger schrieb:
>> Schmeiss mal den lcd_clear und den gotoxy raus. Je weniger du im
>> Programm hast, was schief gehen kann, desto besser.
>>
>> int main(void)
>> {
>>
>>   /* initialize display, cursor off */
>>   lcd_init(LCD_DISP_ON);
>>     for (;;) {                           /* loop forever */
>>     lcd_puts("TEST");
>>     _delay_ms(1000);
>>   }
>> }
>
> Funktioniert leider auch nicht.
> Ich glaube ja immernoch das LCD ist für den µC zu langsam (LCD arbeitet
> noch die Initialisierung ab und der µC ist schon beim nächsten Befehl).

Du kannst natürlich im LCD Code mal alle Wertezeiten etwas länger 
machen.

> Kann es sein, dass die Optimierung -Os zuviel weg optimiert?

Nein.

> Die initialisierung funktioniert mitlerweile auch nurnoch bei jedem
> zweiten oder dritten Neustart des µC.

OK.
Das ist ein Hinweis.
Mach die Wartezeiten im LCD Code überall ein wenig länger. Das dürfte 
sich dann schon knapp am Limit bewegen.

von Mr.x (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe heute wieder ein bischen Zeit mich um das LCD Problem zu 
kümmern.

Karl Heinz Buchegger schrieb:
>> Die initialisierung funktioniert mitlerweile auch nurnoch bei jedem
>> zweiten oder dritten Neustart des µC.
>
> OK.
> Das ist ein Hinweis.
> Mach die Wartezeiten im LCD Code überall ein wenig länger. Das dürfte
> sich dann schon knapp am Limit bewegen.

Deswegen habe ich in der lcd.c in der Funktion "void lcd_init(uint8_t 
dispAttr)" die Wartezeiten mal um 30% erhöht. Bisher aber ohne Erfolg.
Gibt es noch andere Zeiten die man erhöhen muss, die ich bis jetzt 
übersehen habe?


    delay(20800/*16000*/);        /* wait 16ms or more after power-on 
*/

    /* initial write to lcd is 8bit */
    LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);  // _BV(LCD_FUNCTION)>>4;
    LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);  // _BV(LCD_FUNCTION_8BIT)>>4;
    lcd_e_toggle();
    delay(6489/*4992*/);         /* delay, busy flag can't be checked 
here */

    /* repeat last command */
    lcd_e_toggle();
    delay(83/*64*/);           /* delay, busy flag can't be checked here 
*/

    /* repeat last command a third time */
    lcd_e_toggle();
    delay(83/*64*/);           /* delay, busy flag can't be checked here 
*/

    /* now configure for 4bit mode */
    LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);   // 
LCD_FUNCTION_4BIT_1LINE>>4
    lcd_e_toggle();
    delay(83/*64*/);           /* some displays need this additional 
delay */

    /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() 
*/
#else
    /*
     * Initialize LCD to 8 bit memory mapped mode
     */

    /* enable external SRAM (memory mapped lcd) and one wait state */
    MCUCR = _BV(SRE) | _BV(SRW);

    /* reset LCD */
    delay(20800);                           /* wait 16ms after power-on 
*/
    lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit 
interface */
    delay(6489);                            /* wait 5ms 
*/
    lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit 
interface */
    delay(83);                              /* wait 64us 
*/
    lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit 
interface */
    delay(83);


Kann ich die Wartezeiten beliebig weit erhöhen? Habekein Datenblatt zu 
dem LCD gefunden in dem irgendwas daszu steht...

p.S.: Nachdem ich die Wartezeit um 20% erhöht hatte hat das LCD einmal 
funktioniert. (Es wurden in allen Zeilen : angezeigt) Nach dem nächsten 
neustart ging wie gewohnt wieder nichts.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.