mikrocontroller.net

Forum: Compiler & IDEs Interrupt Problem mit UART bei Atmega8535


Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Ich habe ein Problem mit meinem Programm. Ich möchte vom PC eine 1 
senden und dann soll auf dem Board die LED ausgehen, doch es passiert 
nichts.
Kann sich einer mal den Quellcode anschauen und mir weiterhelfen?
Danke!

#include <avr/io.h>
#include <avr/interrupt.h>


#define F_CPU 1000000UL
#define BAUD      9600UL
#define UBRR_BAUD   ((F_CPU/(16L*BAUD))-1)



void uart_init(void)
{
UBRRH = (uint8_t) (UBRR_BAUD>>8);
UBRRL = (uint8_t) (UBRR_BAUD & 0xFF);
UCSRB = (1<<TXEN) | (1<<RXEN)|(1<<RXCIE); 
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}

void led_init(char value)
{
  if(value=='1')
    PORTA=0x01;

  else

  PORTA=0x00;
}

ISR(USART_RXC_vect)
{
  led_init(UDR);
}

int main(void)
{
DDRA = 0xff;
uart_init();
sei();
while(1){
}
return 0;
}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert dein Programm im Pollingmodus oder

1/ hast du die üblichen Probleme mit dem internen RC-Oszillator (1. 
Vermutung bei 1 MHz) die erforderliche Baudratengenauigkeit für 
reibungslosen UART-Transfer einzuhalten?

2/ stimmt die Verbindung (TX,RX-Kreuzung) und TTL/RS232-Wandlung 
zwischen µC und PC nicht?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du das U2X-Bit im UCSRA nicht setzt, kriegst Du bei 1 MHz 
CPU-Frequenz und 9600 Baud bereits rein rechnerisch einen 
Baudratenfehler von 7 %. Das ist schon mal tödlich für die Übertragung. 
Entweder das U2X setzen (und natürlich den Wert im UBRR entsprechend 
anpassen) oder eine andere CPU-Frequenz nehmen oder eine andere 
Baudrate.

Und was den internen RC-Oszillator angeht, kann ich mich Stefan nur 
anschließen: Asynchrone Übertragung mit so einer Taktquelle ist generell 
Glückssache.

BTW:
Sorry, dass ich auf Deine Mail (anscheinend ja zur selben Problematik) 
nicht geantwortet hab. Hatte in den letzten Tagen nen Haufen Stress und 
hab überhaupt nicht in den Email-Account reingeschaut. Hoffe, das 
Problem ist damit geklärt.

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Sorry das ich erst so spät antworte, denn ich war krank!
Ich habe das Programm, aber mal ohne Interrupt geschrieben und da hatte 
alles reibungslos funktioniert.
Da hatte ich genau die gleichen Einstellungen!
Kann es noch an etwas anderes liegen?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, dann gehen mir auch die Ideen aus.

Eine vielleicht noch - lies mal explizit UDR, so wie es im Datenblatt 
beschrieben ist, statt eine Übergabe auf dem Stack zu machen.
ISR(USART_RXC_vect)
{
  unsigned char tmp;

  tmp = UDR

  led_init(tmp);
}

Und noch eine vielleicht, toggel mal die LED in der Interruptroutine, 
dann siehst du, ob die überhaupt angesprungen wird. Trotzdem UDR lesen, 
weil es sonst den RXC Interrupt blockiert.
ISR(USART_RXC_vect)
{
  volatile unsigned char tmp;

  tmp = UDR

  // led_init(tmp);

  PORTA ^= (1<<PA0); // XOR    
  // http://www.mikrocontroller.net/articles/Bitmanipulation#Standard_C_3
}

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Stefan!

Danke nochmal für deine schnelle Antwort!
Ich habe alle deine Varianten durchgespielt, doch keine hat 
funktioniert.
Es muss an dem Interrupt liegen, der wird einfach nicht ausgelöst. Warum 
verstehe ich aber nicht. Ich habe auch den internen Oszilator auf 8Mhz 
gestellt. Ohne Interrupt funktioniert die Sache einwandfrei.
Gibt es noch eine andere Lösung mit einer anderen Interruptroutine?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ISR(USART_RXC_vect)
Ich glaub, der Vektor müsste "USART_RX_vect" heißen (Zumindest lt. 
Tabelle in der libc-Doku). Da ist ein "C" zuviel.

