ATxmega32A4U - 9 Bit UART Problem

OP #5025900
Hallo liebe Community,

ich habe ein stranges Problem mit UART Treiber. Ich arbeite mit dem 
ATxmega32. Hier mal der Link zum Manual: 
http://www.atmel.com/images/Atmel-8331-8-and-16-bit-AVR-Microcontroller-XMEGA-AU_Manual.pdf.

Ich poste hier mal die wichtigsten Segmente meines Codes hinein:
1
// init uart
2

3
/*
4
 * USART_CHSIZE_9BIT_gc = (0x07<<0)
5
 * USART_BAUDCTRL_BSEL_9600 = 621
6
 * USART_BAUDCTRL_BSCALE_9600 = -2
7
 */
8

9
void init_usart_slv(void) {
10
  PORTC.DIRCLR = PIN6_bm;
11
  PORTC.DIRSET = PIN7_bm;
12
  PORTC.PIN7CTRL = PORT_INVEN_bm; // TX Inverted I/O data
13

14
  USART_NineBits_InterruptDriver_Initialize(&USART_SLV, &USARTC1, USART_DREINTLVL_LO_gc);
15
  USART_Format_Set(USART_SLV.usart, USART_CHSIZE_9BIT_gc, USART_PMODE_DISABLED_gc, false);
16
  USART_RxdInterruptLevel_Set(USART_SLV.usart, USART_RXCINTLVL_LO_gc);
17
  USART_Baudrate_Set(&USARTC1, USART_BAUDCTRL_BSEL_9600, USART_BAUDCTRL_BSCALE_9600);
18

19
  USART_Rx_Enable(USART_SLV.usart);
20
  USART_Tx_Enable(USART_SLV.usart);
21
}
22

23

24
// hier das define in der AVR API
25
// siehe optional Seite 296 -> CTRLC – Control register C
26
#define USART_Format_Set(_usart, _charSize, _parityMode, _twoStopBits)  \
27
  (_usart)->CTRLC = (uint8_t) _charSize | _parityMode |    \
28
                    (_twoStopBits ? USART_SBMODE_bm : 0)
29

30
// meine ISR 
31
ISR(USART_SLV_RXC_vect) {
32
  USART_NineBits_RXComplete(&USART_SLV);
33
}
34

35
// angepasste Funktion aus der AVR API
36
// optional: Suchbegriff "RXB8" (Manual)
37
bool USART_NineBits_RXComplete(USART_NineBits_data_t * usart_data)
38
{
39
  USART_NineBits_Buffer_t * bufPtr;
40
  bool ans;
41

42
  bufPtr = &usart_data->buffer;
43
  /* Advance buffer head. */
44
  uint8_t tempRX_Head = (bufPtr->RX_Head + 1) & USART_RX_BUFFER_MASK;
45

46
  /* Check for overflow. */
47
  uint8_t tempRX_Tail = bufPtr->RX_Tail;
48
  uint16_t data;
49

50
  if(usart_data->usart->STATUS & USART_RXB8_bm) {
51
    data = 0x0100 | usart_data->usart->DATA;
52
  } else {
53
    data = usart_data->usart->DATA;
54
  }
55

56
  if (tempRX_Head == tempRX_Tail) {
57
      ans = false;
58
  }else{
59
    ans = true;
60
    usart_data->buffer.RX[usart_data->buffer.RX_Head] = data;
61
    usart_data->buffer.RX_Head = tempRX_Head;
62
  }
63
  return ans;
64
}
65

66
// so lese ich aus
67
bool mdb_receive_9bit(USART_NineBits_data_t *ptr, uint16_t *recv_byte) {
68
  if (USART_NineBits_RXBufferData_Available(ptr)) {
69
    *recv_byte = USART_NineBits_RXBuffer_GetByte(ptr);
70
    return true;
71
  }
72
  return false;
73
}
74

75
// hier die obige Funktion
76
bool USART_NineBits_RXBufferData_Available(USART_NineBits_data_t * usart_data)
77
{
78
  /* Make copies to make sure that volatile access is specified. */
79
  uint8_t tempHead = usart_data->buffer.RX_Head;
80
  uint8_t tempTail = usart_data->buffer.RX_Tail;
81

82
  /* There are data left in the buffer unless Head and Tail are equal. */
83
  return (tempHead != tempTail);
84
}
85

86
// hier die obige Funktion
87
uint16_t USART_NineBits_RXBuffer_GetByte(USART_NineBits_data_t * usart_data)
88
{
89
  USART_NineBits_Buffer_t * bufPtr;
90
  uint16_t ans;
91

92
  bufPtr = &usart_data->buffer;
93
  ans = (bufPtr->RX[bufPtr->RX_Tail]);
94

95
  /* Advance buffer tail. */
96
  bufPtr->RX_Tail = (bufPtr->RX_Tail + 1) & USART_RX_BUFFER_MASK;
97

98
  return ans;
99
}
100

101

102
// hier der Aufrufer in einer Loop
103
uint16_t recv_byte = 0;
104
uint8_t payload = 0;
105
uint8_t modebit = 0;
106
while (mdb_receive_9bit(&USART_SLV, &recv_byte)) {
107
  /* hier passiert der sch*ß */
108
  // ich überprüfe nur beim ersten empfangenen Bit ob gesetzt
109
  if (buf_len == 0) {
110
    modebit = recv_byte >> 8;
111
  }
112
}
113
/* some magic */
114
buf_len = 0;

So nun lese ich in meiner Loop die empfangenen Daten aus. Hier fällt es 
mir auf, dass das 9Bit (modebit) manchmal gesetzt und manchmal wiederum 
nicht gesetzt ist. Könnt ihr mir eventuell weiterhelfen? Ich hab echt 
keinen Plan mehr :-/

Danke im Voraus! LG aus Wien
Beitrag #5026858 wurde von einem Moderator gelöscht.
Du musst das 9 bit aus dem status Register zuerst lesen und dann das 
Data Register.  Das es nun funktioniert ist nur purer Zufall nicht 
wissen und können. Sobald du das Data Register ließt wird es vermutlich 
zurückgesetzt und das 9bit ist weg.
Das Problem ist wenn du in deiner Isr das status Register ließt ist der 
Inhalt wieder ein anderer.  Du musst es in einer variable sicher und mit 
dieser Bedingungen prüfen.

Wenn es sporadisch funktioniert hast du ein von der Laufzeit abhängiges 
Verhalten. Das zeigt das der Ablauf fehlerhaft ist.
OP
Gut kann ich machen. Jedoch würde ich gerne eine Begründung bzw eine 
Erklärung für dein Statement wissen ...

Mein Statement is:
Baud 9600, Übertragung von 11 Bits dauert ~1,1ms, Rx Interrupt wird nach 
Erkennung des Stop bits getriggert, mit einer CPU Freq von 24MHz habe 
ich genug Power und Zeit um die Routine abzuarbeiten bevor das nächste 
Byte reinkommt. So meine Erklärung für die Logik.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.