mikrocontroller.net

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


Autor: Martin Z. (mzahedi)
Datum:

Bewertung
0 lesenswert
nicht 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-bi....

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

/*
 * USART_CHSIZE_9BIT_gc = (0x07<<0)
 * USART_BAUDCTRL_BSEL_9600 = 621
 * USART_BAUDCTRL_BSCALE_9600 = -2
 */

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

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

  USART_Rx_Enable(USART_SLV.usart);
  USART_Tx_Enable(USART_SLV.usart);
}


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

// meine ISR 
ISR(USART_SLV_RXC_vect) {
  USART_NineBits_RXComplete(&USART_SLV);
}

// angepasste Funktion aus der AVR API
// optional: Suchbegriff "RXB8" (Manual)
bool USART_NineBits_RXComplete(USART_NineBits_data_t * usart_data)
{
  USART_NineBits_Buffer_t * bufPtr;
  bool ans;

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

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

  if(usart_data->usart->STATUS & USART_RXB8_bm) {
    data = 0x0100 | usart_data->usart->DATA;
  } else {
    data = usart_data->usart->DATA;
  }

  if (tempRX_Head == tempRX_Tail) {
      ans = false;
  }else{
    ans = true;
    usart_data->buffer.RX[usart_data->buffer.RX_Head] = data;
    usart_data->buffer.RX_Head = tempRX_Head;
  }
  return ans;
}

// so lese ich aus
bool mdb_receive_9bit(USART_NineBits_data_t *ptr, uint16_t *recv_byte) {
  if (USART_NineBits_RXBufferData_Available(ptr)) {
    *recv_byte = USART_NineBits_RXBuffer_GetByte(ptr);
    return true;
  }
  return false;
}

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

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

// hier die obige Funktion
uint16_t USART_NineBits_RXBuffer_GetByte(USART_NineBits_data_t * usart_data)
{
  USART_NineBits_Buffer_t * bufPtr;
  uint16_t ans;

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

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

  return ans;
}


// hier der Aufrufer in einer Loop
uint16_t recv_byte = 0;
uint8_t payload = 0;
uint8_t modebit = 0;
while (mdb_receive_9bit(&USART_SLV, &recv_byte)) {
  /* hier passiert der sch*ß */
  // ich überprüfe nur beim ersten empfangenen Bit ob gesetzt
  if (buf_len == 0) {
    modebit = recv_byte >> 8;
  }
}
/* some magic */
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

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wozu braucht man ein 9-Bit UART?

Autor: Route 6. (route_66)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Max schrieb:
> Wozu braucht man ein 9-Bit UART?

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

Autor: Martin Z. (mzahedi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interrupt Level ftw!

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

Autor: Martin Z. (mzahedi)
Datum:

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

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

Bewertung
0 lesenswert
nicht 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
Autor: Bastian W. (jackfrost)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ist modebit ein uint_8 oder uint_16 ?

Gruß JackFrost

Autor: Martin Z. (mzahedi)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Marco H. (damarco)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Martin Z. (mzahedi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und was steht hier?
if(usart_data->usart->STATUS & USART_RXB8_bm) {
    data = 0x0100 | usart_data->usart->DATA;
  } else {
    data = usart_data->usart->DATA;
  }

Autor: Marco H. (damarco)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Martin Z. (mzahedi)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Marco H. (damarco)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.