Forum: Mikrocontroller und Digitale Elektronik ATxmega32A4U - 9 Bit UART Problem


von Martin Z. (mzahedi)


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

von Max (Gast)


Lesenswert?

Wozu braucht man ein 9-Bit UART?

von Route_66 H. (route_66)


Lesenswert?

Max schrieb:
> Wozu braucht man ein 9-Bit UART?

z.B. in der Multiprozessorkommunikation, als Unterscheidung zwischen 
Adresse und Daten

von Martin Z. (mzahedi)


Lesenswert?

Interrupt Level ftw!

Dem RX ISR habe ich nun ein höheres Lvl gegeben > Futsch ist das Problem 
;-)

von Martin Z. (mzahedi)


Lesenswert?

Und überraschenderweise trägt das zur weiteren Stabilität bei
1
modebit = (recv_byte >> 8) & 0x01;

Beitrag #5026858 wurde von einem Moderator gelöscht.
von Martin Z. (mzahedi)


Lesenswert?

> Immer wieder überraschend: Kaum macht man's richtig - schon
> funktioniert's!

Na zum Glück bist no rechtzeitig hier um gscheite Sprüche zu klopfen ;)

: Bearbeitet durch User
von Bastian W. (jackfrost)


Lesenswert?

Hi,

ist modebit ein uint_8 oder uint_16 ?

Gruß JackFrost

von Martin Z. (mzahedi)


Lesenswert?

Hi.

Ist ein u8, hab ich oben eh gepostet :)

Und jedes u16 (recv-byte, Wert > 255) >> 8 ist wahr für die if 
Überprüfung => für den Kollegen oben .. so viel zu kaum macht mans 
richtig

LG

von Marco H. (damarco)


Lesenswert?

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.

: Bearbeitet durch User
von Martin Z. (mzahedi)


Lesenswert?

Und was steht hier?
1
if(usart_data->usart->STATUS & USART_RXB8_bm) {
2
    data = 0x0100 | usart_data->usart->DATA;
3
  } else {
4
    data = usart_data->usart->DATA;
5
  }

von Marco H. (damarco)


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.

von Martin Z. (mzahedi)


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.

von Marco H. (damarco)


Lesenswert?

Denkst du, der Zustand des Registers kann sich ändern auch wenn man es 
ausließt werden einige Bits zurückgesetzt.  Deswegen sichert man den 
Zustand und arbeitet mit diesem weiter.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.