mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega328P: 9-Bit UART


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Simon F. (saimenf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend,

Ich habe gerade ein kleines C-Projekt am laufen, mit dem ich 9-Bit Werte
auslesen und verarbeiten möchte.
Mit dem 9ten Bit möchte ich zwischen Adress-/ und Datenbits
unterscheiden.

Das auslesen Funktioniert ohne Probleme, bloß die Verarbeitung des 2
Byte Wertes bereitet mir bis jetzt Kopfzerbrechen.


Hier mein Code:
#define F_CPU 16000000UL                    

#include <avr/io.h>                        
#include <util/delay.h>                      

#define USART_BAUDRATE 9600UL                  
#define BAUD_Prescale ((F_CPU / (USART_BAUDRATE*16UL)) -1)    


void Extended_USART_init ()              
{
  UBRR0H = (unsigned char)(BAUD_Prescale>>8);          
  UBRR0L = (unsigned char)(BAUD_Prescale);          
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);                
  UCSR0C = (1<<USBS0)|(1<<UCSZ02)|(1<<UCSZ01)|(1<<UCSZ00);  
}

void Extended_USART_Transmit (unsigned int xdata)   
{
  while (!(UCSR0A & (1<<UDRE0)));            
  UCSR0B &= ~(1<<TXB80);              
  if (xdata & 0x0100)                
  {
    UCSR0B |= (1<<TXB80);
  }
  UDR0 = xdata;                  
}

unsigned int Extended_USART_Receive (void)      
{
  unsigned char status, resh, resl;        
  
  while (!(UCSR0A & (1<<RXC0)));          
  
  status = UCSR0A;                              
  resh = UCSR0B;                  
  resl = UDR0;                  
  
  if (status & ((1<<FE0) | (1<<DOR0) | (1<<UPE0)))
  {
    return 1;                  
  }
  
  resh = (resh >> 1) & 0x01;            
  return ((resh << 8) | resl);          
}

void Extended_EIN_AUS ()
{
  unsigned int xWert;        
  xWert = Extended_USART_Receive();
  
  if (xWert == 300)
  {
    PORTB = 0xff;
  }
}


int main(void)                    
{  
  Extended_USART_init();                
  DDRB = 0xff;                  
  
    while (1)                    
    {
    Extended_EIN_AUS();
    }
}
Den eingelesenen 2-Byte Wert möchte ich zu Testzwecken mit einer Zahl
(300) vergleichen. Sobald beide Werte gleich sind, sollen alle
PORTB-Pins auf High geschaltet werden.

Dadurch, dass in "Extended_USART_Receive" die Bits im return schon
verknüpft werden, müsste doch ein 2-Byte Wert an "xWert" zurückgegeben
werden.
Oder liege ich falsch?

Hat vielleicht jemand von euch einen Lösungsansatz?

Gruß

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon F. schrieb:
> resh = (resh >> 1) & 0x01;
>   return ((resh << 8) | resl);

Caste das mal nach int

