Hallo,
ich habe ein Programm für eine ATmega88 geschrieben, das kontinuierlich
Daten aus mehreren Sensoren ausliest (SPI) und diese via UART versendet.
Gestartet wird der Auslese- und Sendevorgang in dem ich ein t(=transmit)
sende und gestoppt werden soll der kontinuierliche Datenstrom mit dem
senden eines s(=stop).
Die Routinen für den SPI Zugriff sind sehr kurz gehalten und laufen
atomar, d.h. in dieser Zeit sind keine Interrupts erlaubt.
Nach dem auslesen der Sensordaten (Integer), wandel ich diese mit der
itoa()-Funktion aus der stdlib in einen String um und versende dann
anschließend die Daten.
Nun habe ich folgendes Problem, wenn ich keine Pause (7ms) in die
kontinuierliche Schleife einfüge dann bekommt der µC das senden von
s(=stop) nie mit und ich kann den Datenstrom nur durch einen Reset
stoppen. Die 7ms sind mir aber zu lang.
Hat dafür jemand eine Lösung?
Erstmal den Code posten. Du kannst dir noch so viel Mühe mit einer
Beschreibung geben, wir wissen dann trotzdem noch nicht, was genau
dein aktueller Code macht. Eine Beschreibung entspricht schließlich
immer dem, was du denkst oder möchtest, nicht unbedingt dem, was
tatsächlich passiert.
@Karlheinz: wartende Schleifen?
Ich warte halt mit
while( !hal_smb380_new_acc_read( 0x02, &acc_x)){};
darauf, bis der Sensor wieder einen neuen Wert ausgibt
Und die _delay_ms(7);
wurden nötig, da der µC keinen RX-Interrupt mehr angenommen hat.
Die Warteschleifen sind ja nicht unbedingt schlecht, in der Zeit könnte
ja ein RX-Interrupt auftreten und verarbeitet werden, oder?
Hast du einen besseren Vorschlag wie ich das programmieren kann?
Thomas schrieb:
> Hast du einen besseren Vorschlag wie ich das programmieren kann?
Wartende Schleifen sind immer schlecht.
In einem µC funktioniert der Status-Gedanke meistens am besten.
Dein Programm (die Hauptschleife) ist in einem Zustand. Irgendwelche
Ereignisse verändern den Zustand. Aber: Es wird nicht gewartet.
Reaktionen erfolgen nur aus Zustandsänderungen heraus.
Bei dir wäre zb ein Zustand: Daten vom Sensor holen und verschicken -
kurz sampleData, der entweder TRUE oder FALSE sein kann
1
intmain()
2
{
3
unsignedintc;
4
unisgnedcharsampleData;
5
6
...
7
8
9
sampleData=0;
10
while(1){
11
c=uart_getc();
12
13
if((unsignedchar)c=='t')
14
sampleData=1;
15
16
if((unsignedchar)c=='s')
17
sampleData=0;
18
19
if(sampleData){
20
if(hal_smb380_new_acc_read(0x02,&acc_x){
21
itoa(acc_x,buffer_acc_x,10);
22
uart_puts("acc , ");
23
uart_puts(buffer_acc_x);// and transmit string to UART
Hallo Karl-Heinz,
ich hab das Programm jetzt mal umgeschrieben, siehe Dateien im Anhang.
Allerdings mein eigentliches Problem bekomme ich damit nicht gelöst.
Wenn ich das Main-Programm mit dem auskommentierten Bereich in der
Endlosschleife laufen lasse, dann funktioniert das starten der
Übertragung mit dem senden von 't' wenn ich dann ein 's' sende dann
stopt das Programm auch, aber etwas verzögert.
Wenn ich nun den auskommentierten Bereich auch ausführen lasse, dann
kann ich das Proagramm wieder mit 't' starten aber auf das senden von
's' reagiert das Programm nicht mehr, auch nicht verzögert ( ich hab mal
1 Min gewartet). Daten liest das Programm weiterhin aus und sendet diese
auch noch.
Irgendwie habe ich das Gefühl, dass der RX-Interrupt nicht mehr
bearbeitet wird.
Ich würde mal die ganzen CRITICAL_REGION Makros weglassen. Du benutzt
Hardware-SPI, daher können die Interrupts die ganze Zeit über enabled
bleiben.
Wenn du das Gefühl hast, dass der RX-Interrupt nicht mehr angesprungen
wird, dann mach dir in die ISR eine Ausgabe rein. Nein, nicht über UART;
schalte eine LED ein. In der mainLoop setzt du nach jeder Ausgabe die
LED wieder zurück. Wenn du dann Zeichen versendest, müsste die LED
zumindest blinzeln. Dann weißt du, dass die ISR aufgerufen wird.
Hallo,
was ich schon mal probiert habe war, die Makros durch cli() und sei() zu
ersetzen hat aber auch nichts geändert. Ich werde die Makros heute Abend
mal ganz raus machen und schauen ob das was bringt.
Ich habe zwar keine LED (spezielles Board) aber einige Port-Pins habe
ich noch frei. Werde das dann mal mit einem Oszi prüfen.
Könnte es evtl. auch am RS232/USB-Wandler (FT232RL) liegen? Dort
flackern allerdings die beiden RX- und TX-LEDs.
Thomas schrieb:
> Könnte es evtl. auch am RS232/USB-Wandler (FT232RL) liegen? Dort> flackern allerdings die beiden RX- und TX-LEDs.
Häng doch dein Oszi an den Rx Pin vom µC, dann weißt du mit Sicherheit
ob da was ankommt, wenn du die Taste drückst bzw. wieviel Verzögerung
dir der FT232 einbaut.
@Karl-Heinz: Danke schon mal!
Ich hab das Problem jetzt genauer lokalisieren können, es liegt am
USB/Seriell-Wandler (FT232RL). Der FT232RL gibt (bei Baudraten >=9600)
die RX-Daten nicht aus, während er kontinuierlich mit TX-Daten versorgt
wird.
Ob das ein Problem des Chips, des Treibers oder der USB-Geschwindigkeit
(USB 1.0 / USB 2.0) ist konnte ich noch nicht genauer eingrenzen. Für
Vorschläge, wie ich das genauer bestimmen kann wäre ich sehr dankbar.