Hallo Forum,
ich habe ein Problem mit der im Betreff stehende Sache. Ich möchte
innerhalb der ISR des Timers1 des Atmega32 gern einen per SPI
ausgelesenen Wert von einem Sensor mittels eines Pointers in ein Array
schreiben. Zum Verständnis ein wenig Code:
Signal(SIG_OUTPUT_COMPARE1)
{
getaccl(); //Werte aus dem Sensor auslesen
*pdata= Werte; //Die ausgelesenen Werte mittels Pointer dem array
zuweisen
}
Nun erstmal die Hauptfrage: Geht das einfach so? Ich habe es natürlich
schon probiert und es geht bei mir nicht. Ich weiß aber nicht woran es
liegt. Zeitkritisch ist es nicht, da der Interrupt nur alle 30ms
aufgerufen wird. Wenn ich das Zuweisen der Werte weglasse und
stattdessen noch aufwendige Funktionen in der ISR aufrufe, macht er das
auch ohne Probleme. Also nochmal, weiß jemand, warum er bei dem
Wertezuweisen Probleme hat?
Gruß,
Marian
Klaus Peter wrote: > schreiben. Zum Verständnis ein wenig Code: > Signal(SIG_OUTPUT_COMPARE1) > { > getaccl(); //Werte aus dem Sensor auslesen > *pdata= Werte; //Die ausgelesenen Werte mittels Pointer dem array > zuweisen > } > > Nun erstmal die Hauptfrage: Geht das einfach so? Im Prinzip ja. Der Teufel steckt, wie immer, im Detail. Zb. Darin, dass Arrays nicht als Ganzes zugewiesen werden können etc. > Ich habe es natürlich schon probiert und es geht bei mir nicht. Dann hast du einen Fehler gemacht. > Ich weiß aber nicht woran es liegt. Wir auch nicht. Es ist nur so, dass du uns gegenüber einen Vorteil hast: Du siehst deinen konkreten Code, wir nicht. Wenn überhaupt, dann kannst also nur du deinen Fehler finden. Oder aber du zeigst deinen richtigen Code her, dann können auch wir den mal durchstöbern.
Gast
#519637
@Klaus Peter >schreiben. Zum Verständnis ein wenig Code: >Signal(SIG_OUTPUT_COMPARE1) >{ > getaccl(); //Werte aus dem Sensor auslesen > *pdata= Werte; //Die ausgelesenen Werte mittels Pointer dem array Das ist so oder so Quark. entweder pdata[index] = Wert; // EIN einzelner Wert oder *(pdata+index) = Wert; >Nun erstmal die Hauptfrage: Geht das einfach so? Ich habe es natürlich Ja, aber wie bereits von Karl Heinz gesagt, die Details sind der Knackpunkt. 1.) Dass Array muss global und volatile definiert sein volatile uint8_t pdata[10]; 2.) Du musst die einzelnen Elemente einzeln zuweisen, ggf. über ne Schleife. >schon probiert und es geht bei mir nicht. Ich weiß aber nicht woran es >liegt. Zeitkritisch ist es nicht, da der Interrupt nur alle 30ms >aufgerufen wird. Wenn ich das Zuweisen der Werte weglasse und Na dann sollte aber das Auslesen per SPI weniger als 30ms dauern. MFG Falk
Ok, dann hat sich meine Hauptfrage ja erledigt, es muss also gehen. Da ich nicht den vollständigen Code hier zeigen darf, werde ich versuchen alles nötige darzustellen.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
So ich hoffe, dass dieser Ausschnitt schon reicht. Die verwendeten Funktionen funktionieren soweit alle, das alte Programm ansich läuft auch schon seit einiger Zeit. In diesem Programm habe ich die Werte immer in der main ausgelesen und dann zugewiesen, ohne Probleme. Ich will jetzt "nur" mein altes Programm umbauen, so wie ich es oben beschrieben habe. Leider klappt das nicht so ganz. Sobald ich die Wertezuweisung mittels *pdata einbaue, gibt mir mein Atmega32 seltsame Sonderzeichen per Uart aus. Wenn ich es rauskommentiere, funktioniert alles super. Kann mir, mit dem was ich bis jetzt beschrieb, schon jemand weiter helfen?
Falk wrote:
> 1.) Dass Array muss global und volatile definiert sein
global ja, volatile sehr wahrscheinlich nicht (aber das hängt vom
Rest ab).
Gast
#519690
Wo/Wie wird der Speicher angelegt, auf den pdata zeigt? Liegt das Array in Data, Bss oder im Stack? Besteht die Gefahr, dass die Endgrenze vom Array überschritten wird? Dein Code enthält kein Zurücksetzen von pdata. Was passiert, wenn du die lange Berechnung durch eine kurze Zuweisung ersetzt z.B. *pdata = 42; ?
Achso, ich habe noch vergessen die main zu zeigen.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
Also das Array liegt meines Wissens nach in data. Nein die Grenzen werden nicht überschritten, wie meine vergessene main zeigt :). Hab ich auch getestet. Das mit der einfachereren Zuweisung hatte ich nur so getestet: *pdata = acclx; Ich probiere es mal mit der 42.
Hm sehr interessant. Ich habe gerade die Sache mit *pdata=42; getestet. Nun kann ich keine Verbindung mehr mit dem Controller herstellen, das Programm bleibt sofort hängen, die LED, die eigentlich nach einer Sekunde ausgeht, leuchtet ständig. Wenn ich *pdata=acclx; schreibe, kann ich mich wieder vebinden aber die Sonderzeichen sind anders als bei der oben genannten Zuweisung.
>Also das Array liegt meines Wissens nach in data. Nein die Grenzen >werden nicht überschritten, wie meine vergessene main zeigt :). Hab ich >auch getestet. Das mit der einfachereren Zuweisung hatte ich nur so >getestet: *pdata = acclx; Die Arraygrenzen werden sehr wohl überschritten, sobald aus Deinem Testprogramm ein "richtiges" main wird: Wenn main mal länger beschäftigt ist als Deine 30ms UND während dieser Zeit der Pointer > &dataraw[SIZE] wird, überschreibst Du den Speicher hinter dem Array. Und noch schlimmer: weil Du in main auf pdata == &dataraw[SIZE] testest, wird Dein main() diesen Überlauf nichtmal bemerken, Dein koompletter Speicher wird ab diesem Zeitpunkt sukzessive zugemüllt. Deshalb: Den Pointer immer an der Stelle testen, wo er auch verändert wird, also in Deinem Fall in der ISR. Und: Nie auf ==, sondern auf >= testen. Stefan
Ok danke für den Hinweis, daran hatte ich noch nicht gedacht. Ich habe es nun geändert, aber an meinem Problem hat sich nichts getan, er verhält sich immer noch genau so.
Gast
#519786
int index=0; // global
SIGNAL(SIG_OUTPUT_COMPARE1)
{
if (zeitgeber==30)
{
getaccl(); //Auslesen der Beschleunigungswerte
dataraw[index]=(acclx*acclx) + (accly*accly) + (acclz*acclz);
//Zuweisen der Beschleunigungswerte
index++;
if (index >= SIZE) index=0;
zeitgeber=0;
}
else
{
zeitgeber++;
}
}
Gast
#519789
Ähhh, du musst erst ALLE Variablen (und vor allem deinen Pointer) initialisieren, bevor du die Interrupts freigibst. Ich nehme an, dass Timerinit1(); //Timerinitialisierung des Timers1 den Timer initialisiert und freigibt. Allerdings wird dein Pointer erst nach einer Sekunde LED Blinken initialisiert! pdata=&dataraw[0]; Es muss definiv umgekehrt sein. MFG Falk
SUPER! Genau das war der Knackpunkt, danke Falk. Ich habe jetzt den Pointer gleich als erstes initialisiert und nun macht er alles, wie ich es will. Endlich...nochmals vielen dank! Gruß, Marian
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.