Forum: Mikrocontroller und Digitale Elektronik ATmega8 multiprozessorkommunikation problem


von duron005 (Gast)


Lesenswert?

Hallo,

Ich bin gerade dabein Multikontorllersystem mit 2 atmega8 aufzubauen 
(später werden noch mehrere ATmega8 verbaut)

Der Sender wid folgendermassen initialisiert: (Master)
1
void USART_Init( unsigned int ubrr)
2
{
3
  // Set baud rate 
4
  UBRRH = (unsigned char)(ubrr>>8);
5
  UBRRL = (unsigned char)ubrr;
6
  // Enable receiver and transmitter--> 9 bit modus einstellen durch register bit UCSZ2 
7
  UCSRB = (1<<TXEN) | (1<<UCSZ2);// | (1 << RXCIE) |(1<<RXEN);  
8
  // Set frame format: 9data, 1stop bit 
9
  UCSRC = (1<<URSEL)|(0<<USBS) | (1<<UCSZ0)| (1<<UCSZ1);
10
}

Die Senderoutine sieht so aus (Master):
1
void USART_Transmit( unsigned char data, unsigned char adress)
2
{
3
4
  /* Wait for empty transmit buffer */
5
  while ( !( UCSRA & (1<<UDRE)) )
6
  ;
7
  UCSRB =UCSRB & 0b11111110;    //bit zuerst loeschen
8
  UCSRB =UCSRB | adress;      //dann das 9te bit setzen
9
10
11
  /*daten senden*/
12
  UDR = data;
13
}

