Hi!
Danke für die schnellen Antworten!
Ich habe mal alle eure Tipps befolgt, bis auf das ohne Sinus, das mach ich morgen, und jetzt sieht der Code so aus:
Code:
#include <avr\io.h>
#include <avr\interrupt.h>
#include <math.h>
#define F_CPU 8000000
#define interruptsProSekunde (F_CPU/256)
#define periodendauer (1/frequenz)
#define interruptsProPeriode (periodendauer/interruptsProSekunde)
#define round(x) ((unsigned) ((x) + .5))
volatile uint16_t frequenz; //frequenz in Hz
volatile uint8_t signalform; //gewünschte signalform 0=sinus, 1=dreieck, 2=sägezahn, 3=rechteck
uint8_t ausgang; //Ausgangsport
double spg=0; //Berechneter Spannungswert des Ausganges
uint16_t x;
double x2;
double x3;
void init(void)
{
TIMSK=(1<<TOV0); //Timer Overflow Interrupt einschalten
TCNT0=0x00; //Zähler-Startwert setzen
TCCR0=(1<<CS00); //vorteiler: 1
sei(); //Interrupts einschalten
}
ISR(TIMER0_OVF_vect) //Interrupt-Routine
{
if(x<=interruptsProPeriode)
{
x++; //x nimmt werte von 0-interruptsproperiode an
}
else
{
x=0;
}
x2=x/interruptsProPeriode*2*M_PI; //x2 nimmt werte von 0-2Pi an
x3=x/interruptsProPeriode; //x3 nimmt werte von 0-1 an
switch(signalform)
{
case 0: //signalform=sinus
spg=sin(x2); //spannungsberechnung für sinus-signal mit sinus funktion
break;
case 1: //signalform=dreieck
if((0<=x3)&(x3<=0.25))
{
spg=x3*2+0.5; //spannungsberechnung für dreieck-signal mit dreieck funktion
}
if((0.25<x3) &(x3<0.75))
{
spg=1-(x3-0.25)*2;
}
if((0.75<=x3)&(x3<=1))
{
spg=(x3-0.75)*2;
}
break;
case 2: //signalform=sägezahn
spg=x3; //spannungsberechnung für sägezahn-signal mit sägezahn funktion
break;
case 3: //signalform=rechteck
if(x3<0.5) //spannungsberechnung für rechteck-signal mit rechteck funktion
{
spg=0;
}
else
{
spg=1;
}
//verstellbarer dutycycle wäre praktisch
break;
}
spg=spg*255; //vorher spg: 0-1, nacher spg: 0-255
ausgang=round(spg); //runden
PORTD=ausgang; //gerundeten wert auf port D (r2r-netzwerk angeschlossen) legen
if(PORTB==0b00000001)
{
PORTB=0b00000000;
}
else
{
PORTB=0b00000001;
}
}
int main(void)
{
DDRD=0b11111111;
DDRB=0b11111111;
init();
while (1)
{
frequenz=1000;
//frequenz einstellen
signalform=0;
//signalform einstellen
}
}
Die LED an PB0 Blinkt mit einer Periodendauer von 1,3ms, das entspricht 770Hz, also viel zu langsam. wahrscheinlich dauert die Interruptroutine zu lange. Was passiert eigentlich, wenn während der Ausführung der Interruptroutine ein Interrupt ausgelöst wird? Bricht sie dann ab und Beginnt von vorne, oder macht sie einfach weiter?
EDIT: was ich noch vergessen habe: PD0 und PD1 sind jetzt dauerHigh, der restliche PortD ist Low
Lesezeichen