Hallo,
ich bin dabei ein seriellen Bus über USART aufzubauen. Dafür möchte ich
dien MPCM benutzen um die angeschlossenen Controller adressieren zu
können.
Irgendwie funktioniert der Mode aber nicht so richtig.
Ich habe das Format mit 9 Datenbits, 1 Parity, 2 Stoppbits gewählt. Das
9. DB nur wegen dem MPCM.
Darum habe ich noch folgende Fragen:
Muss ich bei der MAster CPU das MPCM Bit auch setzten? (Habe ich jetzt
nicht gemacht)
Wird automatisch beim Empfangen (Slave) geschaut ob das TXB8 Bit gestzte
ist und dann entschieden ob es sich dabei um eine Adresse handelt?
Irgendwie verstehe ich das mit dem MPCM und TXB8 nicht so richtig, wann
wird welches Bit automatisch gestzt und gelöscht?
Muss ich in der Receive Funktion noch irgendwelche Bits beachten bzw.
setzten, löschen?
Ich habe das Senden folgender Maßen geschrieben (teilweise aus dem
Datasheet übernommen):
1
voidUSART_Transmit_Data(uint16_tdata)
2
{
3
uint8_tbyte;
4
uint16_tword=data;
5
byte=word;
6
for(uint8_ti=0;i<=1;i++)
7
{/* Wait for empty transmit buffer */
8
9
while(!(UCSRA&(1<<UDRE)));
10
UCSRB&=~(1<<TXB8);//TXB8: 0= Daten Senden /* Put data into buffer, sends the data */
11
UDR=byte;
12
while(!(UCSRA&(1<<TXC)));
13
UCSRA|=(1<<TXC);
14
byte=(word>>8);
15
}
16
}
17
18
voidUSART_Transmit_Adress(uint8_tadress)
19
{
20
/* Wait for empty transmit buffer */
21
while(!(UCSRA&(1<<UDRE)));
22
UCSRB|=(1<<TXB8);//TXB8: 1=Adresse senden /* Put data into buffer, sends the data */
23
UDR=adress;
24
while(!(UCSRA&(1<<TXC)));
25
UCSRA|=(1<<TXC);
26
27
}
28
29
unsignedcharUSART_Receive(void)
30
{
31
unsignedcharstatus,daten;
32
33
while(!(UCSRA&(1<<RXC)));
34
35
status=UCSRA;//Flags sichern
36
daten=UCSRB;//Verwerfen des 9Bits
37
38
if(!(status&((1<<FE)|(1<<DOR)|(1<<UPE))))
39
returnUDR;
40
else
41
return0;
42
}
Also das Senden und Empfangen funktioniert ohne Probleme, nur es wird
nicht automatisch zwischen Adresse und Daten unterschieden, d.h. beim
senden von Daten antwortet der Slave was er aber nicht soll, da es sich
ja um Daten handelt.
> Ich habe das Format mit 9 Datenbits, 1 Parity, 2 Stoppbits gewählt.
Unterstützt denn der gewählte Controller dieses Format überhaupt?
Manche können nur insgesamt 11 Bit übertragen.
Hi
Ich habe das vor kurzem in Assembler gemacht.
Bei dir vermisse ich in der Empfangsroutine einen Adressvergleich.
Am Anfang muss der Slave im MPC-Mode sein. Damit empfängt er nur Daten
mit gesetzten Bit9. Wenn Daten empfangen wurden, muss ein Vergleich: UDR
mit Slaveadresse stattfinden. Bei Nichübereinstimmung wird alles
verworfen und der Slave kann weiterschlummern. Bei Übereinstimmung wird
der Slave in den Normalmode versetzt und kann Daten mit Bit9=0
empfangen. Wenn alle Daten übertragen sind, versetzt sich der Slave
wieder in den MPC-Mode und spielt mit den empfangenen Daten.
MfG Spess
Im Datenblatt auf Seite 132 steht folgendes:
"The following procedure should be used to exchange data in
Multi-processor Communi-
cation mode:
1. All Slave MCUs are in Multi-processor Communication mode (MPCM in
UCSRA
is set).
2. The Master MCU sends an address frame, and all slaves receive and
read this
frame. In the Slave MCUs, the RXC flag in UCSRA will be set as normal.
3. Each Slave MCU reads the UDR Register and determines if it has been
selected. If so, it clears the MPCM bit in UCSRA, otherwise it waits for
the next
address byte and keeps the MPCM setting.
4. The addressed MCU will receive all data frames until a new address
frame is
received. The other Slave MCUs, which still have the MPCM bit set, will
ignore
the data frames.
5. When the last data frame is received by the addressed MCU, the
addressed
MCU sets the MPCM bit and waits for a new address frame from master. The
process then repeats from 2."
Besonders der Punkt 3 macht mir kopfzerbrechen.
Soll ich das so verstehen, wenn eine Adresse empfangen wird, dann wird
das MCPM bit gelöscht, wenn es Daten sind dann bleibt es '1'. Also dann
müsste ich warten bis das Bit gelöscht ist und mir dann die Adresse
ansehen und schauen ob es die des jeweiligen Slave ist. ?
Aber wenn man das so manuell machen muss, dann wäre ja der Modus für den
Ar***, dann könnte ich doch einfach das 9.DB dazu verwenden um zwischen
Adresse und Daten zu unterscheiden. Für was also dann dass MPCM bit?
@spess53
Also ich habe bei mir im Code es so gedacht, dass wenn der Slave eine
Adresse Empängt diese dann von Receive() zurück gegeben wird und in der
Main verglichen wird. Normalerweise sollte doch der Slave solange in der
Receive() Funktion verharren bis eine Adresse kommt. Das ist doch der
Sinn von MPCM, das automatisch die Daten gefiltert werden und erst wenn
das erste mal eine Adresse kommt dann die Datendurchgelassen werden...
Hm wobei jetzt fällt mir beim schreiben auf, woher weiss der Controller
das die gesendete Adresse jetzt seine ist und somit die nachkommenden
Daten durchlässt?
Hi
Wo du den Vergleich machst, ist eigentlich egal. Ich habe das gleich in
die RX-ISR gepackt.
>Hm wobei jetzt fällt mir beim schreiben auf, woher weiss der Controller>das die gesendete Adresse jetzt seine ist und somit die nachkommenden>Daten durchlässt?
Die Adresse musst du ihm verpassen. Evtl. im EEPROM.
Was noch wichtig ist: Der Slave muss wissen, wann die Daten fertig
übertragen sind. Damit er dann wieder zurückschalten kann.
MfG Spess
Also muss ich quasi mit der Hand das RX8B auslesen und feststellen ob es
sich um eine Adresse handelt oder es Daten sind?
wenn eine Adresse, dann vergleichen mit der Slave Adresse. -->Wenn die
gleich sind muss ich das MPCM löschen, wenn nicht, dann nichts tun.?
Danach kann ich die Daten empfangen, nach dem Empfang aller Bytes muss
ich MPCM wieder auf '1' setzen, d.h. der Slave muss genau wissen
wieviele Frames als Daten gesendet werden!
Aber irgendwie raffe ich das mit dem Mode immer noch nicht, das ist doch
dann alles per Software gelöst, nichts hardwaremäßig!
Und der Fall wenn die Adresse nicht übereinstimmt:
Der Slave muss doch trotzdem immer hören ob es sich um eine Adresse
handelt, es könnte ja sein dass das nächste Byte wieder eine Adresse
ist...
Ich blick es einfach nicht was jetzt der große Vorteil von MPCM ist, für
mich ist das einfach nur ein Bit in einem register was man löschen und
setzen kann und sonst keine funktion hat.
Hi
>Also muss ich quasi mit der Hand das RX8B auslesen und feststellen ob es>sich um eine Adresse handelt oder es Daten sind?
Nein. Im MPC-Mode empfängt der Slave nur 'Bytes' mit gesetzten Bit9.
Also nur Adressen. Alles andere wird ignoriert.
>wenn eine Adresse, dann vergleichen mit der Slave Adresse. -->Wenn die>gleich sind muss ich das MPCM löschen, wenn nicht, dann nichts tun.?
Ja.
>Und der Fall wenn die Adresse nicht übereinstimmt:>Der Slave muss doch trotzdem immer hören ob es sich um eine Adresse>handelt, es könnte ja sein dass das nächste Byte wieder eine Adresse>ist...
Nein. Siehe oben.
MfG Spess
Wird RXC eigentlich gestzt wenn kein Adressbyte kommt?
Wenn ich mir das Oszillogramm ansehe, wird auf ein empfangenes
Datenbeyte eine 1 zurück gesendet.
in der Main() des Masters 2 DATEN Bytes gesendet, in der Slave Main()
wird einfach nur das Empfangene zurückgesendet.
Da es sich um Datenbytes handelt dürfte der Slave garnicht senden.
Und wenn eine '1' zurück gesendet wird, muss das heißen dass die
while(...) Warteschleife in der Receive Funktion beendet wurde, obwohl
keine Adresse gesendet worden ist!
Ich versteh die Welt nicht mehr!?
Hi
Also, ich bin notorischer Assemblerprogrammierer mit rudimentären
C-Kenntnissen.
In der Testphase würde ich auf solche Sachen, wie Fehlerüberprüfung
verzichten. Machen das Ganze nur unübersichtlicher und ist eine
zusätzliche Fehlerquelle.
> unsigned char status, daten;> static unsigned char datenlaenge=0;
Sitzt das nicht an der falschen Stelle? Meinesachtens löscht du
Datenlänge damit bei jedem Aufruf.
Hast du auch mit unterschiedlich gesetzten Bit9 gesendet und die
richtige Adresse benutzt?
Hab dir mal mein Assenblerprogramm angehängt (kleine Rache). Der erste
Teil ist für den Master, der Zweite für den Slave.
MfG Spess
>> unsigned char status, daten;>> static unsigned char datenlaenge=0;>Sitzt das nicht an der falschen Stelle? Meinesachtens löscht du>Datenlänge damit bei jedem Aufruf.
Also ich glaube dass bei "static" die variable beim Aufruf nur einaml
deklariert wird und beim beenden der Funktion erhalten bleibt.
Mit Fehlerüberprüfung meinst du FE, UPE?
Das ist eigentlich kein Problem, eine 128 wird nie zurück gesendet.
>Hast du auch mit unterschiedlich gesetzten Bit9 gesendet und die>richtige Adresse benutzt?
Also wie im erstn Post setzte ich TXB8 auf 1 wenn ich Adresse sende und
0 wenn ich Daten senden möchte.
Die Slave Adresse stimmt, aber ist ja eigentlich egal da ich diesen MPCM
Mode teste in dem ich gar keine Adresse sende! Einfach nur um zu
überprüfen ob der Receiver vom Slave die empfangenen Bytes verwirft, da
es ja hier nicht um eine Adresse handelt.
Genau das ist ja das Problem, der Receiver verwirft bzw. ignoriert das
nicht!
PS die Rache ist dir geglückt. ;-)
Hi
>Also ich glaube dass bei "static" die variable beim Aufruf nur einaml>deklariert wird und beim beenden der Funktion erhalten bleibt.
Mag sein. Aber du setzt sie jedesmal auf 0.
>Genau das ist ja das Problem, der Receiver verwirft bzw. ignoriert das>nicht!
Zeig mal die Initialisierung der Slave UART. Wie realisiert du das
Senden?
MfG Spess
>Mag sein. Aber du setzt sie jedesmal auf 0.
Ich glaube nicht, zumindest wenn man dieser Beschreibung glauben darf
http://tutorial.schornboeck.net/static.htm
Slave USART Initalieserung:
Hi
>void USART_Transmit_Data( uint16_t data )
Irgendwie herrscht bei dir ein Durcheinander von Datentypen. Wieso
benutzt du beim Senden 'uint16_t data' und beim Empfangen 'unsigned
char'. Das Ganze kommt mir sehr unsystematisch vor.
>Ich glaube nicht, zumindest wenn man dieser Beschreibung glauben darf
Du denkst noch dran, das ich Assemblerprogrammierer bin. Ich bewege mich
hier auf sehr unsicheren Terrain.
MfG Spess
>Irgendwie herrscht bei dir ein Durcheinander von Datentypen. Wieso>benutzt du beim Senden 'uint16_t data' und beim Empfangen 'unsigned>char'. Das Ganze kommt mir sehr unsystematisch vor.
Das Ganze hat aber ein System:
Ich verwende 1Byte beim Senden von Adressen und 2Bytes beim Senden von
Daten. 1Byte Adresse langt völlig aus um alle Slaves zu Adressieren.
Bei den Daten habe ich mich auf eine Paketgröße von 2Byte festgelegt
weil ich immer 16Bit große Wörter verschicke. Das macht die Main auch
übersichtlicher, denn dann brauch ich nicht jedesmal die Word to Byte
umwandlung hinschreiben.
Zum empfangen langt die funktion mit dem return von 1Byte. Ich schreib
dann in der Main einfach zwei Receive() Aufrufe hintereinander.
Aber all das dürfte eigentlich nichts mit meinem Problem zu tun haben.
In der USART_Transmit_Adress(...) setze ich TXB8 auf '1' und bei
USART_Transmit_data(...) wird TXB8 auf '0' gesetzt.
Wenn also TXB8='0' ist müsster der Slave (MPCM=1) erkennen, dass es sich
dabei nicht um eine Adresse handelt und die Empfangenen Daten
ignorieren, das macht er aber nicht!!!
Ich werd nochmal verrückt mit diesem Modus. :-( Ist irgendwie schlecht
beschrieben im Datenblatt.
Hi
Dann liegt der Fehler möglicherweise in anderen Codeteilen. Hast du dir
mal meinen Code angesehen. Der funktioniert 100%-tig (JTAG
ICE-getestet).
MfG Spess
Hi
>Was ist damit? UCSZ2 ist gestzt um 9 Bits zu versenden. Das neunte ist>TXB8.
Nein!
UCSZ2 = 2
1<<UCS2 = 4
mit |(UCSZ2) versuchst du RXB8 zu beschreiben.
MfG Spess