hallo,
ich stehe bei einem Programmierproblem total auf dem Schlauch.
In einem C Programm (Atmega 328P über ISP mit AtmelStudio 6) speichert
mir mein Programm einfache Arraywerte falsch und ich find den Fehler
nicht!
eigentlich lasse ich nur über diese Billo-Funktion:
void fill_pwm_values()
{
for (uint8_t j = 0; j < 16; j++)
{
pwm_values[j] = 100;
}
}
ein array beschreiben, welches global so
uint16_t pwm_values[16];
definiert ist.
Genutzt wird das Array dann so:
void create_pwm_values_for_spi()
{
uint8_t counter = 0;
fill_pwm_values();
for (uint8_t i = 0; i < 16; i += 2)
{
pwm_values_for_spi[counter] = ((pwm_values[i] & 0x0ff) >> 4);
pwm_values_for_spi[counter+1] = ((pwm_values[i] & 0x0f) << 4) |
(pwm_values[i+1] >> 8);
pwm_values_for_spi[counter+2] = (pwm_values[i+1]) << 8;
counter += 3;
}
}
Lasse ich mir jetzt über die watch die Werte anzeigen, zeigt er mir
irgendwelche 16bit Werte an (pwm_value[0] = 50197, pwm_value[1] = 287,
pwm_value[2] = 8224, pwm_value[3] = 0, pwm_value[4] = 7876 ...)
Wenn ich meine Funktion einzeln in ATMEL-Studio teste, zeigt mir die
watch die richtigen Werte an. Was ist denn da los? Die Werte ändern sich
auch dauernd. Im Anhang mein Test-Code, es muss irgendwie an dem liegen,
aber ich find den Fehler nicht.
Ist bisher nur Testcode, es speichert eigentlich nur ein 16-bit-Array,
zerlegt die 16bit-Werte SPI-kompatibel in 8bit und sendet diese an den
TLC.
Über den Timer wird ein Takt erzeugt und mitgezählt, brauch ich für die
Ansteuerung des TLC5940. Ob das alles schon so funktioniert weiß ich
nicht, weil ich ja schon vorher stecken bleibe...
Danke für etwaige Hilfe,
c.
blinksdinks schrieb:> pwm_values_for_spi[counter+2] = (pwm_values[i+1]) << 8;
Mit pwm_values[i+1] greift Du bei i == 15 hinter Dein Array, was schon
mal nicht stimmen kann.
Edit: OK, sehe gerade, dass Du in der Schleife immer um 2 hochzählst und
die Schleife somit nur bis 14 zählt.
sorry fürdie blöde formatierung oben, hier besser:
void create_pwm_values_for_spi() {
uint8_t counter = 0;
fill_pwm_values();
for (uint8_t i = 0; i < 16; i += 2)
{
pwm_values_for_spi[counter] = ((pwm_values[i] & 0x0ff) >> 4);
pwm_values_for_spi[counter+1] = ((pwm_values[i] & 0x0f) << 4) |
(pwm_values[i+1] >> 8);
pwm_values_for_spi[counter+2] = (pwm_values[i+1]) << 8;
counter += 3;
}
}
Der TLC5940 ist ein 16Kanal-PWM-IC, er hat 16 12-bit-PWM-Kanäle. Ich
zerlege mit dieser Funktion meine 12bit-Werte (gespeichert als 16bit) in
8-bit-Werte und sende diese Über SPI. Diese Zerlegefunktion funktioniert
auch im Test.
Olly T. schrieb:> Mit pwm_values[i+1] greift Du bei i == 15 hinter Dein Array, was schon> mal nicht stimmen kann.
deswegen läuft i aber nur bis 14...
Problem gelöst!
Jim M. schrieb:> Was glaubst Du das diese Zeile macht? Die ist falsch, Du wolltest hier> vermutlich> pwm_values_for_spi[counter+2] = (pwm_values[i+1]) & 0xFF;>> schreiben.
Danke für den Hinweis, vielleicht wollte ich das wirklich so schreiben
;-)
War aber nicht die Ursache.
Dieter F. schrieb:> "schwurbelst" Du da hin:>> https://de.wikipedia.org/wiki/Byte-Reihenfolge
An sowas dachte ich auch, aber es ist eine ISR, die mir dazwischenfunkt.
Oder der Timer. Würde mich freuen, wenn mir jemand erklären könnte,
warum dem so ist:
Ich erzeuge mir einen Takt über Timer0 für den TLC5940. Der braucht nen
Takt für die Erzeugung seiner PWM; Nach 4096 Takten muß man den IC
einmal toggeln. Eigentlich wollte ich den Takt über Compare Match Mode
machen, habs dann aber über Fast-PWM gemacht. Ich lege TOP und Compare
Match fest und krieg so meinen 50%Duty-Cycle. In einer ISR zähle ich den
Takt mit.
Ich wollte den Tak so schnell wie möglich machen und hab deswegen als
TOP einfach mal 15 und Compare Match auf 7 gesetzt. Und das zerhaut mir
die Speicherung meiner Variablen. Lege ich den Top-Wert auf 63 und
Compare Match auf 31, läuft alles wie gewünscht, also in meinem Array
sind meine Werte und nicht irgendein Quatsch.
Oder hab ich da nen Programmierschnitzer? Bin noch recht neu auf dem
Gebiet, teste gerade mit den Timern rum und es bereitet mir schon auch
Probleme, dass alles zu verstehen - und umzusetzen! Also falls es eher
mit meinen Code als mit einer Überforderung des Atmegas zu tun hat,
würde ich mich freuen, wenn sich jemand nochmal den Code anschaut, ob
der Timer oder die ISR irgendwie blöd sind. Habe ihn deswegen nochmal
überarbeitet angehängt. Ob die Ansteuerung des TLC5940 jetzt
funktioniert kann ich grad nicht testen, weil Aufbau nicht hier, aber
ist für die Frage mit dem wirren Speichern der Variablen ja auch egal.
Danke für die ganzen Hinweise bisher! Schöne Nacht euch allen!
blinksdinks schrieb:> Ich wollte den Tak so schnell wie möglich machen und hab deswegen als> TOP einfach mal 15 und Compare Match auf 7 gesetzt. Und das zerhaut mir> die Speicherung meiner Variablen.
Dürfte das sei im zusammenhang mit dem zu knappen Timing sein. Das
enabled den Interrupt bevor die Aufräumarbeiten des Stacks fertich sind
-> Stack overflow.
Man sollte auch daran denken dass da signifikant Zyklen zum Sichern und
Wiederherstellen von Registern nötig sind - 15 Clocks sind für die ISR
deutlich zuwenig.
Danke Jim für die Erläuterung... Es freut mich immer sehr, wenn Leute
dieses Forum sich die Zeit für sowas nehmen.
Ach, diese Mikrocontroller. Es ist zwar -wenn man sich alles selbst
beibringt - saukompliziert, aber es macht auch dolle Spaß sich die
Architektur der kleinen Biester zu erarbeiten! Als nächstes kommt dann
jetzt wohl der stack, dann weiß ich bald endlich was der berühmte stack
overflow ist! Und mit dem Timing und der Antsteuerung des TLC hab ich
grad auch noch zu kämpfen, aber diese Geschichte wird in einem
Extrathread weitergeschrieben.
Schönen Sonntag euch allen!