Forum: Mikrocontroller und Digitale Elektronik Usart + Timer Interrupt Problem


von Hannes A. (m4f1)


Lesenswert?

Hallo,
ich komme direkt zu meinem Problem: Es ist mir nicht möglich Zeichen 
über die USART Schnittstelle einzulesen und im Anschluss einen Timer 
laufen zu lassen.
Es handelt sich dabei um einen XMEGA128A3.
Ich lese via USART Schnittstelle Zeichen wie folgt ein
1
char usart_getc(void)
2
{
3
  char c;
4
  while (!( USARTF0.STATUS & USART_RXCIF_bm));
5
  c=USARTF0.DATA;
6
7
  return(c);
8
}
Lese ich nun ein oder mehrere Zeichen ein, so wird mein Timer overflow 
Interrupt im Anschluss nicht mehr ausgelöst.

Hat jemand eine Idee worran es liegen oder wie ich das Problem umgehen 
könnte?

von holger (Gast)


Lesenswert?

>Hat jemand eine Idee worran es liegen oder wie ich das Problem umgehen
>könnte?

Mit dem popeligen Stück Quellcode hat da sicher niemand eine Idee.

von Hannes A. (m4f1)


Lesenswert?

Die USART Schnittstelle initialisiere ich wie folgt
1
void USART_Init_intern(void) 
2
{
3
  // BSEL ausrechnen, Berechnung siehe Datenblatt Seite 238 (bscale = -5)
4
  // Berechnung für internen Oszillator f=32 MHz, RS232 Geschwindigkeit 256K0
5
  USARTF0.BAUDCTRLA = 218&0xff;          // siehe Seite 254 Datenblatt
6
  USARTF0.BAUDCTRLB = (-5<<4)|(218>>8);       // siehe Seite 254 Datenblatt
7
  USARTF0.CTRLA = 0x30;                 // USART_RXCINTLVL_HI_gc;   //RX interrupt high level
8
    USARTF0.CTRLB = 0x18;              // RX und TX enable, siehe Seite 251
9
    USARTF0.CTRLC = 0x03;              // Datenformat einstellen, ansynchron, keine Parity, 1 Stop-Bit, 8 Daten-Bits siehe Seite 252 ff
10
  PORTF.DIR |= (1<<PIN3); 
11
  PORTF.DIR &= ~(1<<PIN2); 
12
  PMIC.CTRL |= 0x04;              //set PMIC high level enable
13
}

Den Timer wie folgt
1
TCC0_INTCTRLA = TC_OVFINTLVL_HI_gc;  // enable interrupt

Routine
1
void move(uint16_t step)
2
.
3
.
4
.
5
  // start counter
6
  TCC0_CTRLA = TIMER_PRESCALE_gc;
7
8
  // acceleration phase
9
  accel_function = accelerate;
10
  while ( steps > threshold_2 )
11
  {
12
    TCC0_PER = accel_function();  // set new timer value
13
    while ( !timer_ovf );  // wait for timer
14
    CHOPPER_STEP();
15
  }

Timer Interrupt
1
ISR( TCC0_OVF_vect )
2
{
3
  timer_ovf = TRUE;
4
}

Meine main sieht wie folgt aus:
1
        Verschiedene Variablien Deklarationen
2
        .
3
        .
4
  clock_intern_32(); //Interner 32Mhz Oszillator
5
  USART_Init_intern();
6
  inputs_Init();  //Input Ports
7
  outputs_Init(); //Output Ports
8
        SPI_INIT_E();   //ADC Schnitstelle
9
  STEPPERMODE();  //Motor
10
  pullup();  //Pullup Widerstand
11
  init_move();    //Timer Initialisierung
12
  sei();
13
        while(1)
14
        {  
15
                switch((int)usartgetc())
16
                {
17
                  case '1':
18
        
19
                    CW();
20
                    move(15000);
21
                    CCW();
22
                    move(15000);
23
                }    
24
        }

Rufe ich usartgetc vorher nicht auf, funktioniert alles wunderbar, 
leider aber bin ich auf Benutzereingaben angewiesen.
Mit usart... hängt meine Routine move()... an
1
while ( !timer_ovf );
 da es nicht mehr zum Timer Interrupt kommt.

Ich hoffe ich konnte euch das Problem damit näher bringen

von Karl H. (kbuchegg)


Lesenswert?

Slawa Kabanovic schrieb:


> Mit usart... hängt meine Routine move()... an
1
while ( !timer_ovf
2
> );
 da es nicht mehr zum Timer Interrupt kommt.

bist du sicher, dass das programm an dieser stelle hängt un nicht 
einfach nur hier drinnen?
1
char usart_getc(void)
2
{
3
  char c;
4
  while (!( USARTF0.STATUS & USART_RXCIF_bm));
5
  c=USARTF0.DATA;
6
7
  return(c);
8
}

Sprich: Hast du kontrolliert, ob du von der USART ein Zeichen bekommst 
und wenn ja, welches das ist?

von Karl H. (kbuchegg)


Lesenswert?

timer_ovf ist hoffentlich volatile definiert?

von Hannes A. (m4f1)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Sprich: Hast du kontrolliert, ob du von der USART ein Zeichen bekommst
> und wenn ja, welches das ist?

Ich bin mir sogar sehr sicher, da bei richtiger Eingabe in die 
Switch-Case Anweisung/Schleife gesprungen wird und ich per Ausgabe via 
USART getestet habe an welcher Stelle das Programm hängt.

Karl Heinz Buchegger schrieb:
> timer_ovf ist hoffentlich volatile definiert?

Kann ich leider erst morgen genauer sagen, weil ich gerade wieder zu 
hause bin. Wenn es daran scheitern sollte, warum hat das Ganze dann aber 
ohne USART so wunderbar geklappt?

von Hannes A. (m4f1)


Lesenswert?

Ich werde gleich weiter an meinem Problem Arbeiten und timer_ovf auf 
volatile prüfen, auch wenn nicht denke das es daran liegt.
Ich kann mir im Grunde nur vorstellen, dass
> while (!( USARTF0.STATUS & USART_RXCIF_bm));
irgendwie im Konflikt mit dem Timerinterrupt steht, kann das sein? Lasse 
ich nämlich die USART-Funktion weg, klappt das ganze wunderbar.

von Hannes A. (m4f1)


Lesenswert?

So, ich habs. Es liegt an
1
USARTF0.STATUS
 und der Timer vertragen sich nicht :( wie aber kann diese Abfrage 
umgehen?

von Hannes A. (m4f1)


Lesenswert?

Ich habe den Fehler inzwischen gefunden es lag an der Initialisierung 
der USART Schnittstelle
1
USARTF0.CTRLA = 0x30;  // USART_RXCINTLVL_HI_gc;   //RX interrupt high level
Da ich auf den Interrupt nicht angewiesen war/bin, habe ich auch nicht 
daran gedacht ihn zu definieren, hätte also entweder eine leere 
Interruptroutine erstellen müssen oder aber den Interrupt ausstellen mit
1
USARTF0.CTRLA = USART_RXCINTLVL_OFF_gc;
Ich bedanke mich bei den Helfern, der Thread kann geschlossen werden 
/closed

von Stefan (Gast)


Lesenswert?

etwas spät die Antwort aber durch scharfes hinsehen:

 ISR( TCC0_OVF_vect )
 {
    ...
 }

entspricht nicht der Konfiguration

 USARTF0.xxx = yyy;

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.