www.mikrocontroller.net

Forum: Compiler & IDEs LCD funktioniert ab 4Mhz nicht mehr


Autor: Tobias R. (mumum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe ein Atmega 8 mit einem LCD (HD44780) im 4 Bit Modus.
Es Funktioniert auch alles super blos wenn ich den Internen Takt von
1 MHZ auf 4MHZ stellen will läuft das Programm normal aber mein LCD 
zeigt nur noch wirres Zeug.
Hintergrund ist das ich dan mal einen 8Mhz Quarzoszillator anschließen 
will damit meine Uhrzeit genau ist. Aber es Funktioniert ja noch 
nichtmal mit dem Internen 8 Mhz Takt.
#include <avr/io.h>
#include <avr/interrupt.h>
#include "lcd-routines.c"
#include <util/delay.h>

extern int sprintf(char *__s, const char *__fmt, ...);       //Umwandeln einer Zahl in einen String

volatile int timer=0;
volatile int z=0;                          // Toggle Variable für Sekunden
int  stunden=23, minuten=59, sekunden=0;             //hier bitte die Uhrzeit einstellen
int min_on=0, std_on=0;
int min_of=0, std_of=1;
char minutenstring[3], stundenstring[3];            //, sekundenstring[3];
char std_on_string[3], min_on_string[3], std_of_string[3], min_of_string[3];


ISR(TIMER1_OVF_vect){
  TCNT1 = 34286;
  timer++;
  z++;
  PORTB ^= (1<<PB0);  // PB0 ist Status-LED Ausgang
}
//###########################FENSTER_1##################################################################################
void FENSTER_1(void){
int x=1;
  lcd_clear();
  set_cursor (3, 1); lcd_string ("Uhrzeit");
  sprintf(stundenstring, "%d", stunden);
        set_cursor (3, 2);
        if (stunden<10) lcd_string ("0");
        lcd_string (stundenstring);
  sprintf(minutenstring, "%d", minuten);
        set_cursor (6, 2);
        if (minuten<10) lcd_string ("0");
        lcd_string (minutenstring);  


while (x){

if ((sekunden!=timer) && (PINC &(1<<PINC5) )) {      //Zeiteinstellschalter nicht gedrückt

      if (z<=1)   {set_cursor (5, 2);lcd_string (":");}    // Toggle den Sekundendoppelpunkt
      else     {set_cursor (5, 2);lcd_string (" ");z=0;}

      sekunden=timer;
      
      if (sekunden==60)      {          //Sekunde bis 60 Zählen dan 0
        timer=0;  sekunden=0; minuten++;
        
        if (minuten==60)  {            //Minute bis 60 Zählen dan 0
          minuten=0; 
          stunden++;
          if (stunden==24) stunden=0;
                  }
        
        sprintf(minutenstring, "%d", minuten);
        set_cursor (6, 2);
        if (minuten<10) lcd_string ("0");
        lcd_string (minutenstring);
          
        sprintf(stundenstring, "%d", stunden);
        set_cursor (3, 2);
        if (stunden<10) lcd_string ("0");
        lcd_string (stundenstring);
                    }

      if ((std_on==stunden)&&(min_on==minuten)) PORTD &= ~(1<<PD7);
      if ((std_of==stunden)&&(min_of==minuten)) PORTD |=  (1<<PD7);
                                             
                        }    
            
                
        
if (!(PINC &(1<<PINC5) ))             {  //Schalter für Zeiteinstellung 

      set_cursor (5, 2);lcd_string (":");
        
      if (!(PINC &(1<<PINC3) ))  {      //Stundeneinstellung
        stunden++;
        if (stunden==24) stunden=0;  
        sprintf(stundenstring, "%d", stunden);
        set_cursor (3, 2);
        if (stunden<10) lcd_string ("0");
        lcd_string (stundenstring);
        _delay_ms(255);
                    }
      if (!(PINC &(1<<PINC2) ))  {      //Minuteneinstellung
        minuten++;
        if (minuten==60) minuten=0;
        sprintf(minutenstring, "%d", minuten);
        set_cursor (6, 2);
        if (minuten<10) lcd_string ("0");
        lcd_string (minutenstring);
        _delay_ms(255);
                    }
      timer=0;
                        }
if (!(PINC &(1<<PINC1) )) x=0; 
      }
    }
//#########################FENSTER_2###########################################################################################
void FENSTER_2(void) {
char x=1;              // Fenster_Bit
char y=0;              // ON / OF Bit



  lcd_clear();

  while (x)  {

    sekunden=timer;
      
    if (sekunden==60)      {          //Sekunde bis 60 Zählen dan 0
      timer=0;  sekunden=0; minuten++;
        
      if (minuten==60)  {            //Minute bis 60 Zählen dan 0
        minuten=0; 
        stunden++;
        if (stunden==24) stunden=0;
                }  }

    set_cursor (3, 1); lcd_string ("Schaltzeit");
    set_cursor (6, 2);lcd_string ("bis");
    sprintf(std_on_string, "%d", std_on);  
    sprintf(min_on_string, "%d", min_on);        
    sprintf(std_of_string, "%d", std_of);
    sprintf(min_of_string, "%d", min_of);

    if (!(PINC &(1<<PINC5) )) {_delay_ms(200);y++;}

    //Zeige Einschaltzeit Stunde
    set_cursor (0, 2);
    if (std_on<10) lcd_string ("0");
    lcd_string (std_on_string);

    //Doppelpunkt
    set_cursor (2, 2);lcd_string (":");set_cursor (13, 2);lcd_string (":");

    //Zeige Einschaltzeit Minute
    set_cursor (3, 2);
    if (min_on<10) lcd_string ("0");
    lcd_string (min_on_string);

    //Zeige Ausschaltzeit Stunde
    set_cursor (11, 2);
    if (std_of<10) lcd_string ("0");
    lcd_string (std_of_string);

    //Zeige Ausschaltzeit Minute
    set_cursor (14, 2);
    if (min_of<10) lcd_string ("0");
    lcd_string (min_of_string);

      if (y==1)       {            //Einschaltzeit
        if (z<=1)   {set_cursor (2, 2);lcd_string (":");}    // Toggle den Sekundendoppelpunkt
        else     {set_cursor (2, 2);lcd_string (" ");z=0;}
        if (!(PINC &(1<<PINC3) ))  {      //Einschalt Stunde
          std_on++;
          _delay_ms(255);
          if (std_on==24) std_on=0;
                      }
                        
        if (!(PINC &(1<<PINC2) ))  {      //Einschalt Minute
          min_on++;
          _delay_ms(255);
          if (min_on==60) min_on=0;
                      }      
                }

      if (y==2)       {            //Ausschaltzeit
      if (z<=1)   {set_cursor (13, 2);lcd_string (":");}    // Toggle den Sekundendoppelpunkt
      else     {set_cursor (13, 2);lcd_string (" ");z=0;}
        if (!(PINC &(1<<PINC3) ))  {      //Ausschalt Stunde
          std_of++;
          _delay_ms(255);
          if (std_of==24) std_of=0;
                      }      

        if (!(PINC &(1<<PINC2) ))  {      //Ausschalt Minute
          min_of++;
          _delay_ms(255);
          if (min_of==60) min_of=0;
                  }      
            }
      if (y==3)  y=0;  
                    
          
      if (PINC &(1<<PINC1) ) {y=0;x=0;}
      }
  }
//#########################MAIN#################################################################
int main(void){


    DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2);         // Ausgang
  DDRC &= ~(1<<PC5) | ~(1<<PC3) | ~(1<<PC2) | ~(1<<PC1);  // Eingang
  PORTC|= (1<<PC5) | (1<<PC3) | (1<<PC2) | (1<<PC1);     //internen Pull-Up-Widerstand einschalten
  DDRD |=  (1<<PD7);PORTD |= (1<<PD7);          // Ausgang und erstmal AUS
  
  //Timer 1 initialisieren:
  TIMSK |= _BV(TOIE1);                       //aktivieren des �berlaufinterrupts von Timer1 
  TCCR1B = _BV(CS12);                       //Prescaler = 256
  TCNT1 = 0xFFFF;                         //Z�hlregister vorladen mit FFFF zum Sofortstart 
  
  sei();                              //Interrupts aktivieren
  
  lcd_init();
  lcd_clear();
  
  
  sprintf(stundenstring, "%d", stunden);  
  sprintf(minutenstring, "%d", minuten);        
                                  //  sprintf(sekundenstring, "%d", sekunden);

  
  
  while(1){

  if (PINC &(1<<PINC1) )      FENSTER_1();

  if (!(PINC &(1<<PINC1)) )  FENSTER_2();

    }    
 
  return(0);
  }




