Hallo!
Ich habe eine serielle Verbindung mit meinem ATmega64 zu meinem PC
aufgebaut (mit Silabs USB-Bridge).
Ich nutze die "Interrupt UART library" von Peter Fleury.
Ich möchte nun ein Software-Handshake unterbringen. Wo genau muss ich
diese Steuerzeichen unterbringen?
Hier mal die Sende- und Empfangsroutine:
1
voiduart_putc(unsignedchardata)
2
{
3
inttmphead;
4
5
tmphead=(UART_TxHead+1)&UART_TX_BUFFER_MASK;
6
7
while(tmphead==UART_TxTail){
8
;/* wait for free space in buffer */
9
}
10
11
UART_TxBuf[tmphead]=data;
12
UART_TxHead=tmphead;
13
14
/* enable UDRE interrupt */
15
UCSR0B|=(1<<UDRIE0);
16
17
}/* uart_putc */
18
19
ISR(USART0_RX_vect){
20
21
// read UART status register and UART data register
22
uart_menu_rxdata=UCSR0A;// Empty the Status Register
23
uart_menu_rxdata=UDR0;// Read desired data
24
25
UART_RX_OFF;// Kein weiterer Empfang (nur ein Zeichen)
26
27
uart_menu_rxflag=1;// Flag, dass etwas empfangen wurde
28
29
}
Nun ist die Frage wo ich den Software-Handshake einbaue. Der
Software-Handshake macht doch auch nur Sinn, wenn der Sender dauerhaft
sendet oder?
Dies tue ich aber nicht, ich "trigger" aus LabView heraus den Controller
mit einem Zeichen und daraufhin wird mir der gewünschte String
zurückgesendet.
Das Problem ist, dass ich zwei Funkmodule habe (die mein Kabel ersetzen
sollen), die mit Software-Handshake arbeiten. PC-seitig kann man das ja
einstellen. Nur wie mache ich das bei meinem Controller?
Ich hoffe ihr könnt mir helfen.
Viele Grüße
Daniel
Daniel schrieb:
> Ich möchte nun ein Software-Handshake unterbringen. Wo genau muss ich> diese Steuerzeichen unterbringen?
In möglichst tief liegenden Treiberschichten.
> Hier mal die Sende- und Empfangsroutine:>>
1
>voiduart_putc(unsignedchardata)
2
>{
3
>inttmphead;
4
>
5
>tmphead=(UART_TxHead+1)&UART_TX_BUFFER_MASK;
6
>
7
>while(tmphead==UART_TxTail){
8
>;/* wait for free space in buffer */
9
>}
10
>
11
>UART_TxBuf[tmphead]=data;
12
>UART_TxHead=tmphead;
13
>
14
>/* enable UDRE interrupt */
15
>UCSR0B|=(1<<UDRIE0);
16
>
17
>}/* uart_putc */
guter Platz. Noch besser wäre es allerdings die Sendefreigabe
unmittelbar vor Ausgabe des Zeichens ins UDR Register zu prüfen. Da das
aber im Interrupt passiert, ist das nicht so simpel. Denn im Interrupt
sollte man nicht warten.
Auf der anderen Seite muss die Gegenstelle nach dem Senden eins XOFF
sowieso damit rechnen, dass noch ein paar Zeichen eintrudeln werden. Es
ist nicht spezifiziert wieviele das sein können aber wenn dein
UART_TxBuf nicht allzugross dimensioniert ist, sollte das eigentlich
kein allzugroßes Problem sein. Muss man ausprobieren.
Also: Gesendet werden darf nur dann, wenn die Gegenstelle nicht mit
einem XOFF das Senden unterbunden hat.
Also wirst du in der Empfangsroutine eine Erkennung von XOFF (und XON)
einbauen. Wird XOFF erkannt, dann wird eine static volatile globale
Variable SenderAllowsTransmission auf FALSE gesetzt. In der uart_putc
fragst du ab, ob SenderAllowsTransmission auf TRUE steht und wenn nicht,
dreht die Sendroutine ihre Runden, solange, bis sie die Freigabe über
diese Variable bekommt.
> ISR (USART0_RX_vect) {>> // read UART status register and UART data register> uart_menu_rxdata = UCSR0A; // Empty the Status Register> uart_menu_rxdata = UDR0; // Read desired data>> UART_RX_OFF; // Kein weiterer Empfang (nur ein> Zeichen)>> uart_menu_rxflag=1; // Flag, dass etwas empfangen wurde>> }> [/c]
In dieser Funktion wird das empfangene Zeichen angeschaut.
Ist es XOFF, dann wird SenderAllowsTransmission auf FALSE gesetzt, ist
es XON dann wird selbige Variable auf TRUE gesetzt. Ist es keinen von
beiden, dann wird mit dem empfangenen Zeichen verfahren wie bisher auch.
> Nun ist die Frage wo ich den Software-Handshake einbaue. Der> Software-Handshake macht doch auch nur Sinn, wenn der Sender dauerhaft> sendet oder?
Nö.
Ein Handshake kann immer Sinn machen, wenn die Gegenstelle zeitweise
nicht aufnahmebereit ist. Das kann viele Ursachen haben, zb. weil eine
längere Berechnung im Gange ist, und die Gegenstelle nicht aufnahmefähig
ist. Oder weil die Gegenstelle befürchtet, dass wenn du weitersendest
ihr Eingangspuffer überlaufen wird.
Hint: Das ist auch das Stichwort wann dein Programm an die Gegenstelle
ein XOFF schicken könnte. Wobei dann natürlich die paradoxe Situation
enstehen kann, dass die Gegenstelle ihrerseits bereits mittels XOFF
mitgeteilt hat, dass sie zur Zeit nicht belästigt zu werden wünscht :-).
Wenn also die Gegenstelle bereits einen XOFF geschickt hat, darfst du
ihr dann deinerseits einen XOFF schicken (denk logisch nach)
Hallo,
ich hab da noch ein Problem. Ich weiß nicht genau ob es mit dem
vorherigen Problem zusammenhängt, aber es trat erst jetzt auf.
Ich habe obigen Quellecode geflasht. Via AVR-Studio (AVR-Prog). Nach dem
Flashen lasse ich die Spannung am Controller vom USB-Port, stecke das
Empfängermodul an den Rechner und lasse mir was schicken ->
funktioniert.
Sobald ich den USB-Stecker ziehen und somit auch die Spannung und auf
meine externe Spannungsquelle umstelle, funktioniert die
Datenübertragung nicht mehr.
Abhängig von der USB-Spannung ist das Problem offenbar nicht, da ich
meine externe Spannungsquelle parallel dran hatte und dann die
USB-Spannung entfernt hatte. Dann klappte es auch noch. Nachdem ich dann
aber die externe Spannungsquelle entfernt habe und wieder angeschlossen
habe, funktionierte die Verbindung nicht mehr.
Kann das ein Pegelproblem sein?
Und AVR-Prog führt doch automatisch einen Reboot des Controllers durch,
der doch auch durchgeführt wird, wenn die Spannungsversorgung des
Controllers nicht mehr da ist oder?
Die andere Frage ist, ob ich dem Funkmodul controllerseitig ein XOFF
bzw. XON schicken muss? Wenn ja, wo sollte ich das machen? Bisher
verarbeite ich ja nur die Empfangenden Zeichen am Controller. Das wird
aber nicht mit dem obigen Problem zusammenhängen denke ich.
ganz schoen heftig !
was funktioniert nicht mehr wenn du die spannung kappst ?
laeuft der prozessor weiter ? (blinkled zur kontrolle oder so was,
lebensbit)
mach mal die masse irgendo gegen. das funkmodul koennte schwingen, also
noch senden, nur eben so dass es keiner mehr versteht
wie ist das aufgebaut ?
die kapazitaet des netzteils ist ja riesig, vieleicht ist die der
anderen versorgung zu keil ?
wegen dem xon/xoff:
welche baudrate ? womit kommunizierst du ? und wie wichtig sind die
daten ?
wiederholende daten, z.b. messwerte, kannst auf der empfaengerseite auch
auf plausibilitaet pruefen, also wenn werte kommen 100, 102, 101, 17,
104 koenntest die 17 ja erkennen da die abweichung zu gross ist.
da wuerd ich kein handshake bauen, wenn es aber daten sind wie z.b. ein
nc-programm und eine achse gesteuert wird, da wuerd ich mich nicht mal
auf das handshake verlassen, sondern ne pruefsumme einbauen (ist
einfacher)
generell ist handshake von 3 faktoren abhaengig damit es funktioniert
1. puffergroesse
2. baudrate
3. reaktionsgeschwindigkeit der gegenstelle
da ich selber kaum erfahrung mit atmel habe und in zukunft auch solche
probleme bekommen werde wuerd es mich freuen wenn du mir das ergebnis
hier wieder kund tust
gruss
w. :-)
Problem gelöst.
Nach der Initialisierung des UART schicke ich an das Funkmodul ein XON.
Scheinbar ist das Flashen mit AVR-Prog was anderes als der Reboot des
Controllers wenn man die Spannung weg nimmt.
@wolfgang
Ich muss leider den Software-Handshake nutzen, da die Funkmodule, die
ich habe, das voraussetzen.
Daniel
Kannst du mir dein ganzes UART Zeug zukommen lassen. Ich verstehe es
nicht ganz und würde es gern da einige deiner Variablen im Quellcode den
du gepostet hast nicht definiert sind.
Danke