Forum: Mikrocontroller und Digitale Elektronik LCD zusammen mit Tastenprellung macht Probleme


von Daniel (Gast)


Lesenswert?

Vielleicht kann mir jemand helfen. Stehe etwas auf dem Schlauch. Und 
zwar benutze ich die Tastenprell Routine aus dem Tutorial von Peter 
Dannegger. Funktioniert einwandfrei, nur wenn ich zu schnell die Tasten 
druecke, dann kommt mein LCD Display nicht mehr mit und zeigt nichts 
mehr an. Ich habe schon versucht, die Zeiten zu aendern, aber leider 
ohne Erfolg. Dies liegt wahrscheinlich daran, dass ich nicht weiss, ob 
ich die Zeiten von der Tastenabfrage aendern soll oder die Zeiten meiner 
LCD Routine.
Die Tastenabfrage hab ich in der main Schleife drin(wie im Tutorial), 
nur benutze ich nicht den Overflowinterrupt sondern den 
Compareinterrupt, da ich eine Uhr parrallel dazu laufen habe. Mein 
Systemtakt liegt bei 4Mhz und der Overflow wird erreicht alle 10ms.
Leider bin ich kein Profi und habe noch Schwierigkeiten mit dem einen 
oder anderen Problem. Daher hoffe ich, dass mir einer helfen kann.
Gruss
Daniel

von Daniel (Gast)


Lesenswert?

Hab gerade gemerkt, dass auch bei langsamen schalten, eine Stoerung 
auftreten kann und dass Display nicht mehr funktioniert. Es scheint als 
ob sich irgenwie etwas zufaellig ueberlappt.

von Daniel (Gast)


Lesenswert?

Nochmal ich. Vielleicht habe ich das Problem gefunden. Ich habe zwei 
Datenbits fuer das Display am Pin PC7 und PC6. Leider kann ich diese 
nicht mehr verschieben. Da in der Abfrage der Tastenentprellung der PINC 
geprueft wird koennte ich mir vorstellen, dass es da Konflikte gibt. Wie 
begrenze ich die Abfrage nur auf die Pins 0-3
i = key_state ^ ~KEY_PIN;
#define KEY_PIN    PINC

Oder kann da es da kein Problem geben und es liegt doch an den Zeiten. 
Bitte helft mir.

von Karl H. (kbuchegg)


Lesenswert?

Daniel wrote:

> begrenze ich die Abfrage nur auf die Pins 0-3
> i = key_state ^ ~KEY_PIN;
> #define KEY_PIN    PINC
>

Da im Tastencode reine Abfragen des PIN Registers gemacht
werden, sollte das kein Problem sein. Der Tasten Code führt
dir 2 Pseudo Tasten mit, die sich etwas seltsam verhalten
werden aber wenn du die Tasten nicht benutzt sollte das
kein Problem darstellen.

Welchen LCD Code benutzt du? Könnte es eventuell ein Problem
mit dem Handling des DDR Registers sein?

Was ich mal tun würde: Alle High-Level LCD Funktionen
dahingehend bearbeiten, dass sie am Funktionsstart einen cli()
und am Funktionsende einen sei() haben. Dann kann dir zumindest
der Tasten-Interrupt nicht mehr in die LCD Funktionen reinspucken.

von Daniel (Gast)


Lesenswert?

Hier mal meine LCD Routine. Wie gesagt, LCD_D6 und 7 sins als Pin PC6 
und PC7 definiert. Wenn ich ein cli() und sei() in die LCD_data routine 
einsetze, dann resetet mein µC beim druecken der Taste.

P.S. Die delay Zeiten musste ich aendern, sodass die Anzeige was 
anzeigt.



#define  LCD_D4    SBIT( PORTC, 7 )
#define  LCD_DDR_D4  SBIT( DDRC, 7 )

#define  LCD_D5    SBIT( PORTC, 6 )
#define  LCD_DDR_D5  SBIT( DDRC, 6 )

#define  LCD_D6    SBIT( PORTD, 2 )
#define  LCD_DDR_D6  SBIT( DDRD, 2 )

#define  LCD_D7    SBIT( PORTD, 3 )
#define  LCD_DDR_D7  SBIT( DDRD, 3 )

#define  LCD_RS    SBIT( PORTD, 4 )
#define  LCD_DDR_RS  SBIT( DDRD, 4 )

#define  LCD_E0    SBIT( PORTD, 5 )
#define  LCD_DDR_E0  SBIT( DDRD, 5 )

void lcd_data( u8 d )
{
  LCD_RS = 1;
  lcd_byte( d );

}

