Hallo
Nur keine Panik! In der Hex-Datei ist jedes Byte des Programms mit zwei Zeichen hexdezimal codiert, zusätzlich noch die Zieladressen und die Checksummen. Du kannst sie mal im Editor öffnen. Die ersten 8 Zeichen pro Zeile sind die Zieladresse im Speicher des Mega8, dann kommen 16 Bytes Daten und ein Byte Checksumme, jeweils als Hex-Wert.
Wenn ich dein Progamm kompiliere, komme ich auf 2226 Bytes Programmlänge, die Hex-Datei wird mit 7kb angezeigt. Meine Optimierung ist auf "Size" eingestellt.
Ich habe dein Programm nicht genauer untersucht, denn es scheint mir auf den ersten Blick etwas kompliziert. Möglicherweise bringt dies eine Funktion:
volatile uint16_t frequenz; //frequenz in Hz
volatile uint8_t signalform; //gewünschte signalform 0=sinus, 1=dreieck, 2=sägezahn, 3=rechteck
volatile zwingt den Kompilier, für die Variable einen Speicherplatz anzulegen. Dadurch können sowohl das Hauptprogramm wie auch die ISR auf den Wert der Variable zugreifen. (Nicht wissenschaftlich und von mir nur nachgeplappert;) Mit dieser Änderung sieht dein Programm dann so aus:
Code:
#include <avr\io.h>
#include <avr\interrupt.h>
#include <math.h>
#define F_CPU 8000000
#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
uint16_t interruptspersecond; //anzahl der interrupts pro sekunde
uint8_t ausgang; //Ausgangsport
float periodendauer; //in S
uint16_t interruptsproperiode; //anzahl der interrupts pro periode
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
{
interruptspersecond = F_CPU/256;
periodendauer=1/frequenz;
interruptsproperiode=periodendauer/interruptspersecond;
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
if(signalform==0) //signalform=sinus
{
spg=sin(x2); //spannungsberechnung für sinus-signal mit sinus funktion
}
if(signalform==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;
}
}
if(signalform==2) //signalform=sägezahn
{
spg=x3; //spannungsberechnung für sägezahn-signal mit sägezahn funktion
}
if(signalform==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
}
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
}
int main(void)
{
DDRD=0b11111111;
init();
while (1)
{
frequenz=1000;
//frequenz einstellen
signalform=0;
//signalform einstellen
}
}
Allerdings, so aus dem Bauchgefühl heraus, könnte mindestens bei Kurvenform 1 ein Überlauf der ISR auftreten.
Gruß
mic
Lesezeichen