Hallo habe folgende Code und komme nicht mehr klar. Timer 0 sollte doch alle 800000/1/256=31250 ausgeführt werden. Also 32250/2= 15625Hz Warum leuchtet bei der Siebensegmentanzeige aber die Einerstelle immer heller bei einer Refreshrate von 15kHz? Danke Bruno Code // WINAVR 20090306 // AVR Studio 4.16.628 #include <avr/io.h> #include <avr/interrupt.h> volatile uint8_t tausender, hunderter, zehner, einer; volatile uint16_t wert; #define maxwert 999 const int8_t numbers [10] = { // 1gfedcba 0b10111111, //0 0b10000110, //1 0b11011011, //2 0b11001111, //3 0b11100110, //4 0b11101101, //5 0b11111101, //6 0b10000111, //7 0b11111111, //8 0b11101111, //9 }; void out_zahl(uint8_t wertig, uint8_t stelle) { // Ausschalten sonst nachleuchten der Zahl PORTB = 0b00000000; PORTD = 1 << stelle; // Neue Zahl ausgeben PORTB = numbers[wertig]; PORTD = 1 << stelle; } void out_nummer() { for(int8_t position=4; position>=0; position--) { switch (position) { case 3: { // out_zahl(tausender, 3); break; } case 2: { out_zahl(hunderter, 2); break; } case 1: { out_zahl(zehner, 1); break; } case 0: { out_zahl(einer, 0); break; } } } } // Timer 0 - 8 Bit Overflow ISR (TIMER0_OVF_vect) { // Anzeige erneuern out_nummer(); // Timer hochstellen } // Timer 1 - 16 Bit // Zähler um eins erhöhen ISR (TIMER1_OVF_vect) { // Maximaler zähler if (wert == maxwert) { wert=0; } // Eins hoch wert++; uint16_t auswert; auswert = wert; // tausender tausender = auswert/1000; auswert = auswert%1000; // hunderter hunderter = auswert/100; auswert = auswert%100; // zehner zehner = auswert/10; // einer einer = auswert%10; } int main(void) { // Port C 4 auf Ausgang DDRD |= (1 << DDD0) | (1 << DDD1) | (1 << DDD2) | (1 << DDD3) | (0 << DDD4) | (0 << DDD5) | (0 << DDD6) | (0 << DDD7); // Port B alles auf Ausgang DDRB |= (1 << DDB0) | (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4) | (1 << DDB5) | (1 << DDB6) | (1 << DDB7); // Variablen init wert = 0; einer = 0; zehner = 0; hunderter = 0; tausender= 0; // Ausgabe neu zeichnen // Timer 0 // Prescaler = 1 Clock Takt!!! TCCR0 |= (1 << CS00) | (0 << CS01) | (0 << CS02) ; // Prescaler = 8 Clock Takt!!! // TCCR0 |= (0 << CS00) | (1 << CS01) | (0 << CS02) ; // Prescaler = 64 Clock Takt!!! // TCCR0 |= (1 << CS00) | (1 << CS01) | (0 << CS02) ; // Prescaler = 256 Clock Takt!!! // TCCR0 |= (0 << CS00) | (0 << CS01) | (1 << CS02) ; // Prescaler = 1024 // TCCR0 |= (1 << CS00) | (0 << CS01) | (1 << CS02) ; // Hochzählen // Timer 1 // Prescaler = 1 Clock Takt!!! // TCCR1B |= (1 << CS00) | (0 << CS01) | (0 << CS02) ; // Prescaler = 8 Clock Takt!!! // TCCR1B |= (0 << CS00) | (1 << CS01) | (0 << CS02) ; // Prescaler = 64 Clock Takt!!! TCCR1B |= (1 << CS00) | (1 << CS01) | (0 << CS02) ; // Prescaler = 256 Clock Takt!!! // TCCR1B= (0 << CS00) | (0 << CS01) | (1 << CS02) ; // Prescaler = 1024 // TCCR1B= (1 << CS00) | (0 << CS01) | (1 << CS02) ; // TIMER Interrupt Maske Timer 0 und Timer 1 bei Overfow TIMSK |= (1 << TOIE0) | (1 << TOIE1); sei(); //IRQ ein // Timer 0 hochstellen für OVF // TCNT0=253; // Timer 0 für COMP OCR0 = 128; while(1) { // nothing } return 0; }
Danke aber manchmal ist zu schnell eben zu schnell! Bruno void out_zahl(uint8_t wertig, uint8_t stelle) { // Ausschalten sonst nachleuchten der Zahl PORTB = 0b00000000; PORTD = 1 << stelle; // Neue Zahl ausgeben PORTB = numbers[wertig]; PORTD = 1 << stelle; delay_ms(5); }
Bruno schrieb: > void out_zahl(uint8_t wertig, uint8_t stelle) > ... > delay_ms(5); Prust, Lach. out_zahl wird im Interrupt aufgerufen, da sind Delays streng verboten! Aber etwas recht hast Du, 15kHz ist viel zu schnell, da können sich schon Programmlaufzeiten bemerkbar machen. Für 4 Digits reichen 400Hz völlig. Peter
Weil deine AUsgaberoutine Unsinn ist. Du tust pro Interrupt (T0) alle Segmente für 5ms anzeigen, danach den Int. verlassen. Das heißt, alle Segmente, außer dem ersten, werden 5ms angezeigt, die erste solange bis der Int wieder kommt. Das ist Müll. So funktioniert keine Multiplexausgabe!
Das Problem ist, daß er im Interrupt immer
alle 5 Ziffern ausgibt
> for(int8_t position=4; position>=0; position--)
und die letzte dann stehenbleibt.
Richtig ist im Interrupt (400 Hz für 4 Digits mehr als
ausreichend) eine Ziffer einschalten, dann im nächsten
Aufruf diese aus- und die nächste einschalten.
Die Ziffern haben dann alle einen Duty von 1:3 (und etwas
Verarbeitungszeiten).
gruß avr
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.