EDIT:
In der iom8535.h steht es ebenfalls ohne "C". Also müsste
ISR(USART_RX_vect)
{}
funktionieren.

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für deine Antwort.
Du hattest recht! Jetzt funktioniert alles.
Ne Frage habe ich aber trotzdem noch.
Wenn du dir oben mal die led_init ansehen kannst, da steht drin das wenn 
ich 1 an mikrocontroller sende soll die LED ausgehen. Wie schreibe ich 
es aber wenn ich CP001201 senden möchte?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die LED soll angehen, wenn "CP001201" beim µC ankommt? Da musste erstmal 
nen String-Vergleich machen. C kennt keinen Datentyp "string". Da 
müsstest Du die Funktion strncmp aus der string.h benutzen.

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja bei diesem Fall soll die LED angehen. Kannst du es mir vielleicht an 
meinem obigen Beispiel zeigen. Ich bin noch ein Anfänger und habe nicht 
so die Ahnung von einem String-Vergleich.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zunächst mal musst Du den Befehls-String empfangen und in einem 
Buffer-Array speichern. Den Vergleich kannst Du im Prinzip direkt in der 
if-Abfrage machen. Dazu muss man wissen, dass strncmp bei Gleichheit der 
verglichenen Strings eine 0 zurückgibt. Die Abfrage könnte also so 
aussehen:
if(!strncmp(buffer, "CP001201", 9))
    PORTA = 0x01;
Schau Dir am besten in der AVR-libc-Doku die Erläuterungen zur Funktion 
an. Da steht wie's geht...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zuallererst schaltest du die LED nicht mehr in der Interrupt
Routine.

Deine Interrupt Routine hat nur noch die Aufgabe die eingehenden
Zeichen zu sammeln und in einem char-Array bereitszustellen.

Erst nach Erhalt eines Trennzeichens erkennt die ISR dass
damit der Text komplett übertragen wurde und setzt seinerseits
eine gloable Variable auf 1.

An dieser 1 erkennt dann die Hauptschleife in main(), dass
ein kompletter Text empfangen wurde und bearbeitet den Text.
Zb. Dadurch dass sie Stringvergleiche macht um herauszufinden,
welches Kommando übertragen wurde.

Du hast hier also eine Aufgabentrennung. Die UART - ISR ist
nur noch dafür zuständig ein Kommando zu empfangen und das
komplette Kommando zur weiteren Bearbeitung zur Verfügung
zu stellen. Was dieses Kommando bewirken soll, ist nicht mehr
das Bier der ISR.

Sagen wir mal, du hast dich für das Zeichen ';' entschieden
um anzuzeigen, dass hier ein Kommando zu Ende ist.
Dann macht deine ISR zb. das hier
volatile uint8_t HabeKommando;
uint8_t  KommandoCnt;
char     Kommando[128];

ISR(USART_RX_vect)
{
  char c = UDR;

  if( c == ';' ) {
    Kommando[KommandoCnt] = '\0';
    HabeKommando = 1;
    KommandoCnt = 0;
  }

  else {
    Kommando[KommandoCnt] = c;
    KommandoCnt++;
  }
}


int main()
{
   ....


   while( 1 ) {

     if( HabeKommando == 1 ) {
       HabeKommando = 0;

       if( strcmp( Kommando, "abcd" ) == 0 ) {
         // Kommando "abcd" erkannt
       }

       ....
     }
  }
}

Zur Einführung in die Stringverarbeitung empfehle ich die
Lektüre eines C-Buches deiner Wahl. Das ist ein recht umfangreiches
Kapitel. Zur Not findest du das wichtigste aber auch hier:
http://www.mikrocontroller.net/articles/FAQ#Wie_fu...

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für Eure Antworten!
Ich werde es mal versuchen!

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe hier mein fertiges Exemplar mit deiner Variante versucht zu 
vereinen. Jetzt wollte ich wissen ob das so funtionieren kann?
Kannst du mir nochmal genau erklären, was der Quelltext in der ISR und 
in der while Schleife genau macht?


#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <string.h>

#define F_CPU 8000000UL
#define BAUD      9600UL
#define UBRR_BAUD   ((F_CPU/(16L*BAUD))-1)

char buffer[10];
uint8_t position;
volatile uint8_t habekommando;

void uart_init(void)
{

UBRRH = (uint8_t) (UBRR_BAUD>>8);
UBRRL = (uint8_t) (UBRR_BAUD & 0xFF);
UCSRB = (1<<TXEN) | (1<<RXEN)|(1<<RXCIE);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}

