Forum: Compiler & IDEs Schlechter Programmierstil?


von Thomas (Gast)


Lesenswert?

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?

von Sven P. (Gast)


Lesenswert?

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.ä.

von Thomas (Gast)


Lesenswert?

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

von Marius W. (mw1987)


Lesenswert?

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

von Justus S. (jussa)


Lesenswert?

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...

von Thomas (Gast)


Lesenswert?

Wo kann ich denn sowas finden?

von Marius W. (mw1987)


Lesenswert?

Ich hab dir doch schon den entscheidenden Tipp gegeben. UART-Lib von 
Peter Fleury. Wenn du mal eine Suchmaschine bedienst, wirst du sie 
finden.

MfG
Marius

von Thomas (Gast)


Lesenswert?

Habs gefunden! Vielen Dank

von Peter D. (peda)


Lesenswert?

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

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Thomas wrote:
> Ich dachte nur es wäre besser so um die ISR Routine so kurz wie möglich
> zu halten

So kurz wie möglich, aber eben auch so lang wie nötig :-)

Ne ISR, die so kurz ist wie möglich, ist leer....

Johann

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


Lesenswert?

Johann L. wrote:

> Ne ISR, die so kurz ist wie möglich, ist leer....
1
EMPTY_ISR(...);
 :-)

(Hat zuweilen Sinn: wenn man einen Interrupt nur benötigt, um aus
dem Schlaf aufzuwachen, es aber nach dem Aufwachen egal ist, was
genau der Auslöser dafür war.)

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.