Hallo :) Ich versuche derzeit eine SW PWM zu realisieren. Dabei stoße ich jedoch auf folgendes Problem. Ein Timer arbeitet die PWM ab, der andere verändert die gewünschten Helligkeitswerte. Das Ganze soll später noch erweitert werden, daher habe ich das so gelöst. Hier mal der Code: #include <avr/io.h> #include <avr/interrupt.h> #include <stdint.h> #define CPU_SPEED 1000000 #define PWM_CH0 0 #define PWM_CH1 1 #define PWM_CH2 2 #define PWM_PORT PORTB #define PWM_PORT_DIRECTION DDRB volatile uint8_t currentValueInRun = 0; // This is the number of the cycle inside one frame volatile uint8_t currentBrightness[3]; // This is the brightness of the channels volatile uint8_t currentColourRun = 0; volatile uint8_t colourChangeTime = 1; struct { unsigned char stateTimerEnabled:1; // 1 Bit für bStatus_1 unsigned char stateSwitchEnabled:1; // 1 Bit für bStatus_2 } status; void enablePWM(void) { // Set PWM_PORT AS OUTPUT (0 is Output, 1 is input) PWM_PORT_DIRECTION &= ~ ((1 << PWM_CH0) | (1 << PWM_CH1) | (1 << PWM_CH2)); PWM_PORT = 0x00; // Set to Low // Use Timer 2 (8bit timer) for actual PWM TCCR2 |= (1 << WGM21); // CTC Mode (WGM21 -> 1, others 0) TCCR2 |= (1 << CS20); // No pre-scaler (running at CPU speed) (CS20 -> 1) //Calculate Preload value OCR2 = CPU_SPEED / 25600; // will cause an overflow (TIMER2_COMP) if TCNT reaches OCR2 TIMSK |= (1 << OCIE2); // Enable the overflow interrupt } ISR(TIMER2_COMP_vect) { // ISR for PWM // This happens every 100 Cycles (25 600 Times each second) // Every cycle has 256 steps (resolution of brightness, 256 different levels of brightness are possible) - from 0 .. 255 is one frame // We run at 100fps currentValueInRun++; // will overflow automatically at 255 to 0 if (currentValueInRun >= currentBrightness[0]) // check if we are in the range of switching on / off { // Off State PWM_PORT &= ~(1 << PWM_CH0); } else { // On State PWM_PORT |= (1 << PWM_CH0); } } ISR(TIMER0_OVF_vect) { // ISR for Automatic changer currentBrightness[0] = 255; PORTD=0xff; /*currentColourRun++; if (currentColourRun >= colourChangeTime) { currentColourRun = 0; // change color either completely or some step currentBrightness[0]++; } else { currentColourRun++; }*/ } void enableAutomaticChanger(void) { // Use Timer 0 - timing is not important TCCR0 |= (1 << CS00) | (1 << CS02); // Prescaler: 1024, no reload value (will count from 0 ... 255) TIMSK |= (1 << TOIE0); // Enable interrupt } int main(void) { // Init the brightness settings: for (int i = 0; i < 3; i++) { currentBrightness[i] = 0x00; } enablePWM(); enableAutomaticChanger(); PORTD = 0x00; sei(); // Enable global interrupts and wait while(1); // now wait for interrupts } PortD nutze ich zum Überprüfen ob der Atmega8 in die entsprechenden Routinen springt. Nun wirds aber interessant. Aktiviere ich die PWM NICHT, so springt er - wie er soll in die TIMER0_OVERFLOW ISR (PORTD = 0xff). Wenn nun aber parallel dazu die PWM aktiviert wird, so springt er einfach nicht mehr in die TIMER0_OVERFLOW ISR (PORTD bleibt auf 0x00). Was mache ich denn falsch? Um den Effekt herbeizuführen, reicht es aus, die Zeile enablePWM(); einfach mal auszukommentieren. Danke für jegliche Hilfe :)
Du setzt OCR2 auf 39 Zyklen, das ist fast nichts. Warscheinlich kommst Du garnicht aus dem TIMER2_COMP raus. Peter
Uff, tatsächlich. Selten so einen dummen Fehler gehabt. Dank dir vielmals :)
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.