Autor: Simon F. (saimenf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wäre dies eine Möglichkeit zu Casten?
resh = (resh >> 1) & 0x01;             
return Test = (int)(((resh << 8) | resl));
Habe jetzt verschiedene Arten von Typenumwandlungen versucht, keine hat 
so richtig Funktioniert.

Autor: Dirk B. (dirkb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vom Prinzip würde bit0 in einem
>  unsigned char status, resh, resl;
nach  <<8 im status landen und wird deswegen nicht so gerne 
implementiert.
Eigentlich ist da eher die Frage wie der Code in das Datenblatt kommen 
konnte spannend (durch einen Compilerfehler UND return -1 statt return 1 
könnte es zufällig klappen)

evtl. eine Kurzversion:
  
unsigned int Extended_USART_Receive (void)      
{ while (!(UCSR0A & (1<<RXC0)));          
  if UCSR0A & ((1<<FE0) | (1<<DOR0) | (1<<UPE0)))
     return -1; 
  if UCSR0B & (1<<RXB8)
     return (0x100 + UDR0)
  return (UDR0)
}

Autor: Simon F. (saimenf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk B. schrieb:
> unsigned int Extended_USART_Receive (void)
> { while (!(UCSR0A & (1<<RXC0)));
>   if UCSR0A & ((1<<FE0) | (1<<DOR0) | (1<<UPE0)))
>      return -1;
>   if UCSR0B & (1<<RXB8)
>      return (0x100 + UDR0)
>   return (UDR0)
> }

Klingt einleuchtend! Ist sicherlich einfacher als das Beispiel im 
Datenblatt beschrieben.
Habe ich jetzt gerade noch in meinem Projekt korrigiert....

Habe nochmals die Initialisierung des 9-Bit UART auf Richtigkeit 
überprüft, und noch wirklich einen Fehler gefunden.
Ich habe:
(1<<UCSZ02)
nicht im richtigen Register initialisiert. Sollte in "UCSR0B" und nicht 
in "UCSR0C" initialisiert werden.

Zum Test schicke ich die eingelesenen Daten gleich wieder über meinen 
FTDI auf meinen PC und lese die Daten mit HTERM ein.
Komischerweise empfange ich jetzt plötzlich 3 Byte. Jetzt bin ich 
vollkommen verwirrt :'‑)

Autor: H.Joachim S. (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann denn der FTDI überhaupt 9bit? Ich glaube nicht, zumindest nicht der 
meist verwendete FT232RL.

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
H.Joachim S. schrieb:
> Kann denn der FTDI überhaupt 9bit?
Windows behauptet zu 9bit:"The number of data bits must be 5 to 8 bits"
- hTerm: 5..8bit
dazu das C-Beispiel das eigentlich nicht funktionieren 'darf' und der µC 
bei dem 9-bit nicht eingestellt wurde ...
... nur:
>Das auslesen Funktioniert ohne Probleme,[..]
dürfte dann das Hauptproblem sein.

Für µC<->µC könnte 9bit praktisch sein, aber sonst wohl schwierig.

Autor: Simon F. (saimenf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Antworten!

Langsam aber doch bin ich mir nicht mehr so sicher, ob die 9-Bit 
Variante das richtige für das Projekt ist, da dies auch mit der 8-bit 
Variante funktionieren sollte.
Habe mich nur mal aus Interesse an das 9-Bit UART gestürzt ;)

Dirk schrieb:
> dazu das C-Beispiel das eigentlich nicht funktionieren 'darf' und der µC
> bei dem 9-bit nicht eingestellt wurde ...

Es würde mich trotzdem noch Interessieren, was an der Initialisierung in 
meinem Programm falsch gelaufen ist. Habe mich da schon ein Paar mal 
durch das Datenblatt gelesen und nichts markantes mehr gefunden.


Gruß

Autor: Jim M. (turboj)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon F. schrieb:
> return Test = (int)(((resh << 8) | resl));
> Habe jetzt verschiedene Arten von Typenumwandlungen versucht, keine hat
> so richtig Funktioniert.

Typ int reicht nicht. Man darf nicht ins Vorzeichen shiften.

return (((uinsigned int) resh) << 8)|res1;

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk schrieb:

> Windows behauptet zu 9bit:"The number of data bits must be 5 to 8 bits"

> Für µC<->µC könnte 9bit praktisch sein, aber sonst wohl schwierig.

Nicht wirklich, jedenfalls nicht für Windows. Das unterstützt zwar nur 8 
Datenbits, aber zusätzlich ein Paritätsbit und zwar in den Ausprägungen 
even, odd, mark und space. Also ist es trivial, das Wordformat auf 8M1 
oder 8S1 festzulegen und die Information des 9. Datenbits eben als 
Parity-Error zu empfangen. Kinderkram, das habe ich schon vor >30 Jahren 
erstmals machen müssen...

Allerdings: für hohe Datenraten ist das Konzept eher nicht geeignet. Da 
fehlt dann doch zunehmend die Hardwarunterstützung...

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon F. schrieb:
> Habe mich nur mal aus Interesse an das 9-Bit UART gestürzt ;)
vom Prinzip ist 9-bit für 8-bit Daten + 1-bit meta/out-of-band/(andere 
Bezeichnung je nach Betrachtung oder Verwendung) Datum ja auch eine u.U. 
praktische Idee. Im letzten Jahrtausend wurden allerdings Kinder mit der 
Idee malträtiert, da für die damaligen BWL-ler Kinderarbeit praktisch 
kostenlos kalkuliert wurde und µC in der Leistungsklasse eines C0,64 als 
Transciver/Proxy etc. ein (umgerechnet) Pullover gekostet hätten.
Den jungen Menschen denen damals erzählt wurde Bit/Byte-Banging sei 
trivial, da Bits nur in den Ausprägungen Mark/Space 0/1 low/high ../.. 
vorkommen und die erst bei hohen Modemgeschwindigkeiten die 
Schwierigkeiten von 9/10/.. oder auch 4-bit Übertragungen bemerkt haben 
(bzw. teilweise wohl nicht) ging es da nicht so gut.
Rein praktisch ist 9-bit auch eher für synchrone Übertragung geeignet, 
da leichte Gangunterschiede sich bei der Asynchronen summieren. Also 
9-bit als 2*6-bit (inkl. Meta information)mit doppelter Baudrate dürfte 
schneller und zuverlässiger als 1*9 bit sein.
So ein Kinderkram kann ja auch durchaus Spass machen und ich fände es 
auch spannend was da genau schief gelaufen ist. Ich hab zumindest 
herausgefunden, dass ich wohl nächstes WE 8-bit mit 6-bit getestet hätte 
(einige Atmel µC benötigen das UMSEL-bit für USCRC) und manchmal 
passieren die unbeschreiblichsten Fehler gerade wenn ein Teil ohne 
Probleme läuft und bspw. zur Fehlersuche noch kurz die Kontroll-Led 
initialisiert wird und der µC daraufhin komplett abstürzt. Kurzer Blick 
ins Handbuch: VCC gehört doch direkt mit einer Spannungsquelle verbunden 
und die Notstromversorgung über einen versehentlich als Eingang 
geschalteten Pin ist gar nicht dokumentiert (und funktioniert wohl auch 
nur mit falsch angeschlossener LED). Kurz: es gibt bei dem 
Versuchsaufbau zu viele Möglichkeiten von einfachst bis kompliziert 
Fehlerchen, als dass es im Forum wirklich konsequent gecheckt werden 
könnte und wenn du so einen µC ohne Spannungsversorgung, leicht 
unterschiedliches Modell, falscher Takt,.... hast, dann passieren 
schnell die zwei Meinungen:
a) der µC hat eine Stromversorgung, da er eigentlich funktioniert und
b) der µC hat keine Stromversorgung, da der Pin nicht angeschlossen ist 
und
c) die Frage: "benötigt der µC eine Stromversorgung an VCC ?" im Forum 
passt auch nicht.
Solche Fehler sind dann schwer zu finden.
(ganz genau bekomme ich den Fehler nicht rekonstruiert, aber +5V an VCC 
hat in dem Fall geholfen)

