Hallo zusammen!
Ich möchte mit einem ATtiny1634 was über einen RS422-Bus senden. dafür
nutze ich den USART1 mit 9600 8N1 und einen MAX489 Treiber.
Zum Testen schicke ich einen String raus mit:
1 | void RS422_PutStr(unsigned char *s) {
|
2 | /* enable output*/
|
3 | PORTB |= (1 << PORTB3);
|
4 |
|
5 | USART1_PutStr(s);
|
6 |
|
7 | /* disable output */
|
8 | PORTB &= ~(1 << PORTB3);
|
9 | }
|
PORTB3 geht hierbei auf den Datenrichtungs-Pin auf dem MAX489.
Selsamerweise werden dabei immer die letzten beiden Zeichen im
beliebigen String nicht gesendet.
Meine Vermutung war dass der Datenrichtungs-Pin zu schnell wieder auf
low gezogen wird sobald der ATtiny aus der USART1_PutStr(s) Funktion
zurückkommt und die letzten beiden Bytes zu dem Zeitpunkt noch in
irgendwelchen Buffer-Registern hängen und noch nicht rausgeschiftet
wurden.
Tatsächlich funktioniert das Ganze ohne Probleme wenn ich ein kurzes
delay einbaue:
1 | void RS422_PutStr(unsigned char *s) {
|
2 | /* enable output*/
|
3 | PORTB |= (1 << PORTB3);
|
4 |
|
5 | USART1_PutStr(s);
|
6 |
|
7 | _delay_ms(20);
|
8 |
|
9 | /* disable output */
|
10 | PORTB &= ~(1 << PORTB3);
|
11 | }
|
Jetzt möchte ich das aber etwas eleganter lösen und einfach auf den
TXC-Flag warten, denn im Datenblatt heißt es:
"This flag is set when the entire frame in the transmit shift register
has been shifted out and there is no new data
currently present in the transmit buffer (UDRn)." Also probiere ich das
mit:
1 | void RS422_PutStr(unsigned char *s) {
|
2 | /* enable output*/
|
3 | PORTB |= (1 << PORTB3);
|
4 |
|
5 | USART1_PutStr(s);
|
6 |
|
7 | while (!(UCSR1A & (1 << TXC1)))
|
8 | ;
|
9 |
|
10 | /* disable output */
|
11 | PORTB &= ~(1 << PORTB3);
|
12 | }
|
Überraschenderweise werden auch hier wieder die letzten beiden Zeichen
nicht gesendet! Hat jemand eine Idee was ich falsch mache?
Vielen Dank und viele Grüße!