Forum: Projekte & Code Software UART


von peter dannegger (Gast)


Angehängte Dateien:

Lesenswert?

Da ja verschiedentlich nach ner Software-UART gefragt wurde, hier mal
meine Lösung.


Das Problem bei ner Soft-UART ist das Timing. Es darf nur ein geringer
Jitter entstehen und keinesfalls eine Jitterakkumulation, damit auch
noch das letzte Bit einwandfrei gesendet bzw. empfangen wird.

Daher bietet sich dazu der T1 an.

Das Senden ist einfach, man nimmt einen Compare-Output und hat damit
keinen Jitter.

Das Empfangen ist etwas komplexer. Um die Startflanke möglichst genau
festzustellen ist der Input-Capture Eingang zu verwenden. Danach kann
man dann mit dem 2 Compareinterrupt die einzelnen Bits abfragen.

Im Beispiel wird bei 16MHz eine Baudrate von 57,6kBaud eingestellt.


Werden noch andere Interrupts verwendet, ist darauf zu achten, daß der
Empfangsinterrupt (CompareB) nicht länger als 1/2 Bitzeit und der
Sendeinterrupt (CompareA) nicht länger als 1 Bitzeit verzögert werden.

Die höhere Baudrate sollte deshalb immer mit der Hardware-UART
erfolgen.


Die Soft-UART ist Voll-Duplex.

Der T1 ist durchlaufend (Mode 0), kann also per Overflow-Interrupt noch
anderweitig verwendet werden (z.B. als RTC, Debouncer usw.).

Bei anderen AVRs ist die andere Zuordnung der ICP- und OC1A-Pins zu
beachten. Es kann natürlich auch der OC1B Pin verwendet werden.


Peter

von Manne (Gast)


Lesenswert?

Hallo Peter,

ist ja ganz nett die Dateien in dieses Forum zu stellen,
aber die Dateien #include <interrupt.h> #include <signal.h>
fehlen, und somit ist das alles nicht zu gebrauchen.

Gruß Manne

von Stefan K. (_sk_)


Lesenswert?

Oh Mann Manne,

schonmal eine weit verbreitete C-Compiler-Distribution angeschaut, der
hier ein eigenes Forum gewidmet ist?

Kopfschüttel,

Stefan

von TheMason (Gast)


Lesenswert?

@manne

die dateien sind (soweit ich weiß) vom gcc, und wenn man diesen
installiert hat sind diese dateien automatisch dabei. hängt also nur am
compiler.
für andere compiler/prozessoren muß man eh den prototypen für die
interrupt routine anpacken.
also entweder gcc nutzen oder entsprechend dem verwendeten compiler
anpassen.

gruß
rene

von Manne (Gast)


Lesenswert?

Ja, es gibt auch noch andere Compiler als gcc.
zb. IAR
Das scheint, mir hier eher ein Verein für Hochnässige
zu sein, als ein Forum.

Rene: Danke für die Info

von Stefan K. (_sk_)


Lesenswert?

Sorry, ich konnte mich einfach nicht uirückhalten ;-)

Gruß, Stefan

von Stefan K. (_sk_)


Lesenswert?

oh Mann ... einmal kurz drüberschauen wäre auch nicht schlecht:

Sorry, ich konnte mich einfach nicht zurückhalten ;-)

Gruß, Stefan

von Manne (Gast)


Lesenswert?

Tja, der eine kennt sich nur mit IAR aus
der andere hat Probleme mit dem schreiben ;-))
( lol )

von Peter D. (peda)


Lesenswert?

@Manne

Oh Gott, da geilt sich tatsächlich einer an der Interrupt-Syntax auf.

Interrupt-Handler gehören nunmal nicht zum C-Standard.
Jeder C-Programmierer weiß doch, daß jeder Compilerbauer da sein
eigenes Süppchen kocht.


Und wenn Du C könntest, dann wüßtest Du also, wie Du Interrupthandler
in die Form Deines Compilers umschreiben kannst (die Zeile vor der
'{').

Du hast wohl sehr viel Langeweile und wenig C-Kenntnis um sich über
sone Lappalien aufregen zu müssen.

Wie wärs denn mal mit konstruktiven Beiträgen ?


Peter

von Michi (Gast)


Lesenswert?

Tja Manne, frage mich wer hier hochnäsig ist.
"Ja es gibt noch andere Compiler z.B. IAR".
So wie man in den Wald hineinschreit kommt es zurück.

von Rahul (Gast)


Lesenswert?

Dann muss man sich halt mit den Fehlermeldungen des Compilers
auseinandersetzen, und sie beheben. Man könnte natürlich auch Peter
einen Obolus bezahlen, dass er das Programm auch an den IAR anpasst.
Dann werden aber die Codevision-Leute kommen und rumjammern...
Von den BASCOM-Leuten ganz zu schweigen - die jammern über alles
gerne...(BASCOM hat eine eigene SoftUART implementiert; das nur so am
Rande)

von pittbull_nt@yahoo.com (Gast)


Lesenswert?

mich würde mal ein software-uart interessieren, der ohne interruptfähige
eingänge auskommt d.h. wo alles eingesampled wird. das wär' mal
spannend...

von peter dannegger (Gast)


Lesenswert?

@pittbull_nt

Von Philips gibts dazu die application note AN446:

http://www.standardics.philips.com/support/documents/microcontrollers/pdf/an446.pdf


Sowas ist allerdings extrem Ressourcen hungrig, daher eignet es sich
nur für kleine Baudraten und sollte in Assembler geschrieben sein.


Peter

von komment (Gast)


Lesenswert?

software serielle schnittstelle uart mega 8 c

von tubbu (Gast)


Lesenswert?

Hi,

vielen Dank, genau das, was ich brauche und des öfteren brauchen werde 
:-)
An dieser Stelle auch vielen Dank für die anderen praktischen 
Codebeispiele!

von Marco S. (masterof)


Lesenswert?

Eine Frage wie viele Software-UART kann man da mit diesem Beispiel im 
Mega8 realisieren?

von Thomas Zemanek (Gast)


Lesenswert?

Hallo Götter des Mikrocontrollers,


ich habe mich sehr gefreut, dass ich eine SWUART lib wie vom Peter 
Dannegger gefunden habe...aber leider funktioniert sie bei mir nicht so 
recht.
Der pin(OC1A) geht einfach nur auf high und verbleibt so...leider keine 
Frequenz zu finden....
Hänge mit dem Oszi dran.
Merkwürdig ist, dass mir das bei allen libs die ich getestet habe 
passiert ist!

Das ist sicher ein triviales Problem.

Ich wäre echt froh wenn mir jemand helfen könnte.

Vielen Dank!!!

von TheMason (Gast)


Lesenswert?

@thomas

selbst auf die gefahr hin das ich verhauen werde ...

hast du die interrupts (vor allem den globalen) aktiviert ?! oder 
anpassungen für deinen ziel-controller vergessen ?!

hab mich selbst auch mal an einem sw uart versucht, und bis auf ein 
timing-problem funktionierte es wunderbar (senden war vollkommen 
unproblematisch, empfangen schon eher)

von Matthias L. (matze88)


Lesenswert?

Hallo!

Erstmal danke an Peter für diese Lib! Ich werde die in meinem jetzigen 
Projekt (GPS Logger mit Bluetooth zum PC) an nem Mega88 benutzen. Eine 
Frage kommt mir hierzu auf: Die empfangenen Bits werden auf der Hälfte 
der Bitzeit gesampled. Nun besteht das Problem, dass jegliche 
Verschiebung des OC1B Interrups auch den Samplezeitpunkt weiter zum 
Bitende verschiebt. Bei 3,6864 MHz und 38400 bps habe ich "nur" 96 Takte 
pro Bitzeit, die halbe Bitzeit Verschiebung die maximal erlaubt ist 
wären nun 48 Tate. Wenn nun ein anderer Interrupt 30 davon nimmt, 
bleiben 18. Interrupt aufruf bis zum Sample sind auch schon nochmal 16 
(4 für den Interrupt aufruf, der 13. Zyklus in der Funktion ist der in 
Befehl in meinem Listing). Bedeutet: Das würde arg knapp werden. 
Verschiebe ich nun den FRÜHESTEN Sample Zeitpunkt nur auf 0,1 Bitzeit, 
so sollte das doch wesentlich besser funktionieren? Durch den Input 
Capture Noisefilter habe ich ne verschiebung um 4 Takte, der Interrupt 
nun jedes mal 16. Macht zusammen 20, was bei mir nun schonmal 0,2 
Bitzeit ist.

Denkfehler meinerseits?

Bei kurzen Leitungen (5cm vom Bluetooth Modul zum µC, den HW Uart 
bekommt das GPS wegen geringerem Stromverbrauch im Hauptbetrieb, das 
Bluetooth Modul krieg ich eh nicht > 38400 bps konfiguriert von daher 
ist das egal) sollte doch der Bitzustand ziemlich kurz nach den Flanken 
bereits stabil sein.

Bin gespannt, wieviel von meinem Post jetzt auf Denkfehler 
zurückzuführen ist :-)

cu
Matze

von Peter D. (peda)


Lesenswert?

@Matthias Larisch,

ja, bei hohen Baudraten sollte man noch einen Korrekturwert abziehen.

Ich würde aber eher ein 18,432MHz Quarz nehmen, dann entschärft sich das 
erheblich.


Peter

von Matthias L. (matze88)


Lesenswert?

Gut, ich werde einfach mal mit nem Korrekturwert testen. Habe gerade mal 
schlampig alle benötigten ISRs zusammengeschrieben, die längste kommt 
auf insgesamt 62 Takte. Etwas optimieren kann ich da allerdings sicher 
noch, oder aber ich müsste für 100%ige Funktion den Sampleoffset auf 
1,05 oder sogar 1,0 stellen (wie vorgerechnet kommt ja alleine durch die 
ICP ISR "0,2 * Bitzeit" dazu, deshalb dürfte das keine Probleme 
darstellen).

Ein anderer Quarz geht wegen des höheren Stromverbrauchs nicht. Bei 16 
MHz @ 3,3V bin ich bei 5mA. Okay, sooo tragisch wäre das wohl auch 
nicht, aber ich versuche halt, so batteriefreundlich wie möglich zu 
arbeiten. Solange meine Taktfrequenz reicht, ist das in meinen Augen 
auch völlig in Ordnung. Der µC muss eigentlich auch nur aktiv sein, wenn 
er gerade GPS Daten empfängt (Allerdings kann ich meine SystemClock in 
der Zwischenzeit nicht abschalten - wenn ich den über nen externen Int. 
mit dem Startbit vom Uart aufwachen lassen, verpasse ich einige Bytes 
bis mein Takt läuft, deshalb arbeite ich gleich mit einem möglichst 
niedrigen Takt der wenig Strom verbraucht.)

cu
Matze

von Gerhard. (Gast)


Lesenswert?

Es gibt natürlich oft wichtige Gründe ein Software UART zu verwenden und 
bin hier mit meinen Beitrag etwas eben dem ursprünglichen Thema dieses 
Threads. (Bitte nicht gleich Kopf abbeissen; -)   )

Manchal ist ein zweites (zusätzliches) HW-UART sehr nützlich. Sehr gute 
Erfahrungen machte ich vor jahren mit den SPI UARTS von MAXIM 
(MAX3100-3110). Der dayu notwendige Code im Interruptbetrieb war sehr 
einfach zu verwirklichen und funktionierte einwandfrei. Der MAX3110 ist 
sehr bequem weil da ein RS232 Interface ähnlich des MAX232 gleich 
mitintegriert ist.

Die I2C UARTS von NXP habe ich allerdings noch nicht ausprobiert. 
Sollten aber auch sehr brauchbar sein ausser der 3.3V Betriebsspannung.

Grüsse,
Gerhard

von holm (Gast)


Lesenswert?

@Manne:
Was zahlst Du für die beiden Dateien?
Ich habe die hier und kann die Dir auf eine CD brennen.
Ich nehme 59 Euro /h.

Gruß,

Holm

von Sitzer (Gast)


Lesenswert?

holm (Gast)

Was möchtest du für die beiden Dateien?!

von Matthias L. (matze88)


Lesenswert?

Ich melde mich nochmal zu meinem Thema: 3,686400 MHz und 38400 bps. Es 
geht nicht, zumindest nicht mit dem oben vorliegenden Code. Der Compare 
Match B läuft in den letzten Bits "über", d.h. er wird aufgerufen noch 
bevor er beendet ist, das füllt den nächsten Comparewert mit ner Zeit 
aus der Vergangenheit und schwups haben wir ein Problem :-)

Ich könnte jetzt rumwuseln und den TX Compare Interrupt deaktivieren 
wenn empfangen wird, aber das ist alles nur Mist und führt zu Problemen. 
Meine Lösung sieht jetzt so aus, dass ich nen 8 MHz Quarz einsetze. Habe 
leider keinen 7,??? Baudratenquarz mehr da, aber 8 MHz tuns ja auch 
(0,2% Error).
Pauschal zum berechnen würde ich sagen, dass 3,6864 MHz für 38400 bps 
~10-20% zu langsam sind. Damit stelle ich mal die Formel in den Raum: 
maximale Baudrate SWUart = Fclk / 120. Dann hat man sogar noch ein paar 
Instruktionen Luft :-) Schon erstaunlich, wieviel Arbeit ein HW Uart da 
abnimmt.

von Sven F. (finkman)


Lesenswert?

Hi!
Bis auf den ganzen ünnützigen, persönlichn Müll (mehr Keilerei als 
Produktives) möchte ich mir für den Code bedanken.
Trotzdem habe ich folgendes Problem:
Dein Code verwendet den 16bit Timer1 des Atmega8s (richtig?).
Diesen brauch ich jedoch ganz dringent für einen Sensor, der über den 
Timer gemessen wird.
Die beiden anderen Timer sind für die Messung leider zu klein mit ihren 
8bit.
Gibts da Ausweichmöglichkeiten? Zb Nutzung der 8bit-Timer für das 
SW-UART?

PS:
Das eine Interface brauch ich um mit einen RGB-Puls-Controller zu 
kommunizieren und das zweite bräuchte ich um den Atmega per PC 
anzusprechen.


Gruß und Danke im Vorraus

Sven Fink

von Peter D. (peda)


Lesenswert?

Sven Fink wrote:

> Gibts da Ausweichmöglichkeiten? Zb Nutzung der 8bit-Timer für das
> SW-UART?

Ja.
Im
Beitrag "I2C (TWI) Sniffer mit AVR"
ist ne Senderoutine und im
Beitrag "LCD über nur einen IO-Pin ansteuern"
ein Empfänger.

Beides für nen ATtiny25.
Allerdings kann der den Prescaler in 2-er Schritten einstellen.
Bei 8-er Schritten kann es zu hohe Fehler bei bestimmten Baudraten geben 
oder man nimmt ein Baudratenquarz.


Peter

von Newbie (Gast)


Lesenswert?

Hallo,

wie werden die beiden "neuen" RX/TX-Pins mit dem PC verbunden, direkt 
oder per Max232?

von Matthias L. (matze88)


Lesenswert?

Es ist nach wie vor eine UART auf TTL Pegel. Also brauchst du zur 
Verbindung mit dem PC einen MAX232 oder ähnliches.

von Matthias R. (matsch)


Lesenswert?

Hallo,
kann mir bitte jemand die Zeile
1
TIMSK = 1<<TICIE1^1<<OCIE1A;
aus suart.c erklären? Verallgemeinert kann die Zeile auch so aussehen
1
REGISTER = 1<<BIT5^1<<BIT4
Das '^' ist doch eine Bitweise EXOR Verknüpfung. Werden die Bits 
Abhängig von ihrem Urzustand gesetzt bzw. gelöscht?

Da in dem Register TIMSK auch die Interrupts für Timer0 und Timer2 
maskiert werden, muss ich eher so etwas schreiben, um die anderen Bits 
nicht zu verändern.
1
TIMSK |= 1<<TICIE1;
2
TIMSK |= 1<<OCIE1A;
Ist das das Gleiche?

von Micha (Gast)


Lesenswert?

@ Matthias R.
Ist zwar schon ne Weile her, aber trotzdem:

> Das '^' ist doch eine Bitweise EXOR Verknüpfung. Werden die Bits
> Abhängig von ihrem Urzustand gesetzt bzw. gelöscht?
Es wird nur das hier 1<<TICIE1^1<<OCIE1A ver-x-odert und dann in TIMSK 
geschrieben.

> Da in dem Register TIMSK auch die Interrupts für Timer0 und Timer2
> maskiert werden, muss ich eher so etwas schreiben, um die anderen Bits
> nicht zu verändern.
> TIMSK |= 1<<TICIE1;
> TIMSK |= 1<<OCIE1A;
>
> Ist das das Gleiche?
Theoretisch schon. Da TIMSK aber anfangs 0x00 ist, kannst du auch
1
TIMSK = 1<<TICIE1;
2
TIMSK |= 1<<OCIE1A;
schreiben. Oder eben Peters Schreibweise...


@ Peter Dannegger
Ich möchte gerne deinen Code aus dem ersten Post verwenden, habe 
allerdings das Problem, dass ich auch 0x00 als Datum senden und 
empfangen muss. Bei den zu sendenden und zu empfangenden Frames steht 
dafür an 4. Stelle immer die Frame-Länge in Bytes.

Hattest du auch schon einmal einen solchen Fall und eine entsprechende 
Version der Software?

Senden ist kein Problem, da ich statt
1
void sputs( u8 *txt )
2
{
3
  while( *txt )
4
    sputchar( *txt++ );
5
}
einfach
1
void sputs( u8 *txt, u8 bytes_to_send )
2
{
3
  while( bytes_to_send-- )
4
    sputchar( *txt++ );
5
}
schreiben kann.

Für das Empfangen ist mir allerdings noch nichts effektives eingefallen.

von Micha (Gast)


Lesenswert?

Ich habe vergessen zu erwähnen, dass ich immer Frame-weise senden und 
empfangen muss und zwischen einzelnen Frames einige ms Pause sind.

von Kermit (Gast)


Lesenswert?

Hallo,
bei mir klappt das empfangen (9600baud) nicht auf einem Atmega644 mit 
1Mhz internen Takt. Mit der HW UART klappts dagegen einwandfrei.

Was ich schon nicht verstehe ist die seltsame Formel für die Bitdauer:

#define BIT_TIME  (u16)((XTAL + BAUD/2) / BAUD)

Wieso nicht einfach XTAL/BAUD?


Hat jemand vielleicht schon jemand erfolgreich eine (für gcc 
geschriebene) SW_UART auf dem Atmega644 laufen?

Vielen Dank,
Kermit

von Kermit (Gast)


Lesenswert?

Achso, senden mit der SW UART geht einwandfrei! Mus ich den ICP-Eingang 
(beim Atmega644 PD6) vielleicht vorher noch als I/O Eingang 
konfigurieren? In der suart_init() wird der TX-Port nämlich als Ausgang 
gesetzt mit

STXDDR |= 1<<STX;      // TX output

Ein Eingang wird aber nicht konfiguriert?

Ich musste übrigens etliche Register- und Bitnamen anpassen, weil sie 
beim Atmega644 leicht anders heißen.

von Runder (Gast)


Lesenswert?

> Wieso nicht einfach XTAL/BAUD?

Um zum nächstliegenden Wert auf- und abzurufen, dann wird ggf. der 
Fehler kleiner.

von Benjamin (Gast)


Lesenswert?

>Ich musste übrigens etliche Register- und Bitnamen anpassen, weil sie
>beim Atmega644 leicht anders heißen.

Hi Kermit,

ich wollte in den nächsten Tagen ebenfalls anfangen mich mit der SW UART 
für den ATmega644 zu beschäftigen.
Wenn du, wie du sagst, die Dateien schon für den ATmega644 angepaßt 
hast, magst du die vielleicht auch hier zur Verfügung stellen?
Wäre wirklich ne super Sache.

Gruß,
Benjamin

von Öpf (Gast)


Lesenswert?

Hi,

ich habe den SW-UART mal auf einen ATMega644 portiert und benutze dort 
Timer 0.

Ich habe einige Änderungen vorgenommen. Wie immer auch hier die 
Auskunft, das die Änderungen meiner Ansicht nach keine wesentlichen 
Auswirkungen haben. Naja, wie immer ist sowas mit Vorsicht zu geniessen.

Leider habe ich von dem System aus weder eine Internetverbindung noch 
kann die Krücke hier meinen USB-Stick lesen. Vielleicht guckt Ihr 
trotzdem mal.

Am Anfang habe ich in suart_init die Zeilen mit OCR0A = TCNT0 + 1 und 
TCCR0A rausgelöscht. Ich war der Meinung das die nichts bewirken, aber 
vielleicht habe ich mich geirrt.
Dann habe ich im Compare B Int noch eingesetzt, dass in EIFR der INTF0 
gelöscht wird, weil er störte obwohl der INT selbst garnicht aktiviert 
war.

Ausserdem habe ich zwei Stellen rausgelöscht, for ICF1 in TIFRx gesetzt 
wird, da Timer 0 im 644 keine Capture Unit hat. Abgesehen davon bin ich 
neugierig wozu das nutze ist, wenn die Capture-Unit im Original nicht 
benutzt wird. Vielleichet in Bug.

Ich habe das Problem, das die Ganze Mimik gut funktioniert aber nur ein 
gewisse Zeit lang. Dann wird kein Zeichen mehr empfangen.
Auffällig ist, das bei srx_done = 0 und srx_mask = 1 der Capture 
Interrupt B nicht mehr enabled ist. (Nur noch der für A).

Es scheint das im INT0 die Bedingung, das der RX-Pin immer noch low ist 
manchmal nicht zutrifft. Das ist, soweit ich sehe der einzige Punkt wo 
OCIE0B aktiviert wird.

Zum einen möchte ich gerne fragen wozu die Bedingung an sich gut ist. 
(Zum Entprellen oder sowas?) Wenn sie nicht zutrifft steht der Empfang 
völlig, da der Flankeninterrupt nicht mehr aktiviert wird.
Zum anderen möchte ich wissen, ob es, abgesehen vom völligen entfernen 
der Bedingung noch andere Möglichkeiten habe.
Der Eingang hängt an einem Ausgang von nem MAX202.

Vielleicht hat ja sogar Peter Dannegger einen Moment Zeit da mal 
raufzugucken. Das wäre sehr nett.

von Peter D. (peda)


Lesenswert?

Öpf schrieb:
> ich habe den SW-UART mal auf einen ATMega644 portiert und benutze dort
> Timer 0.

Das könnte bei einigen Baudraten Probleme mit der Genauigkeit geben. da 
der Prescaler nur in 8-er Stufen wählbar ist.


> Ich habe einige Änderungen vorgenommen.

Ein exakter Quelltext sagt mehr als 1000 Beschreibungen.


> Am Anfang habe ich in suart_init die Zeilen mit OCR0A = TCNT0 + 1 und
> TCCR0A rausgelöscht. Ich war der Meinung das die nichts bewirken, aber
> vielleicht habe ich mich geirrt.

Steht doch im Kommentar (ist für eilige).


> Dann habe ich im Compare B Int noch eingesetzt, dass in EIFR der INTF0
> gelöscht wird, weil er störte obwohl der INT selbst garnicht aktiviert
> war.

???


> wenn die Capture-Unit im Original nicht
> benutzt wird.

Und was ist dann das hier:
1
...
2
SIGNAL( SIG_INPUT_CAPTURE1 )    // rx start
3
...


> Ich habe das Problem, das die Ganze Mimik gut funktioniert aber nur ein
> gewisse Zeit lang. Dann wird kein Zeichen mehr empfangen.
> Auffällig ist, das bei srx_done = 0 und srx_mask = 1 der Capture
> Interrupt B nicht mehr enabled ist. (Nur noch der für A).

Ohne Code schwer zu sagen.


Ich würde zu der SW-UART mit FIFO raten.


Peter

von Öpf (Gast)


Angehängte Dateien:

Lesenswert?

@ Peter Dannegger

>Und was ist dann das hier:

>...
>SIGNAL( SIG_INPUT_CAPTURE1 )    // rx start
>...

Da ist mir ein Irrtum unterlaufen. Es ist ein paar Monate her, das ich 
den Code gezogen habe und ich finde die ZIP-Datei nicht mehr.
Tatsächlich steht in dem Download oben die von Dir genannte 
Interrupt-Routine. Da ich aber Timer 0 verwenden musste, habe ich den 
Code geändert und musste daher mit dem Flanken-Interrupt auskommen. Mag 
sein, das ich dabei was übersehen habe.
Timer 1 brauchte ich um so eine Uhrensynchronisation à la ntp zu machen.

Daher betrachtest Du das vielleicht nicht mehr als Deinen Code, wenn er 
auch auf Deinem basiert. Jedenfalls meine ich das es möglich ist, das Du 
1. keinen Rat zu Code geben willst/kannst, der sich stark verändert hat 
und das 2. evtl. ein zweiter Thread von Nöten ist. Ich hatte auf jeden 
Fall im Kopf, das ich Deinen Code genommen und abgewandelt habe. 
Gedanklich hat der Code damit zumindest teilweise immer noch Dir gehört. 
(Bin so ein alter Vogel der in den 80igern mit Computern angefangen hat. 
Da hat man noch Skrupel).

>Das könnte bei einigen Baudraten Probleme mit der Genauigkeit geben. da
>der Prescaler nur in 8-er Stufen wählbar ist.
Grundsätzlich ja, aber bei 18.432MHz und 9600 Baud ist das meiner 
Rechnung nach kein Problem. Prescaler ist 64. OCR0A daher dezimal 30.

>> Ich habe einige Änderungen vorgenommen.
>Ein exakter Quelltext sagt mehr als 1000 Beschreibungen.
Sicherlich.

>> Am Anfang habe ich in suart_init die Zeilen mit OCR0A = TCNT0 + 1 und
>> TCCR0A rausgelöscht. Ich war der Meinung das die nichts bewirken, aber
>> vielleicht habe ich mich geirrt.
>Steht doch im Kommentar (ist für eilige).
Nun, dann habe ich mich missverständlich ausgedrückt. Da steht zwar, das 
ein Overflow-Interrupt ausgelöst werden soll, aber nicht wozu das gut 
ist.
Jetzt wo ich nochmal darauf schaue, denke ich, das es darum geht, das 
die Prüfung auf ein zu sendendes Byte definitiv einmal sofort 
stattfindet.

Ich füge hier mal den Code bei. Wenn wir den Fehler finden, dann mag er 
vielleicht jemandem von Nutzen sein.

Ich meine allerdings, nach dem ein paar Stunden vergangen sind, das mein 
Problem nicht von der SW her kommt, sondern von der HW. Wahrscheinlich 
gibt die HW, der ich den Strom anschalte am Anfang mal so ein "Blurbs" 
von sich, das die Interrupt-Routine triggert. Werde mal versuchen den 
ISR zu disablen bis die Spannung sich stabilisiert hat und das Gerät 
hochgekommen ist (ist auch nur ein uC, allerdings nicht von mir).

Fakt ist jedenfalls das der Empfang relativ lange Zeit geht. Es werden 
teilweise Kilobyte empfangen ohne das Probleme auftreten (Und das ohne 
FIFO).

>Ich würde zu der SW-UART mit FIFO raten.
Nun, da der Mechanismus der selbe ist nur eben der FIFO oben drauf, 
würde das meiner Ansicht nach nichts bringen wenn das Problem 
tatsächlich in der Empfangsmimik liegt. Aber wiegesagt, glaube ich das 
nicht mehr.

Wäre trotzdem nett wenn Du mal einen Blick drauf wirfst.

von Peter D. (peda)


Lesenswert?

@Öpf,
1
EIMSK &= ~(1 << INT0);      // disable edge interrupt
2
  if( !(SRXPIN & 1<<SRX))    // still low

Bei Dir greift die Störunterdrückung zu spät, d.h. Du hast den Interrupt 
schon disabled.
Du darfst das Disable erst im if machen.


Peter

von Öpf (Gast)


Lesenswert?

"Bei Neumann" - das ist es.

Vor dem if weiss ich ja noch gar nicht ob es ein Störimpuls ist und darf 
den INT noch nicht sperren. Erst wenn die Störbedingung ausgeschlossen 
ist.

Also so:
1
if( !(SRXPIN & 1<<SRX)) {    // still low
2
  EIMSK &= ~(1 << INT0);      // disable edge interrupt
3
  TIMSK0 = 1<<OCIE0A^1<<OCIE0B;  // wait for first bit
4
}

Danke. ;-)

von Öpf (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe die Änderung getestet und es läuft stabil.
Ich poste hier mal den Code für einen ATMega644.

Er basiert auf dem Code von Peter Dannegger.
Die Unterschiede sind:
1. Verwendung von Timer 0 (8-Bit) anstelle Timer 1 (16-Bit).
Das hat Auswirkung auf die möglichen Baudraten (wie P.D. schon bemerkt 
hat)
läuft aber z.B. mit einem 18.432MHz Quarz und 9600 Baud.
2. Verwendung des Flankeninterrupts INT0 anstelle des 
Capture-Interrupts.

Umstellung auf andere Flankeninterrupts oder Timer sollte gehen, ist 
hier aber nicht mit #defines gemacht.

Da P.D.s SW-UART mit FIFO auf diesem Code basiert ist er auch einfach 
mit FIFO auszurüsten. Einfach mal die Unterscheide ansehen.

Einiges an Code ist auskommentiert, aber ich bin jetzt zu faul, das 
rauszulöschen.

Viel Spass und danke an Peter D. für die Hilfe bei der 
Betriebsblindheit. (Ein INT der gesperrt ist, kann natürlich nicht mehr 
auslösen).

von Öpf (Gast)


Lesenswert?

Habe leider einen Teil des Textes vergessen, den ich posten wollte.

Die Verwendung des Flanken-Interrupts anstelle des Caputure-Interrupts 
hat den Nachteil, das die Bitzeit nicht mehr so genau stimmt wie im 
ersten Fall.
Es muss also im Einzelfalls geprüft werden, ob evtl. noch eine Konstante 
subtrahiert werden muss oder die Differenz von ausreichend geringer 
Bedeutung ist. Grundsätzlich wird das kritischer je mehr höherpriore 
Interrupts beteiligt sind und je höher die Baudrate wird.

Meine Variante ist also nicht grundsätzlich und immer ein Ersatz für 
Peter Dannegers Originial.

von Marc (Gast)


Lesenswert?

Hallo liebe Experten!

Ich möchte gern diesen Software UART auf einem ATmega32 mit 16MHz 
benutzen. Leider kommt jedoch schon beim Verwenden des Beispielcodes 
eine Fehlermeldung des Compilers : undefined reference to 'suart_init'

Ich gehe mal davon aus, dass ich die Datei "suart.c" noch nicht richtig 
ins Projekt eingebunden habe, weiß aber auch nicht wirklich wie das 
geht.

Wenn ich den Code in meine .c kopiere wirds dann compiliert.

Beim versuch das ganze dann zu testen wird allerdings immer mein AVR 
Dragon abgeschossen, sodass ich da erst die Firmware neu aufspielen 
muss, damit es geht.

Vorher (ohne die Erweiterung mit dem SUART) ging das einwandfrei.


Ich benutze wie gesagt einen ATmega32 mit 16MHz, das AVR Studio mit 
WINAVR und den AVR Dragon zum Programmieren und Debuggen.


Ich hoffe ihr könnt mir helfen, da ich das ganze noch bis zum Freitag 
zum laufen bringen muss (Projektarbeit).

MfG und schönen 3. Advent
Marc

von Marc (Gast)


Lesenswert?

PS: Hab doch noch was vergessen: der SUART-Code ist natürlich der ganz 
oben in diesem Fred...

von Peter D. (peda)


Lesenswert?

Marc schrieb:
> Beim versuch das ganze dann zu testen wird allerdings immer mein AVR
> Dragon abgeschossen, sodass ich da erst die Firmware neu aufspielen
> muss, damit es geht.

Was bedeutet "abgeschossen"?
Was für eine Firmware?

Zu Dragon Problemen kann ich Dir nicht helfen.
Kann man den Dragon denn nicht wie jeden anderen AVR programmieren?


Peter

von Marc (Gast)


Lesenswert?

Hallo Peter,

der AVR Dragon ist ein Programmier und Debug Gerät! Und das Gerät hat 
natürlich eine Firmware drauf.

Wenn du in AVR Studio Hilfe mal Dragon eingibst, findest du das. Und da 
steht dann z.B. bei Troubleshooting, dass wenn die LED gelb leuchtet, 
die Firmware korrupt ist und man sie neu aufspielen soll. Danach kann 
ich wieder einmal das compilierte Programm auf den ATmega übertragen und 
schwupps... LED des Dragon wieder gelb! Aber nur wenn ich den SoftUart 
-Teil mit drin habe.

Hoffe das war jetzt verständlich :-)

von Patrick P. (xadas)


Lesenswert?

Super! Funktioniert einwandfrei, sowohl auf einem ATMega8 als auch auf 
einem ATMega644.
Hier die Anpassungen für den ATMega644:
1
#ifdef _AVR_IOM644_H_
2
#define SRX     PD6     // ICP on Mega644
3
#define SRXPIN  PIND
4
5
#define STX     PD5     // OC1A on Mega644
6
#define STXDDR  DDRD
7
8
#define TIFR    TIFR1
9
#define TIMSK   TIMSK1
10
#define TICIE1  ICIE1

von Thoralt F. (thoralt)


Lesenswert?

Hallo Leute,

ich weiß, der Thread ist schon nicht mehr ganz frisch, aber ich wollte 
auf einen Fehler hinweisen, welcher weiter oben in die Diskussion 
eingebracht wurde:
1
 TIMSK0 = 1<<OCIE0A^1<<OCIE0B;  // wait for first bit

Das führt nicht zum gewünschten Resultat, denn die Priorität des 
Shift-Left-Operators ist viel niedriger als des EXOR. Im vorliegenden 
Fall wird also folgendes compiliert:
1
 TIMSK0 = 1<<(OCIE0A^1)<<OCIE0B;  // wait for first bit

Um es richtig zu machen, sind bei Shift-Operationen fast immer Klammern 
nötig:
1
 TIMSK0 = (1<<OCIE0A)^(1<<OCIE0B);  // wait for first bit

Ich hoffe, das hilft irgendjemandem.

Viele Grüße
Thoralt

von Peter D. (peda)


Lesenswert?

Nö, es wird zuerst geschoben (Prio 11) und dann EXOR (Prio 7).
Siehe:
http://www.ostc.de/c-precedence.pdf

Klammern sind unnötig.

Klammern braucht man, wenn man bitweise Verknüpfungen vergleicht. Das 
ist eine gern gemachte Fallgrube, da man intuitiv das Gegenteil 
erwartet.
Z.B.
1
  if( i&7 == 1 )
ist falsch.


Peter

von Edgar M. (emi)


Lesenswert?

Hallo,

zunächst mal vielen Dank an die beteiligten für den SOft UART. Genau das 
habe ich gesucht. Zu dem Code habe ich doch eine Frage.
Ich benötige den UART für eine Schnittstelle die permanent Daten schickt
mit 2400 Baud. D.h. an dem Zeitpunkt, wenn der Soft UART
initialisiert wird ist es nicht synchronisiert. Damit meine ich -
das erkennen des Startbits kann durchaus ein Datenbit auf "0" sein.
Üblicherweise werden 10 Bits verschickt - Start+ 8 Daten + Stop.
In dem obigen Code wird das Stop-Bit nicht ausgewertet (oder ich 
verstehe den Code nicht). Sollte man nicht
        srx_done = 1;      // mark rx data valid
erst dann setzen wenn als 10. Bit eine "1" anliegt???

Viele Grüße
Edgar

von Öpf (Gast)


Lesenswert?

>Zu dem Code habe ich doch eine Frage. ...
>In dem obigen Code wird das Stop-Bit nicht ausgewertet (oder ich
verstehe den Code nicht). Sollte man nicht
1
        srx_done = 1;      // mark rx data valid
>erst dann setzen wenn als 10. Bit eine "1" anliegt?

Nein. Das ist nicht der Zweck von srx_done. Es soll anzeigen, ob der 
Empfang vollständig (nach Anzahl der Bits ) ist, und nicht, ob der 
Empfang korrekt ist.

von Jörg E. (jackfritt)


Lesenswert?

Is schon älter ich weiss. Kurze Frage zu Peters Code.
Dort wird ja in uart.c prescaler und bauddiv "berechnet". Da wird ja 
Code erzeugt. Könnte ich das in unten aufgeführter Art erledigen? Würde 
mir Codespeicher sparen ? Oder habe ich mal wieder einen "blutiger 
Anfänger" Denkfehler ?
1
#if defined (__AVR_ATtiny13__) || (__AVR_ATtiny85__) || (__AVR_ATtiny84__)
2
#define OCR 255
3
#else
4
#error Look into Datasheet if 8 or 16 Bit Timer and change OCR=255 or OCR=65536
5
#endif
6
  // Find Prescaler
7
#if ( F_CPU/FREQ  ) <= OCR
8
TCCR0B = (0 << CS02)  | (0 << CS01) | (1 << CS00);
9
#define PRESCALER 1 // 0 but not good for Mathematics
10
#   warning Timer without Prescaler
11
#elif (F_CPU/8/FREQ ) <= OCR
12
TCCR0B = (0 << CS02)  | (1 << CS01) | (0 << CS00);
13
#define PRESCALER 8
14
#   warning Timer with 8 Prescaler
15
#elif (F_CPU / 64 / FREQ ) <= OCR
16
TCCR0B = (0 << CS02)  | (1 << CS01) | (1 << CS00);
17
#define PRESCALER 64
18
#   warning Timer with 64 Prescaler
19
#elif (F_CPU / 256 / FREQ ) <= OCR
20
TCCR0B = (1 << CS02)  | (0 << CS01) | (0 << CS00);
21
#define PRESCALER 256
22
#   warning Timer with 256 Prescaler
23
#elif (F_CPU / 1024 / FREQ ) <= OCR
24
TCCR0B = (1 << CS02)  | (0 << CS01) | (1 << CS00);
25
#define PRESCALER 1024
26
#   warning Timer with 1024 Prescaler
27
#elif (F_CPU / 1024 / FREQ ) > OCR
28
#   error No Prescaler could be defined !!
29
#endif

von Jörg E. (jackfritt)


Lesenswert?

Sorry ich nehme alles zurück. War ein anderer Code(I2Csniff) von Peter.
Also einfach nicht weiter beachten :)

Gruss,

Jörg

von Volker U. (volkeru)


Lesenswert?

Peter Dannegger schrieb:
> Nö, es wird zuerst geschoben (Prio 11) und dann EXOR (Prio 7).
> Klammern sind unnötig.

Ich frage mich aber, warum du überhaupt eine XOR-Verknüpfung benutzt, 
wenn es auch eine einfache OR-Verknüpfung täte!? Gefällt dir das Hütchen 
einfach nur besser, als der senkrechte Strich, oder gibt es einen 
plausiblen Grund dafür?

Da XOR eine andere logische Funktionalität besitzt, als ein OR, sollte 
man es m.E. auch nur dann benutzen, wenn es einen echten Grund dafür 
gibt.

Beim Bearbeiten deines Codes habe ich mich nämlich erheblich darüber 
gewundert, warum du die Bits unnötigerweise ver"x"oderst und länger 
überlegt, ob das im Gesamtkonzept irgendeinen Sinn hat. Ich kann aber 
keinen erkennen. Insofern ist der Code verwirrend.

Und hier verstehe ich den Sinn auch nicht:

Du schreibst:
#define  TX_HIGH    (1<<COM1A1^1<<COM1A0)
#define  TX_LOW    (TX_HIGH^1<<COM1A0)

Warum schreibst du dafür nicht einfach folgendes, was viel 
übersichtlicher ist:
#define  TX_HIGH    ((1<<COM1A1) | (1<<COM1A0))
#define  TX_LOW    (1<<COM1A1)

Gruß, Volker

von Uwe (Gast)


Lesenswert?

Hallo Volker,

ich erkläre mir die Schreibweise wie folgt:
jeder Programmierer hat seine Stiel, und Peters ist kurz und 
zielführend.

Hier rechnet auch nicht der atmel, sondern der crosscomüiler, bzw. der 
Präprozessor des avr-gcc.

Naja ich finde es sehr gut von Peter und anderen Funktionsmodule nutzen 
zu können, das erspart mir doch Arbeit.

von Volker U. (volkeru)


Lesenswert?

Hi Uwe,

> jeder Programmierer hat seine Stiel, und Peters ist kurz und
> zielführend.

Ähm, ja sicher hat jeder seinen Stil. Aber trotzdem sollte man sich, 
wenn man vorhat, den Code evtl. zu veröffentlichen, dem allgemein 
gebräuchlichen Stil anpassen, wie ich finde. Allein schon deshalb, damit 
man auch fremden Code schnell verstehen kann. Gerade C ermöglicht (durch 
die Defines) einen Stil bis hin zur völligen Unkenntlichkeit. Viele 
Defines sind vielleicht schnell und komfortabel beim Schreiben, aber 
machen den Code sehr unübersichtlich.

Was "kurz und zielführend" betrifft: Ein "|" ist ebenso kurz wie ein 
"^". Und in meinem obigen Beispiel ist der von mir vorgeschlagene Code 
sogar kürzer als der von Peter. Übersichtlicher allemal.

> Hier rechnet auch nicht der atmel, sondern der crosscomüiler, bzw. der
> Präprozessor des avr-gcc.

Die Versionen oben werden beide vom Compiler gleich hoch optimiert. Ich 
sehe da keinen Unterschied. Was wirklich VIEL Code verursacht, ist 
Fließkommaarithmetik, weil die meisten AVRs keine FPU haben (gibts 
überhaupt einen, der eine hat?) und die Fließkommaarithemtik daher 
simuliert werden muss.

Beispiel:

#define BIT_TIME  (u16)(XTAL * 1.0 / BAUD + 0.5)

erzeugt (theoretisch) viel Code, weil mit Fließkomma gearbeitet wird.

#define BIT_TIME  (u16)(((XTAL * 10 / BAUD) + 5) / 10 )

erzeugt das selbe Ergebnis, kommt aber ohne Fließkomma aus und bedeutet 
daher i.d.R. ganz erheblich weniger Code. Wenn man also Code einsparen 
will, sollte man z.B. immer auf Fließkommaoperationen verzichten! In 
diesem Beispiel ist das allerdings egal, weil nur Konstanten verwendet 
werden und die vollständige Berechnung daher schon vom Compiler 
durchgeführt wird und deshalb keine Arithmetik im Microcontroller 
stattfinden muss. Aber wenn diese Berechnung nicht mit Konstanten, 
sondern mit Variablen für XTAL oder BAUD dürchgeführt würde, entstünde 
im ersten Beispiel erheblich mehr Code! Ich habe es gerade mal 
ausprobiert. Eine kleine Testroutine erzeugt mit Fließkommaarithmetik 
890 Bytes Code, während sie mit Integer-Arithmetik (unteres Beispiel) 
nur 198 Bytes erzeugt. Das sind die Stellen, wo man richtig Code 
einsparen kann. Und nicht bei irgendwelchen logischen Operationen.

> Naja ich finde es sehr gut von Peter und anderen Funktionsmodule nutzen
> zu können, das erspart mir doch Arbeit.

Aber klar, zweifelsohne! Dieses Forum ist ein wahrer Schatz! Aber wie 
ich finde, sollte man doch auch gut verständlichen Code veröffentlichen.

Ich suche schon länger eine Routine für einen Softuart, die wirklich gut 
ist. Alle die ich bisher finden konnte, waren leider wenig 
leistungsfähig. Bei 4 MHz bekommen die meisten Routinen schon Probleme 
mit 9600 baud und 19200 geht gar nicht.

Die hier vorgestellte Routine habe ich noch nicht getestet, aber sie ist 
vermutlich erheblich besser. Sie hat aber auch einen riesigen Nachteil: 
Sie läuft nur mit Controllern, die eine Input Capture Unit (ICP) im 16 
Bit-Timer haben. Das sind nicht viele. Ich kenne nur die AtTiny 
24/44/84, die das haben.

Insofern ist also auch diese Routine wieder nur auf wenigen, bestimmten 
AVRs verwendbar :-(.

Gruß, Volker

von SUART (Gast)


Lesenswert?

Einen herzlichen Dank an den Super-Algorithmus! ;-)

-------

Noch ein kl. Tipp an all jene, die genau wie ich kurz vor der 
Verzweiflung standen/stehen, warum der Code "nur Müll" liefert: Das 
MOSI-Signal teilt sich mit dem OC1A-Signal einen Pin. Während des 
Programmiervorgangs steht somit am seriellen Port sehr viel Datenmüll 
an. Dieser Datenmüll hat in meinem Fall die Terminal-Software etwas "aus 
dem Tritt" gebracht und diese zeigte somit -je nach Zeichen- etwas 
anderes an.. ;-)

Ein "Terminal zurücksetzen" nach dem Programmiervorgang bewirkt Wunder.. 
;-D

von Alex - BE (Gast)


Lesenswert?

Hallo zusammen,

Ich habe die Software-UART verwendet, um auf Loconet Bussytem (Digitrax) 
zu kommunizieren.

Funktioniert schon gut, sondern möchte ich jetzt die mögliche 
Kollisionen erkennen und vermeiden.

Meine Idee wäre, das RX- und TX- Pegel zu vergleichen, damit könnte man 
mit dem ersten gesendete Bit sehen, wenn es eine Kollision gibt.

Aber ich weiß nicht genau, wie man das stellen könnte.

Danke für ihr Hilfe!

Alex

P.S. : Entschuldigung für die Sprachfehler, ich bin französisch :-/

von amateur (Gast)


Lesenswert?

Ich weiß zwar nicht, über welchen Prozessor Du redest, aber "am" 
Prozessor selber sind fast immer reine Logikpegel angesagt. Lässt dein 
Prozessor es nicht zu, dass Du Rx oder Tx nebenher abfragst, so musst Du 
die Anschlüsse nur zusätzlich auf "Mess"-Ports (Typ 08/15) legen und 
dann diese fragen.

Andererseits, empfängst Du etwas und bist selber am Senden, so kannst Du 
bei einem 1-Draht-System davon ausgehen, dass Du Dich selber "reden" 
hörst. Einfache Logik.

Bei völlig autarken Systemen, die ein 1-Draht-System verwenden, lässt 
sich eine Kollision, aus Gründen der Geschwindigkeit nicht vermeiden.

von Alex - BE (Gast)


Lesenswert?

Danke für deine Antwort, und du siehst nicht so ein amateur wie ich aus 
:)

Ich benutze ein ATmega 168, also überhaupt kein Problem, um Rx und Tx 
abzufragen.

Was meinst du genau mit "1-Draht-System" ?

von Christian F. (cmf) Benutzerseite


Lesenswert?

Hallo,

erstmal danke für diese Bibliothek — funktioniert super! Die einzige 
Frage die sich mir stellt ist ob ich den Code in einem OpenSource/GPL 
Projekt verwenden kann. Sprich unter welcher Lizenz steht der Code?
Danke, Christian

von Peter D. (peda)


Lesenswert?

Der Code ist frei verwendbar.

von Christian F. (cmf) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Der Code ist frei verwendbar.
Ok, danke!

von PROgrammer (Gast)


Lesenswert?

Achja, und mal wieder wird dieses Thema aufgefrischt

Aber ich komm einfach nicht weiter:
Ich debugge mein ATmega32, der  mit 4 MHz getaktet ist und der mit 5V 
gespeist ist, mit dem JTAGICE mk II. Wo weit so gut alles läuft nur die 
Software-USART nicht. In Peters' Code hab ich schonmal das Zurücksetzen 
des Interrupt-Flags in die IF-Schleife gezogen und seit dem hält der 
Controller auch immer an meinem Breakpoint in der main.c hinter dem 
while( !kbhit() ); an. Aber als Wert bekomme ich immer eine 255 
ausgegeben.
Mein Signal, welches aucjh beim 20 Pin ankommt, sieht so aus:
1       Dauerzustand
0 4us   Start
1 28us  1.-7. Bit
0 4us   8. Bit
1-      2*Stop und danach wieder auf HIGH

Woran könnte das liegen? Wofür ist die 
Service-Routine(SIG_OUTPUT_COMPARE1B)

Das Senden funktioniert auch noch nicht. Aber das kommt später erst mal 
muss das Empfangen funktionieren!
Wobei ich schonmal sagen kann, dass der Mirkrocontroller dort dauernd 
anhält, wenn ich da ein Breakpoint setzte. Aber das muss wahrscheinlich 
so sein? Komisch ist nur das am Ausgang(Pin 19) keine Änderung 
festzustellen ist...

Meine Baudrate ist übrigens 250kHz.

Danke schonmal im Voraus
Justus

von Uwe S. (de0508)


Lesenswert?

Hi Justus,

mache deine Tests mit realer Hardware, dann gehts.

Diesem Simulator traue ich nicht und habe ihn niemals eingesetzt.

von PROgrammer (Gast)


Lesenswert?

Ich hab jetzt noch mal genau nach gemessen am Pin 19 wechselt der 
Zustand alle ca. 16ms

von PROgrammer (Gast)


Lesenswert?

Danke Uwe für die schnelle Antwort. Das ging ja so schnell, dass ich gar 
nicht gemerkt, wie sie bei mir ankam, während ich noch meine zweite 
Nachricht geschriebenn habe. Aber ich muss mich wohl unvertständlich 
ausgedrückt haben, ich habe das alles nicht mit einem Simulator geprüf 
ich nutze eine reale Hardware mein Compter sendet über ein 
USB-Seriell-Adapter das oben beschiebene Signal an meine Platine. Auf 
der Platine geht das Signal über den MAX 3232 an den Pin 20 meines 
ATmega's. Nur überwache ich noch über ein JTAG-Schnittstelle das 
Vorgehen im Controller und  dabei ist mir halt aufgefallen, dass, wenn 
mein Osciloskop mein Signal anzeigt, der Contoller anhält(Weil ich wie 
bereits oben beschrieben, dort ein Breakpoint liegen habe). Er geht auch 
in die Empfangsroutine in usart.c rein aber dann empfängt er immer den 
Wert 255. Ebenso geht mein Contoller die ganze Zeit in die Senderoutine 
rein, aber dennoch kann ich nur alle 16ms eine Zustandsänderung am Pin19 
feststellen. Alle anderen Abläufe funktionieren ja auch einbahnfrei. 
Kann es sein, dass mein Signal invertiert ist und er es deshalb flasch 
empfängt?!?

Ich hoffe, ich habe mich jetzt verständlicher ausgedrückt und mir kann 
man wieder so schnell antworten, wie Uwe es getan hat.

Gruß Justus

von Helmut S. (helmuts)


Lesenswert?

Mal eine blöde Frage. Wozu braucht man einen Software UART, wenn der 
Prozessor einen Hardware UART hat?
Software UART war doch schon vor 30 Jahren nur eine Notlösung, aber wenn 
man heutzutage noch einen braucht, dann hat man bei der Auswahl des 
Prozessors nicht aufgepasst.

von PROgrammer (Gast)


Lesenswert?

An der Hardware USART liegt ein DMX-Signal sonst würde ich selbst 
verständlich auch lieber den Hardwarekanal nutzen. Kann es sein das mein 
Controller ein Timingproblem hat mit den 250kHz? Vllt empfängt er ja nur 
noch den Dauertzustand...

von PROgrammer (Gast)


Lesenswert?

Wobei ich hab gerade mal die Sendefrequez vom Computer auf 10000Hz 
runtergeregelt und beim Mirkocontoller dass dann auch so eingesellt und 
wieder empfange ich nur "255".

von PROgrammer (Gast)


Lesenswert?

Okay nächste Mal überprüfe ich es ein zweites Mal bevor ich was 
schreibe, ich habe die DMX-Baudrate runtergesetzt und nicht die von der 
S-USART

Jetzt funktioniert alles. Ich teste mal nachher Spaßes halber  wie hoch 
ich komme...

DANKE für alles, auch wenn es nur "zuhören" war

von PROgrammer (Gast)


Lesenswert?

Ach wenn ich gerde gesendet habe, dass es funktioniert: Da hatte ich 
noch nicht Werte über 127(also mit dem 8.Bit gesendet). Woran kann das 
liegen? Ist ja vielleicht keine so spezielle Frage, sodass ihr mir kurz 
ein paar Tipps geben könnt, denn eigentlich brauch ich den Code in 1 
Std. fertig :-{

von PROgrammer (Gast)


Lesenswert?

Ach wenn ich gerde gesendet habe, dass es funktioniert: Da hatte ich 
noch nicht Werte über 127(also mit dem 8.Bit gesendet). Woran kann das 
liegen? Ist ja vielleicht keine so spezielle Frage, sodass ihr mir kurz 
ein paar Tipps geben könnt, denn eigentlich brauch ich den Code in 1 
Std. fertig :-{

Auch beim Sende komm ich nur bis zum 7. Bit!

Danke
Justus

von max (Gast)


Lesenswert?

signed / unsigned problem?

von PROgrammer (Gast)


Lesenswert?

Okay danke hast du eine Vermutung wo im Code? Ich teste es mal nachher, 
für heute ist es eh zu spät. Dann versuche ich mal mein Projekt bis 
morgen fertig zu bekommen

von PROgrammer (Gast)


Lesenswert?

Senden hab ich jetzt hin bekommen, dass lag nicht an dem Software-USART 
Code, aber beim Empfangen ist es jetzt immernoch so, dass ich Werte bis 
127 richig empfange und bei Werten dadrüber nur noch eine 63...
Auch wenn Max erstmal ein sehr logischen Grund genannt hat, konnte ich 
keine Stelle finden, wo einer Variable s8(also nur Werte von -128 bis 
127) zugewiesen wurde.

Gibt es noch einen anderen Punkt an dem man den Fehler vielleicht finden 
würde?

von PROgrammer (Gast)


Lesenswert?

Vielleicht noch eine Ergänzung:
Das ich, wie oben angeregt, die Zeilen:"TIMSK = 
(1<<OCIE1A)^(1<<OCIE1B);"(Zeile 55) und "TIMSK = 
(1<<TICIE1)^(1<<OCIE1A);        // enable tx and wait for start"(Zeile 
75) in Klammern setze hat kein Unterschied gebracht.
Auch das Verschieben des Zurücksetzen des Flag in die folgende 
If-Schleife("TIFR = 1<<OCF1B;  // clear pending interrupt"(Zeile 52)) 
bringt kein Unterschied
Vielleicht hilft das ja noch weiter, auch wenn ich das nicht glaube, ich 
habe gerade die folgende Warning-Meldung in meiner Ausgabe gefunden: 
"cc1plus.exe: warning: command line option "-std=gnu99" is valid for 
C/ObjC but not for C++"


DANKE, dass ihr mir immer so schnell antwortet

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Irgend wann einmal, wenn man schon mehrere Wochen rein gesteckt hat, 
hätte es sich gelohnt gleich einen für die Aufgabe "richtigen" µC zu 
verwenden.
z.B. STM32F427 hat 8 UART's drin ... und noch vieles mehr.
Artikel: STM32

: Bearbeitet durch User
von PROgrammer (Gast)


Lesenswert?

Es lag mal wieder nicht an dem Code für die Software UART, mein 
Computerprogramm enthielt den Fehler. Jetzt bin ich aer fertig und danke 
euch allen nochmal

Justus

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.