Hier wäre spannend ob der falsche Atmel-Code mit einem nicht ganz 
korrekt arbeitenden Compiler evtl. das gewünschte Ergebnis bringen 
könnte, ansonsten ob und wie die anderen Bits ankommen.

c-hater schrieb:
> even, odd, mark und space. Also ist es trivial, das Wordformat auf 8M1
> oder 8S1 festzulegen und die Information des 9. Datenbits eben als
> Parity-Error zu empfangen. Kinderkram, das habe ich schon vor >30 Jahren
> erstmals machen müssen...
häufig sollen bei bei einer Datenübertragung mehrere Daten übertragen 
werden und dann erschließt sich sich die Schwierigkeit von solchem 
Byte-Banging, auch wenn diu als junger Mensch dazu gezwungen wurdest ...

NB.: triviales Bit empfangen von IR-FB mit einem PC kann auch 
interessante Fehler verursachen: mir ist damals der PC bei Sonnenschein 
abgestürzt, da da der IR-Detektor wohl bei Überdosis angefangen hast zu 
schwingen und so eine hohe Datenrate geliefert hat. Dadurch dass 
damalige Mäuse tw. ähnliche Effekte hatten ging die Fehlersuche noch 
einigermaßen schnell und Strahlenschutzmaßnahmen haben geholfen, aber 
ein PC der beim ersten Sonnenstrahl der ihn trifft abgestürzt hat schon 
einen gewissen Charme ;-)

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.