Attiny2313, Timer 1 Starten, 1Minute, Fehler: left-hand operand of comma expression has no effect

Gast #3278922
Hallo,

Ich möchte den Timer 1 (16Bit) eines Attiny 2313 benutzen um ca eine 
Minute zu messen.

Danach möchte ich die Ausgänge abschalten...

Nun bekomme ich oft den Fehler:
left-hand operand of comma expression has no effect

Dabei muss ich doch den Timer richtig einstellen.
Hier mein Programm:
1
#include <avr/io.h>
2
#define F_CPU 1000000UL    // 1 MHz (fuer delay.h)
3
#include <util/delay.h>
4

5

6
int main(void)
7
{
8
  PORTD = 0x00;      //Pin für Taster und ADC(Reset) als Eingang
9
  DDRD  = 0xff;
10
  PORTB = 0x00;
11
  DDRB  = 0x00;
12
  //-------TIMER-1----------------------------------
13
  TCCR1A  &= (0<<COM1A0,0<<COM1A1);  // CTC Modus
14
  TCCR0B &= (0<<ICNC1,0<<ICES1,0<<CS11);
15
  TCCR0B |= (1<<WGM12,1<<CS10,1<<CS12);  // Prescaler 1024
16
  OCR1A = 0x0400;                    //Zählen bis 1024;
17
  //------> Timer läuft nun
18
  int lauft=0;
19
    while(1)
20
    { 
21
          lauft = TIFR&(1<<OCF1A);
22
          if(lauft)
23
          {
24
            PORTD=0x00;
25
            while(1)
26
            {
27
              ;
28
            }
29
            TIFR |= (1<<OCF1A);
30
          }
31
          else
32
          {
33
            PORTD=0x55
34
          }      
35

36
    }
37
}
Da PORTD immer auf 0x55 geht, läuft der Timer wohl nicht.

Ich komm nicht auf den Fehler.

Danke dür eure Hilfe.
#3278927
Matze schrieb:

> Nun bekomme ich oft den Fehler:
> left-hand operand of comma expression has no effect
>
> Dabei muss ich doch den Timer richtig einstellen.

Schon.
Aber nicht so
1
TCCR0B |= (1<<WGM12,1<<CS10,1<<CS12);

sondern so
1
TCCR0B |= (1<<WGM12) | (1<<CS10 ) | (1<<CS12);

und natürlich die anderen auch.
Persönliche Seite #3278935
Matze schrieb:
> TCCR1A  &= (0<<COM1A0,0<<COM1A1);  // CTC Modus
>   TCCR0B &= (0<<ICNC1,0<<ICES1,0<<CS11);
>   TCCR0B |= (1<<WGM12,1<<CS10,1<<CS12);  // Prescaler 1024
>   OCR1A = 0x0400;                    //Zählen bis 1024;


Was den das ? Das ist kompletter müll und kein C
Die einzelnen bits kannst du nicht einfach mit nem Komma trennen.

http://www.mikrocontroller.net/articles/Bitmanipulation#Standard_C
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Ver.C3.A4ndern_von_Registerinhalten

kennst du ? Da stehts wie du Bitmanipulationen richtig machst.
Gast #3279748
Danke, die fehler sind nun weg.

Der Timer läuft wohl immer noch nicht, muss ich ihn irgendwie speziell 
starten?
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 1000000UL    // 1 MHz (fuer delay.h)
4
#include <util/delay.h>
5

6
int main(void)
7
{
8
  PORTD = 0x00;      //Pin für Taster und ADC(Reset) als Eingang
9
  DDRD  = 0xff;
10
  PORTB = 0x00;
11
  DDRB  = 0x00;
12
  //-------TIMER-1----------------------------------
13
  TCCR1A  &= (0<<COM1A0)|(0<<COM1A1);  // CTC Modus
14
  TCCR0B &= (0<<ICNC1)|(0<<ICES1)|(0<<CS11);  // Prescaler 1024
15
  TCCR0B |= (1<<WGM12)|(1<<CS10)|(1<<CS12);  
16
  OCR1A = 0x0400;
17
  TIMSK |= (1<<OCIE1A);            //Compare Interrupt Enable
18
  sei();                    //Globale Interrupts ein
19
  //------> Timer läuft nun
20
  int lauft=0;
21
    while(1)
22
    {   
23
    lauft = TIFR&(1<<OCF1A);
24
    if(lauft)
25
    {
26
      PORTD=0x00;
27
      while(1)
28
      {
29
        ;
30
      }
31
      TIFR |= (1<<OCF1A);
32
    }
33
    else
34
    {
35
      PORTD=0x55;
36
    }      
37
    }
38
}
39

40
ISR(TIMER1_COMPA_vect) 
41
{
42
  PORTD=0x00;
43
  while(1)
44
  {
45
    ;
46
  }
47
}
Nun inst er hoffentlich auf Compare eingestellt.
Nach allem was ich gelesen habe müsste er bei einem Compare-Match das 
Bit OCF1A setzen, und einen Interrupt auslösen.

Der Interrupt soll durch
1
  TIMSK |= (1<<OCIE1A);            //Compare Interrupt Enable
2
  sei();                    //Globale Interrupts ein
ermöglicht werden.

Leider löst er nicht aus und ich kann die Minute so nicht messen.

Grüße
Matze
Gast #3279770
Habe den Fehler gefunden.

Ich nutze Timer 1 und stelle das Kontroll-Register von Timer 0 ein.

  TCCR1A  &= (0<<COM1A0)|(0<<COM1A1);  // CTC Modus
  TCCR1B &= (0<<ICNC1)|(0<<ICES1)|(0<<CS11);  // Prescaler 1024
  TCCR1B |= (1<<WGM12)|(1<<CS10)|(1<<CS12);

Grüße
Matze
Gast #3279775
Matze schrieb:
> TCCR1A  &= (0<<COM1A0)|(0<<COM1A1);  // CTC Modus
>   TCCR1B &= (0<<ICNC1)|(0<<ICES1)|(0<<CS11);  // Prescaler 1024

das ist zwar kein fehler, aber unsinn. da kannst du auch gleich

TCCR1A  = 0;
TCCR1B  = 0;

schreiben.
#3279793
Es ist ziemlich unwahrscheinlich, dass dein Programm ausgerechnet hier
1
    while(1)
2
    {   
3
    lauft = TIFR&(1<<OCF1A);
4
    if(lauft)
5
    {
6
      PORTD=0x00;
7
      while(1)
8
      {
9
        ;
10
      }
11
      TIFR |= (1<<OCF1A);
12
    }
13
    else
14
    {
15
      PORTD=0x55;
16
    }      
17
    }

das OCF1A Flag als gesetzt antreffen wird. Sobald es vom Timer gesetzt 
wird, erfolgt der Aufruf der ISR innerhalb der nächsten 2 bis 3 
Taktzyklen, je nachdem welchen Befehl die CPU gerade in Arbeit hat. Dann 
passieren 2 Dinge: zum einen wird dadurch genau dieses Flag sofort 
wieder gelöscht, so dass die Hauptschleife es nicht zu Gesicht kriegen 
kann und zum zweiten hältst du das Programm durch die Endlosschleife 
innerhalb der ISR fest, so dass die Hauptschleife schon alleine aus 
diesem Grund nicht weiter arbeiten kann.


Und ich seh gerade, dass du da schon wieder eine Endlosschleife 
reingeschachtelt hast. Mit Endlosschleifen scheinst du es ganz im 
Speziellen zu haben. Lass den Unsinn! Es gibt nur EINE Endlosschleife 
und das ist die eine in main()!
#3279798
machs doch nicht so kompliziert
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 1000000UL    // 1 MHz (fuer delay.h)
4
#include <util/delay.h>
5

6

7
volatile uint8_t tick;
8

9
int main(void)
10
{
11
  PORTD = 0x00;      //Pin für Taster und ADC(Reset) als Eingang
12
  DDRD  = 0xff;
13

14
  PORTB = 0x00;
15
  DDRB  = 0x00;
16

17
  //-------TIMER-1----------------------------------
18
  TCCR1A  &= (0<<COM1A0)|(0<<COM1A1);  // CTC Modus
19
  TCCR0B &= (0<<ICNC1)|(0<<ICES1)|(0<<CS11);  // Prescaler 1024
20
  TCCR0B |= (1<<WGM12)|(1<<CS10)|(1<<CS12);  
21
  OCR1A = 0x0400;
22
  TIMSK |= (1<<OCIE1A);            //Compare Interrupt Enable
23
  sei();                    //Globale Interrupts ein
24
  //------> Timer läuft nun
25

26
  while(1)
27
  {   
28
    if( tick )
29
    {
30
      tick = 0;
31

32
      PORTD ^= 0x55;
33
    }
34
  }
35
}
36

37
ISR(TIMER1_COMPA_vect) 
38
{
39
  tick = 1;
40
}

Wenn deine Timereinstellungen stimmen, was ich nicht kontrolliert habe, 
dann müssten deine LED jetzt im Sekundentakt blinken.
#3279800
Wie kommst du eigentlichg auf die Idee, dass dein Programm im 1 
Sekundenrhythmus die ISR aufruft? Wenn ich nachrechne, krieg ich da aber 
was ganz anderes raus. Mal abgesehen davon, dass deine 1Mhz vom internen 
Takt keine 1Mhz sein werden und die ganze Rechnerei schon alleine 
deswegen nicht stimmt. Oder hast du einen 1Mhz QUarz am Tiny hängen?

FAQ: Timer
#3279806
Und ehe du da jetzt noch weiter rumhampelst:
Mal ausgehend davon, dass du den OCR1A Wert soweit korrigierst, dass du 
leidlich genau 1 Sekunden Abstände im ISR Aufruf hast, kann man Zeiten 
zb so abmessen, indem man einen Countdown-Zähler rückwärts zählen lässt, 
bis er bei 0 ist
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 1000000UL    // 1 MHz (fuer delay.h)
4
#include <util/delay.h>
5

6

7
volatile uint8_t tick;
8

9
int main(void)
10
{
11
  PORTD = 0x00;      //Pin für Taster und ADC(Reset) als Eingang
12
  DDRD  = 0xff;
13

14
  PORTB = 0x00;
15
  DDRB  = 0x00;
16

17
  //-------TIMER-1----------------------------------
18
  TCCR1A  &= (0<<COM1A0)|(0<<COM1A1);  // CTC Modus
19
  TCCR0B &= (0<<ICNC1)|(0<<ICES1)|(0<<CS11);  // Prescaler 1024
20
  TCCR0B |= (1<<WGM12)|(1<<CS10)|(1<<CS12);  
21
  OCR1A = 0x0400;
22
  TIMSK |= (1<<OCIE1A);            //Compare Interrupt Enable
23

24
  sei();                    //Globale Interrupts ein
25
  //------> Timer läuft nun
26

27
  tick = 60;                // 60 Sekunden Countdown
28

29
  while(1)
30
  {   
31
    if( tick > 0 )          // läuft der Countdown noch?
32
      PORTD = 0x55;         //   Yep -> Led ein
33
    else
34
      PORTD = 0;            //   No -> Countdown ist fertig, Led aus
35
  }
36
}
37

38
ISR(TIMER1_COMPA_vect) 
39
{
40
  if( tick > 0 )
41
    tick--;
42
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.