Schlechter Programmierstil?

Gast #1191587
Kann mir jemand sagen wieso das so nicht geht?
Hier mein Programmbeispiel:
volatile char c=0;
ISR(TIMER2_OVF_vect)
{
  time++;
  itoa(time,li,10);
  if(time>=0)
  uart1_puts(li);
}
ISR(USART0_RXC_vect)
{
  while(!(UCSR0A & (1<<RXC0)));
  c=UDR0;
}
int main()
{       uart0_init();
  uart1_init();
  sei();
  timer2_init();
  time=0;

  uart0_puts("at\r");
  while(z!=1)
  {
     while(c!='\r')
    uart1_putc(c);
     while(c!='\r');
     while(c!='\n');
     while(c!='\r')
    uart1_putc(c);
     while(c!='\n');
     z=1;
  }
 while(1);
 return(0);
}
habe jetzt nicht alle Variablen deklariert aber ich glaube da liegt auch 
nicht der Fehler drin!
Also folgendes Problem tritt auf: Das Programm wird Initialisiert. Bevor 
es in die while(1) Schleife rein kommt, wird über die uart0 at\r zum GSM 
geschickt. Normalerweise würde das GSM Modul folgendes zurückgeben:
<CR><N>OK<CR><N>. Folgendes bekomme ich angezeigt über uart1:
at


    OK123usw
Kann mir jemand helfen?
Gast
Zum Stil: In meinen Augen gruselig, total wüst eingerückt, oder auch 
garnicht :-)

Du hast dir da eine wunderbare 'Race Condition' konstruiert: stell dir 
mal vor, zwei Bytes kommen schneller nacheinander an, als du sie in der 
Hauptschleife abfragst. Erweitere deine Empfängerei mal durch einen 
gescheiten Ringpuffer o.ä.
Gast
Also meinst du ich sollt die ganze Empfängerrei in der ISR Routine 
abhandeln?
Ich dachte nur es wäre besser so um die ISR Routine so kurz wie möglich 
zu halten
Ist es ja auch. Du bastelst dir einfach zwei Ringpuffer mit ein paar 
Byte Kapazität. Einen fürs Senden, einen fürs Empfangen. Dann ließt du 
in den ISRs nur kurz das nächste Byte ausm Ringpuffer oder legst es 
hinein. Den Rest erledigst du in der Hauptschleife.

Aber warum nimmst du nicht einfach ne vorgefertigte UART-Implementierung 
zb. von Peter Fleury oder so?

MfG
Marius
Thomas wrote:
> Also meinst du ich sollt die ganze Empfängerrei in der ISR Routine
> abhandeln?
> Ich dachte nur es wäre besser so um die ISR Routine so kurz wie möglich
> zu halten

du sollst in der ISR die empfangenen auch nicht komplett auswerten, 
sondern in einen Puffer schreiben...eine kurze Interrupt-Routine bringt 
nix, wenn du deswegen Bytes verlierst...
Thomas wrote:
1
> ISR(TIMER2_OVF_vect)
2
> {
3
>   time++;
4
>   itoa(time,li,10);
5
>   if(time>=0)
6
>   uart1_puts(li);
7
> }

Ja das ist extrem schlechter Stil, weil es die CPU lange blockiert.
Du darfst Dich nicht wundern, wenn dadurch andere Interrupts verloren 
gehen.

Unterfunktionsaufrufe in Interrupts möglichst vermeiden, weil dann 
sämtliche Register gesichert werden müssen.

itoa dürfte 4 Divisionen benötigen, ist aufm AVR ein Langläufer, daher 
besser im Main.

UART-Ausgaben generell nicht in Interrupts, da auch Langläufer.
Bzw. wenn gepuffert, kanns sogar nen Deadlock geben. Der Puffer kann im 
Sendeinterrupt nicht geleert werden, da Du bereits in nem Interrupt 
bist.


Peter

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 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.