void led_init
{
  if(strcmp (buffer, "CP001201E") == 0)

  {
    PORTA=0x01;
  }

  else if(strcmp (buffer, "CP001200E") == 0)
  {
  PORTA=0x00;
  }
}



ISR(USART_RX_vect)
{
  char c = UDR;


  if (c == 'E')
  {
  buffer[position] = '\0';
  habekommando = 1;
  position = 0;
  led_init(UDR);
}

else {

  buffer[position] = c;
  position++;

     }
}



int main(void)
{
DDRA = 0xff;
uart_init();
sei();
while(1)  {

  if (habekommando == 1) {
    habekommando = 0;
  }

}
return 0;
}

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OT:
Karl Heinz:

Dein Code ist wie immer vorbildlich!
Du musst wissen, ich bin Code-formatierungs-Fetischist (Sprich Wenn 
Variablen aus mehreren Worten bestehen jedes Wort am Anfang groß 
schreiben, abundzu auch mal zwei Linefeeds machen, schön überall 
Leertasten an den kritischen Stellen)

Was ich mir noch angewöhnt habe, ist g_ als Prefix für globale Variablen 
(wie m_ für Membervariablen bei C++)

Ich wünsche manchmal, dass der ein oder andere Lehrer des Faches 
"Programmieren" uns sowas vorlegt. (Quasi als gutes Beispiel). Aber 
Fehlanzeige. Stattdessen bekommen wir unformatierte Klassendeklarationen 
(Keine durchgängige Schreibweise von Variablen (Groß/Kleinschreibung 
gemischt) und so weiter).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich habe hier mein fertiges Exemplar mit deiner Variante versucht zu
> vereinen. Jetzt wollte ich wissen ob das so funtionieren kann?

Teil des Programmiererlebens ist es, Dinge auszuprobieren.
Normalerweise kann ja nichts kaputtgehen, die Dinge funktionieren
halt einfach nicht.

> Kannst du mir nochmal genau erklären, was der Quelltext in der ISR und
> in der while Schleife genau macht?

Das ist ein 5-Zeiler. Den solltest du schon selbst analysieren können.
Nimm dir Papier und Bleistift und analysiere was da passiert.

Wie geht das?
Du spielst Computer. Dein Papier ist dein Speicher auf dem du Variablen
erzeugst und Werte zuweist bzw. von wo du die Werte von Variablen
abliest.

Wie in jedem C-Programm beginnt die Programmausführung damit, dass
zuerst die globalen Variablen erzeugt werden.

char buffer[10];
uint8_t position;
volatile uint8_t habekommando;

Also machst du das mal auf deinem Papier

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   |   |   |   |   |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |     |       |      |
   +-----+       +------+

Bei globalen Variablen gibt es noch einen Sonderfall: Sie werden
automatisch mit 0 initialisiert. Also mach das mal

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   0 |       |    0 |
   +-----+       +------+

Nachdem die Initialsierug abgeschlossen ist, beginnt die
Programmausführung bei main(). Dort wird die USART
initialisiert, die Interrupts freigegeben und danach
die while Schleife betreten. In der while Schleife wird
ständig habekommando auf 1 abgefragt. Dein Papier (=Speicher)
zeigt, das habekommando den Wert 0 hat, daher passiert
jetzt noch nichts weiter in der while Schleife.

Aber jetzt nehmen wir mal an, dass ein Zeichen über die USART
herein kommt. Konkret nehmen wir mal an, das wäre ein 'C'
gewesen. Als Folge davon wird die ISR aufgerufen.
Was macht die?

  char c = UDR;

Da wird also eine neue Variable c erzeugt. Also machen wir das
mal:

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   0 |       |    0 |
   +-----+       +------+

   c
   +-----+
   |     |
   +-----+

Aber damit nicht genug. Die Initialiserung von c sagt, dass sie
den Wert von UDR bekommt. UDR steht für das Register in dem die
UART das empfangene Zeichen abgelegt hat. Da kommt also das
empfangene 'C' wieder heraus und wird in der Variablen c abgelegt:

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   0 |       |    0 |
   +-----+       +------+

   c
   +-----+
   |   C |
   +-----+

Was kommt als nächstes:

  if (c == 'E')

Sieh am Papier nach (das ist wichtig: Immer im Speicher nachsehen,
welchen Wert Variablen tatsächlich haben und sich nicht darauf
verlasssen, das man deren Wert schon wüsste). c hat den Wert 'C'
und das ist ungleich 'E'. Also wird nicht der then Zweig genommen
sondern der else Zweig.
Was passier dort?

  buffer[position] = c;

