Hallo Zusammen,
ich bastele mir gerade einen einfachen Logik-Analyser auf Basis eines
AtMega2560.
Ziel ist es, das PINC-Register in einem konstanten Intervall von 1
Mikrosekunde mittels des USARTs an den PC zu schicken, wo die Daten
geloggt werden. Nun stellt sich die Frage, wie ich sinnvollerweise
hierbei vorgehen könnte.
Meine Idee zur Umsetzung ist im untenstehenden Code zu erkennen. Mittels
Timer 1, der im CTC-Modus bei 1 MHz betrieben wird, soll der
TIMER1_COMPA-Interrupt ausgelöst werden, innerhalb dessen ISR das
PINC-Register über den USART an den PC gesendet wird.
Verwende ich die auskommentierte Variante, d.h. werden die Daten so
schnell wie möglich versendet (immer wenn das Sende-Register leer ist),
funktioniert alles problemlos. Allerdings habe ich Probleme mit dem
unten stehenden Code, d.h. der Kombination aus Timer und USART. Es
kommen hierbei einfach keine Daten am PC (Putty) an.
Sieht zufällig jemand meinen Fehler? Oder habt ihr grundlegend andere
Vorschläge, wie man Daten in einem festen Zeitintervall von 1 us über
den USART zu verschicken könnte?
Vielen Dank schonmal!
Beste Grüße
Lukas
1
constfloatsample_rate=1000000;// [Samples per sec.]
Bei der Datenrate von 1 MBit und zwei Stopbits dauert die Übertragung
eines Bytes 11µs, da wirst Du wohl kaum jede µs ein neues Datenbyte
verschicken können!
Lukas Bommes schrieb:> ich bastele mir gerade einen einfachen Logik-Analyser auf Basis eines> AtMega2560.
Du weißt, dass es von Cypress den CY7C68013a gibt und der einen
wunderbaren, einfachen 8-Bit Logik-Analyser mit 24MHz Abtastrate abgibt?
Bei ebay gibt es den Chip fertig im Gehäuse für unter 7€ (z.B.
331803014389).
Außer aus sportlichem Ehrgeiz gibt es da eigentlich keinen Grund, einen
ATmega zu quälen, um mal ein paar Bits live auf die Finger zu schauen.
Hallo ihr beiden,
danken für eure Antworten!
@Thomas: Ich hatte nicht bedacht, dass pro Sendevorgang 11 bit
verschickt werden müssen. Somit hast du natürlich vollkommen Recht.
Allerdings erreicht der Mega 2560 damit bei 16 MHz Systemtakt nur knapp
90 KHz Sampling-Rate, was ja nicht so viel ist.
@Wolfgang: Danke für den Tipp! Aber "sportlicher Ehrgeiz" ist das
Stichwort. ;-) So ein Logik Analyzer ist ja ein ganz nettes Projekt, um
mal ein bisschen zeitkritischeren Code zu schreiben.
Aber ich habe noch eine prinzipielle Frage, bei der ihr mir ja
vielleicht weiterhelfen könnt. Und zwar kommt mir meine Lösung über den
Timer etwas unelegant vor. Kann man stattdessen auf Basis der Kenntnis
der Baud Rate von 1 Mbit pro Sekunde und der Größe eines Frames von 11
bit eine exakte Aussage über die Zeit machen, in der in meinem Code oben
das PINC-Register via UART versendet wird? (Bei Verwendung des
USART0_UDRE-Interrupts.)
Sprich, darf ich davon ausgehen, dass alle gesendeten Messpunkte
tatsächlich in einem Abstand von exakt 11 us liegen, oder ist mit
Abweichungen zu rechnen?
Viele Grüße
Lukas
P.S. In meinem Code oben muss es übrigens TIMER1_COMPA_vect statt
TIMER1_COMPA_vec heißen. Daher wurde die ISR auch nicht aufgerufen.
Nein, der Sendepuffer muss ja auch noch gelehrt werden.
Mach dir doch ein einfaches Programm, schick deinen Port direkt über UDR
raus. Prüfe aber vorher ob der Sendepuffer auch leer ist (UDRE Bit im
UCSRA Register). Und mess das ganze mal mit deinem Oszi nach.
Lukas Bommes schrieb:> Aber ich habe noch eine prinzipielle Frage, bei der ihr mir ja> vielleicht weiterhelfen könnt. Und zwar kommt mir meine Lösung über den> Timer etwas unelegant vor. Kann man stattdessen auf Basis der Kenntnis> der Baud Rate von 1 Mbit pro Sekunde und der Größe eines Frames von 11> bit eine exakte Aussage über die Zeit machen, in der in meinem Code oben> das PINC-Register via UART versendet wird? (Bei Verwendung des> USART0_UDRE-Interrupts.)
Natürlich. Da die USART double-buffered ist, kann man einen
kontinuierlichen Datenstrom mit Vmax darüber verschicken. Jedes Byte
wird dann exakt in dem Abstand versandt, der durch Bitrate und Bitzahl
der Frames vorgegeben ist. Das gilt natürlich nur, so lange nix anderes
(insbesondere konkurrierende längliche ISRs) den Ablauf stört und der µC
deshalb nicht dazu kommt, schnell genug Daten nachzuliefern...
Übrigens: Wenn die einzige Aufgabe des Gerätes die Sache sein soll, die
Eingabe eines 8Bit-Port per USART zu versenden, ist ein Mega2560
natürlich massiv überdimensioniert, dafür reicht dann auch ein Tiny2313
völlig aus.
Und man braucht dann auch keinen Interrupt, dann ist es wesentlich
effizienter, die Sache in einer kleinen Endlosschleife in main()
abzuwickeln. Es entfällt dann nämlich der Interrupt-Overhead, der gerade
bei einem Mega2560 sogar deutlich grosser als bei den meisten anderen
AVR8 ist (wegen des 22Bit-PC).
> tatsächlich in einem Abstand von exakt 11 us liegen
Warum eigentlich 11µs? Bei 8N1 wären es 10. Die runde Zahl kommt
irgendwie viel cooler.
Also mich würde es extrem stören wenn ich bei einem Logikanalyzer keinen
Trigger hätte ;-) Ansonsten ist das ganze nämlich bloß nen 8 Kanal /
1Bit Oszilloskop - eben auch ohne Trigger.
Draco schrieb:> Also mich würde es extrem stören wenn ich bei einem Logikanalyzer keinen> Trigger hätte
Mich auch. Aber was hat das jetzt mit dem Thema des Threads zu schaffen?
Draco schrieb:> Also mich würde es extrem stören wenn ich bei einem Logikanalyzer keinen> Trigger hätte ;-)
Der Trigger kann doch auf dem empfangenden PC Laufen. Der µC streamt nur
fortlaufend die Daten.
Wolfgang schrieb:> Der Trigger kann doch auf dem empfangenden PC Laufen. Der µC streamt nur> fortlaufend die Daten.
Das hat außerdem den Vorteil, daß man auch sehen kann, was kurz vor dem
Triggerzeitpunkt passiert ist!
Man sollte mit einem Tracebuffer auf dem Mega arbeiten. Dort waehrend
dem Trigger erwarten in einen ringbuffer aufzeichen, und erst
uebertragen wenn der Trigger gekommen ist und der Tracebuffer die
gewuenschten Daten enthaelt.