Timer und UART vertragen sich nicht

Gast #301160
Lesenswert?

Hallo,

ich verwende einen ATMega16, WinAVR und Ponyprog.

In einer Anwendung verwende ich den UART um Daten zwischen PC und uC
auszutauschen. Die Kommunikation geht interruptgesteuert, also mit
RXIE, TXIE usw...
In einer anderen Anwendung verwende ich einen Timer mit dessen Hilfe
ich ein paar Servomotoren steuere. Auch interrupt gesteuert. Beides
funktioniert einzeln sehr gut.
Wenn ich aber in meinem UART-Programm das Servosteuermodul einbauen
will funktionierts nicht. Ich bekomme keinen Datenaustausch mehr hin.

Ich hab auch schon heraus woran es ungefaehr liegt:
Ich initialisiere den UART und anschliessen den Timer (interrupt flags
setzen usw...). Wenn ich den Timer starte (CS-bits setzen) funktioniert
es nicht mehr. Wenn ich die Zeile mit TCCR2 |= ... wie unten
auskommentier funktioniert mein UART. Mit der Zeile funktioniert er
nicht.

//Initialization of UART
  UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8);
  UBRRL=(uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_CPU);

  UCSRB |= (1<<RXEN) | (1<<TXEN);  // enable RxD & TxD
  UCSRB |= (1<<RXCIE) | (1<<TXCIE);// enable Rx- and Tx- interrupts

//Timer2 config (8bit)
   TIMSK=0x00;
 //TCCR2 |= (1<<CS22) | (1<<CS21) | (1<<CS20);
   SETBIT(TIMSK, TOIE2); // overflow interrupt enable Timer2


Wo liegt da ein Zusammenhang?
Wo ist das Problem?

freue mich über Tips!

mg,
Johannes
Gast #301162
Lesenswert?

Ohne halbwegs kompletten Quelltext wird Dir niemand helfen können. Bau
am besten mal ein lauffähiges Minimalbeispiel, um den Fehler zu
reproduzieren, oft findet man die Ursache dann auch selbst.

Eine Vermutung: Die Timer-ISR braucht zu lange, z.B. durch
Warteschleifen innerhalb der ISR, so daß die UART-Interrupts nicht
schnell genug bedient werden.

Was sind denn die Symptome für die fehlerhafte Übertragung? Rührt sich
gar nix, oder kommt nur Datenmüll an (z.B. auch Framing-Error), oder
gehen einzelne Zeichen verloren? Verwendest Du Ringpuffer für
eingehende und ausgehende Daten?

MfG Olaf
Gast #301163
Lesenswert?

Hallo Olaf,

die ISR fuer den Timerueberlauf hab ich noch gar nicht eingebunden.
In meinem "Minimalbeispiel" hab ich einfach nur den Timer
initialisiert und gestartet wie im Quelltext oben. Das hat zur Folge,
dass der UART nicht mehr geht.
Inzwischen hab ich mit einema nderen Timer (16bit) gearbeitet und wenn
der läuft, egal ob mit oder ohne seine ISR, funzt der UART.

Ich poste gerne auch den ganzen Quellcode (bitte bescheid sagen!); aber
ehrlich: ich glaube kaum, dass sich jemand die Arbeit macht fuer mich in
meinem Code Fehler zu suchen...

mg,
Johannes
Gast #301164
Lesenswert?

"die ISR fuer den Timerueberlauf hab ich noch gar nicht eingebunden."


Jo, dann gehts natürlich ab in den Wald.

Bevor man einen Interrupt freigibt, muß ein Handler am entsprechenden
Interruptvektor existieren !!!

Für diese Regel gibt es keine Ausnahme !!!


Peter
Gast #301165
Lesenswert?

Aha!

ich nehm alles wieder zurück. Das hab ich nicht gewusst.
Dachte, der Timer laeuft dann vor sich hin...

hmm...Compilerspezialist bin ich nicht, aber sowas koennte der ja auch
merken, oder? ich nehm die Schuld aber ganz auf meinen Puckl,stell mich
5min in eine Ecke und schäme mich dreimal ganz laut!

