das hab ich mittels poti und ADC auf nem ATMega8 bei 8MHz getestet .... bis auf ein paar übergangsflackereien (vermutlich vom poti und beim updaten des OCR register) funktioniert es eigentlich ganz gut, und man könnte theoretisch für jeden port ne neue Duty Variable und StatusVariable einbauen ... zu not kann man auch PIN statt der statusvariable abfragen, aber mir rennt die zeit davon das noch zu testen ...
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/timer.h>
#include <avr/signal.h>
#include <avr/sleep.h>
#define ON 1
#define OFF 0
#define ULONG_MAX 199
volatile unsigned char OFVal;
unsigned char LED1Duty;
unsigned char LED1Stat;
SIGNAL(SIG_OUTPUT_COMPARE2)
{
if (OFVal++ == 200) OFVal = 0;
LED1Duty = (ADC*10)/(1024/10)-1;
if (LED1Stat == OFF && (ULONG_MAX-LED1Duty) == OFVal)
{
PORTB |= BV(PB1);
LED1Stat = ON;
}
if (LED1Stat == ON && ULONG_MAX-(ULONG_MAX-LED1Duty) == OFVal)
{
PORTB &= ~BV(PB1);
LED1Stat = OFF;
}
}
int main(void)
{
cli();
OFVal = 0;
DDRB = BV(PB1)|BV(PB2)|BV(PB3)|BV(PB4);
TIMSK = BV(OCIE2)|BV(TOIE2); //TOIE2 musste ich mit einschalten hat sonst nciht fuinktioniert (komisch ....)
TCNT2 = 0;
OCR2 = 100; //damit kannste die auflösung einstellen 100% sind wegen der ADC formel notwendig
TCCR2 = BV(WGM21)|BV(CS20); //CTC modus, prescaler 1
LED1Duty = 1;
LED1Stat = OFF;
ADCSRA = BV(ADFR) | BV(ADPS2) | BV(ADPS1); // ADC einstellungen
ADMUX = BV(REFS0);
ADCSRA |= BV(ADEN);
ADCSRA |= BV(ADSC);
sei();
while(1) ;
}
da bleiben auch noch ausreichend takte für die while schleife übrig, zur not kannst den prescaler auch noch hochschrauben, dann haste allerdings nen flackernden effekt wenn du es schnell hinundher bewegst
hoffe ich konnte helfen
MfG
Ceos
PS den duty berechne ich im interrupt, ADC 0-1024 mit der formel gibt das 0-100 (0-100%) wenn du ne andere auflösung verwendest brauchst du hier ein duty zwischen 0 - OCR (achtung, OCR bedeutet LED aus, OCR-1 allerdings maximum)
Lesezeichen