Autor: G Ast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann ist wohl dein Timing zum LCD falsch.
Es reicht auch nicht nur die Fuses zu verändern, dein Programm musst du 
bei Verwendung der delay_ms() mit der korrekten Frequenz auch neu 
compiliere.

Ansonsten: lcd-routines.c fehlt.

Autor: Mike R. (thesealion)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich tippe auf eine fehlerhafte initialisierung des LCDs :-)

Für eine genauere Analyse mußt du aber ein paar mehr Informationen 
liefern.

edit
Mist zu langsam :-)

Ansonsten fällt mir gerade noch auf: Hast du die CPU Frequenz auch im 
Makefile bzw. den Projekteinstellungen angepasst? Ansosnten kann die 
delay() Funktion nicht richtig arbeiten.

Autor: Tobias R. (mumum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super danke also hat gereicht im Makefile 8MHZ einzustellen. So LCD 
Funktioniert jetzt aba die delay Funktion macht noch bisschen wirres 
Zeug muss man die Frequenz noch wo anders umstellen?

Autor: Thomas K. (muetze1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum zum Teufel inkludierst du eine .c Datei?

Autor: MeinerEiner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> #include "lcd-routines.c"

Pfui! Macht man nicht.

Eigentlich gibts nur 2 Stellen für die CPU-Frequenz, die zusammenpassen 
müssen: Die mit den Fuses eingestellten sowie F_CPU.
(Natürlich muss die Angabe auf dem Quarz dann zu F_CPU passen, wenn denn 
so einer verwendet wird).

Damit _delay_ms() & Co. richtig arbeiten, muss auch eine Optimierung 
aktiv sein. Mit -O0 arbeiten die nicht (richtig).

Autor: Mike R. (thesealion)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außerdem gibt es für die delay() Funktionen Obergrenzen, bis zu welcher 
Wartezeit die bei einer bestimmten Frequenz funktionieren.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Außerdem gibt es für die delay() Funktionen Obergrenzen, bis zu welcher
>Wartezeit die bei einer bestimmten Frequenz funktionieren.

Enee. Schon seit ewigen Zeiten (speich: avrlibc-Versionen) nicht mehr. 
Wie schreibt die Doku:

"...providing delays up to 6.5535 seconds (independent from CPU 
frequency). "

Die Genauigkeit wird ab einer CPU-frequenzabhängigen Wartezeit 
reduziert, aber gewartet wird. Das sollte für eine LCD-Ansteuerung bei 
weitem ausreichen.

Oliver

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.