Forum: Mikrocontroller und Digitale Elektronik Wechsel von ATmega8 auf ATmega32 - Codeanpassung


von Tobi (Gast)


Lesenswert?

Hallo zusammen,

da mein Programm nach einer Erweiterung für einen ATmega8 zu groß 
geworden ist, versuche ich gerade auf einen ATmega32 umzusteigen.
Ohne die Erweiterung lief das Programm einwandfrei auf dem ATmega8, 
selbiges läuft nach Anpassung aber nicht auf dem 32er.
Genauer gesagt funktionieren die Button nicht. Diese entprelle ich mit 
dem Code von Peter Fleury.
Angeschlossen sind sie nun an Port C (Pin 0-3) des 32ers. JTAG sollte 
eigentlich ausgeschaltet sein über Fuse Bit.
Habe es auch schon an PortB versucht um sicher zu gehen.

Ein angeschlossenes LCD funktioniert so wie es soll, und hat mir bei dem 
ATmega8 immer angezeigt ob ein Button gedrückt wurde (vereinfacht).

Nun bleibt für mich als Fehlerursache ein eventuell falsch 
initialisierter Timer0, der für das "Debouncen" genutzt wird. Kann mir 
jemand sagen, ob ich bei der Anpassung einen Fehler gemacht habe?

Funktionierende Timer-Initialisierung bei ATmega8:
1
void init_8Bit_Timer0(void){
2
3
  TCCR0B = (1<<CS02)|(1<<CS00);         // divide by 1024
4
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
5
  TIMSK0 |= 1<<TOIE0;                   // enable timer interrupt
6
 
7
    sei();
8
9
}

Timer-Initialisierung bei ATmega32:
1
void init_8Bit_Timer0(void){
2
3
  TCCR0 = (1<<CS02)|(1<<CS00);         // divide by 1024
4
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
5
  TIMSK |= 1<<TOIE0;                   // enable timer interrupt
6
 
7
    sei();
8
9
}

Hat vielleicht jemand noch Ideen, an welcher Stelle der Fehler sonst 
lauern könnte?

Ich hoffe die Informationen genügen. Für erste Hilfestellungen wäre ich 
dankbar.

PS.: Mir fällt noch ein, das ich nun mit 8MHz arbeite und nicht wie 
vorher mit 1MHz. Dies habe ich aber als F_CPU eingestellt und auch beim 
Flashen. Sonst würde das LCD ja nicht funktionieren.

Gruß
Tobi

von Detlef K. (adenin)


Lesenswert?

Gibt es beim ATmega8 ein TCCR0B Register?
Ich kenne nur TCCR0.
Und TIMSK0 ???

Was sagt den der Simulator zu deinem Code?

von Tobi (Gast)


Lesenswert?

Hallo,

ich bitte um Entschuldigung, ich hätte die Typen genauer angeben sollen.
Bei dem ATmega8 handelt es sich um einen ATmega48-20PU.
Bei dem ATmega32 um einen ATmega32-16PU.
Die Register heißen bei diesem Typ wohl etwas anders ;)

Detlef Kunz schrieb:
> Und TIMSK0 ???

Dort setze ich nur das "overflow interrupt enable" Flag.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Tobi schrieb:
> Bei dem ATmega8 handelt es sich um einen ATmega48-20PU.
Das ist ein ganz schöner Unterschied.

Öh, wenn nur das Programm zu gross wurde, warum nimmst du dann nicht den 
Mega88/168/328?
Bei denen ist nämlich bis auf RAM und Flashgrösse alles genauso wie beim 
Mega48.

Detlef Kunz schrieb:
> Ich kenne nur TCCR0.

Und auch nur dieses gibt es beim Mega32, nix TCCR0B.

von Detlef K. (adenin)


Lesenswert?

Ok, damit ist die Sache mit den Registernamen geklärt.
Jetzt must Du nur noch klären ob im alten Code PinChange-Interrupts 
benutzt wurden, bzw die Flags zu diesen Interrupts.
Hier fehlt (wie üblich) sehr viel an Information zum Programm und der 
verwendeten Hardware.

von Tobi (Gast)


Lesenswert?

Matthias Sch. schrieb:
> Öh, wenn nur das Programm zu gross wurde, warum nimmst du dann nicht den
> Mega88/168/328?

Weil ich den ATmega32 noch hier herumfliegen habe ;)

Was sind denn "PinChange-Interrupts", und was fehlt an Infos? Fehlt euch 
die Abfrage der Interrupts von Peter Fleury?
1
ISR( TIMER0_OVF_vect )                            // every 10ms
2
{
3
  static uint8_t ct0, ct1, rpt;
4
  uint8_t i;
5
 
6
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
7
 
8
  i = key_state ^ ~KEY_PIN;                       // key changed ?
9
  ct0 = ~( ct0 & i );                             // reset or count ct0
10
  ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
11
  i &= ct0 & ct1;                                 // count until roll over ?
12
  key_state ^= i;                                 // then toggle debounced state
13
  key_press |= key_state & i;                     // 0->1: key press detect
14
#ifdef KEY_REPEAT_ON
15
  if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
16
     rpt = REPEAT_START;                          // start delay
17
  if( --rpt == 0 ){
18
    rpt = REPEAT_NEXT;                            // repeat delay
19
    key_rpt |= key_state & REPEAT_MASK;
20
  }
21
#endif
22
}

