LCD-Initialisierung

Gast #40637
Hallo,
ich hab Probleme mit der Initialisierung meines LCD. Ich benutze den
8535 mit 8MHz.
Ich denke es liegt an den Pausen, die man einlegen muss, weil ich mit
den Verzögerungsschleifen auch noch nicht so recht klarkomme.
Vielleicht könnt ihr euch den Qullcode mal angucken und mir
weiterhelfen. Danke

#include <lcd.h>



#define LCD_BLANK()        {lcd_send_command(1);delay_ms(2);}

#define DISPLAY_ON()     {lcd_send_command(12);}

#define DISPLAY_OFF()     {lcd_send_command(8 v);}

#define nop() asm volatile ("nop")


typedef unsigned char byte;


// Hier befinden sich die Eigenschaften der LCD-Anzeige für die
Initialisierung
byte LCD_INIT_STRING[] = {0x28, 0x0C, 0x01, 0x06};
// 44 = FunktionSet 44 = 0010 1000 = 2C
// 0, 12 = Display an
// 0, 1  = clear Display
// 0, 6 = Entry mode set

//Wartearray für Initialisierung
byte wait[] = {,,};
//5ms, 110us, 110us


int main(void)
{




  //Portbelegung
  //PortA Taster
  outp(0x00, DDRA);

  //PortB LEDs
  outp(0xff, DDRB);
  outp(0x00, PORTB);



  lcd_init();                // Initialisierung der LCD-Anzeige



  lcd_putc(1, "Ein Test");



  for(;;)
  {



      {
        outp(0xf0, PORTB);

      }


  }
}




void lcd_send_nibble( byte n )
{


        outp(n<<4, PORTC);

  sbi(PORTC, 2);  //Enable = 1
           nop();
        cbi(PORTC, 2);  //Enable =0

}

void lcd_send_byte( byte address, byte n )
{
  if(address)
     sbi(PORTC,0);  //RS = 1 ->Daten schreiben
   else
     cbi(PORTC,0);  //RS = 0 ->Kommando senden

      cbi(PORTC, 1);  //RW = 0
   //   sbi(PORTC, 2);  //E = 1

  wait_busy();
      lcd_send_nibble(n >> 4);
  wait_busy();
      lcd_send_nibble(n & 0x0f);

}

byte lcd_init()
{
    byte i;

    outp(0xff, DDRC);

   //RS, RW auf 0,E auf 0
    cbi(PORTC, 0);               // siehe 4-Bit Initialisierung
(LCD-Datenblatt)
   // cbi(PORTC, 1);
    cbi(PORTC, 2);


  //Länger als 15ms warten
  long_delay();  // 16 ms Pause

    for(i=0;i<3;i++)
    {
       lcd_send_nibble(3);
       if(i==0 || i == 1)
           long_delay(wait[i]);

       else
          delay(wait[i]);

    }


  lcd_send_nibble(2);
  delay();

    for(i=0; i <= 3; i++)
    {
       lcd_send_command(LCD_INIT_STRING[i]);

    }


}



void lcd_gotoxy( byte x, byte y)
{
   byte address;

   if (y==1)  address=0;  //
   else if (y==2) address=0x40;
   else address=0;

   address += x-1;

   lcd_send_command(0x80|address); //mmmmmh, ob das stimmt?
}



void lcd_putc( byte Zeile, char f)
{
//  lcd_gotoxy(1, Zeile);
  lcd_send_data(f);
}


void lcd_send_command(byte cmd)
{
  lcd_send_byte(0, cmd);
}

void lcd_send_data(byte data)
{
  lcd_send_byte(1, data);
}


void wait_busy()
{
      register byte data;

  cbi(PORTC,0);  //RS = 0
      sbi(PORTC, 1);  //  RW = 1
   //   sbi(PORTC, 2);  //E = 1 (HIGH)
      outp(0x0f, DDRC);  //BIT 7-4 als Input

  do
  {
    sbi(PORTC, 2);  //Enable = 1
    nop();
         data = inp(PINC);
          cbi(PORTC, 2);  //Enable = 0

  }while(data & 0x80);

  //Standards Wiederherstellen
  outp(0xff, DDRC); //Port C wieder Ausgang
  cbi(PORTC,1);  //RW wieder 0

}





void delay(unsigned char n)            //Wie kann ich hier die
                                       //verstrichene Zeit errechnen?
{
  while(n--);
}

