Hallo. Ich wuerde gerne ueber eine 8bit pwm leds Ansteuern. Mit der 8bit Counter klappt das auch. Nur mit dem 16bit Counter habe ich ein Problem. Ich schreibe die Werte von 0 - 255 in OCR1AL und schreibe 0x00 nach OCR1AH. Die WGM Bits sind folgendermasze gesetzt: WGM13 WGM12 WGM11 WGM10 0 1 0 1 Laut Datenblatt ist das der 8Bit FastPwm Mode, und Top ist 0x00FF. Wenn ich die Werte nun 'von Hand' schreibe: for( uint8_t i=0; i < 256; i++ ) { OCR1AH = 0x00; OCR1AL = i; } klappt das ganze auch gut. Wenn ich die Werte aber aus einer uint8_t Tabelle nehme: table[360][3] = { {0, 4, 0} ..... } }; Wird die Led erst hell, flackert dann einmal kurz und faengt von Vorne an. Hat jemand eine Idee warum die flackert? Die Werte in der Tabelle uebersteigen 255 nicht. Die Tabelle ist wirklich als uint8_t angelegt und auch die Indizierung ist richtig. Die Tabelle enhaelt RGB-Werte die einmal den HSV-Farbraum durchlaufen von 0-360Grad. Grusz Florian
Ich vergasz zu sagen: Ich deaktiviere alle Interrupts bevor ich in das High/Low register schreibe.
Du must nicht das OCR1AH und OCR1AL register getrennt schreiben, OCR1A = DeinWert; tut es auch. und wenn Du das in der ISR machst musst Du auch keine Interrups deaktivieren. for( uint8_t i=0; i < 256; i++ ) ist alte coding style deklariere i vorher und dann nur for( i=0; i < 256; i++ ) bei einem i als uint8_t wird Deine Bedingung (i < 256) immer war sein Ju
> for( uint8_t i=0; i < 256; i++ ) > > ist alte coding style eigentlich nicht. Das ist eigentlich neuer Stil und ist eine Empfehlung es so zu machen. > Hat jemand eine Idee warum die flackert? Die Werte in der > Tabelle uebersteigen 255 nicht. Die Tabelle ist wirklich als > uint8_t angelegt und auch die Indizierung ist richtig. Na denn. Wenn ohnehin alles richtig ist, dann gibt es auch kein Problem. Da es aber ein Problem gibt, wird eben nicht alles richtig sein. Moral von der Geschichte: Anstatt deinen Code zu beschreiben poste ihn lieber! Denn irgendwo hast du einen Fehler, den du selber nicht siehst. Du du ihn selber aber nicht siehst, taucht er logischerweise auch in deiner Prosabeschreibung des Codes nicht auf. Aber abgesehen davon uint8_t table[360][3] = .... das sind 360*3 Bytes. Also 1080 Bytes. Wieviel SRAM hat ein Mega8 noch mal?
Karl Heinz Buchegger schrieb: >> for( uint8_t i=0; i < 256; i++ ) >> >> ist alte coding style > > eigentlich nicht. > Das ist eigentlich neuer Stil und ist eine Empfehlung es so zu machen. > uups, ich hab C vor vielen Jahren mit for( int i=0; i < 256; i++ ) gelernt. Dann musste ich es irgenwann verwerfen weil die Compiler es immer angemeckert haben. Jetzt hab ich mich daran gewoehnt und schon geht es "back to the roots" ? Nach der Aussage von kbuchegg musste ich das natuerlich gleich testen, und er hat recht, mein compiler benutzt -std=gnu99 und er mecker es nicht mehr an. Also dann, Kommando zurueck. Es koente ja langweilig werden. Ju
Juergen G. schrieb: > ich hab C vor vielen Jahren mit > > for( int i=0; i < 256; i++ ) > > gelernt. Da hattest du einen neueren Compiler > Dann musste ich es irgenwann verwerfen weil die Compiler es > immer angemeckert haben. Ältere Compiler. > Jetzt hab ich mich daran gewoehnt und schon geht es "back to the roots" > ? Anders rum. Am Anfang der Zeit galt die Regel: Variablendefinitionen werden an den Funktionsanfang zusammengezogen. Diese Regel wurde irgendwann gelockert zu: Variablendefinitionen können auch innerhalb von Blöcken passieren und werden an den Blockanfang zusammengezogen Danach konnte man die Variablendefinitionen an die Stelle verschieben, an die die Variable das erste mal tatsächlich benutzt wird. Der Weg geht also hin zu: Variablendefinitionen sollen so eng wie möglich und so kurz wie möglich vor der verwendenden Stelle passieren. Das Ziel ist es, den Scope von Variablen möglichst einzuschränken und die Scopegrenzen möglichst eng um die verwendende Stelle legen zu können. Mit etwas Phantasie könnte man sagen: Die logische Fortsetzung der Doktrin globale Variablen sind böse. Und so wie funktionslokale Variablen einen Ausweg aus globalen Variablen darstellen, so sind blocklokale Variablen der Ausweg aus funkions-'globalen' Variablen. Wenn man jetzt noch definiert, dass ein for sich in dieser Beziehung wie ein Block verhält, dann sind wir genau bei der jetzigen Situation. for( int i = 0; i < 10; i++ ) { ... } .... (A) for( int i = 0; i < 10; i++ ) { ... } das sind 2 verschiedene Variablen i. Im Code dazwischen (A) existiert keine Variable i, ein Zugriff darauf ist an dieser Stelle daher illegal. C++ hatte da einen großen Einfluss auf diesen Weg, weil dort die Objektkonstruktion mittels Konstruktor unter Umständen eine teure Operation ist. void foo() { MeineKlasse xyz; if( Operation_gültig ) xyz.Machwas(); } hat das 'Problem', dass xyz auf jeden Fall konstruiert werden muss, selbst wenn es danach überhaupt nicht benutzt wird. Zieh ich das aber in einen Block rein void foo() { if( Operation_gültig ) { MeineKlasse xyz; xyz.Machwas(); } } dann spare ich diese Konstruktionskosten im Fall, dass überhaupt nichts mit dem Objekt gemacht wird. In weiterer Folge hat sich dann herausgestellt, dass diese Vorgehensweise softwaretechnisch nicht schlecht ist und zu einer positiven Codequalität beiträgt. C hat das dann von C++ abgekupfert (genauso wie const).
Okay ich habe den Fehler noch nicht finden koennen und poste hier mal den code. Vielleicht sieht ja jemand was schief laeuft oder woraum ich nicht gedacht habe. Vielen Dank schonmal fuer die bisherigen Antworten.
1 | uint8_t color[360][3] = { *snip* }; |
2 | |
3 | int main( void ) |
4 | {
|
5 | DDRB = 0xff; |
6 | // Init pwm:
|
7 | // FastPwmMode -> ATMEGA8. pwm 8bit -> only 2 16 bit
|
8 | // channels avail and we want to drive 3 leds...
|
9 | // TCCR1A COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
|
10 | // | | | | | | | +--> Waveform Generation Mode
|
11 | // | | | | | | +--------> Waveform Generation Mode
|
12 | // | | | | | +---------------> Force Output Compare
|
13 | // +-------+-----+-----+------+------------------------> CompareMatchModes ASO.
|
14 | // COM sets output compare mode depending on WGM (WaveformGenerationMode)
|
15 | // FastPwm: COM1A1/COM1B1 COM1A0/COM1B0
|
16 | // 1 0 Clear OC1A/OC1B on compare match - set at BOTTOM
|
17 | |
18 | // WaveformGenerationMode
|
19 | // WGM13 WGM12 WGM11 WGM10
|
20 | // 0 1 0 1 Fast PWM 8bit -> TOP(0x00ff) UpdateOCR1x(Bottom) TOV(TOP)
|
21 | |
22 | TCCR1A = 0x00; |
23 | TCCR1A |= ( 1 << COM1A1 ) | ( 1 << COM1B1 ) | ( 0 << COM1A0 ) | ( 0 << COM1B0 ) | ( 0 << FOC1A ) | ( 0 << FOC1B ) | ( 0 << WGM11 ) | ( 1 << WGM10 ); |
24 | |
25 | //TCCR1B: ICNC1 ICES1 xxx WGM13 WGM12 CS12 CS11 CS10
|
26 | // | | | | | | | +--> ClockSelect 1 -+{
|
27 | // | | | | | | +--------> ClockSelect 0 + -> clk/1
|
28 | // | | | | | +---------------> ClockSelect 0 -+{
|
29 | // | | | | +------------------------> WaveformGeneration
|
30 | // | | | +-------------------------------> WaveformGeneration
|
31 | // | +-------------------------------------------> InputCaptureEdgeSelect
|
32 | // +---------------------------------------------------> InputCaptureNoiseCanceler
|
33 | |
34 | TCCR1B = 0x00; |
35 | TCCR1B |= ( 0 << ICNC1 ) | ( 0 << ICES1 ) | ( 0 << 5 ) | ( 0 << WGM13 ) | ( 1 << WGM12 ) | ( 0 << CS12 ) | ( 0 << CS11 ) | ( 1 << CS10 ); |
36 | |
37 | TCCR2 = 0x00; |
38 | TCCR2 |= ( 0 << FOC2 ) | ( 1 << WGM20 ) | ( 1 << COM21 ) | ( 0 << COM20 ) | ( 1 << WGM21 ) | ( 0 << CS22 ) | ( 0 << CS21 ) | ( 1 << CS20 ); |
39 | |
40 | uint16_t k=1; |
41 | |
42 | uint8_t r=0; |
43 | uint8_t g=0; |
44 | uint8_t b=0; |
45 | sei(); |
46 | for( ;; ) |
47 | {
|
48 | if(k == 359 ) |
49 | k=0; |
50 | OCR1A = color[k][0]; // b |
51 | OCR1B = color[k][1]; // g |
52 | OCR2 = color[k][2]; // r |
53 | _delay_ms(50); |
54 | k+=1; |
55 | }
|
56 | return 0; |
57 | }
|
Nachtrag: Variablendeklaration ist in C89 immernoch nicht erlaubt. Der C99 Standart machts aber moeglich, duerfte somit kein Ansi-C mehr sein.
Ich meinte Variablendeklaration innerhalb der for schleife also for( INT i..) anstelle von int i; for( i=0...) Gab es hier nicht mal ein Edit-button fuer die beitraege?
Florian schrieb: > Vielen Dank schonmal fuer die bisherigen Antworten. Hast du alle gelesen? > uint8_t color[360][3] = { snip }; 360 * 3 Bytes mach 1080 Bytes. Du wirst dir schwer tun diese Datenmenge in 1024 Bytes SRAM, mehr hat der Mega8 nicht, unterzubringen.
Karl Heinz Buchegger schrieb: > Florian schrieb: > >> Vielen Dank schonmal fuer die bisherigen Antworten. > > Hast du alle gelesen? > >> uint8_t color[360][3] = { snip }; > > 360 * 3 Bytes mach 1080 Bytes. Du wirst dir schwer tun diese Datenmenge > in 1024 Bytes SRAM, mehr hat der Mega8 nicht, unterzubringen. Mein Fehler. Mit einer kuerzeren Tabelle laeuft es reibunslos. Vielen Dank
@Florian: Wenn sich deine Werte nicht ändern, schau dir mal PROGMEM in
der avrlib an. Damit kannst du die Werte im Flash statt im RAM
speichern.
Zugriff ist dann z.B. mit read_pgm_byte(Adresse) möglich.
Jetzt muss ich aber mal nachhaken. Wenn i eine uint_8t Variable ist,
kann die doch nie grösser als 255 werden, oder? Damit würde doch die
Abbruchbedingung niemals erfüllt sein:
Juergen G. schrieb :
> for( uint8_t i=0; i < 256; i++ )
Matthias Sch. schrieb: > Jetzt muss ich aber mal nachhaken. Wenn i eine uint_8t Variable ist, > kann die doch nie grösser als 255 werden, oder? Damit würde doch die > Abbruchbedingung niemals erfüllt sein: Das übliche: Code extra fürs Forum zurecht gemacht und dabei 5 Fehler eingebaut :-) > > Juergen G. schrieb : >> for( uint8_t i=0; i < 256; i++ )
Karl Heinz Buchegger schrieb: > > Das übliche: > Code extra fürs Forum zurecht gemacht und dabei 5 Fehler eingebaut :-) > >> >> Juergen G. schrieb : >>> for( uint8_t i=0; i < 256; i++ ) Ich hoffe das bezieht sich nicht auf meinen Post. ich hab das for( uint8_t i=0; i < 256; i++ ) vom TO aus dem ersten Post kopiert und auch in meinem ersten Post zum Thema darauf hingewiesen. >bei einem i als uint8_t wird Deine Bedingung (i < 256) immer war sein Ju
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.