es tut jetzt vorläufig wie ich will!

mg,
Johannes
Gast #301168
Lesenswert?

ich auch.
Man sollte die Liste vielleicht noch verlängern (ohne Wertung in Bezug
auf die Reihenfolge:
Rufus, HanneS, Jörg Wunsch, OldBug, CrazyHorse.
Das sind die, die mir jetzt gerade eingefallen sind.
Gast #301170
Lesenswert?

Könnt ihr mir vielleicht sagen wann ich denn extern Interrupt auf 1
setzen soll und wann und wie???

#pragma small code symbols debug
#include "bremslicht.h"

unsigned int aktuellerWert; /* speichert die aktuelle negative
Beschleunigung 0..100 */
unsigned int leuchtendeLEDs; /* speichert die Anzahl anleuchtenden LEDS
*/
float LEDratio; /* hier wird errechnet, wie viel  % eine LED
"repräsentiert" */

unsigned int timer0_wert;

/*

  INT0 Verlauf über die Zeit (Input vom Accelerometer, PWM moduliert)

  ...----><---T1---><--------T2-----------><--T1--><----...
           _______                         _______
          |        |                       |        |
          |        |                       |        |
   _______|        |_______________________|        |_____________

                   |<--Interrupt                   |<--Interrupt

          |<--timer0 fängt an hier         |<--timer0 fängt an hier
              hochzuzählen, weil               hochzuzählen, weil
              GATE0=1 und INT0 high            GATE0=1 und INT0 high

   -----------------------------Zeit------------------------------->

*/

void irq_timer0(void) interrupt 1
{

    timer0_wert = 256*TH0 + TL0;




    TL0 = 0x00;
    TH0 = 0x00;
    TF0 = 0;
    TF1 = 0;



    TMOD = 0x19;//0001=vom Tim1 M0 auf1, 1001=Auslösen desTim0,dann
16Bit Zähler laufen lassen




}


void LEDsInit()
{
    register int i;
    for (i = 0; i < ANZAHL_LEDS; i++)
    {
        LEDs[i] = 0;    // schalte LED aus
    }
    MAX7300SetzeLEDs(LEDs);
}

void AccMeterInit() {

    TR0 = 0;

    TMOD = 0x19;

    TH0 = 0x00;
    TL0 = 0x00;

    ET0 = 1;
    EA = 1;

    IT0=1;// TCON = TCON | 0x11;
    TR0=1;

}



void Initialisieren()
{
    MAX7300Init();
    LEDsInit();
    aktuellerWert = 0;
    leuchtendeLEDs = 0;
    LEDratio = (float) 100 / ANZAHL_LEDS;

    timer0_wert = 0;
    AccMeterInit();
}


void HoleWert() {
    if (timer0_wert > 0 ) {

        aktuellerWert = (int) ((timer0_wert / TIMER1_MAX) * 100);

        if (aktuellerWert < 50) {
            aktuellerWert *= 2;
        }
        else {
            //positive Beschleunigung interessiert uns nicht
            aktuellerWert = 0;
        }
    }
}

void BerechneWert()
{
    leuchtendeLEDs = (unsigned int) aktuellerWert / LEDratio;
}

void AusgabeWert()
{
    register int i;
    if (leuchtendeLEDs > 0) {
        P1_6 = 1;
        P1_7 = 1;
    }
    else {
        P1_6 = 0;
        P1_7 = 0;
    }
    for (i = 0; i < leuchtendeLEDs; i++)
    {
        LEDs[i] = 1;    //lass LED leuchten
    }

    for (i = leuchtendeLEDs; i < ANZAHL_LEDS; i++)
    {
        LEDs[i] = 0;    // schalte LED aus
    }
    MAX7300SetzeLEDs(LEDs);
}

void main()
{
    Initialisieren();
    for (;;) //forever
    {
        HoleWert();
        BerechneWert();
        AusgabeWert();
    }
}

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