void lcd_nibble( u8 d )
{

  LCD_D4 = 0; if( d & 1<<4 ) LCD_D4 = 1;
  LCD_D5 = 0; if( d & 1<<5 ) LCD_D5 = 1;
  LCD_D6 = 0; if( d & 1<<6 ) LCD_D6 = 1;
  LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;

  LCD_E0 = 1;
  _delay_us( 4 );//1      // 1us
  LCD_E0 = 0;

}


void lcd_byte( u8 d )
{
  lcd_nibble( d );
  lcd_nibble( d<<4 );
  _delay_us( 45 );//45
        // 45us
}


void lcd_command( u8 d )
{
  LCD_RS = 0;
  lcd_byte( d );
  switch( d ){
    case 1:
    case 2:
    case 3: _delay_ms( 4 );//2    // wait 2ms
  }

}


void lcd_init( void )
{
  LCD_DDR_D4 = 1;
  LCD_DDR_D5 = 1;
  LCD_DDR_D6 = 1;
  LCD_DDR_D7 = 1;
  LCD_DDR_RS = 1;
  LCD_DDR_E0 = 1;

  LCD_E0 = 0;
  LCD_RS = 0;        // send commands
  _delay_ms( 40 );//15      // wait 15ms

  lcd_nibble( 0x30 );
  _delay_ms( 13 );  //5    // wait >4.1ms

  lcd_nibble( 0x30 );
  _delay_us( 400 );  //100      // wait >100æs

  lcd_nibble( 0x30 );      // 8 bit mode
  _delay_us( 400 );  //100    // wait >100æs

  lcd_nibble( 0x20 );      // 4 bit mode
  _delay_us( 400 );//100      // wait >100æs

  lcd_command( 0x28 );      // 2 lines 5*7
  lcd_command( 0x08 );      // display off
  lcd_command( 0x01 );      // display clear
  lcd_command( 0x06 );                  // cursor increment
  lcd_command( 0x0C );
        // on, no cursor, no blink
}


// setzt den Cursor in Zeile y (1..4) Spalte x (0..15)

void set_cursor(uint8_t column, uint8_t line)
{
   if( line & 1 )
    column += 0x40;

  lcd_command( 0x80 + column );
}


// Schreibt einen String auf das LCD

void lcd_string(char *data)
{
    while(*data) {
        lcd_data(*data);
        data++;
    }
}



Deine Routine wird im Compare Interrupt mit dieser Funktion abgefragt.



void exe_keypad(void)
{

static unsigned char ct0, ct1, rpt;
  unsigned char i;

  //TCNT0 = (u8)(s16)-(XTAL / 1024 * 10e-3 + 0.5);  // preload for 10ms

  i = key_state ^ ~KEY_PIN;    // key changed ?
  ct0 = ~( ct0 & i );      // reset or count ct0
  ct1 = ct0 ^ (ct1 & i);    // reset or count ct1
  i &= ct0 & ct1;      // count until roll over ?
  key_state ^= i;      // then toggle debounced state
  key_press |= key_state & i;    // 0->1: key press detect

  if( (key_state & REPEAT_MASK) == 0 )  // check repeat function
     rpt = REPEAT_START;    // start delay
  if( --rpt == 0 ){
    rpt = REPEAT_NEXT;      // repeat delay
    key_rpt |= key_state & REPEAT_MASK;
  }
}

von Peter D. (peda)


Lesenswert?

Lange Sachen immer als Anhang!

Es ist auch völlig nutzlos, nur Fragmente zu posten.

Insbesondere das main fehlt.


Poste was compilierbares, was den Fehler enthält.
Bei mehreren Files als ZIP.


Peter

von Daniel (Gast)


Angehängte Dateien:

Lesenswert?

Ich hoffe du kannst mir irgendwie helfen. Dies ist so ungefaer mein 
erstes grosse Projekt. Daher ist es wahrscheinlich bei weitem nicht 
optimal. Aber vielleicht findest du das Problem. Ich bin naemlich schon 
am verzweifeln.
Vielen Dank schon mal!!!!

von Daniel (Gast)


Lesenswert?

Sorry, kleiner Fehler. LCD_routines wird nicht verwendet, ist aber in 
der ZIP Datei.

von Daniel (Gast)


Lesenswert?

@Peter Hab wahrscheinlich an der falschen Stelle mein cli() gesetzt. 
Jetzt funktionierts. Danke aber vielmals!!!! Mit deiner Hilfe kann man 
immer rechnen

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.