Für Softwar-PWM bin ich gerade für das SEDU ein wenig am Basteln. Ich habe die Software-PWM-Routinen von "the-powl" genutzt und zumindest die 1-Port-Version in eine Lib für C gepackt.
Das bedeutet, man bindet im Projekt nur die Lib und die Header-Datei ein, trägt im Header die benötigten Werte ein und hat damit bis zu 8 PWM-Kanäle. Beispiel-Quellcode folgt unten. Ich stelle es auch nochmal offiziell vor. Ich denke, es sollte auch möglich sein, weniger Ausgabeports zu verwenden, so dass der Rest frei für andere Dinge ist. Getestet ist es allerdings bisher nur auf ATmega16 und 168. Bin mir gerade nicht sicher, ob da Hardware-abhängiger Code in der Lib drin ist. Das wäre ja schlecht.
C
// Software-PWM by PoWl - 25.10.08
// webmaster@the-powl.de
//
// N. Turianskyj 03.07.2011
// Modifikation für SEDU-Addon 2xRGB + Taster
// Verwendung von 6 der 8 PWM-Ports für die LEDs
//
// ATmega16 @ 16Mhz (SEDU)
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdbool.h>
//PWM-Routine
#include "SoftPWM1p.h"
// Sinustabelle für Demo
const uint8_t sinetable[] = {
128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167,170, 173, 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206,
208, 211, 213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235,237, 238, 240, 241, 243, 244, 245, 246, 248, 249, 250, 250, 251, 252,
253, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 254, 254,254, 253, 253, 252, 251, 250, 250, 249, 248, 246, 245, 244, 243, 241,
240, 238, 237, 235, 234, 232, 230, 228, 226, 224, 222, 220, 218, 215,213, 211, 208, 206, 203, 201, 198, 196, 193, 190, 188, 185, 182, 179,
176, 173, 170, 167, 165, 162, 158, 155, 152, 149, 146, 143, 140, 137,134, 131, 128, 124, 121, 118, 115, 112, 109, 106, 103, 100, 97, 93,
90, 88, 85, 82, 79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47,44, 42, 40, 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14,
12, 11, 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 14, 15, 17, 18, 20,
21, 23, 25, 27, 29, 31, 33, 35, 37, 40, 42, 44, 47, 49, 52, 54, 57,59, 62, 65, 67, 70, 73, 76, 79, 82, 85, 88, 90, 93, 97, 100, 103,106, 109, 112, 115, 118, 121, 124 };
int main(void)
{
// PWM initialisieren
for(uint8_t i=0; i<CHANNELS; i++)
{
pwm_queue[i] = i;
}
//Festlegung der Reihenfolge der Ausgabeports (hier immer nur einen Port verwenden!)
pwm_pin[0] = PA0; pwm_pin[1] = PA1; pwm_pin[2] = PA2; pwm_pin[3] = PA3;
pwm_pin[4] = PA4; pwm_pin[5] = PA5; pwm_pin[6] = PA6; pwm_pin[7] = PA7;
//Ports auf Ausgang schalten. Muss mit Definition von pwm_pin[] harmonieren
DDRA = (1 << PA0) | (1 << PA1) | (1 << PA2) | (1 << PA3) | (1 << PA4) | (1 << PA5) | (1 << PA6) | (1 << PB7);
// Timer für Software-PWM
OCR1A = 255;
TIMSK = (1 << OCIE1A) | (1 << OCIE1B);
TCCR1B = (1 << WGM12) | 4;
//Interrupts freigeben
sei();
uint8_t pos = 0;
//Hauptschleife zur Ausgabe des Farbwechsels
//hier können beliebige andere Algorithmen verwendet werden
//Wertebereich 0-255
while(1)
{
for(uint8_t i=0; i<8; i++)
{
pwm_value[i] = sinetable[(uint8_t) (pos + i * 20)];
}
//Ausgabe der PWM-Berechnung
pwm_update();
pos++;
_delay_ms(10);
}
}
Alles anzeigen