Forum: Mikrocontroller und Digitale Elektronik TXC FLag Problem mit dem ATmega644P


von Tommy (Gast)


Lesenswert?

Hab jetzt folgendes Programm geschrieben:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<avr/sleep.h>
4
#include<util/delay.h>
5
#include"timer.h"
6
#include"uart.h"
7
8
#define F_CPU 4000000UL
9
10
// 9600 baud
11
#define UART_BAUD_RATE 9600
12
13
volatile uint8_t time=0;
14
15
ISR(TIMER2_OVF_vect)
16
{  
17
  time++;
18
}
19
int main()
20
{  uint8_t test=0;
21
   DDRA=0xff;
22
  PORTA=0xff;
23
24
  while(test!=100)
25
  {  _delay_ms(10);
26
    test++;
27
  }test=0;
28
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
29
  sleep_enable();
30
  
31
  timer2_init();
32
33
  sei();
34
35
  while(1)
36
  {
37
    if(time==5)
38
    {  
39
      uart_puts("jip das klappt");
40
      while ((UCSR0A & (1 << TXC0)) != 1);
41
  //    UCSR0A =(1 << TXC0);
42
      time=0;
43
    
44
    }
45
    else
46
      {
47
        PORTA=time;
48
        sleep_cpu(); 
49
      }
50
  }
51
  return(0);
52
}

Jedoch läuft das Programm einmal durch und dann bleibt der Timer stehen.
Hab irgendwo gelesen, dass man das TXC FLag zurücksetzen muss habs mit 
der auskommentierten Zeile versucht, klappt aber auch nicht!

von STK500-Besitzer (Gast)


Lesenswert?

Wo initialisierst du das USART?

> while ((UCSR0A & (1 << TXC0)) != 1);
Ungünstig, wenn TXC0 nicht an der ersten Stelle im Byte steht.
besser ist
 while ((UCSR0A & (1 << TXC0)) == 0);

oder
 while (!(UCSR0A & (1 << TXC0)));

von Stefan E. (sternst)


Lesenswert?

Nicht der Timer bleibt stehen, sondern deine main landet in einer 
Endlosschleife, denn "(UCSR0A & (1 << TXC0))" ist immer ungleich 1.
Es ist nämlich entweder 0 oder 64.

von Tommy (Gast)


Lesenswert?

Wieso denn 64?

von Stefan E. (sternst)


Lesenswert?

Tommy wrote:
> Wieso denn 64?

Weil das Bit an Position 6 steht. Wenn das Bit gesetzt ist, ist das 
Ergebnis von "(UCSR0A & (1 << TXC0))" 01000000 (=64).

Komm jetzt aber nicht auf Idee "!= 64" zu schreiben. Benutze eine der 
schon genannten Varianten.

von STK500-Besitzer (Gast)


Lesenswert?

>Wieso denn 64?

Das TXC0-Bit steht an der 7.Stelle des UCSRA0-Bytes.
Dein TXC0 ist nichts anderes als eine Textersetzung zur besseren 
Lesbarkeit für eine 7.
2hoch7 ist 64.
1<<TXC0 ist gleich 1<<7 also = 64

In deinem Vergleich steht dann entweder:
64 == 1
oder
0 == 1

beides ist natürlich falsch (vom logischen Vergleich aus gesehen).
Teste lieber auf 0.

von Stefan E. (sternst)


Lesenswert?

STK500-Besitzer wrote:

> Dein TXC0 ist nichts anderes als eine Textersetzung zur besseren
> Lesbarkeit für eine 7.
> 2hoch7 ist 64.
> 1<<TXC0 ist gleich 1<<7 also = 64

Ersetze 7 durch 6, dann passt es. ;-)

von Tommy (Gast)


Lesenswert?

Danke danke habs vertsanden!

von Peter D. (peda)


Lesenswert?

Man könnte aber auch schreiben:
1
while (!!(UCSR0A & (1 << TXC0)) != 1);

Die doppelte logische Negation ist immer 1 bei einem wahren Ausdruck.


Peter

von Florian D. (Gast)


Lesenswert?

Naja, die nächste Frage ist: Was weckt deine MCU wieder auf? Du gehst in 
den Power Save Mode, und dann bleibt natürlich der Timer stehen. Ausser 
du versorgst ihn mit einem externen Takt (Uhrenquarz,...).

von Tommy (Gast)


Lesenswert?

Ja hab ich , timer2 mit 32,768khz

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger wrote:
> Man könnte aber auch schreiben:
>
1
> while (!!(UCSR0A & (1 << TXC0)) != 1);
2
>

