UART, 7 Bit mit Odd Parity

TommyB

Team Bitschubse
17. Mai 2010
2.151
80
48
40
127.0.0.1 ;)
Sprachen
  1. C#
  2. VB.Net
  3. LunaAVR
  4. Assembler
  5. Python
Blöde Frage.

Hat irgendwer einmal was mit UART Parity gemacht, nebst der "krummen" Übertragung mit 7 Bits?
Ich bräuchte (nur zum testen) ein Programm (hex File reicht, daher ist Sprache egal) für nen ATmega168. Es soll einfach nur dummy Daten (am besten nicht nur 0 Bytes, Inhalt ist aber egal) im Format 2400 Baud, 7 Datenbits, Odd Parity, 1 Stopbit senden. Im Idealfall 11 Bytes auf einmal mit ~500mS Pause vor dem nächstem Block, aber darauf kommts überhaupt nicht an. Nur dass das 2400,7,O,1 eingehalten wird. Takt ist der interne, also wahlweise 1 oder 8 MHz. Nur senden.

Vielleicht hat da jemand ja schon was fertiges was mit 1-2 kleinen Änderungen anpassbar ist, oder eine andere Programmiersprache lässt das mit wenigen Handgriffen zu.
 
Wie eilig ist das ganze? Hab jetzt noch etwas zu tun, danach such ich Dir die Werte für die Register gern zusammen..

Der HW-UART kann 7Bit mit beliebiger Parität in Hardware, Deine Anforderungen wären also eigentlich nur'n Timer der alle 500ms triggert (16bit bei 8MHz mit Vorteiler 256 im CTC erfordert 15624 im Vergleichsregister OCR0A etc),

In der ISR kopierst Du irgendwas ins UART Data Register (UDR0)

Ich kann die nötigen I/O-Register nachher mal durgehen, wie gesagt, aber auf dem Telefon tu ich mir das jetzt nicht an...

Edit: UBRR sollte 207 erhalten, bei U2X=0
Fehler bei 0.16
 
Na kommt jetzt auf n Tag mehr oder weniger nicht an, also nicht eilig.

Es ist ja nicht so alsob ich nicht schon selber mal geschaut hatte. Hab sogar schon mal n Testprogramm gemacht. Was ich empfangen habe war manchmal erfolgreich (sogar bei Werten > 127! was ja bei 7 Bit garnicht sein darf). Aber sie waren übersäht mit Parity Fehlern. Soweit ich gelesen habe muss die Parity auch selber berechnet werden (kA ob das auf alle Controller zutrifft) und ein paar sagen man muss 9 Bit Mode nutzen (also eigentlich 9 Datenbits, AVR scheint das aber anders zu sehen) wenn man 8 Bit + Parity verwenden will. Also müsste ich in meinem Fall 8 Bit setzen... Irgendwie ist das alles extrem konfus... Und ich debugge extremst ungerne an beiden Seiten gleichzeitig :-/
 
Im UCSR0C stellst Du die Zahl der Datanbits ein (eines der Bits liegt in UCSR0B), und den Polarity-Mode. Ichfinde nnirgends was, warum es nicht gehen sollte...
 
So, einfach mal munter drauflosgetippt:
Code:
;include "m168def.inc"	;ATmega168
.org 0x0000
jmp start
.org OC1Aaddr
jmp sendeWas			;500ms-Takt
start:
;**********UART*********************************************
sbi DDRD, DDD1
;U2X=0 in UCSR0A ist default
;UCSR0C - asynchron, odd parity, 1 Stopbit, 7 Databits
ldi r16, (1<<UPM01)|(1<<UPM00)|(1<<UCSZ01)
sts UCSR0C, r16
;Baudrate 2400 bei 8MHz, U2X=0
ldi r16, 207
sts UBRR0L, r16
;UCSR0B - Transmitter aktivieren
ldi r16, (1<<TXEN0)
sts UCSR0B, r16
;**********Timer1 soll alle 500ms triggern*******************
;TCCR1A - COM=0, WGM-Bits default
;OCR1A=15624 - CTC triggert alle 500ms
ldi r16, high(15624)
sts OCR1AH, r16
ldi r16, low(15624)
sts OCR1AL, r16
;TIMSK1 - OCR1A-IRQ scharfmachen
ldi r16, (1<<OCIE1A)
sts TIMSK1, r16
;TCCR1B - CTC bis OCR1A, Prescaler=256
ldi r16, (1<<WGM12)|(1<<CS12)
sts TCCR1B, r16
sei
ldi r17, 0
ldi r18, 10
loop:			;********main-loop***************************
rjmp loop
;*************************ISR********************************
sendeWas:
sts UDR0, r17 ;R17 senden und inkrementieren
inc r17
auf_UDRE0_warten:
lds r19, UCSR0A
sbrs r19, UDRE0
rjmp auf_UDRE0_warten ; auf UDRE0 in UCSR0A warten
dec r18
brcc sendeWas	;11mal widerholen
ldi r18, 10
reti

sollte nach dem start alle halbe Sekunde so'n Elferpaket rausschicken. Der Wert inkrementiert immer um 1. Wenn ein Wert mit gesetztem 8ten Bit gesendet werden soll, wird dieses 8te Bit ignoriert (Datenblatt S.179 20.6.1), verhält sich also so wie'n Überlauf.
In der ISR 11mal auf UDRE zu warten ist zwar nicht schön, sollte es hier aber machen (2400baud entsprechen 2400 Bits/s oder 1200 Bits pro Halbsekunde, Du hast 1 Start, 7 Data, 1 Parity, 1 Stop also 10Bit pro Zeichen oder 110 Bits pro Paket - da ist noch Luft).

Womit versuchst Du das zu empfangen? Wie wandelst Du ggf für PC oder so? Kannste mit'nem LA mal sehen, was der Controller wirklich sendet? Der logic8 bietet entsprechende Analyzer bzw läßt sich darauf einstellen, ich könnte also wenn nötig 'n Mega88PA auf'nem Steckbrett testen...
 
Ich habe leider kein Logic Analyzer. Vielleicht kann ich ja bei den Verhandlungen noch ein Mixed Signal Oszilloskop raus schlagen, wer weiß...

Heut Abend hab ich mein BreadBoard wieder, denn teste ich deinen Code mal :)
Aber wie ich dich kenne hab ich vollstes Vertrauen :)

PC Anbindung erfolgt via fertigen FTDI Chip (ich hab den Pegelwandler entfernt, daher TTL, funktion mit dem RasPI getestet) und Software in VB.Net (nutzt die interne SerialPort Klasse, ich gehe mal stark davon aus dass die fehlerfrei funktioniert).
 
Und sowohl VB/Raspi als auch der RS232(TTL)-USB-Wandler können Deine 7-Bit?
Edit: mein Code haut nach dem PowerUp+Init ununterbrochen Deine Pakete raus - Inwiefern das vom PC verstanden wird, anschalten der UART usw, weiß ich jetzt nicht... vielleicht sollte man in der Hauptschleife irgend'n Beinchen Pollen, und den Timer starten/stoppen. Achtung: ich verwende in der ISR R17, R18 und R19 als reservierte Register, außerdem wird das SREG manipuliert - bisher habe ich nix gesichert...

man könnte allerdings einfach (1<<WGM12) nach r16 laden, mit SBIS/SBIC das Bein direkt pollen und damit ggf die Zeile überspringen, wi (1<<CS12) dazugeodert wird, anschließend R16 nach TCCR1B schreiben.
Während der Init das Beinchen ggf hochziehen (pullup)...

Viel Erfolg;)
 
Das sollten sie können. Mit 7 Bit habe ich noch nie was gemacht. Ich kann es nicht über's Herz bringen so ein armes Byte zu beschneiden ^^
Scherz bei Seite, privat hab ich immer mit 8N1 gearbeitet
 
Es sind diese WTF Momente.....

Gesteckt und geflasht, USB COM Adapter dran, Controller an diesen dran. Saft drauf. Auf einmal wird ein Treiber installiert. "Serielle Microsoft Maus". Mauszeiger springt wild umher und klickt hier und da.

LotadaC, du hast ne Maus programmiert!

Und ich dachte schon nach der Spigelschrift kann mir nix mehr passieren...


Jetzt steh ich grad offiziell aufm Schlauch...
 
...teste ich deinen Code mal :)
Aber wie ich dich kenne hab ich vollstes Vertrauen :)...
Bei mir hat er nur fehlerfrei compiliert - ob er macht, was er soll, hab ich noch nicht getestet...

Bei Problemen könntest Du auch erstmal bei der Zuweisung des UCSR0C die Parität weglassen (beide UPM0-Bits auf 0), und/oder erstmal mit 8 Datenbits versuchen (UCSZ00 auch high setzen)
Wenns nicht geht, meld Dich... dann versuche ich das hier mit dem Mega88 und Logic8 nachzuvollziehen

Edit: ok, ich bau meinen Kram auf...

P.S.: (*auf dem Boden lieg*)
 
Ich muss selber immernoch lachen ^^

Gut möglich dass dein Code fehlerfrei arbeitet. Vielleicht etwas zu fehlerfrei :D

Aber mit diesen Nebenwirkungen hätte ich nicht gerechnet :D
Vielleicht sind deswegen die oberen 3 Bits immer 011 ? Um eben die Plug-and-pray Sache zu umgehen. Wäre einen Test wert.


p.s.: schrotte dir nicht dein System mit "deiner Maus" :D
 
ich schau mir das erstmal nur mit'm LA an....

Du mußt erst den Wandler am rechner haben, und die COM geöffnet (Terminalprogramm etc) danach erst PowerUp des AVR

'ne serielle Maus sendet ja auch nur irgendwelche Bits, die der Rechner interpretiert

Geht Dein Wandler ohne AVR dran wieder normal?
 
Du mußt erst den Wandler am rechner haben, und die COM geöffnet (Terminalprogramm etc) danach erst PowerUp des AVR

Sehr gute Idee!
Jetzt konnte ich mich mit nem Dump-Tool drauf verbinden und es kamen keine Übertragungs- also Parity-Fehler rein. Funktioniert alles bestens (bis auf das 500ms Delay, aber vielleicht sieht das auch nur so aus, weil mein USB COM Ding immer nur 4 Bytes auf einmal sendet / empfängt. FTDI hat da wohl kräftig am Puffer gespart, kA).

Also augenscheinlich funktioniert es bestens (wenn auch mit Nebenwirkungen ^^)
Vielen lieben Dank :)
 
Nein, der Fehler lag nicht im Timer, sondern im Zählen der 11 Bits - dec beeinflußt das Carry nicht (boah, was'n peinlicher Fehler), also entweder subi mit 1, oder dec und aufs Zero reagieren:
Code:
.org 0x0000
rjmp start
.org OC1Aaddr
rjmp sendeWas			;500ms-Takt
start:
;**********UART*********************************************
sbi DDRD, DDD1
;U2X=0 in UCSR0A ist default
;UCSR0C - asynchron, odd parity, 1 Stopbit, 7 Databits
ldi r16, (1<<UPM01)|(1<<UPM00)|(1<<UCSZ01)
sts UCSR0C, r16
;Baudrate 2400 bei 8MHz, U2X=0
ldi r16, 207
sts UBRR0L, r16
;UCSR0B - Transmitter aktivieren
ldi r16, (1<<TXEN0)
sts UCSR0B, r16
;**********Timer1 soll alle 500ms triggern*******************
;TCCR1A - COM=0, WGM-Bits default
;OCR1A=15624 - CTC triggert alle 500ms
ldi r16, high(15624)
sts OCR1AH, r16
ldi r16, low(15624)
sts OCR1AL, r16
;TIMSK1 - OCR1A-IRQ scharfmachen
ldi r16, (1<<OCIE1A)
sts TIMSK1, r16
;TCCR1B - CTC bis OCR1A, Prescaler=256
ldi r16, (1<<WGM12)|(1<<CS12)
sts TCCR1B, r16
sei
ldi r17, 0
ldi r18, 11
loop:			;********main-loop***************************
rjmp loop
;*************************ISR********************************
sendeWas:
sts UDR0, r17 ;R17 senden und inkrementieren
inc r17
auf_UDRE0_warten:
lds r19, UCSR0A
sbrs r19, UDRE0
rjmp auf_UDRE0_warten ; auf UDRE0 in UCSR0A warten
dec r18
brne sendeWas	;10mal widerholen
ldi r18, 11
reti

Achtung, da sind jetzt rjmps wegen meinem Mega88 drin (in der IVT 2x) - jetzt paßts

Nachtrag: Ok, ich bau dann mal wieder ab
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)