Dämmi
02.06.2013, 21:21
Hallo,
ich bin gerade dabei ein kleines Programm für eine Ladeschaltung zu Programmieren. Ich benutze einen Atmega8. Im Allgmeinen ist das Programm wie folgt aufgebaut:
Ich benutze 2 Timer. Timer1 für die PWM generierung der LED. Einmal steuern der Helligkeit und einmal Ein und Aus schalten in abhängigkeit des ADUs. Außerdem ereuge ich durch zwei hochzählende Variablen Takte als abaufsteuerung des restlichen Programms
Timer0 soll den µC aus dem Idle Mode wecken.
Das alles funktioniert auch schön und gut. Allerdings möchte ich auch das der µC durch INT0 geweckt wird durch eine Positive Flanke. Leider funktioniert es nicht wirklich. Er springt glaub ich in die ISR rein allerdings hab ich da wohl nicht sauber Programmiert. Kann mir da einer helfen? Wäre super hab mir schon total den kopf zerbrochen....
Ich bedanke mich schon einmal für die Hilfe.
Gruß Jonas
Hier der Code:
#define F_CPU 1000000UL //CPU takt auf 1MHz#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include "ADC.h"
#define Uladeschluss 1014
#define UladeschlussLED Uladeschluss-0
#define UladeschlussR 914
#define Uladeunter 814
#define UladeunterLED Uladeunter+0
#define UladeunterR 914
#define adupwmmin Uladeunter
#define adupwmmax Uladeschluss
#define helligkeit 5 //10 ist maximum
#define devidedeltaU (((UladeschlussLED)-(UladeunterLED))/100)
#define ledddr DDRD
#define ledPort PORTD
#define ledG PD7
#define ADC_ONddr DDRB
#define ADC_ONPort PORTB
#define ADC_ON PB0
#define ladeddr DDRD
#define ladeport PORTD
#define ladeschlussS PD3
#define ladeschlussR PD4
#define ladeunterS PD5
#define ladeunterR PD6
#define ladeschlussRelais PD0
#define ladeunterRelais PD1
#define DynOn PD2
#define Relaisddr DDRD
#define RelaisPort PORTD
#define RelaisPins PIND
volatile unsigned char timerz=0;
volatile unsigned char timerpwm = 0;
volatile unsigned short adupwm;
volatile unsigned short takt1 = 0;
volatile unsigned short takt2 = 0;
volatile unsigned char status1 = 0;
volatile unsigned short adu, adu1, adu2;
ISR(INT0_vect)
{
GICR &= ~(1<<INT0); //INT0 aus
MCUCR &= ~(1<<SE);
timerz=0;
timerpwm=0;
takt1=0;
takt2=0;
TCCR0 |= (1<<CS01); //Timer0 ein mit prescler 8
TCCR1B = 0; //Timer1 aus
}
ISR(TIMER0_OVF_vect)
{
takt1++;
takt2++;
timerz++;
if(timerz <= helligkeit)
{
if (adupwm < timerpwm)
{
ledPort &= ~(1<<ledG);
}
else
{
ledPort |= (1<<ledG);
}
if (timerpwm>=100)
{
timerpwm=0;
}
}
else
{
ledPort &= ~(1<<ledG);
}
if(timerz==10)
{
timerz=0;
timerpwm++;
}
}
ISR(TIMER1_OVF_vect)
{
MCUCR &= ~(1<<SE);
GICR &= ~(1<<INT0); //INT0 aus
timerz=0;
timerpwm=0;
takt1=0;
takt2=0;
TCCR0 |= (1<<CS01); //Timer0 ein mit prescler 8
TCCR1B = 0; //Timer1 aus
}
void impuls(volatile uint8_t *port, uint8_t pin);
int main(void)
{
//extern ref.. ADC0 als Eingang, rechts Ausrichtung
ADMUX = 0;
//ADU Einstellung:Einzelwandlung, 128 Teilung, keine Interrupts
ADCSRA = 0;
ADCSRA |= (1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0);
//Timer0 Teiler
TCCR0 = 0;
TCCR0 |= (1<<CS01); //prescaler auf 8 2ms pro Überlauf bei 1MHz
//Timer0 Interrupt einschalten
TIMSK = 0;
TIMSK |= (1 << TOIE0);
//Timer1 Teiler
TCCR1B = 0;
TCCR1B |= (1<<CS12)|(1<<CS10); //prescaler auf 1024 alle 61sec ein Überlauf bei 1MHz
//Timer1 Interrupt einschalten
TIMSK |= (1<<TOIE1);
//Extern Interrupt
MCUCR |= (1<<ISC01)|(1<<ISC00); //INT0 auf steigende Flanke (1<<ISC01)|(1<<ISC00)
// Den Pin, an den die LED angeschlossen ist, als Ausgang setzen
ledddr = 0;
ladeddr = 0;
ADC_ONddr = 0;
Relaisddr = 0;
ledddr |= (1 << ledG);
ladeddr |= (1 << ladeunterR)|(1<<ladeunterS)|(1<<ladeschlussS)|(1<<ladeschlussR); //Als Ausgang
ADC_ONddr |= (1<<ADC_ON);
RelaisPort |= (1<<ladeschlussRelais)|(1<<ladeunterRelais); //Eingänge setzen
sei();
/*
do //Ersten ADU wert einlesen
{
timerz=0;
ledPort &= ~(1<<ledG);
if (takt1>489) //takt1 wird vom zähler gezählt, d.h. warten
{
if (!(status1 & (1<<0))) //wenn noch nicht in schleife
{
ADCSRA |= (1<<ADEN); //Einschalten des ADU
ADC_ONPort |= (1<<ADC_ON); //Einschalten ADC_ON um Spannungsteiler vom ADC auf Masse zu legen
status1 |= (1<<0);
}
if (takt1>=500 && !(status1 & (1<<1))) //Erste AD Wandlung danach eine Zweite
{ //beide werden verglichen ob sie auf bis zu
adu1 = getADC(); //10 stellen ähnlich sind wenn ja
status1 |= (1<<1); //weiter mit arbeiten
}
if (takt1>=510)
{
adu2 = getADC();
if ((adu1<=(adu2+5)) && (adu1 >=(adu2-5)))
{
adu=adu2;
}
if (adu<=UladeunterLED) //Kontrolle ob ladeunter- oder Ladeüberspannung
{ //erreicht wurde und dadrauf die grenzen für das
adupwm=0; //blinken der LED setzen
}
else
{
if (adu >= UladeschlussLED)
{
adupwm=100;
}
else
{
adupwm=((adu-UladeunterLED)/devidedeltaU);
}
}
ADCSRA &= ~(1<<ADEN); //Auschalten des ADU
ADC_ONPort &= ~(1<<ADC_ON);
status1 &= ~(1<<0);
status1 &= ~(1<<1);
}
}
} while (takt1<=513);
takt1=0;
*/
while (1) //Hauptschleife
{
if (takt1>489) //takt1 wird vom zähler gezählt, d.h. warten
{
if (!(status1 & (1<<0))) //wenn noch nicht in schleife
{
ADCSRA |= (1<<ADEN); //Einschalten des ADU
ADC_ONPort |= (1<<ADC_ON); //Einschalten ADC_ON um Spannungsteiler vom ADC auf Masse zu legen
status1 |= (1<<0);
}
if (takt1>=500 && !(status1 & (1<<1))) //Erste AD Wandlung danach eine Zweite
{ //beide werden verglichen ob sie auf bis zu
adu1 = getADC(); //10 stellen ähnlich sind wenn ja
status1 |= (1<<1); //weiter mit arbeiten
}
if (takt1>=510)
{
adu2 = getADC();
if ((adu1<=(adu2+5)) && (adu1 >=(adu2-5)))
{
adu=adu2;
}
if (adu<=UladeunterLED) //Kontrolle ob ladeunter- oder Ladeüberspannung
{ //erreicht wurde und dadrauf die grenzen für das
adupwm=0; //blinken der LED setzen
}
else
{
if (adu >= UladeschlussLED)
{
adupwm=100;
}
else
{
adupwm=((adu-UladeunterLED)/devidedeltaU);
}
}
ADCSRA &= ~(1<<ADEN); //Auschalten des ADU
ADC_ONPort &= ~(1<<ADC_ON);
takt1=0;
status1 &= ~(1<<0);
status1 &= ~(1<<1);
//Kontrolle ob Ladeunter- oder Ladeüberspannung erreicht wurde dann Kontrolle ob Relais
//schon geschaltet haben sonst selber schalten
if ((adu > Uladeschluss) && !(RelaisPins & (1<<ladeschlussRelais)))
{
ladeport |= (1<<ladeschlussS);
}else ladeport &= ~(1<<ladeschlussS);
if ((adu < UladeschlussR) && (RelaisPins & (1<<ladeschlussRelais)))
{
ladeport |= (1<<ladeschlussR);
}else ladeport &= ~(1<<ladeschlussR);
if ((adu < Uladeunter) && !(RelaisPins & (1<<ladeunterRelais)))
{
ladeport |= (1<<ladeunterS);
}else ladeport &= ~(1<<ladeunterS);
if ((adu > UladeunterR) && (RelaisPins & (1<<ladeunterRelais)))
{
ladeport |= (1<<ladeunterR);
}else ladeport &= ~(1<<ladeunterR);
}
}
takt2=0;
if (!(RelaisPins & (1<<DynOn)))
{
do //Nichts tun nur Timer0 läuft daher LED blinkt
{
} while (takt2<=2100 && !(RelaisPins & (1<<DynOn)));
TCCR0 = 0; //Timer0 aus
TCCR1B |= (1<<CS12)|(1<<CS10); //Timer1 ein
ledPort &= ~(1<<ledG); //LED aus
GICR |= (1<<INT0); //INT0 ein
MCUCR |= (1<<SE); //Sleep Modus ein
}
}
}
ich bin gerade dabei ein kleines Programm für eine Ladeschaltung zu Programmieren. Ich benutze einen Atmega8. Im Allgmeinen ist das Programm wie folgt aufgebaut:
Ich benutze 2 Timer. Timer1 für die PWM generierung der LED. Einmal steuern der Helligkeit und einmal Ein und Aus schalten in abhängigkeit des ADUs. Außerdem ereuge ich durch zwei hochzählende Variablen Takte als abaufsteuerung des restlichen Programms
Timer0 soll den µC aus dem Idle Mode wecken.
Das alles funktioniert auch schön und gut. Allerdings möchte ich auch das der µC durch INT0 geweckt wird durch eine Positive Flanke. Leider funktioniert es nicht wirklich. Er springt glaub ich in die ISR rein allerdings hab ich da wohl nicht sauber Programmiert. Kann mir da einer helfen? Wäre super hab mir schon total den kopf zerbrochen....
Ich bedanke mich schon einmal für die Hilfe.
Gruß Jonas
Hier der Code:
#define F_CPU 1000000UL //CPU takt auf 1MHz#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include "ADC.h"
#define Uladeschluss 1014
#define UladeschlussLED Uladeschluss-0
#define UladeschlussR 914
#define Uladeunter 814
#define UladeunterLED Uladeunter+0
#define UladeunterR 914
#define adupwmmin Uladeunter
#define adupwmmax Uladeschluss
#define helligkeit 5 //10 ist maximum
#define devidedeltaU (((UladeschlussLED)-(UladeunterLED))/100)
#define ledddr DDRD
#define ledPort PORTD
#define ledG PD7
#define ADC_ONddr DDRB
#define ADC_ONPort PORTB
#define ADC_ON PB0
#define ladeddr DDRD
#define ladeport PORTD
#define ladeschlussS PD3
#define ladeschlussR PD4
#define ladeunterS PD5
#define ladeunterR PD6
#define ladeschlussRelais PD0
#define ladeunterRelais PD1
#define DynOn PD2
#define Relaisddr DDRD
#define RelaisPort PORTD
#define RelaisPins PIND
volatile unsigned char timerz=0;
volatile unsigned char timerpwm = 0;
volatile unsigned short adupwm;
volatile unsigned short takt1 = 0;
volatile unsigned short takt2 = 0;
volatile unsigned char status1 = 0;
volatile unsigned short adu, adu1, adu2;
ISR(INT0_vect)
{
GICR &= ~(1<<INT0); //INT0 aus
MCUCR &= ~(1<<SE);
timerz=0;
timerpwm=0;
takt1=0;
takt2=0;
TCCR0 |= (1<<CS01); //Timer0 ein mit prescler 8
TCCR1B = 0; //Timer1 aus
}
ISR(TIMER0_OVF_vect)
{
takt1++;
takt2++;
timerz++;
if(timerz <= helligkeit)
{
if (adupwm < timerpwm)
{
ledPort &= ~(1<<ledG);
}
else
{
ledPort |= (1<<ledG);
}
if (timerpwm>=100)
{
timerpwm=0;
}
}
else
{
ledPort &= ~(1<<ledG);
}
if(timerz==10)
{
timerz=0;
timerpwm++;
}
}
ISR(TIMER1_OVF_vect)
{
MCUCR &= ~(1<<SE);
GICR &= ~(1<<INT0); //INT0 aus
timerz=0;
timerpwm=0;
takt1=0;
takt2=0;
TCCR0 |= (1<<CS01); //Timer0 ein mit prescler 8
TCCR1B = 0; //Timer1 aus
}
void impuls(volatile uint8_t *port, uint8_t pin);
int main(void)
{
//extern ref.. ADC0 als Eingang, rechts Ausrichtung
ADMUX = 0;
//ADU Einstellung:Einzelwandlung, 128 Teilung, keine Interrupts
ADCSRA = 0;
ADCSRA |= (1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0);
//Timer0 Teiler
TCCR0 = 0;
TCCR0 |= (1<<CS01); //prescaler auf 8 2ms pro Überlauf bei 1MHz
//Timer0 Interrupt einschalten
TIMSK = 0;
TIMSK |= (1 << TOIE0);
//Timer1 Teiler
TCCR1B = 0;
TCCR1B |= (1<<CS12)|(1<<CS10); //prescaler auf 1024 alle 61sec ein Überlauf bei 1MHz
//Timer1 Interrupt einschalten
TIMSK |= (1<<TOIE1);
//Extern Interrupt
MCUCR |= (1<<ISC01)|(1<<ISC00); //INT0 auf steigende Flanke (1<<ISC01)|(1<<ISC00)
// Den Pin, an den die LED angeschlossen ist, als Ausgang setzen
ledddr = 0;
ladeddr = 0;
ADC_ONddr = 0;
Relaisddr = 0;
ledddr |= (1 << ledG);
ladeddr |= (1 << ladeunterR)|(1<<ladeunterS)|(1<<ladeschlussS)|(1<<ladeschlussR); //Als Ausgang
ADC_ONddr |= (1<<ADC_ON);
RelaisPort |= (1<<ladeschlussRelais)|(1<<ladeunterRelais); //Eingänge setzen
sei();
/*
do //Ersten ADU wert einlesen
{
timerz=0;
ledPort &= ~(1<<ledG);
if (takt1>489) //takt1 wird vom zähler gezählt, d.h. warten
{
if (!(status1 & (1<<0))) //wenn noch nicht in schleife
{
ADCSRA |= (1<<ADEN); //Einschalten des ADU
ADC_ONPort |= (1<<ADC_ON); //Einschalten ADC_ON um Spannungsteiler vom ADC auf Masse zu legen
status1 |= (1<<0);
}
if (takt1>=500 && !(status1 & (1<<1))) //Erste AD Wandlung danach eine Zweite
{ //beide werden verglichen ob sie auf bis zu
adu1 = getADC(); //10 stellen ähnlich sind wenn ja
status1 |= (1<<1); //weiter mit arbeiten
}
if (takt1>=510)
{
adu2 = getADC();
if ((adu1<=(adu2+5)) && (adu1 >=(adu2-5)))
{
adu=adu2;
}
if (adu<=UladeunterLED) //Kontrolle ob ladeunter- oder Ladeüberspannung
{ //erreicht wurde und dadrauf die grenzen für das
adupwm=0; //blinken der LED setzen
}
else
{
if (adu >= UladeschlussLED)
{
adupwm=100;
}
else
{
adupwm=((adu-UladeunterLED)/devidedeltaU);
}
}
ADCSRA &= ~(1<<ADEN); //Auschalten des ADU
ADC_ONPort &= ~(1<<ADC_ON);
status1 &= ~(1<<0);
status1 &= ~(1<<1);
}
}
} while (takt1<=513);
takt1=0;
*/
while (1) //Hauptschleife
{
if (takt1>489) //takt1 wird vom zähler gezählt, d.h. warten
{
if (!(status1 & (1<<0))) //wenn noch nicht in schleife
{
ADCSRA |= (1<<ADEN); //Einschalten des ADU
ADC_ONPort |= (1<<ADC_ON); //Einschalten ADC_ON um Spannungsteiler vom ADC auf Masse zu legen
status1 |= (1<<0);
}
if (takt1>=500 && !(status1 & (1<<1))) //Erste AD Wandlung danach eine Zweite
{ //beide werden verglichen ob sie auf bis zu
adu1 = getADC(); //10 stellen ähnlich sind wenn ja
status1 |= (1<<1); //weiter mit arbeiten
}
if (takt1>=510)
{
adu2 = getADC();
if ((adu1<=(adu2+5)) && (adu1 >=(adu2-5)))
{
adu=adu2;
}
if (adu<=UladeunterLED) //Kontrolle ob ladeunter- oder Ladeüberspannung
{ //erreicht wurde und dadrauf die grenzen für das
adupwm=0; //blinken der LED setzen
}
else
{
if (adu >= UladeschlussLED)
{
adupwm=100;
}
else
{
adupwm=((adu-UladeunterLED)/devidedeltaU);
}
}
ADCSRA &= ~(1<<ADEN); //Auschalten des ADU
ADC_ONPort &= ~(1<<ADC_ON);
takt1=0;
status1 &= ~(1<<0);
status1 &= ~(1<<1);
//Kontrolle ob Ladeunter- oder Ladeüberspannung erreicht wurde dann Kontrolle ob Relais
//schon geschaltet haben sonst selber schalten
if ((adu > Uladeschluss) && !(RelaisPins & (1<<ladeschlussRelais)))
{
ladeport |= (1<<ladeschlussS);
}else ladeport &= ~(1<<ladeschlussS);
if ((adu < UladeschlussR) && (RelaisPins & (1<<ladeschlussRelais)))
{
ladeport |= (1<<ladeschlussR);
}else ladeport &= ~(1<<ladeschlussR);
if ((adu < Uladeunter) && !(RelaisPins & (1<<ladeunterRelais)))
{
ladeport |= (1<<ladeunterS);
}else ladeport &= ~(1<<ladeunterS);
if ((adu > UladeunterR) && (RelaisPins & (1<<ladeunterRelais)))
{
ladeport |= (1<<ladeunterR);
}else ladeport &= ~(1<<ladeunterR);
}
}
takt2=0;
if (!(RelaisPins & (1<<DynOn)))
{
do //Nichts tun nur Timer0 läuft daher LED blinkt
{
} while (takt2<=2100 && !(RelaisPins & (1<<DynOn)));
TCCR0 = 0; //Timer0 aus
TCCR1B |= (1<<CS12)|(1<<CS10); //Timer1 ein
ledPort &= ~(1<<ledG); //LED aus
GICR |= (1<<INT0); //INT0 ein
MCUCR |= (1<<SE); //Sleep Modus ein
}
}
}