Die Daten werden in der interruptservice routine ausgelesen und zwar 
folgendermassen (Slave):
1
SIGNAL(SIG_UART_RECV)
2
{
3
4
5
  if(UCSRB&0b00000010) //wenn 9tes datenbit existiert
6
  {
7
    UCSRB=UCSRB&0b11111101;    //9tes bit loeschen
8
    mydata=UDR;
9
    
10
 
11
    UCSRA=UCSRA|0b00000001;                       //multiprozessormodus aktivieren
12
    
13
    if  ( (KONTROLLERADRESSE==mydata)//checke ob ich damit gemeint bin
14
    {
15
    
16
      UCSRA=UCSRA&0b11111110;               //multiprozessormodus aktivieren
17
      
18
      return;            // aus funktion zurueckgehen
19
    
20
    }
21
    else
22
    {
23
      return;
24
    }
25
  
26
  }
27
28
  mydata=UDR;
29
30
}



Initialsierung  der RS232 im Slave:
1
void USART_Init( unsigned int ubrr)
2
{
3
  // Set baud rate 
4
  UBRRH = (unsigned char)(ubrr>>8);
5
  UBRRL = (unsigned char)ubrr;
6
  // Enable receiver and transmitter--> 9 bit modus einstellen durch register bit UCSZ2 
7
  UCSRB = (1<<RXEN) | (1<<UCSZ2)| (1 << RXCIE);//|(1<<TXEN);
8
  // Set frame format: 9data, 1stop bit 
9
  UCSRC = (1<<URSEL)|(0<<USBS) | (1<<UCSZ0)| (1<<UCSZ1);
10
  UCSRA =UCSRA|0b00000001;        //multipozessor kommunikation aktivieren // es wird wieder auf die naechste adresse gewartet
11
}

Das ganze sollte so funktionieren:
Der Master schickt ein Adressframe. Der Slave erkennt ob das Adressframe 
für ihn bestimmt ist. Wenn ja loescht er das MPCM bit (damit werden auch 
Dataframes akzeptiert). Der Slave akzeptiert nun alle Dataframe bis 
wieder ein Adresframe erkannt wird ( 9tes bit gesetzt) Das ganze 
funtioniert auch soweit. Ich schicke zum Beispiel einmalig ein 
Adressframe. Danach schicke ich nur noch Dataframes und sporadisch 
erkennt der Slave meine Dataframes nicht mehr als Dataframes. Nur durch 
erneutes senden der Adresse werden die Dataframes wieder akzeptiert. 
Sieht jemand einen Fehler in meinem Code?

von Gast (Gast)


Lesenswert?

__interrupt  void rx_int()
{
char temp, mpcm;
  mpcm = UCSRB & 2;    // adresse oder datum
  temp = UDR;    /* zeichen immer lesen */
  if(mpcm) {
    if(temp == my_address) {  // adressierung
      UCSRA = 0;    /* MPCM-bit abschalten */
      ser_status |= (ADRESSIERT + NEUE_ADRESSE);
      clr_inbuf1();    // synchronisieren
      clr_outbuf1();    // nichts mehr ausgeben
    } else {
      UCSRA = 1;    /* MPCM-bit einschalten */
      ser_status &= ~ADRESSIERT;
    }
    return;
....

So mache ich es beim Empfangen; vergleiche bitte selbst.

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

duron005 wrote:
> Hallo,
>
> Ich bin gerade dabein Multikontorllersystem mit 2 atmega8 aufzubauen
> (später werden noch mehrere ATmega8 verbaut)

Wie darf ich mir das vorstellen? Da eignet sich RS232 nicht zu, es sei 
denn Du benutzt RS485? Hier wuerde ich zum Bleistift TWI anbieten.

Sind die Prozessoren auf dem selben Board oder wie gross ist die 
Distanz? Beschreibe erstmal, was Du machen willst, bevor Du nach einer 
Loesung fragst.

Michael

von Gast (Gast)


Lesenswert?

>UCSRA=UCSRA|0b00000001

Gut, wenn man die Funktion des niedrigstwertigen Bits in UCSRA im Kopf 
hat (ich muss da gerade leider passen).  Sonst weiß man gar nicht, was 
diese Zeile bewirkt, und müsste zur Klärung der Frage das Datenblatt 
herauskramen.

Tipp: Jedem belegten Bit in den I/O-Registern ist ein Namenskürzel 
zugewiesen, und wenn man es benutzt, macht das den Quellcode nicht 
unverständlicher.  Hat auch für einen selbst Vorteile, spätestens dann, 
wenn man nach nem halben Jahr noch was an dem Code ändern will.

Na, erinnerst Du Dich an 
Beitrag "atmega8 multiprozessor kommunikation rs232"):

>"Nein, sowas läuft zum
>Beispiel ein paar Minuten und stürzt dann "völlig unerklärlicherweise"
>ab.  Da kann man bei der Fehlersuche dann viel Spaß haben."

Fast schon prophetisch, was? ;-)

von duron005 (Gast)


Lesenswert?

Hallo,

Die Distanzen sind mindestens 25 meter. TWI eignet sich daher leider 
nicht dafür.
Der Grund wieso ich die rs232 Schnittstelle nehmen möchte ist, dass ich 
weniger Bauteile benötige. Ich denke schon dass ich ein einfaches System 
damit aufbauen kann, wenn immer nur Master an einen Slave Daten schickt, 
und dieser dann antwortet. Slaves sollen niemals miteinander reden 
dürfen.

lg

von duron005 (Gast)


Lesenswert?

Ich habe deine routine gerade getestet. Hat manchmal funktioniert  und 
manchmal nicht (wie meine routine)
Das einzige was unterschiedlich ist sind die Funktionsaufrufe
      clr_inbuf1();    // synchronisieren
      clr_outbuf1();    // nichts mehr ausgeben

Diese habe ich nicht eingebunden, weil ich den Codeinhalt nicht kenne. 
Kannst du mir den Code dieser routinen reinstellen, dass ich es mit 
diesen noch versuchen kann?

danke und lg

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Joa aber an ner RS232 kannst Du nur insg. zwei Controller anschliessen. 
Und bei 25 Metern duerften auch nur kleine Baudraten moeglich sein. Kenn 
jetzt die Spec nicht genau aber das ist schon ne ziemlich lange Strecke.

von Gast (Gast)


Lesenswert?

>Diese habe ich nicht eingebunden, weil ich den Codeinhalt nicht kenne.

Die brauchst Du nicht.
Welche Frequenz ist eigentlich auf Deinen Quarzen aufgedruckt?

von Hannes L. (hannes)


Lesenswert?

Michael G. wrote:
> Joa aber an ner RS232 kannst Du nur insg. zwei Controller anschliessen.

Nööö...
Es gibt verschiedene Möglichkeiten, mehrere Controller über RS232 
miteinander zu verbinden.

Man kann durch Protokoll dafür sorgen, dass die TX aller nicht 
adressierten Slaves deaktiviert und hochohmig sind, worauf sie parallel 
geschaltet werden können.

Man mann die TX aller beteiligten Controller über Puffer mit Open-Coll 
führen, das gibt zusätzliche Sicherheit gegen Schäden bei Kollisionen, 
erlaubt Kurzschlussschutz und erhöht etwas die Reichweite.

> Und bei 25 Metern duerften auch nur kleine Baudraten moeglich sein.

Kleine Controller mit kleinen RAMs (Mega8) brauchen wohl selten hohe 
Bausraten, wenn sie Informationen austauschen wollen. Es ist halt kein 
Multimedia.

> Kenn
> jetzt die Spec nicht genau aber das ist schon ne ziemlich lange Strecke.

Sicher ist RS485 besser geeignet, erfordert aber auch einen höheren 
Aufwand. Und der ist nicht in jedem Falle gerechtfertigt.

...

von duron005 (Gast)


Lesenswert?

3.6864 MHZ.. Baudrate habe ich ganz gering eingestellt.. 9600 baud. An 
Übertragungsfehler glaube ich kaum,weil wenn ich zuerst die Adresse 
schicke und dann erst die Daten, es auch immer funktioniert.

Die Höhe der Baudrate ist mit ganz egal. Kann so klein wie möglich sein, 
da es nicht viele Daten sind. Wichtig ist mir nur, dass es richtig 
ankommt, auch wenn ich es 5 mal schicken muss. Zeitkritisch ist es auch 
nicht. Wie gesagt möchte ich das Softwwartechnisch lösen, damit immer 
nur einer sendet, und dieser nur mit dem Master kommuniziert. Die Slaves 
müssen keine Daten miteinander austauschen. rs484 kommt nicht in Frage 
da ich einen erhöhten bauteil aufwand habe und eine zusätzliche 
Datenleitung brauche. 25 meter 3 adriges Kabel habe ich schon und möchte 
mir nicht ein neues kaufen. Außerdem sind 4adrige Kabel teurer als 3 
adrige.

lg

von Alter Mann (Gast)


Lesenswert?

Wie wäre es als Alternative mit einer Ringleitung? Also

TxD Controller 1 an RxD Controller 2
TxD Controller 2 an RxD Controller 3
TxD Controller 3 an RxD Controller 4
TxD Controller 4 an RxD Controller 5
TxD Controller 5 an RxD Controller 6
TxD Controller 6 an RxD Controller 1

Man muss dann nur über die Programmierung sicherstellen, das die Daten, 
die  nicht für den jeweiligen Controller gedacht sind immer weiter 
gereicht werden.

Das vermeidet es, einen Kollisionsschutz einbauen zu müssen. Jeder 
Controller kann senden, wann er will, er muss nur nachher die 
empfangenen Datenpakete weiter reichen, die nicht für ihn bestimmt sind.

Der Nachteil ist natürlich, das, wenn ein Controller ausfällt oder die 
Leitung an einer Stelle defekt ist, das ganze System stillgelegt ist.

Florian

von Falk B. (falk)


Lesenswert?

@ Alter Mann (Gast)

>Wie wäre es als Alternative mit einer Ringleitung? Also

Ist nicht sonderlich schön, weil

>Der Nachteil ist natürlich, das, wenn ein Controller ausfällt oder die
>Leitung an einer Stelle defekt ist, das ganze System stillgelegt ist.

Strangförmiger Bus ist scon OK, und wenn nur ein Master die Slaves 
abfragt, geht das schon.

MfG
Falk

von duron005 (Gast)


Lesenswert?

Ringpuffer kommt nicht in Frage, weil nicht immer jeder kontroller 
vorhanden sein muss;)

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.