mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Soft PWM Beispiel (ATMEGA32) auf ATMEGA168 umschreiben


Autor: Hansi Cardell (honsey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich sitze jetzt schon den ganzen nachmittag dran, aber bekomme es 
einfach nicht hin. in der artikelsammlung gibt es ein beispiel für soft 
pwm auf einem mega32.

der code sieht wie folgt aus:
/*
    Eine 8-kanalige PWM mit einfachem Lösungsansatz
 
    ATmega32 @ 8 MHz
 
*/
 
// Defines an den Controller und die Anwendung anpassen
 
#define F_CPU 8000000L                  // Systemtakt in Hz
#define F_PWM 100                       // PWM-Frequenz in Hz
#define PWM_STEPS 256                   // PWM-Schritte pro Zyklus(1..256)
#define PWM_PORT PORTD                  // Port für PWM
#define PWM_DDR DDRD                    // Datenrichtungsregister für PWM
 
// ab hier nichts ändern, wird alles berechnet
 
#define T_PWM (F_CPU/(F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt
 
#if (T_PWM<(152+5))
    #error T_PWM zu klein, F_CPU muss vergrösst werden oder F_PWM oder PWM_STEPS verkleinert werden
#endif
 
// includes
 
#include <stdint.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
 
// globale Variablen
 
volatile uint8_t pwm_setting[8];                    // Einstellungen für die einzelnen PWM-Kanäle
 
// Timer 1 Output COMPARE A Interrupt
 
ISR(TIMER1_COMPA_vect) {
    static uint8_t pwm_cnt=0;
    uint8_t tmp=0, i=0, j=1;
 
    OCR1A += (uint16_t)T_PWM;
 
    for (; i<8; i++) {    
      if (pwm_setting[i] > pwm_cnt) tmp |= j;
            j<<=1;
  }
    PWM_PORT = tmp;                         // PWMs aktualisieren
    if (pwm_cnt==(uint8_t)(PWM_STEPS-1))
        pwm_cnt=0;
    else
        pwm_cnt++;
}
 
int main(void) {
 
    // PWM einstellen
    
    PWM_DDR = 0xFF;         // Port als Ausgang
    
    // Timer 1 OCRA1, als variablem Timer nutzen
 
    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
    TIMSK |= (1<<OCIE1A);   // Interrupt freischalten
 
    sei();                  // Interrupts gloabl einschalten
 
/*********************************************************************/
// nur zum Testen, im Anwendungsfall löschen
 
    volatile uint8_t tmp;
const uint8_t t1[8]={27, 40, 3, 17, 150, 99, 5, 9};
const uint8_t t2[8]={27, 40, 3, 0, 150, 99, 5, 9};
const uint8_t t3[8]={27, 40, 3, 17, 3, 99, 3, 0};
const uint8_t t4[8]={0, 0, 0, 0, 0, 0, 0, 0};
const uint8_t t5[8]={0, 0, 0, 0, 0, 0, 0, 9};
const uint8_t t6[8]={33, 33, 33, 33, 33, 33, 33, 33};
 
// Messung der Interruptdauer
    tmp =0;
    tmp =0;
    tmp =0;
 
// Debug 
 
    memcpy(pwm_setting, t1, 8);
    
    memcpy(pwm_setting, t2, 8);
 
    memcpy(pwm_setting, t3, 8);
 
    memcpy(pwm_setting, t4, 8);
 
    memcpy(pwm_setting, t5, 8);
    
    memcpy(pwm_setting, t6, 8);
 
/*********************************************************************/
 
    return 0;
}

ich habe eigentlich alles unverändert gelassen, bis auf wenige stellen.

1) der cpu takt. mein atmega168 wird mit einem externen quarz auf 16Mhz 
betrieben, deshalb:
#define F_CPU 16000000L                  // Systemtakt in Hz

2) die aktivierung des interrupts:
    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
    TIMSK1 |= (1<<OCIE1A);   // Interrupt freischalten

leider funktioniert es garnicht. die leds bleiben einfach dunkel... was 
übersehe ich? da ich davon ausgehe, dass der code stimmt, wenn er so in 
der artikelsammlung abgeheftet ist, wird es wohl nicht an dem liegen was 
ich vermuten würde. (habe es auch ausprobiert, aber es hat auch nicht 
geholfen...)

1) zum zeitpunkt, wenn der interrupt aktiviert wied ist OCR1A noch 
garnicht definiert?
2) die helligkeitswerte müssten doch an irgendeiner stelle im programm 
in das array pwm_setting geschrieben werden?

vielen dank für eure hilfe,
hans

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In dem Artikel sind drei Varianten der Soft-PWM gezeigt. Nimm die 
letzte, die sollte funktionieren. Deine Änderungen sind wohl so in 
Ordnung.

Oliver

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Honsey Kk (honsey)

>#define F_CPU 16000000L                  // Systemtakt in Hz

Kein Problem, das ist der Sinn der Sache.

>    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
>    TIMSK1 |= (1<<OCIE1A);   // Interrupt freischalten

Hab das Datenblatt im Moment nicht hier.

>1) zum zeitpunkt, wenn der interrupt aktiviert wied ist OCR1A noch
>garnicht definiert?

Ist auch unwichtig, das regelt sich allein.

>2) die helligkeitswerte müssten doch an irgendeiner stelle im programm
>in das array pwm_setting geschrieben werden?

Das machen die Zeilen

    memcpy(pwm_setting, t1, 8);

MFG
Falk

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.