LCD funktioniert ab 4Mhz nicht mehr

OP #1512134
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.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "lcd-routines.c"
4
#include <util/delay.h>
5

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

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

16

17
ISR(TIMER1_OVF_vect){
18
  TCNT1 = 34286;
19
  timer++;
20
  z++;
21
  PORTB ^= (1<<PB0);  // PB0 ist Status-LED Ausgang
22
}
23
//###########################FENSTER_1##################################################################################
24
void FENSTER_1(void){
25
int x=1;
26
  lcd_clear();
27
  set_cursor (3, 1); lcd_string ("Uhrzeit");
28
  sprintf(stundenstring, "%d", stunden);
29
        set_cursor (3, 2);
30
        if (stunden<10) lcd_string ("0");
31
        lcd_string (stundenstring);
32
  sprintf(minutenstring, "%d", minuten);
33
        set_cursor (6, 2);
34
        if (minuten<10) lcd_string ("0");
35
        lcd_string (minutenstring);  
36

37

38
while (x){
39

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

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

45
      sekunden=timer;
46
      
47
      if (sekunden==60)      {          //Sekunde bis 60 Zählen dan 0
48
        timer=0;  sekunden=0; minuten++;
49
        
50
        if (minuten==60)  {            //Minute bis 60 Zählen dan 0
51
          minuten=0; 
52
          stunden++;
53
          if (stunden==24) stunden=0;
54
                  }
55
        
56
        sprintf(minutenstring, "%d", minuten);
57
        set_cursor (6, 2);
58
        if (minuten<10) lcd_string ("0");
59
        lcd_string (minutenstring);
60
          
61
        sprintf(stundenstring, "%d", stunden);
62
        set_cursor (3, 2);
63
        if (stunden<10) lcd_string ("0");
64
        lcd_string (stundenstring);
65
                    }
66

67
      if ((std_on==stunden)&&(min_on==minuten)) PORTD &= ~(1<<PD7);
68
      if ((std_of==stunden)&&(min_of==minuten)) PORTD |=  (1<<PD7);
69
                                             
70
                        }    
71
            
72
                
73
        
74
if (!(PINC &(1<<PINC5) ))             {  //Schalter für Zeiteinstellung 
75

76
      set_cursor (5, 2);lcd_string (":");
77
        
78
      if (!(PINC &(1<<PINC3) ))  {      //Stundeneinstellung
79
        stunden++;
80
        if (stunden==24) stunden=0;  
81
        sprintf(stundenstring, "%d", stunden);
82
        set_cursor (3, 2);
83
        if (stunden<10) lcd_string ("0");
84
        lcd_string (stundenstring);
85
        _delay_ms(255);
86
                    }
87
      if (!(PINC &(1<<PINC2) ))  {      //Minuteneinstellung
88
        minuten++;
89
        if (minuten==60) minuten=0;
90
        sprintf(minutenstring, "%d", minuten);
91
        set_cursor (6, 2);
92
        if (minuten<10) lcd_string ("0");
93
        lcd_string (minutenstring);
94
        _delay_ms(255);
95
                    }
96
      timer=0;
97
                        }
98
if (!(PINC &(1<<PINC1) )) x=0; 
99
      }
100
    }
101
//#########################FENSTER_2###########################################################################################
102
void FENSTER_2(void) {
103
char x=1;              // Fenster_Bit
104
char y=0;              // ON / OF Bit
105

106

107

108
  lcd_clear();
109

110
  while (x)  {
111

112
    sekunden=timer;
113
      
114
    if (sekunden==60)      {          //Sekunde bis 60 Zählen dan 0
115
      timer=0;  sekunden=0; minuten++;
116
        
117
      if (minuten==60)  {            //Minute bis 60 Zählen dan 0
118
        minuten=0; 
119
        stunden++;
120
        if (stunden==24) stunden=0;
121
                }  }
122

123
    set_cursor (3, 1); lcd_string ("Schaltzeit");
124
    set_cursor (6, 2);lcd_string ("bis");
125
    sprintf(std_on_string, "%d", std_on);  
126
    sprintf(min_on_string, "%d", min_on);        
127
    sprintf(std_of_string, "%d", std_of);
128
    sprintf(min_of_string, "%d", min_of);
129

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

132
    //Zeige Einschaltzeit Stunde
133
    set_cursor (0, 2);
134
    if (std_on<10) lcd_string ("0");
135
    lcd_string (std_on_string);
136

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

140
    //Zeige Einschaltzeit Minute
141
    set_cursor (3, 2);
142
    if (min_on<10) lcd_string ("0");
143
    lcd_string (min_on_string);
144

145
    //Zeige Ausschaltzeit Stunde
146
    set_cursor (11, 2);
147
    if (std_of<10) lcd_string ("0");
148
    lcd_string (std_of_string);
149

150
    //Zeige Ausschaltzeit Minute
151
    set_cursor (14, 2);
152
    if (min_of<10) lcd_string ("0");
153
    lcd_string (min_of_string);
154

155
      if (y==1)       {            //Einschaltzeit
156
        if (z<=1)   {set_cursor (2, 2);lcd_string (":");}    // Toggle den Sekundendoppelpunkt
157
        else     {set_cursor (2, 2);lcd_string (" ");z=0;}
158
        if (!(PINC &(1<<PINC3) ))  {      //Einschalt Stunde
159
          std_on++;
160
          _delay_ms(255);
161
          if (std_on==24) std_on=0;
162
                      }
163
                        
164
        if (!(PINC &(1<<PINC2) ))  {      //Einschalt Minute
165
          min_on++;
166
          _delay_ms(255);
167
          if (min_on==60) min_on=0;
168
                      }      
169
                }
170

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

180
        if (!(PINC &(1<<PINC2) ))  {      //Ausschalt Minute
181
          min_of++;
182
          _delay_ms(255);
183
          if (min_of==60) min_of=0;
184
                  }      
185
            }
186
      if (y==3)  y=0;  
187
                    
188
          
189
      if (PINC &(1<<PINC1) ) {y=0;x=0;}
190
      }
191
  }
192
//#########################MAIN#################################################################
193
int main(void){
194

195

196
    DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2);         // Ausgang
197
  DDRC &= ~(1<<PC5) | ~(1<<PC3) | ~(1<<PC2) | ~(1<<PC1);  // Eingang
198
  PORTC|= (1<<PC5) | (1<<PC3) | (1<<PC2) | (1<<PC1);     //internen Pull-Up-Widerstand einschalten
199
  DDRD |=  (1<<PD7);PORTD |= (1<<PD7);          // Ausgang und erstmal AUS
200
  
201
  //Timer 1 initialisieren:
202
  TIMSK |= _BV(TOIE1);                       //aktivieren des �berlaufinterrupts von Timer1 
203
  TCCR1B = _BV(CS12);                       //Prescaler = 256
204
  TCNT1 = 0xFFFF;                         //Z�hlregister vorladen mit FFFF zum Sofortstart 
205
  
206
  sei();                              //Interrupts aktivieren
207
  
208
  lcd_init();
209
  lcd_clear();
210
  
211
  
212
  sprintf(stundenstring, "%d", stunden);  
213
  sprintf(minutenstring, "%d", minuten);        
214
                                  //  sprintf(sekundenstring, "%d", sekunden);
215

216
  
217
  
218
  while(1){
219

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

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

224
    }    
225
 
226
  return(0);
227
  }
Gast #1512155
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.
#1512161
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.
Gast #1512722
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).
Gast #1512817
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren