Ne UART mit ein paar Bytes Puffer ist doch ganz praktisch, nimmt ne
ganze Menge Streß aus der Mainloop.
Hier mal mit der Software-UART kombiniert, für die schnuckeligen ATtinys
(Beispiel mit ATtiny44).
Oder als 2.UART für nen ATmega328P.
Statt dem ICP kann man auch einen externen Interrupt nehmen
(ATtiny25..85).
Peter
@ Peter
Ich habe den Code auf meinem ATtiny44 ausprobiert, aber leider
funktioniert er nicht so gut.
Der Code wird irgendwie langsamer ausgeführt als sonst. Die
"delay-funktion" lässt eine LED ca. 10mal länger blinken als in einem
einfachen main.c .
Die Daten die ich auf der UART sehe sind dem entsprechend auch nur wirr.
ICh betreibe den Controller mit den 8Mhz vom internen Osz. ( ...denke
ich, denn ich habe die fuses nie geändert und avr-studio zeigt es so
an.)
Gleichzeitig bin auf der Suche nach einer anderen Portbelegung. Ich muss
die RX und TX Leitungen auf anderen Pins haben. Auch bei deinen anderen
Soft-UARTS verwendest du immer die gleichen. Wie kann ich diese Belegung
ändern?
Es wäre schön, wenn du mir etwas Starthilfe geben könntest.
Danke
Sabine schrieb:> Der Code wird irgendwie langsamer ausgeführt als sonst. Die> "delay-funktion" lässt eine LED ca. 10mal länger blinken als in einem> einfachen main.c .
Kann es sein, dass die LED exakt 8 mal langsamer blinkt?
> Die Daten die ich auf der UART sehe sind dem entsprechend auch nur wirr.> ICh betreibe den Controller mit den 8Mhz vom internen Osz. ( ...denke> ich, denn ich habe die fuses nie geändert und avr-studio zeigt es so> an.)
Ich nehme mal an, dass der ATTiny nur mit 1MHz statt 8MHz läuft. Dafür
ist die CKDIV-Fuse zuständig, siehe auch:
http://www.engbedded.com/fusecalc/
Gruß,
Frank
Danke für den Hinweis mit dem CKDIV.
Du hattest Recht im Auslieferungszustand steht er zwar auf 8MHz aber der
Vorteiler ist auch gesetzt.
Mein Problem ist damit so recht immer noch nicht gelöst.
Wie kann es sein,das der folgende Code in einem einfachen MAIN die LED
eine halbe Sekunde blinken läßt. Wenn ich die Zeilen aber in die Main
aus Peters Code einfüge, blinkt sie 5 sekunden.
1
PORTA|=(1<<PA3);//rot einschalten
2
_delay_ms(500);// verzögerung
3
PORTA&=~(1<<PA3);
Dazu kommt noch erschwerend, dass ich doch die RX-TX auf anderen Pins
brauche. Wenn du mir da auch noch einen Tip geben könntest, wäre ich dir
sehr dankbar.
Ich bins schon wieder.
Denn fehler mit den unterschiedlichen Zeiten habe ich gefunden.
Peter schreibt ich seiner MAIN.H:
1
#define XTAL 11.0592e6
2
#define BAUD 57600
3
#define F_CPU XTAL
F_CPU wird wiederum für die "delay" verwendet ... und das sind
eigentlich nun mal nur 1MHz.
F_CPU hatte ich in meinen Test-Programm nicht definiert....
Die 500ms, die "delay" produzieren soll, stimmen aber auch nicht.
Es sind 860ms.
Kannst du mir das bitte erklären?
Sabine schrieb:> Die 500ms, die "delay" produzieren soll, stimmen aber auch nicht.> Es sind 860ms.> Kannst du mir das bitte erklären?
Nein, kann ich leider nicht. Wie hast Du denn nun XTAL resp. F_CPU im
Programm eingestellt?
Wenn Du das folgendermaßen änderst:
#define XTAL 8.0e6
dann sollte Dein delay richtig laufen.
Läuft der interne Takt nun mit 8MHz, d.h. Du hast die CKDIV-Fuse
korrigiert?
Und wie hast Du die 860ms gemessen?
Beachte auch, dass Du eine identische F_CPU-Definition in allen
Source-Modulen verwendest, am besten setzt Du F_CPU im Projekt und
löscht Peters eigene Definitionen von XTAL und F_CPU.
Gruß,
Frank
Sabine schrieb:> Gleichzeitig bin auf der Suche nach einer anderen Portbelegung. Ich muss> die RX und TX Leitungen auf anderen Pins haben. Auch bei deinen anderen> Soft-UARTS verwendest du immer die gleichen. Wie kann ich diese Belegung> ändern?
Peter nutzt den sog. ICP-Pin des Tinys und den dazugehörenden Interrupt.
Um einen anderen Pin zu verwenden, musst Du einen anderen externen
Interrupt verwenden. Ich weiß jetzt aber nicht, ob der ATTiny44 weitere
Interrupts auf den anderen Pins bietet, habe noch nie mit dem ATTiny44
gearbeitet bzw. mir das Datenblatt dazu angeschaut.
EDIT:
Habe gerade mal ins Datenblatt geschaut, es sagt: "External Interrupt
Sources: Pin Change Interrupt on 12 Pins". Das heisst, Du kannst fast
jeden Pin verwenden, Du musst dann aber die ISR auf den Pin Change
Interrupt umstellen.
Eine andere Möglichkeit, einen Soft-Uart zu implementieren, ist die
Verwendung eines Timer-Interrupts und dazugehörendes Polling. Das geht
aber mit Peters Code nicht - jedenfalls nicht mit dem Code aus diesem
Thread.
Tante Google mit folgenden Suchwörtern
software uart avr timer
sollte dazu noch mehr sagen können.
Gruß,
Frank
Noch eine Ergänzung: Einen Soft-Uart zu implementieren ohne
angeschlossenen Quarz kann in die Hose gehen. Der interne Oszillator ist
nicht sehr genau und insb. auch temperaturabhängig. Bei zu großen
Abweichungen der realen Taktfrequenz kann es zu Übertragungsfehlern
kommen - jedenfalls bei höheren Baudraten.
Bei 8MHz würde ich mich nicht trauen, mehr als 9600Bd zu verwenden -
jedenfalls bei einem HW-Uart. Bei einem Soft-Uart könnten die 9600Bd
auch schon zu viel sein, muss man ausprobieren.
Gruß,
Frank
Wenn Du keine >=11MHz nimmst, könnten 57kB Probleme bereiten.
Nimm also ne entsprechend kleinere Baudrate, z.B. 9600.
> Die 500ms, die "delay" produzieren soll, stimmen aber auch nicht.> Es sind 860ms.> Kannst du mir das bitte erklären?
Delay ist keine Uhr. Wenn Du genaue Zeiten brauchst, nimm nen Timer.
Delay zählt einfach nur Befehle, d.h. jeder Interrupt verlängert es um
seine Ausführungszeit.
Peter
@ Frank
Die F_CPU habe ich als define in der main.h neu festgelegt und die
definitionen von Peter habe ich entsorgt. (auskommentiert)
Sollte doch gehen. (oder)
Ja, die CKDIV-Fuse habe ich jetzt auch korrigiert.
Die 860ms habe ich mit einem Scope gemessen.
Die baudrate habe ich schon reduziert auf 4800.
Tja, und das mit den Schwankungen bei dem internen Oszillatorhabe ich
als harmlos eingestuft, da ich den Controller sowieso immer bei
Raumtemp. betreiben will.
Das mit den RX-TX-Pins ist so mein Problem, den Peter benutzt 3
Interruptroutinen:
1
ISR(TIM1_CAPT_vect)// start detection
2
ISR(TIM1_COMPB_vect)// receive data bits
3
ISR(TIM1_COMPA_vect)// transmit data bits
Jetzt ist für mich nicht so ganz klar, welcher Interrup für was
zuständig ist.
... und laut Datenblatt, haben zwar einige Pins einen Interrupt, aber
ich kann Sie in der Tabelle nicht finden. Da gibt es nur PCINT1 und
PCINT2.
Wo bekomme ich denn den passenden Vector für PCINT1 und PCINT5 her?
@Peter
Könntest du bitte mal kurz nennen an welchen Stellen ich drehen muss, um
RX auf PA5 und TX auf PA1 zu haben. (... das in main.h ist klar, das
leuchtet sogar mir ein. Aber in uart.c wird es schwieriger.)
Ich denke das es für einen fortgeschrittenen Coder etwas leichter ist
den Code zu lesen wie eine "Matrix". Aber dazu sehe ich mich noch nicht
in der Lage.
Das die "delay" durch Interrupts länger wird leuchtet mir ein. Aber Sie
ist konstant 860ms, auch wenn ich nur einen Pin mit dieser Funktion
kippen lasse.
Könnte das schon ein Hinweis auf den sehr ungenauen internen Oszillator
sein?
So, ich habe es geschafft.
Ich kann nun mit dem internen Oszilator bei 4800Bd senden.
Empfangen habe ich noch nicht getestet.
Leider will es mir nicht gelingen den TX-Pin umzuverlegen.
In der main.h (nd auch in der uart.c) habe ich folgende zeilen ergänzt:
1
#define NEU_STXD SBIT( PORTA, PA1 ) //
2
#define NEU_STXD_DDR SBIT( DDRA, PA1 )
und in der suart.c bei jedem:
1
TX_OUT=TX_HIGH;
noch ein
1
PORTA|=(1<<PA1);//High
bzw bei
1
TX_OUT=TX_LOW;
2
PORTA&=~(1<<PA1);//Low
Ich verstehe es nicht denn der PA1 bewegt sich garnicht. Dabei sollte
doch der TX nun auf beiden Pins vorhanden sein. (oder?)
Es wäre schön, wenn da jemamd was zu sagen könnte.
Hallo,
hab den Softwareuart zum laufen bekommen...
Verwende AVR Studio (WinAVR) + Atmega48... 16Mhz cyristal
Musste nur alle interruptvectoren umbennenen... also aus TIM1_ ->
TIMER1_ machen
Danke für den Quellcode... kombiniert mit deinem Bootloader muss ich
fast nie mehr den RS232 Stecker am STK 500 umstecken :)
Hallo,
ich möchte den attiny861 mit diesen Code verwenden, leider fehlt mir
noch die Erfahrung eine Anpassung durch zu führen.
Wer kann Helfen ?
Im Zielcode sind:
* OCR1A, OCR1B, bzw. die Pins PB1, PB3 belegt und geben ein Audio PWM
Signal aus.
* Eine SD Karte ist über PB0 (CS), PA0 (DataIn), PA1 (DataOut) und PA2
(Clk) angeschlossen.
* Der attiny861 läuft mit dem internen 8MHz Takt.
* PB4 - PB6 und PA3, PA4 - PA7 können für den "Software UART" verwendet
werden.
Hallo.
Erstmal danke für den super SoftUART.
Hab ihn für nen ATmega32 modifiziert und bei 16MHz vom internen Oszi und
57600 Baud laufen die ersten Versuche ohne Probleme.
Jetzt habe ich aber doch noch eine Schwierigkeit.
Ich schaffe es nicht mit uputchar() ein einzelnes Zeichen zu senden.
uputs("Hallo Peter \n\r") wie in der Test main.c läuft. Ich schaue mir
den output via TeraTerm an.
Vielleicht kann mir ja jemand einen Tip geben.
Gruß Sebastian
Von Sabine:
>Das die "delay" durch Interrupts länger wird leuchtet mir ein. Aber Sie>ist konstant 860ms, auch wenn ich nur einen Pin mit dieser Funktion>kippen lasse.>Könnte das schon ein Hinweis auf den sehr ungenauen internen Oszillator>sein?
Wenn das delay ohne die Interrupt-Funktionen im Hintergrund korrekt
läuft, wird das Problem nicht vom Oszillator verursacht.
Auch wenn je nach Situation verschieden große Teile des Interrupt-Codes
ausgeführt werden, so vermute ich dass die Prologe und Epiloge der
Interruptroutinen so lang sind, dass sich verschieden lange
Codeabschnitte innerhalb der Routinen zeitlich gar nicht bemerkbar
machen.
//OT:
Ich bin eh kein Freund der mitgelieferten Delay-Funktion
Wenn ich die Chance habe, nutze ich meine eigene und greife dafür auf
einen der Timer zurück. (In den meisten Fällen ist es sogar möglich auf
einen bereits genutzten Timer aufzusatteln ;)
Auf diese Weise ist es sogar möglich nicht-blockierende Delays zu
nutzen, also während der Wartezeit mit etwas anderem weiterzumachen!
//!OT
EDIT: hahahaaa, man sollte mal aufs Datum gucken...
Hy zusammen,
Ich bin ein anfänger in sachen coden.
Ich versuche gerade den code auf den Attiny13 umzuschreiben, der erfolg
hält sich aber in grenzen, bekomme fehler meldungen die ich nicht
verstehe, es geht um DDRA und PORTA
=> ../MAIN.C:21: error: 'DDRA' was not declared in this scope
=> ../MAIN.C:23: error: 'PORTA' was not declared in this scope
Wie bekomme ich die felher weg und könnt ihr mir vieleicht erklären wo
her die PORTS kommen, denn der attiny45 hat doch ur PB0-PB5.
und wenn ich die DDRA und PORTA auskommentiere bekomme ich 5 meldung
=>../SUART.C:105: error: 'PINA' was not declared in this scope
damit ihr wiesst wie ich vorgegangen bin, habe den codes geladen
compeliert (48errors), und der code ist für timer1 geschrieben habe
alles auf timer0 geändert und die register angepasst.
aus
#define STXD SBIT( PORTA, PA6 ) // = OC1A
#define STXD_DDR SBIT( DDRA, PA6 )
#define SRXD_PIN SBIT( PINA, PA7 ) // = ICP
habe ich gemacht
#define STXD SBIT( PORTB, PB4 ) // = OC1A
#define STXD_DDR SBIT( DDRB, PB4 )
#define SRXD_PIN SBIT( PINB, PB5 ) // = ICP
komme dann auf 11 warnung, laufen tuts trozdem nicht :(
hat das einer schon mal von euch gemacht den code für attiny13 geändert?
mfg Lucky
aso, aber ei OC1A, kann ich denn den nicht nehmen? das es nicht leicht
wierd habe ich leider auch schon gemerkt :( kennt ihr eine alternative
für den attiny13 daten an den pc zu schiecken?
Lucky schrieb:> Ich bin ein anfänger in sachen coden.> Ich versuche gerade den code auf den Attiny13 umzuschreiben, der erfolg> hält sich aber in grenzen, bekomme fehler meldungen die ich nicht> verstehe, es geht um DDRA und PORTA
Es beißt sich etwas, wenn man wenig Ahnung von C hat und dann gleich
Beispiele auf den kleinst möglichen MC portieren will.
Versuch erstmal, das Beispiel auf dem genannten Typ laufen zu lassen
oder wenigsten auf einem mit ICP.
Also immer einen Schritt nach dem anderen machen. Wenn man beide Beine
gleichzeitig hebt, fällt man um.
Peter
Hallo,
erst mal danke an Peter für die kleine Lib !
Ich habe sie mir für den atMegax8 angepasst und konnte erfolgreich einen
Datenstrom mit 57600 Baud 8,n,1 versenden.
Die angehängten Quellen habe einige Defines um die Sende- von der
Empfangsroutine auch getrennt nutzen zu können.
Zu meiner Anwendung auf der Hardware Usart0 empfange ich einen
Datenstrom, denn ich nach Datenanalyse umformatiert mit der Software
Uart ausgebe.
Beide Libs könnte ihr in dem Anhang finden, viel Erfolg.
Fred Granna schrieb:> CodeRudi schrieb:> Wie ist bei dir eigentlich der Stand?
Tja, seit nem halben jahr läuft hier eine Bastellösung:
Atmel-Arduino mit einem externen UART (per i2c). Telegramme lesen und
anmelden am System (registriert sich als Servicekey an der Heizung)
laufen.
Will aber grad weg davon. Der Uart macht nur ärger.
Habe mir heute einen Atmel mit 4 Uarts besorgt und spiele grad mit
deinem c-code rum. Leider ist dort nur der Empfangsteil drin und nicht
der Sender. Stehe da grad komplett auf dem schlauch wie ich daten in den
Bus pumpen soll...
Hallo
ICh möchte das gerne auf einem ATTiny2313 zum laufen bringen
Nachdem ich nun alle TIMSK1 durch TIMSK ersetzt habe (und sonstige auch)
lässt sich das teil nun kompilieren.
Habe uach die Ports umgelegt auf
#define STXD SBIT( PORTB, PB3 ) // = OC1A
#define STXD_DDR SBIT( DDRB, PB3 )
#define SRXD_PIN SBIT( PIND, PD6 ) // = ICP
Also sollte dann von OC1A und ICP wieder gleich sein.
Allerdings habe ich das problem, das er mir hängen bleibt
TIMSK = 1<<ICIE1^1<<OCIE1A; // enable tx and wait for start
zumindest blinkt mir meine LED nicht mehr, wenn ich diese Zeile im
suart_init drinnen lasse, sobald ich die auskommentiere, dann blinkt
meine led wieder ...
an was kann es noch liegen?
Hat wer einen code für den 2313?