Aber wirklich besser lesbar im Vergleich zu
1
while ((UCSR0A & (1 << TXC0)) == 0)
2
  /* wait */;

ist das auch nicht.  (Den wait-Kommentar auf einer extra Zeile habe
ich mir generell angewöhnt.  Ein einzelnes Semikolon hinter einer
while-Anweisung ist ziemlich schnell zu übersehen.  Mit dem
Kommentar ist es klar, dass dies so die Absicht des Programmierers
war.)

von Tommy (Gast)


Lesenswert?

So, bin jetzt soweit:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<avr/sleep.h>
4
#include<util/delay.h>
5
#include"timer.h"
6
#include"uart.h"
7
8
#define F_CPU 4000000UL
9
10
// 9600 baud
11
#define UART_BAUD_RATE 9600
12
13
volatile uint8_t time=0;
14
15
ISR(TIMER2_OVF_vect)
16
{  
17
  time++;
18
}
19
int main()
20
{  uint8_t test=0;
21
   DDRA=0xff;
22
  PORTA=0xff;
23
24
  while(test!=100)
25
  {  _delay_ms(10);
26
    test++;
27
  }test=0;
28
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
29
  sleep_enable();
30
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
31
  
32
  timer2_init();
33
34
  sei();
35
36
  while(1)
37
  {
38
    if(time==5)
39
    {
40
      uart_puts("ein durchlauf klappt");  
41
      while ((UCSR0A & (1 << TXC0)) == 0);
42
      time=0;
43
    
44
    }
45
    else
46
      {
47
        PORTA=time;
48
        sleep_cpu(); 
49
      }
50
  }
51
  return(0);
52
}

Der timer2 läuft jetzt zwar weiter, aber über die Uart wird im zweiten 
Durchlauf michts mehr geschickt!
Liegt das jetzt daran, das er zu spät wach wird?

von Tommy (Gast)


Lesenswert?

Habs gelöst, das TXC0 Flag muss wieder gelöscht werden und zwar mit eins 
setzen! jippih

von Tommy (Gast)


Lesenswert?

als nächste versuch ich einen externen Interrupt auszulösen!

von Tommy (Gast)


Lesenswert?

Hab jetzt folgendes Problem!
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<avr/sleep.h>
4
#include<util/delay.h>
5
#include"timer.h"
6
#include"bewgs.h"
7
#include"uart.h"
8
9
#define F_CPU 4000000UL
10
11
// 9600 baud
12
#define UART_BAUD_RATE 9600
13
14
volatile uint8_t time=0;
15
volatile uint8_t bewg=0;
16
17
ISR(TIMER2_OVF_vect)
18
{  
19
  time++;
20
}
21
22
ISR(PCINT3_vect)
23
{
24
  bewg=1;
25
}
26
int main()
27
{  uint8_t test=0;
28
   DDRB=0xff;
29
  PORTB=0xff;
30
31
  while(test!=100)
32
  {  _delay_ms(10);
33
    test++;
34
  }test=0;
35
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
36
  sleep_enable();
37
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
38
  
39
  timer2_init();
40
  pcint0_init();
41
42
  sei();
43
44
  while(1)
45
  {
46
    if(bewg==1)
47
    {  
48
      uart1_puts("interrupt wurde ausgeloest!");
49
      while ((UCSR0A & (1 << TXC0)) == 0);
50
      UCSR0A|=(1<<TXC0);
51
      bewg=0;
52
    }
53
    if(time==5)
54
    {
55
      time=0;
56
    }
57
    else
58
      {
59
        PORTB=time;
60
        sleep_cpu(); 
61
      }
62
  }
63
  return(0);
64
}

Der Interrupt wird zwar ausgelöst, aber über die Uart wird nichts 
geschickt und darauf hin blebt das Programm in der while Schelife drin, 
da ja das txc bit nicht gesetzt wird! Weiß jemand woran das liegen kann?

von Tommy (Gast)


Lesenswert?

Hab jezt schon nen Fehler gesehen! Keine Ahnung warum ich etwas über die 
uart1 schicken will, wobei ich doch uart aktiviert habe!

von Tommy (Gast)


Lesenswert?

Jip das wars! Sorry hätte ich gar nicht posten müssen, habs erst gesehen 
als es schon drin war

von STK500-Besitzer (Gast)


Lesenswert?

Jemand sollte Andreas Schwarz vorschlagen, ein Selbstgesprächsforum 
einzuführen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Tommy könnte sich ja auch in Zukunft Ingrid nennen...

http://de.wikipedia.org/wiki/Ingrid#Sonstiges

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.