Welchen Wert hat position? Ein Blick auf das Papier verrät uns: 0
Also wird an buffer[0] der Wert von c zugewiesen. c hatte den Wert
'C', also sieht das Ergebnis so aus:

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   0 |       |    0 |
   +-----+       +------+

   c
   +-----+
   |   C |
   +-----+

Was passiert weiter?

  position++;

Die Variable position wird um 1 erhöht

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   1 |       |    0 |
   +-----+       +------+

   c
   +-----+
   |   C |
   +-----+

Nachdem auch diese Anweisung ausgeführt wurde, gibt es nichts weiter
in der Funktion zu tun und die Funktion wird beendet. Wie bei jeder
anderen Funktion ist damit noch eine automatische Aktion verknüpft:
die lokalen Variablen werden zerstört. In diesem Fall handelt es
sich um die Variable c. Also: Radiergummi raus und c ausradieren:

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   1 |       |    0 |
   +-----+       +------+

Das ist also die Situation der globalen Variablen nach dem Empfang
des ersten Zeichens.
Lass uns noch ein Zeichen empfangen: ein 'P'.
Wieder beginnt die ISR mit dem Erzeugen von c und dem holen des
Zeichens nach c

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   1 |       |    0 |
   +-----+       +------+

   c
   +-----+
   |   P |
   +-----+

  if (c == 'E')

Ein Blick aufs Papier verrät, dass c kein 'E' enthält, also kommt
wieder der else Zweig zum Zug:

  buffer[position] = c;

position (am Papier nachsehen) enthält den Wert 1, also wird
an buffer[1] der Inhalt von c zugewiesen

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | P | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   1 |       |    0 |
   +-----+       +------+

   c
   +-----+
   |   P |
   +-----+

  position++;

Auch das ist wieder leicht: position um 1 erhöhen:

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | P | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   2 |       |    0 |
   +-----+       +------+

   c
   +-----+
   |   P |
   +-----+

Die Funktion ist wieder fertig, die lokalen Variablen werden
zerstört:

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | P | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   2 |       |    0 |
   +-----+       +------+

Zu guter letzt, lasen wir noch ein Zeichen empfangen:
diesesmal ein 'E'.

Die ISR beginnt:

  char c = UDR;

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | P | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   2 |       |    0 |
   +-----+       +------+

   c
   +-----+
   |   E |
   +-----+

  if (c == 'E')

Ein Blick auf c verrät, diesmal enthält c tatsächlich ein 'E'.
Also wird der then Zweig genommen:

   buffer[position] = '\0';

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | P | \0| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   2 |       |    0 |
   +-----+       +------+

   c
   +-----+
   |   E |
   +-----+

(Damit ist in Buffer ein gültiger String entstanden: Eine Folge
von Zeichen die mit '\0' abgeschlossen ist)

    habekommando = 1;

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | P | \0| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   2 |       |    1 |
   +-----+       +------+

   c
   +-----+
   |   E |
   +-----+

  position = 0;

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | P | \0| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   0 |       |    1 |
   +-----+       +------+

   c
   +-----+
   |   E |
   +-----+

Das position hier wieder auf 0 gesetzt wird, sollte nach dem
ganzen Vorgeplänkel einsichtig sein. position wird ja benutzt
um zu entscheiden wo im Buffer das nächste empfangene Zeichen
abgelegt wird. Nachdem also dieser empfangene String
abgearbeitet wurde, wird das nächste empfangene Zeichen wieder
in buffer[0] abgelegt. Und dafür muss position den Wert 0
haben.

  led_init(UDR);

Dieser Aufruf hat hier eigentlich nichts zu suchen. Er gehört
logisch nicht hier her. Aber was solls. führen wir ihn aus:
Das Argument ist UDR.
UDR ist auch hier wieder das Register in dem Zeichen von der
USART empfangen werden. Nur: Bei jedem lesenden zugriff auf
UDR wird dieses register gelöscht. Die Verwendung von UDR
an dieser Stelle liefert also 0

Die Funktion wird aufgerufen. In der Funktion led_init
gibt es keine lokalen Variablen, also braucht auch auf
dem Papier keine erzeugt werden.

  if(strcmp (buffer, "CP001201E") == 0)

Hier wird ein Stringvergleich von buffer mit dem String
"CP001201E" gemacht. Ein Blick auf das Papier enthüllt:

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | P | \0| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   0 |       |    1 |
   +-----+       +------+

   c
   +-----+
   |   E |
   +-----+

