ATxmega32A4U - 9 Bit UART Problem

OP #5025900
Lesenswert?

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.
#5027111
Lesenswert?

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 #5027121
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren