Forum: Compiler & IDEs LCD-Initialisierung


von Daniel (Gast)


Lesenswert?

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);
}


*/

von Werner Hoch (Gast)


Lesenswert?

Hi,

Ich hab nicht den gesamten Quelltext gelesen:

aber:

wait[] ist undefiniert.

mfg
werner

von Daniel (Gast)


Lesenswert?

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

von Werner Hoch (Gast)


Lesenswert?

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

von Daniel (Gast)


Lesenswert?

Vielen Dank, das mit dem wegoptimieren hab ich mir schon fast gedacht.
ich werd dann mal deine Schleifen ausprobieren.
Nochmal Danke!

Daniel

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.