buffer enthält den String "CP". Da dieser String nicht gleich
"CP001201E" ist, liefert strcmp keine 0. Der else Zweig kommt
zum Zug.

  else if(strcmp (buffer, "CP001200E") == 0)
  {

buffer ist auch nicht gleich "CP001200E", also kommt
auch hier der else Zweig zum Zug, den es aber nicht mehr
gibt.
Damit ist die Funktion zu Ende und es geht wieder zurück
zum Aufrufer, in diesem Falle in die ISR.

In der ISR passiert aber nichts mehr nach dem Funktionsaufruf.
Die ISR beendet sich (und löst die globalen Variablen auf)

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | P | \0| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   0 |       |    1 |
   +-----+       +------+

Nachdem die ISR abgearbeitet wurde, geht die Programmausführung
ganz normal in main() weiter, in der while Schleife, die
ja durch die ISR unterbrochen wurde.

In der while Schleife wird habekommando auf 1 überprüft,
und das ist jetzt auch der Fall! Warum? Weil die ISR
erkannt hat, dass ein Kommando vollständig empfangen
wurde und daher habekommando auf 1 gesetzt hat.

  if (habekommando == 1)

Hier wird also das then ausgeführt. Und eigentlich sollte hier
der Aufruf von led_init stattfinden. Denn hier ist die Stelle
an der bekannt ist, dass ein Kommando empfangen wurde und an
der die Abarbeitung des Kommandos hingehört.
Anschliessend wird habekommando wieder auf 0 gesetzt:

    habekommando = 0;

  buffer
   +---+---+---+---+---+---+---+---+---+---+
   | C | P | \0| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+---+---+

   position      habekommando
   +-----+       +------+
   |   0 |       |    0 |
   +-----+       +------+

Und damit sind wir wieder fast in der Ausgangsposition.
habekommando zeigt an, dass es kein empfangens, nicht
abgearbeitetes Kommando gibt, und position hat korrekter-
weise wieder den Wert 0. Das nächste empfangene Zeichen
wird also wieder bei buffer[0] abgelegt, position um 1
erhöht etc. bis ein empfangenes 'E' anzeigt, dass das
übertragene Kommando vollständig ist. In diesem Fall
wird die ISR in buffer wieder einen kompletten String
aufgebaut haben und habekommando auf 1 setzen.
Die while Schleife in main() sieht diese 1, bearbeitet
das Kommando und setzt habekommando wieder auf 0
zurück. etc. etc. etc.

Du siehst also: Mit Papier und Bleistift ist es gar
nicht so schwer herauszufinden, was eine Funktion
macht und Einsichten zu gewinnen, warum es genau dieses
tut.

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für deinen ausführlichen Beitrag. Er hat mir sehr weitergeholfen!

Autor: Christoph G. (booty3009)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe das Programm noch geändert, so wie sie es beschrieben hatten, 
doch beim senden der String_Kette CP001200 oder CP001201 passiert 
níchts.
ich glaube es liegt an der ISR, die springt einfach nicht an.
Ich habe nur in der main() led_init() eingesetzt und aus dem obigen 
Beispiel rausgenommen.
Können Sie mir bitte weiterhelfen!

int main(void)
{
DDRA = 0xff;
uart_init();
sei();
while(1)  {

  if (habekommando == 1) {
    led init();
    habekommando = 0;
  }

}
return 0;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christoph G. wrote:

> ich habe das Programm noch geändert, so wie sie es beschrieben hatten,
> doch beim senden der String_Kette CP001200 oder CP001201 passiert
> níchts.

Der allererste Schritt sollte immer seibn zunächst mal
zu überprüfen, ob am µC auch tatsächlich die Zeichenkette
ankommt, von der du glaubst, dass sie ankommt:

Dazu schickt man zb. einfach mal die Zeichenkette wieder
zurück, um sie auf einem Terminal ausgeben und begutachten
zu können.

> ich glaube es liegt an der ISR, die springt einfach nicht an.

Woher weist du das?
Hast du das getestet?

Ein einfacher Test wäre es zb. in der ISR einfach mal eine
LED einschalten zu lassen. Geht die LED an, wird die ISR
ausgeführt. Geht sie nicht an, wird die ISR nicht ausgeführt.
Damit hast du schon mal das 'ich glaube, dass ...' in ein
'ich weiss, dass ...' überführt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.