void long_delay(unsigned char loop)
{
  unsigned char warten, i;
  for(i=loop; i>0; i--)
  {
    warten = 1000;
    while(warten--);
  }
}






/* 16-bit count, 4 cycles/loop */
/*void delay_loop_2(unsigned int __count)
{
  asm volatile (
    "1: sbiw %0,1" "\n\t"
    "brne 1b"
    : "=w" (__count)
    : "0" (__count)
  );
}


//  1 Mikrosekunde,      stimmt die Berchnung
// 1us sollten doch 8 Cycles sein, oder? bei 8MHz
void delay_us(unsigned int count)
{
  delay_loop_2( 2 * count);
}


//  1 Millisekunde
void delay_ms(unsigned int count)
{
  delay_us(1000 * count);
}


*/
Gast
Ich hab das undefiniert gelassen, so wie jede andere delay-schleife
auch, weil ich nicht weiß welchen Wert ich da benutzten soll.
Am Ende von dem Quelltext sind zwei unterschiedliche Arten von
Delayloops, die aber beide nicht richtig funktionieren, wobei
zzumindest die, die ich auskommentiert habe, richtig funktionieren
sollte.

mfg
  Daniel
Gast
Deine eigenen delay-Funktion gehen nicht, weil der Compiler die
Zählschleifen wegoptimierten kann.
Aus:
  warten=1000;
  while(warten--);
wird dann:
  warten -=1000;

Ich verwende z.Zt diese Warteschleifen:

void
lcd_delay_5ms() {
  uint16_t i;
  /* t = i * loop / UC_CLOCK
     i = t / loop * UC_CLOCK
     the fastest way the compiler can do that loop takes 5 clocks:
     2 clocks for decrementing, 1 for nop, 2 clocks to branch.
     take care that i does not exceed max(uint16_t) */
  for (i=UC_CLOCK*0.005/5; i; i--)
    asm volatile("nop\n\t"::);   /* required to prevent compiler
optimisation */
}

inline void
lcd_delay_50us() {
  uint8_t i;
  /* t = i * loop / UC_CLOCK
     i = t / loop * UC_CLOCK
     the fastest way the compiler can do that loop takes 4 clocks:
     1 clocks for decrementing, 1 for nop, 2 clocks to branch.
     take care that i does not exceed max(uint8_t) */
  for (i=UC_CLOCK*50e-6/4; i; i--)
    asm volatile("nop\n\t"::);   /* required to prevent compiler
optimisation */
}

meine Init-Routine sieht so aus:
void lcd_init() {
  uint8_t i;

  LCD_DATA_PORT &= ~LCD_DATA_MASK; /* clear the data pins */
  LCD_DATA_DDR |= LCD_DATA_MASK;   /* define the data pins as output */
  LCD_ENABLE_PORT &= ~_BV(LCD_ENABLE_PIN);  /* clear enable pin */
  LCD_ENABLE_DDR |= _BV(LCD_ENABLE_PIN);  /* and define as output */
  LCD_RS_PORT &= ~_BV(LCD_RS_PIN);  /* clear RS pin */
  LCD_RS_DDR |= _BV(LCD_RS_PIN);  /* and define as output */

  for (i=50; i; i--)    /* 250ms power up wait */
    lcd_delay_5ms();

  LCD_DATA_PORT |= 0x03;   /* put the LCD into 8-bit mode, send 3-times
*/
  lcd_enable();
  lcd_delay_5ms();         /* 1 */
  lcd_enable();
  lcd_delay_5ms();         /* 2 */
  lcd_enable();
  lcd_delay_5ms();         /* 3 */

  LCD_DATA_PORT &= ~LCD_DATA_MASK;   /* delete the data port pins */
  LCD_DATA_PORT |= 0x02;   /* put lcd into 4-bit mode */
  lcd_enable();
  lcd_delay_5ms();

  /* function set (bit 7-5 */
  /* 4-bit mode (bit4), 2-lines (bit3), 7*5 dots (bit2), xx bit1-0 */
  lcd_command(0x28);

  /* entry mode set (bit7-2)
     cursor move direction increase (bit1=1), display is not shifted
(bit0=0) */
  lcd_command(0x06);

  /* display mode set (bit7-3)
     display on (bit2=1), cursor on (bit1=1), blinking off (bit0=0) */
  lcd_command(0x0E);
}


mfg
werner

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 23 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.