Zur Schaltung kann ich nur noch sagen, das die Buttons wie vorher auch 
nach Masse geschaltet sind.
Ich kann auch das gesamte Programm hochladen, wenn das jemand möchte. 
Allerdings wird dann sicherlich mehr über meinen Programmierstil 
debattiert, als über potentielle Fehlerursachen ;)

Aber es muss ja mit den angepassten Stellen zusammenhängen und nicht mit 
dem restlichen Code. Bis auf die Einstellung des richtigen Device, die 
Ports und die 2 Timer (der zweite ist für eine Uhr und läuft), war 
nichts zu ändern.

Gruß
Tobi

von Detlef K. (adenin)


Lesenswert?

Im Moment wird nur über den Informationsstil debattiert :P

Und
1
  ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
sollte besser
1
  ct1 = (ct0 ^ ct1) & i;                          // reset or count ct1
lauten

: Bearbeitet durch User
von Tobi (Gast)


Lesenswert?

Hat keiner mehr eine Idee woran es liegen könnte?

von Detlef K. (adenin)


Lesenswert?

Dann musst Du wohl doch den Code mal hochladen. :(

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Detlef Kunz schrieb:
> Und
1
ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
> sollte besser
1
ct1 = (ct0 ^ ct1) & i;                          //  reset or count ct1
> lauten

In PeDas Entprellroutine steht aber die erste Variante - und die 
funktioniert tadellos.
http://www.mikrocontroller.net/articles/Entprellung

: Bearbeitet durch User
von Detlef K. (adenin)


Lesenswert?

Matthias Sch. schrieb:
> In PeDas Entprellroutine steht aber die erste Variante - und die
> funktioniert tadellos.
> http://www.mikrocontroller.net/articles/Entprellung

Und ich hab es mit dem Code von Peter Fleury verglichen, der im ersten 
Post als Quelle angegeben wurde.

Ein echtes Problem ist aber, das hier (wieder mal) nur Teile eines 
Programmes gepostet werden, und der Fehler irgendwo anders erzeugt 
werden könnte.
Es wäre ja sonst auch zu einfach den Code im Simulator zu testen.

von Kaj (Gast)


Lesenswert?

Tobi schrieb:
> Was sind denn "PinChange-Interrupts",
Wenn du ins Datenblatt auf die Pinbelegung schaust, findest du Pins an 
denen PCINTxx steht, (xx durch nummer ersetzen, z.B. 23), das sind die 
Pins fuer Pin-ChangeInterrupt.
Ein Pin-ChangeInterrupt wird ausgeloest, wie der Name ja schon sagt, 
wenn sich das Level an dem entsprechenden Pin aendert. Der Interrupt 
wird dabei aber durch jegliche aenderung am Pin ausgeloest, du hast 
keine Moeglichkeit einzustellen ob der Interrupt nur bei steigender oder 
fallender Flanke ausgeloest werden soll.

Gruesse

von Tobi (Gast)


Lesenswert?

Hallo,

zunächst wünsche ich erst mal allen frohe Weihnachten!

Wie bereits geschrieben, kann ich den Code gerne hochladen... Hier ist 
er:
1
/*************************************************************************
2
Title:    Aquarium Control v2
3
Author:   Tobias xxxxxx
4
Software: AVR-GCC 3.3, HD44780U LCD library by Peter Fleury
5
Hardware: ATmega32, HD44780 compatible LCD text display
6
          
7
**************************************************************************/
8
#define F_CPU 8000000 //8000000
9
10
#include <stdlib.h>
11
#include <avr/io.h>
12
#include <avr/pgmspace.h>
13
#include <util/delay.h>
14
#include <avr/interrupt.h>    //Interruptheader
15
#include "lcd.h"
16
17
#define INTRO_ON
18
#define KEY_PRESSED_ON
19
//#define KEY_REPEAT_ON
20
21
/*Defines für Button-Debouncing*/
22
#define KEY_DDR         DDRC
23
#define KEY_PORT        PORTC
24
#define KEY_PIN         PINC
25
#define KEY0            0
26
#define KEY1            1
27
#define KEY2            2
28
#define KEY3            3
29
#define ALL_KEYS        (1<<KEY0 | 1<<KEY1 | 1<<KEY2 | 1<<KEY3)
30
 
31
#define REPEAT_MASK     (1<<KEY1 | 1<<KEY2)       // repeat: key1, key2
32
#define REPEAT_START    50                        // after 500ms
33
#define REPEAT_NEXT     20                        // every 200ms
34
35
/*Defines für Transistor-Schalter*/
36
#define LED_DDR         DDRA
37
#define LED_PORT        PORTA
38
#define LED_PIN         PINA
39
#define LED_BACKLIGHT   1
40
#define VALVE      0
41
42
/*Alternative*/
43
44
//#define XTAL    11059201L  // nominal value F_CPU
45
//#define F_CPU    11059008L  // after measuring deviation: 1.5s/d
46
47
#define DEBOUNCE  256L    // debounce clock (256Hz = 4msec)
48
49
#define uchar unsigned char
50
#define uint unsigned int
51
52
uchar prescaler;
53
uchar volatile second;      // count seconds
54
uchar volatile minute;      // count minute
55
uchar volatile hour;      // count hour
56
uchar volatile btnCount = 0;      
57
uchar volatile countFLAG;
58
uchar volatile valveFLAG;
59
60
typedef enum {  INTRO, 
61
        INIT_TIMER,
62
        GRUNDZUSTAND, 
63
        UHR_AKTUALISIEREN, 
64
        COUNTER_AKTUALISIEREN, 
65
        UHR_MENU, 
66
        VENTIL_MENU,
67
        VENTIL_MENU1,
68
        LICHT_MENU,
69
        LICHT_MENU1, 
70
        FUTTER_MENU,
71
        FUTTER_MENU1,
72
        UHR_STELLEN1,
73
        UHR_STELLEN2,
74
        UHR_STELLEN3,
75
        UHR_STELLEN4,
76
        VENTIL_AUF_ZU1,
77
        VENTIL_AUF_ZU2, 
78
        VENTIL_AUF_UHR1, 
79
        VENTIL_AUF_UHR2, 
80
        VENTIL_ZU_UHR1,
81
        VENTIL_ZU_UHR2, 
82
        LICHT_STRG, 
83
        FUTTER_STRG
84
       } state_t ;
85
 
86
state_t volatile state;
87
88
volatile uint8_t key_state;                       // debounced and inverted key state:
89
                                                  // bit = 1: key pressed
90
volatile uint8_t key_press;                       // key press detect
91
 
92
volatile uint8_t key_rpt;                         // key long press and repeat
93
94
/*
95
** constant definitions
96
*/
97
98
static const PROGMEM unsigned char sonderzeichen[64] =
99
{
100
  0x00, 0x04, 0x0E, 0x15, 0x04, 0x04, 0x04, 0x00, //Pfeil nach oben
101
  0x00, 0x04, 0x04, 0x04, 0x15, 0x0E, 0x04, 0x00, //Pfeil nach unten
102
  0x0A, 0x00, 0x11, 0x11, 0x11, 0x13, 0x0D, 0x00, //Umlaut ü
103
  0x00, 0x00, 0x07, 0x0A, 0x10, 0x09, 0x07, 0x01, //Fisch Teil 1
104
  0x00, 0x00, 0x11, 0x0D, 0x03, 0x15, 0x18, 0x00, //Fisch Teil 2
105
  0x00, 0x0A, 0x0A, 0x00, 0x11, 0x0E, 0x00, 0x00,  //Smiley
106
  0x00, 0x00, 0x04, 0x0E, 0x1F, 0x0A, 0x0E, 0x00,  //Home
107
  0x00, 0x10, 0x10, 0x14, 0x12, 0x1F, 0x02, 0x04  //Enter
108
109
};
110
#ifdef INTRO_ON
111
static const PROGMEM unsigned char bigFish[] =
112
{
113
  0x00,0x00,0x00,0x03,0x04,0x08,0x10,0x10,
114
  0x00,0x07,0x1F,0x00,0x00,0x08,0x18,0x00,
115
  0x00,0x1C,0x18,0x0C,0x03,0x00,0x00,0x00,
116
  0x00,0x00,0x03,0x05,0x09,0x12,0x02,0x04,
117
  
118
  0x10,0x08,0x06,0x01,0x00,0x00,0x00,0x00,
119
  0x00,0x00,0x08,0x1C,0x06,0x01,0x00,0x00,
120
  0x00,0x11,0x12,0x1C,0x10,0x10,0x00,0x00,
121
  0x04,0x14,0x0C,0x06,0x00,0x00,0x00,0x00 
122
};
123
static const PROGMEM unsigned char bigFish_reverse[] =
124
{
125
  0x00,0x00,0x18,0x14,0x12,0x09,0x08,0x04,
126
  0x00,0x07,0x03,0x06,0x18,0x00,0x00,0x00,
127
  0x00,0x1C,0x1F,0x00,0x00,0x02,0x03,0x00,
128
  0x00,0x00,0x00,0x18,0x04,0x02,0x01,0x01,
129
130
  0x04,0x05,0x06,0x0C,0x00,0x00,0x00,0x00,
131
  0x00,0x11,0x09,0x07,0x01,0x01,0x00,0x00,
132
  0x00,0x00,0x02,0x07,0x0C,0x10,0x00,0x00,
133
  0x01,0x02,0x0C,0x10,0x00,0x00,0x00,0x00
134
};
135
#endif
136
137
/*
138
** function prototypes
139
*/ 
140
141
ISR( TIMER0_OVF_vect )                            // every 10ms
142
{
143
  static uint8_t ct0, ct1, rpt;
144
  uint8_t i;
145
 
146
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
147
 
148
  i = key_state ^ ~KEY_PIN;                       // key changed ?
149
  ct0 = ~( ct0 & i );                             // reset or count ct0
150
  ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
151
  i &= ct0 & ct1;                                 // count until roll over ?
152
  key_state ^= i;                                 // then toggle debounced state
153
  key_press |= key_state & i;                     // 0->1: key press detect
154
#ifdef KEY_REPEAT_ON
155
  if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
156
     rpt = REPEAT_START;                          // start delay
157
  if( --rpt == 0 ){
158
    rpt = REPEAT_NEXT;                            // repeat delay
159
    key_rpt |= key_state & REPEAT_MASK;
160
  }
161
#endif
162
}
163
164
ISR(TIMER1_COMPA_vect)             //Bei Compare-Match mit OCR1A (31250) wird Sekunden um eins erhöht.
165
{
166
  #if F_CPU % DEBOUNCE
167
    OCR1A = F_CPU / DEBOUNCE - 1;    // compare DEBOUNCE - 1 times
168
  #endif
169
    if( --prescaler == 0 ){
170
      prescaler = (uchar)DEBOUNCE;
171
      second++;        // exact one second over
172
  #if F_CPU % DEBOUNCE      // handle remainder
173
      OCR1A = F_CPU / DEBOUNCE + F_CPU % DEBOUNCE - 1; // compare once per second
174
  #endif
175
  }
176
177
  countFLAG = 1;
178
  valveFLAG = 1;
179
  
180
  //Berechnen
181
182
    if(second == 60){
183
      minute++;
184
      second = 0;
185
    }
186
187
    if(minute == 60){
188
      hour++;
189
      minute = 0;
190
    }
191
192
    if(hour == 25){
193
      hour = 0;
194
      state = GRUNDZUSTAND;
195
    }
196
}
197
198
///////////////////////////////////////////////////////////////////
199
//
200
// check if a key has been pressed. Each pressed key is reported
201
// only once
202
//
203
#ifdef KEY_PRESSED_ON
204
uint8_t get_key_press( uint8_t key_mask )
205
{
206
  cli();                                          // read and clear atomic !
207
  key_mask &= key_press;                          // read key(s)
208
  key_press ^= key_mask;                          // clear key(s)
209
  sei();
210
  return key_mask;
211
}
212
#endif
213
///////////////////////////////////////////////////////////////////
214
//
215
// check if a key has been pressed long enough such that the
216
// key repeat functionality kicks in. After a small setup delay
217
// the key is reported being pressed in subsequent calls
218
// to this function. This simulates the user repeatedly
219
// pressing and releasing the key.
220
//
221
#ifdef KEY_REPEAT_ON
222
uint8_t get_key_rpt( uint8_t key_mask )
223
{
224
  cli();                                          // read and clear atomic !
225
  key_mask &= key_rpt;                            // read key(s)
226
  key_rpt ^= key_mask;                            // clear key(s)
227
  sei();
228
  return key_mask;
229
}
230
#endif
231
///////////////////////////////////////////////////////////////////
232
//
233
// check if a key is pressed right now
234
//
235
uint8_t get_key_state( uint8_t key_mask )
236
 
237
{
238
  key_mask &= key_state;
239
  return key_mask;
240
}
241
 
242
///////////////////////////////////////////////////////////////////
243
//
244
uint8_t get_key_short( uint8_t key_mask )
245
{
246
  cli();                                          // read key state and key press atomic !
247
  return get_key_press( ~key_state & key_mask );
248
}
249
 
250
///////////////////////////////////////////////////////////////////
251
//
252
#ifdef KEY_LONG_PRESSED_ON
253
uint8_t get_key_long( uint8_t key_mask )
254
{
255
  return get_key_press( get_key_rpt( key_mask ));
256
}
257
#endif
258
259
/*
260
void Einstellen (void)             //Dient dem Einstellen der Uhr
261
{
262
  
263
}
264
*/
265
void init_16Bit_Timer1(void){
266
  //Registerinitialisierung
267
  
268
  TCCR1B = 1<<WGM12^1<<CS10;    // divide by 1
269
          // clear on compare
270
    OCR1A = F_CPU / DEBOUNCE - 1;
271
    TCNT1 = 0;
272
    second = 0;
273
    prescaler = (uchar)DEBOUNCE;
274
275
    TIMSK = 1<<OCIE1A;
276
277
  sei();
278
279
}
280
281
void init_8Bit_Timer0(void){
282
283
  TCCR0 = (1<<CS02)|(1<<CS00);         // divide by 1024
284
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
285
  TIMSK |= 1<<TOIE0;                   // enable timer interrupt
286
 
287
    sei();
288
289
}
290
#ifdef INTRO_ON 
291
void intro(void){
292
  lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
293
     
294
  int i = 0;
295
    
296
  for(i=0; i<8*8; i++)  {
297
    lcd_data(pgm_read_byte_near(&bigFish[i]));
298
    }
299
  int x = 0;
300
    for(i=0; i<19; i++){
301
    lcd_clrscr();
302
    x = 15-i;
303
    if(x>=0){
304
      lcd_gotoxy(x,1);
305
      lcd_putc(0);
306
      if(i>0) lcd_putc(1);
307
      if(i>1) lcd_putc(2);
308
      if(i>2) lcd_putc(3);
309
      lcd_gotoxy(x,2);
310
      lcd_putc(4);
311
      if(i>0) lcd_putc(5);
312
      if(i>1) lcd_putc(6);
313
      if(i>2) lcd_putc(7);
314
    }else if(x==-1){
315
      lcd_gotoxy(0,1);
316
      lcd_putc(1);
317
      lcd_putc(2);
318
      lcd_putc(3);
319
      lcd_gotoxy(0,2);
320
      lcd_putc(5);
321
      lcd_putc(6);
322
      lcd_putc(7);
323
    }else if(x==-2){
324
      lcd_gotoxy(0,1);
325
      lcd_putc(2);
326
      lcd_putc(3);
327
      lcd_gotoxy(0,2);
328
      lcd_putc(6);
329
      lcd_putc(7);
330
    }else if(x==-3){
331
    lcd_gotoxy(0,1);
332
      lcd_putc(3);
333
      lcd_gotoxy(0,2);
334
      lcd_putc(7);
335
    }
336
    _delay_ms(180);
337
  }
338
339
  lcd_clrscr();
340
  lcd_gotoxy(5,1);
341
  lcd_puts("AquaControl");
342
  lcd_gotoxy(4,2);
343
  lcd_puts("by T. xxxxxxx");
344
  
345
  lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
346
  i = 0;
347
  
348
  for(i=0; i<8*8; i++)
349
  {
350
    lcd_data(pgm_read_byte_near(&bigFish_reverse[i]));
351
    }
352
  _delay_ms(500);
353
  for(i=0; i<=3; i++){
354
    
355
    lcd_gotoxy(0,1);
356
    if(i>2) lcd_putc(0);
357
    if(i>1) lcd_putc(1);
358
    if(i>0) lcd_putc(2);
359
    lcd_putc(3);
360
    
361
    lcd_gotoxy(0,2);
362
    if(i>2) lcd_putc(4);
363
    if(i>1) lcd_putc(5);
364
    if(i>0) lcd_putc(6);
365
    lcd_putc(7);
366
367
    _delay_ms(250);
368
  }
369
  
370
  lcd_gotoxy(4,1);
371
  //lcd_putc(':');//0xDF
372
  lcd_puts("\xdf");
373
  
374
  _delay_ms(250);
375
  lcd_gotoxy(4,1);
376
  lcd_putc(' ');
377
  lcd_gotoxy(4,0);
378
  lcd_putc('o');
379
  _delay_ms(250);
380
  lcd_gotoxy(4,0);
381
  lcd_putc(' ');
382
  
383
  _delay_ms(1000);
384
  
385
}
386
#endif
387
void menuLeiste(void){
388
  lcd_gotoxy(0,3);
389
  lcd_putc(' ');
390
  lcd_putc(1);
391
  lcd_puts("   ");
392
  lcd_putc(0);
393
  lcd_puts("    ");
394
  lcd_putc(7);
395
  lcd_puts("    ");
396
  lcd_putc(6);
397
}
398
int main(void)
399
{
400
    state_t state = INTRO;
401
  char buffer[7];
402
  short int valve = -1;
403
  int uhr_stell_position = 0;
404
  
405
  countFLAG = 0;
406
  valveFLAG = 0;
407
  
408
  short int uhr_stell_mode = 0;
409
410
411
  uchar Ventil_Time_auf_sec = 0;
412
  uchar Ventil_Time_auf_min = 0;
413
  uchar Ventil_Time_auf_hour = 7;
414
415
  uchar Ventil_Time_zu_sec = 0;
416
  uchar Ventil_Time_zu_min = 0;
417
  uchar Ventil_Time_zu_hour = 18;
418
  
419
420
  int change_second = 0;
421
  int change_minute = 0;
422
  int change_hour = 0;
423
  int i = 0;
424
425
  second = 0;
426
  minute = 0;
427
  hour = 0;
428
429
  btnCount = 0;
430
431
  
432
    // Configure debouncing routines
433
    KEY_DDR &= ~ALL_KEYS;                // configure key port for input
434
    KEY_PORT |= ALL_KEYS;                // and turn on pull up resistors
435
436
  LED_PORT |= (1<<LED_BACKLIGHT);
437
  LED_DDR  |= (1 << LED_BACKLIGHT)|(1 << VALVE);
438
  
439
  init_8Bit_Timer0();
440
441
    /* initialize display, cursor off */
442
    lcd_init(LCD_DISP_ON);
443
444
  for (;;) {                           /* loop forever */
445
446
    if(valveFLAG == 1){
447
      valveFLAG = 0;
448
      if(hour == Ventil_Time_auf_hour && minute == Ventil_Time_auf_min && second == Ventil_Time_auf_sec){
449
        LED_PORT &= ~(1 << VALVE);
450
        valve = -1;
451
        state = GRUNDZUSTAND;
452
      }else if(hour == Ventil_Time_zu_hour && minute == Ventil_Time_zu_min && second == Ventil_Time_zu_sec){
453
        LED_PORT |= (1<<VALVE);
454
        valve = 1;
455
        state = GRUNDZUSTAND;
456
      }
457
    }
458
    switch(state){
459
       case INTRO:
460
        #ifdef INTRO_ON
461
        intro();
462
        #endif
463
        lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
464
        i = 0;
465
        for(i=0; i<64; i++)
466
        {
467
          lcd_data(pgm_read_byte_near(&sonderzeichen[i]));
468
          }
469
        state = INIT_TIMER;
470
        break;
471
      case INIT_TIMER:
472
        init_16Bit_Timer1();
473
        state = GRUNDZUSTAND;
474
        break;
475
      case GRUNDZUSTAND:
476
        /* clear display and home cursor */
477
            lcd_clrscr();
478
        
479
            /* put string to display (line 1) with linefeed */
480
            lcd_puts("Zeit:");
481
        
482
        lcd_gotoxy(0,1);
483
        lcd_puts("Zaehler:");
484
485
        lcd_gotoxy(0,2);
486
        if(valve == 1){
487
          lcd_puts("CO2-Zufuhr:   an");
488
        }else{
489
          lcd_puts("CO2-Zufuhr:  aus");
490
        }
491
        lcd_gotoxy(12,3);
492
        lcd_puts("Men");
493
        lcd_putc(2);
494
        state = COUNTER_AKTUALISIEREN;
495
        break;
496
      case UHR_AKTUALISIEREN:
497
        if(countFLAG == 1){
498
          //Zurücksetzen
499
          countFLAG = 0;
500
          //Ausgeben
501
          lcd_gotoxy(8,0);
502
          if(hour <= 9){
503
            lcd_gotoxy(9,0);
504
          }
505
          utoa( hour , buffer, 10);
506
              lcd_puts(buffer);
507
          lcd_putc(':');
508
          if(minute <= 9){
509
            lcd_putc('0');
510
          }
511
          utoa( minute , buffer, 10);
512
              lcd_puts(buffer);
513
          lcd_putc(':');
514
          if(second <= 9){
515
            lcd_putc('0');
516
          }
517
          utoa( second , buffer, 10);
518
              lcd_puts(buffer);
519
        }
520
        if(get_key_short( 1<<KEY0 )){
521
          btnCount++;
522
          
523
          if(btnCount > 100){
524
            btnCount = 0;
525
            state = GRUNDZUSTAND;
526
          }else{
527
            state = COUNTER_AKTUALISIEREN;
528
          }
529
          
530
        }
531
        if(get_key_short( 1<<KEY3 )){
532
          state = UHR_MENU;
533
        }
534
        break;
535
      case COUNTER_AKTUALISIEREN:
536
        lcd_gotoxy(13,1);
537
        if(btnCount<10){
538
          lcd_gotoxy(15,1);
539
        }else if(btnCount<100){
540
          lcd_gotoxy(14,1);
541
        }
542
543
        if(btnCount != 0){
544
          utoa( btnCount , buffer, 10);
545
          lcd_puts(buffer);
546
        }else{
547
          lcd_putc('0');
548
        }
549
        state = UHR_AKTUALISIEREN;
550
        break;
551
      case UHR_MENU:
552
        lcd_clrscr();
553
        lcd_home();
554
        
555
        lcd_puts("Uhr-Einst.");
556
        lcd_gotoxy(1,1);
557
        lcd_puts("Uhr stellen");
558
        state = UHR_STELLEN1;
559
        menuLeiste();
560
        break;
561
      case VENTIL_MENU:
562
        lcd_clrscr();
563
        lcd_home();
564
        lcd_puts("Ventil-Einst.");
565
        lcd_gotoxy(1,1);
566
        lcd_puts("man. Steuerung");
567
        lcd_gotoxy(1,2);
568
        lcd_puts("u.Zeitsteuerung");
569
        menuLeiste();
570
        state = VENTIL_MENU1;
571
        break;
572
      case VENTIL_MENU1:
573
        if(get_key_short( 1<<KEY0 )){
574
          state = LICHT_MENU;
575
        }
576
        if(get_key_short( 1<<KEY1 )){
577
          state = UHR_MENU;
578
        }
579
        if(get_key_short( 1<<KEY2 )){
580
          state = VENTIL_AUF_ZU1;
581
        }
582
        
583
        if(get_key_short( 1<<KEY3 )){
584
          //Home
585
          state = GRUNDZUSTAND;
586
        }
587
        break;
588
      case LICHT_MENU:
589
        lcd_clrscr();
590
        lcd_home();
591
        lcd_puts("Licht-Einst.");
592
        lcd_gotoxy(1,1);
593
        lcd_puts("Keine Einst.");
594
        lcd_gotoxy(1,2);
595
        lcd_puts("m\xEFglich");
596
        menuLeiste();
597
        lcd_gotoxy(9,3);
598
        lcd_puts("  ");
599
        state = LICHT_MENU1;
600
        break;
601
      case LICHT_MENU1:
602
        if(get_key_short( 1<<KEY0 )){
603
          state = FUTTER_MENU;
604
        }
605
        if(get_key_short( 1<<KEY1 )){
606
          state = VENTIL_MENU;
607
        }
608
        if(get_key_short( 1<<KEY3 )){
609
          //Home
610
          state = GRUNDZUSTAND;
611
        }
612
        break;
613
      case FUTTER_MENU:
614
        lcd_clrscr();
615
        lcd_home();
616
        lcd_puts("Futter-Einst.");
617
        lcd_gotoxy(1,1);
618
        lcd_puts("Keine Einst.");
619
        lcd_gotoxy(1,2);
620
        lcd_puts("m\xEFglich");
621
        menuLeiste();
622
        lcd_gotoxy(9,3);
623
        lcd_puts("  ");
624
        state = FUTTER_MENU1;
625
        break;
626
      case FUTTER_MENU1:
627
        if(get_key_short( 1<<KEY0 )){
628
          state = UHR_MENU;
629
        }
630
        if(get_key_short( 1<<KEY1 )){
631
          state = LICHT_MENU;
632
        }
633
        if(get_key_short( 1<<KEY3 )){
634
          //Home
635
          state = GRUNDZUSTAND;
636
        }
637
        break;
638
      case UHR_STELLEN1:
639
        if(get_key_short( 1<<KEY0 )){
640
          state = VENTIL_MENU;
641
        }
642
        if(get_key_short( 1<<KEY1 )){
643
          state = FUTTER_MENU;
644
        }
645
        if(get_key_short( 1<<KEY2 )){
646
          //Uhr stellen
647
          change_second = second;
648
          change_minute = minute;
649
          change_hour = hour;
650
          uhr_stell_position = 0;
651
          uhr_stell_mode = 0;
652
          state = UHR_STELLEN2;
653
        }
654
        
655
        if(get_key_short( 1<<KEY3 )){
656
          //Home
657
          state = GRUNDZUSTAND;
658
        }
659
        break;
660
      case UHR_STELLEN2:
661
        lcd_clrscr();
662
        lcd_home();
663
        lcd_puts("Uhr stellen");
664
        
665
        lcd_gotoxy(uhr_stell_position+1,2);
666
        lcd_putc('^');
667
668
        lcd_gotoxy(0,3);
669
        lcd_puts(" +   -   ");
670
        lcd_putc('\x7E');
671
        lcd_puts("   OK");
672
        state = UHR_STELLEN3;
673
        
674
        break;
675
      case UHR_STELLEN3:
676
        lcd_gotoxy(0,1);
677
        if(change_hour <= 9){
678
          lcd_gotoxy(1,1);
679
        }
680
        
681
        utoa( change_hour , buffer, 10);
682
            lcd_puts(buffer);
683
        
684
        lcd_putc(':');
685
        if(change_minute <= 9){
686
          lcd_putc('0');
687
        }
688
        utoa( change_minute , buffer, 10);
689
            lcd_puts(buffer);
690
        
691
        lcd_putc(':');
692
        
693
        if(change_second <= 9){
694
          lcd_putc('0');
695
        
696
        }
697
        utoa( change_second , buffer, 10);
698
            lcd_puts(buffer);
699
700
        state = UHR_STELLEN4;
701
        break;
702
      case UHR_STELLEN4:
703
        state = UHR_STELLEN3;
704
        //+
705
        if(get_key_short( 1<<KEY0 )){
706
          if(uhr_stell_position == 0){
707
            change_hour++;
708
            if(change_hour >= 24){
709
              change_hour = 0;
710
              state = UHR_STELLEN2;
711
            }
712
          }else if(uhr_stell_position == 3){
713
            change_minute++;
714
            if(change_minute >= 60){
715
              change_minute = 0;
716
            }
717
          }else if(uhr_stell_position == 6){
718
            change_second++;
719
            if(change_second >= 60){
720
              change_second = 0;
721
              
722
            }
723
          }
724
          
725
        }
726
        //-
727
        if(get_key_short( 1<<KEY1 )){
728
          state = UHR_STELLEN3;
729
          if(uhr_stell_position == 0){
730
            change_hour--;
731
            if(change_hour < 0){
732
              change_hour = 23;
733
            }if(change_hour == 9){
734
              state = UHR_STELLEN2;
735
            }
736
          }else if(uhr_stell_position == 3){
737
            change_minute--;
738
            if(change_minute <0 ){
739
              change_minute = 59;              
740
            }
741
          }else if(uhr_stell_position == 6){
742
            change_second--;
743
            if(change_second < 0){
744
              change_second = 59;              
745
            }
746
          }
747
          
748
        }
749
        if(get_key_short( 1<<KEY2 )){
750
          //Weiter ->
751
          uhr_stell_position += 3;
752
          if(uhr_stell_position > 6){
753
            uhr_stell_position = 0;
754
          }
755
          state = UHR_STELLEN2;
756
        }
757
        if(get_key_short( 1<<KEY3 )){
758
          //Okay
759
          if(uhr_stell_mode == 0){
760
            second = change_second;
761
            minute = change_minute;
762
            hour = change_hour;
763
          }else if(uhr_stell_mode == 1){
764
            Ventil_Time_auf_sec = change_second;
765
            Ventil_Time_auf_min = change_minute;
766
            Ventil_Time_auf_hour = change_hour;
767
          }else if(uhr_stell_mode == 2){
768
            Ventil_Time_zu_sec = change_second;
769
            Ventil_Time_zu_min = change_minute;
770
            Ventil_Time_zu_hour = change_hour;
771
          }
772
          state = GRUNDZUSTAND;
773
        }
774
        break;
775
      case VENTIL_AUF_ZU1:
776
        lcd_clrscr();
777
        lcd_home();
778
        lcd_puts("Ventil-Status:");
779
        if(valve == 1){
780
          lcd_gotoxy(7,1);
781
          lcd_puts("geschlossen");
782
        }else{
783
          lcd_gotoxy(8,1);
784
          lcd_puts("ge");
785
          lcd_putc('\xEF');
786
          lcd_puts("ffnet");
787
        }
788
        
789
        menuLeiste();
790
        state = VENTIL_AUF_ZU2;
791
        break;
792
      case VENTIL_AUF_ZU2:
793
        if(get_key_short( 1<<KEY0 )){
794
          state = VENTIL_AUF_UHR1;
795
        }
796
        if(get_key_short( 1<<KEY1 )){
797
          state = VENTIL_ZU_UHR1;
798
        }
799
        if(get_key_short( 1<<KEY2 )){
800
          //Ventil steuern
801
          valve *= -1;
802
          LED_PORT ^= (1<<VALVE);
803
          state = VENTIL_AUF_ZU1;
804
        }
805
        if(get_key_short( 1<<KEY3 )){
806
          //Home
807
          state = GRUNDZUSTAND;
808
        }
809
        break;
810
      case VENTIL_AUF_UHR1:
811
        lcd_clrscr();
812
        lcd_home();
813
        lcd_puts("Zeitpunkt zum");
814
        lcd_gotoxy(0,1);
815
        lcd_putc('\xEF');
816
        lcd_puts("ffnen festlegen");
817
        menuLeiste();
818
        state = VENTIL_AUF_UHR2;
819
        break;
820
      case VENTIL_AUF_UHR2:
821
        if(get_key_short( 1<<KEY0 )){
822
          state = VENTIL_ZU_UHR1;
823
        }
824
        if(get_key_short( 1<<KEY1 )){
825
          state = VENTIL_AUF_ZU1;
826
        }
827
        if(get_key_short( 1<<KEY2 )){
828
          //VENTIL_AUF_UHR einstellen
829
          change_second = Ventil_Time_auf_sec  ;
830
          change_minute = Ventil_Time_auf_min ;
831
          change_hour = Ventil_Time_auf_hour;
832
          uhr_stell_position = 0;
833
          uhr_stell_mode = 1;
834
          state = UHR_STELLEN2;
835
        }
836
        if(get_key_short( 1<<KEY3 )){
837
          //Home
838
          state = GRUNDZUSTAND;
839
        }
840
        break;
841
      case VENTIL_ZU_UHR1:
842
        lcd_clrscr();
843
        lcd_home();
844
        lcd_puts("Zeitpunkt zum");
845
        lcd_gotoxy(0,1);
846
        lcd_puts("schliessen fest-");
847
        lcd_gotoxy(0,2);
848
        lcd_puts("legen");
849
        menuLeiste();
850
        state = VENTIL_ZU_UHR2;
851
        break;
852
      case VENTIL_ZU_UHR2:
853
        if(get_key_short( 1<<KEY0 )){
854
          state = VENTIL_AUF_ZU1;
855
        }
856
        if(get_key_short( 1<<KEY1 )){
857
          state = VENTIL_AUF_UHR1;
858
        }
859
        if(get_key_short( 1<<KEY2 )){
860
          //VENTIL_ZU_UHR einstellen
861
          change_second = Ventil_Time_zu_sec  ;
862
          change_minute = Ventil_Time_zu_min ;
863
          change_hour = Ventil_Time_zu_hour;
864
          uhr_stell_position = 0;
865
          uhr_stell_mode = 2;
866
          state = UHR_STELLEN2;
867
        }
868
        if(get_key_short( 1<<KEY3 )){
869
          //Home
870
          state = GRUNDZUSTAND;
871
        }
872
        break;
873
      case LICHT_STRG:
874
        lcd_clrscr();
875
        lcd_home();
876
        break;
877
      case FUTTER_STRG:
878
        lcd_clrscr();
879
        lcd_home();
880
        break;
881
      default:
882
        break;
883
     }     
884
    }
885
}

Nicht hochgeladen habe ich lcd.c und lcd.h von Peter Fleury, da diese 
bis auf die Port-Anpassung unverändert sind. Aber das Display 
funktioniert ja wie erwähnt tatellos.
Ich möchte an dieser Stelle noch einmal darauf hinweisen, das dieser 
Code hier auf dem ATmega48 keine Probleme bereitet hat.

Gruß
Tobi

von Michael (Gast)


Lesenswert?

Wichtige Regeln - erst lesen, dann posten!

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

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Tobi schrieb:
> if(hour == 25){
>       hour = 0;
>       state = GRUNDZUSTAND;

Unbedeutend, nur ein kleiner Vertipper. Deine Uhr springt erst bei 25:00 
Uhr auf 0 und nicht bei 24:00.
Ahh, sage mal, hast du denn die JTAGEN Fuse desaktiviert? Die JTAG Pins 
belegen nämlich einen Teil von deinem Keyboard Port und haben schon so 
manchen in die Verzweifelung getrieben - möglicherweise zuletzt deine 
Fische.

: Bearbeitet durch User
von Tobi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

das mit 25:00 Uhr ist mir noch gar nicht aufgefallen, vielen Dank ;)
Betreffendes Fuse Bit sollte eigentlich korrekt gelöscht sein, habe mal 
einen Screenshot angehängt.

Gruß
Tobi

von Tobi (Gast)


Lesenswert?

Hallo,

ich habe nun noch ein wenig herum probiert. Leider kann ich das ganze 
nicht anständig debuggen, da ich Hapsim nicht zum laufen bekomme. Der 
AVR-Hook funktioniert angeblich (Haken ist da), die Porteinstellungen in 
Hapsim sind auch korrekt eingetragen, aber leider komme ich nicht über 
die LCD Routine hinaus.

Also habe ich versucht Pseudo-Hardware-Debugging zu betreiben ;)

Wenn ich die Variable btnCount mit in die ISR vom Button-Debouncing 
nehme, wird diese bis 142 hochgezählt und ab da nicht weiter. Das 
entspricht grob 142 * 10 ms Laufzeit... Also wird die ISR wenigstens 
ausgelöst.
Daraufhin habe ich diese Stelle wieder gelöscht und direkt nach dem 
Intro den passenden Button gedrückt und siehe da, es erscheint eine "1" 
für die Variable btnCount auf dem Display. Anschließend werden aber 
wieder keine Button angenommen.

D.h. für kurze Zeit funktioniert die Routine. Vielleicht hilft das ja 
hier dem ein oder anderen für eine neue Theorie... um mir zu helfen ;)

Gruß
Tobi

von Tobi (Gast)


Lesenswert?

Fehler gefunden! :>

Tobi schrieb:
> TIMSK = 1<<OCIE1A;

Trotzdem danke an die, die es wirklich versucht haben ;)

Gruß
Tobi

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.