PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : AC löst keinen Interrupt aus



Che Guevara
05.02.2014, 23:25
Hi,

ich habe ein Problem mit einem AtXMega32A4 bzw. AtXMega16A4. Ich habe den AC so konfiguriert, dass er bei steigender bzw. fallender Flanke (wird im Programm ständig geändert) einen Interrupt auslösen soll und in der ISR dann eine LED toggeln. Das ganze hat auch schonmal funktioniert, tuts aber komischerweise jetzt nicht mehr...
Die bieden versch. µCs hab ich angegeben, weil ich erst dachte, der AC Des XM16A4 sei kaputt und hab deshalb die Chips getauscht, jedoch gleiches Verhalten.
Hab dann probeweise mal den DAC als neg. Quelle benutzt und langsam hochzählen lassen, da hats dann auch funktioniert. Mit der selben Hardware und gleichen Routinen (bis auf den DAC) läufts aber nicht. Die anliegenden Signale hab ich auf dem Oszi, deren Amplituden unterscheiden sich max. ca. 200mV (was ja locker für den AC reichen sollte).
Hier mal der Code:


/*
* BlControlV10.c
*
* Created: 21.01.2014 23:50:02
* Author: Chris
*/


#define F_CPU 32000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
#include <util/twi.h>
#include <math.h>
#include <avr/eeprom.h>



//ADC Defines
#define VoltagePinConfig (PORTA.DIRCLR = 0x10) //PORTA.4
#define CurrentPinConfig (PORTA.DIRCLR = 0x40) //PORTA.6
#define CurrentNegPinConfig (PORTA.DIRCLR = 0x80) //PORTA.7


//RpmTimer Defines
#define RpmTimer (TCE0)
#define RpmTimerOvfVect (TCE0_OVF_vect)


//Global Defines
/*
#define TimerPer (2000)

#define MinPwm (200)
#define MaxPwm (1800)
#define AnlaufPwm (200)
*/

#define TimerPer (1000)

#define MinPwm (100)
#define MaxPwm (900)
#define AnlaufPwm (100)


//Pwm Input Capture Defines
#define PwmInputTimer (TCD0)
#define PwmInputPinConfig (PORTD.DIRCLR = 0x04) //PORTD.2

#define PwmInput (TCD0.CCC)


//PC Uart Defines
#define PCUartPinConfig (PORTD.DIRSET = 0x80)
#define PCUartPort (USARTD1)


//SD Pin Defines
#define PhaseASdConfigPin (PORTB.DIRSET = 0x02) //PORTB.1
#define PhaseASdOn (PORTB.OUTSET = 0x02)
#define PhaseASdOff (PORTB.OUTCLR = 0x02)
#define PhaseASdStatus (PORTB.IN & 0x02)

#define PhaseBSdConfigPin (PORTB.DIRSET = 0x04) //PORTB.2
#define PhaseBSdOn (PORTB.OUTSET = 0x04)
#define PhaseBSdOff (PORTB.OUTCLR = 0x04)
#define PhaseBSdStatus (PORTB.IN & 0x04)

#define PhaseCSdConfigPin (PORTB.DIRSET = 0x08) //PORTB.3
#define PhaseCSdOn (PORTB.OUTSET = 0x08)
#define PhaseCSdOff (PORTB.OUTCLR = 0x08)
#define PhaseCSdStatus (PORTB.IN & 0x08)


//PWM Defines
#define PwmPortPinConfig (PORTC.DIRSET = 0x07)
#define PwmTimer (TCC0)

#define PhaseAPwmConfigPin (PORTC.DIRSET = 0x04) //PORTC.2
#define PhaseAPwm (TCC0.CCC)
#define PhaseAGnd (TCC0.CCC = 0)
#define PhaseAVcc (TCC0.CCC = MaxPwm)

#define PhaseBPwmConfigPin (PORTC.DIRSET = 0x02) //PORTC.1
#define PhaseBPwm (TCC0.CCB)
#define PhaseBGnd (TCC0.CCB = 0)
#define PhaseBVcc (TCC0.CCB = MaxPwm)

#define PhaseCPwmConfigPin (PORTC.DIRSET = 0x01) //PORTC.0
#define PhaseCPwm (TCC0.CCA)
#define PhaseCGnd (TCC0.CCA = 0)
#define PhaseCVcc (TCC0.CCA = MaxPwm)


//AnalogComperator Defines
#define DisableAc (ACA.AC0CTRL = 0x00)

#define NoHysteris (0x00)
#define SmallHysteris (0x02)
#define LargeHysteris (0x04)

#define Hysteris (NoHysteris) //LargeHysteris

#define ClearAcIntFlag (ACA.STATUS |= 0x01)

#define AcRising (ACA.AC0CTRL = 0xF9) //(ACA.AC0CTRL = 0xF9 | Hysteris)
#define AcFalling (ACA.AC0CTRL = 0xB9) //(ACA.AC0CTRL = 0xB9 | Hysteris)
//#define AcRising (ACA.AC0CTRL = 0x39)
//#define AcFalling (ACA.AC0CTRL = 0x39)

#define MittelACConfigPin (PORTA.DIRCLR = 0x08) //PORTA.3

#define PhaseAACConfigPin (PORTA.DIRCLR = 0x20) //PORTA.5
#define PhaseAAcUse (ACA.AC0MUXCTRL = 0x1B)

#define PhaseBACConfigPin (PORTA.DIRCLR = 0x02) //PORTA.1
#define PhaseBAcUse (ACA.AC0MUXCTRL = 0x19)

#define PhaseCACConfigPin (PORTA.DIRCLR = 0x01) //PORTA.0
#define PhaseCAcUse (ACA.AC0MUXCTRL = 0x18)

#define PhaseAACConfigPin (PORTA.DIRCLR = 0x20) //PORTA.5
#define PhaseBACConfigPin (PORTA.DIRCLR = 0x02) //PORTA.1
#define PHaseCACConfigPin (PORTA.DIRCLR = 0x01) //PORTA.0
#define PhaseMittelConfigPin (PORTA.DIRCLR = 0x08) //PORTA.3


//Led Defines
#define LedRedConfigPin (PORTC.DIRSET = 0x10) //PORTC.4
#define LedRedOn (PORTC.OUTSET = 0x10)
#define LedRedOff (PORTC.OUTCLR = 0x10)
#define LedRedTgl (PORTC.OUTTGL = 0x10)

#define LedGreenConfigPin (PORTC.DIRSET = 0x08) //PORTC.3
#define LedGreenOn (PORTC.OUTSET = 0x08)
#define LedGreenOff (PORTC.OUTCLR = 0x08)
#define LedGreenTgl (PORTC.OUTTGL = 0x08)


//Shunt ADC Defines
#define ShuntAdcConfigPin (PORTA.DIRCLR = 0x40) //PORTA.6


//UBat ADC Defines
#define UBatAdcConfigPin (PORTA.DIRCLR = 0x10) //PORTA.4


//KommutierungsPin Defines
#define KommPinConfig (PORTD.DIRSET = 0x04)
#define KommPinTgl (PORTD.OUTTGL = 0x04)



//Routine Defines
void InitClock(void);
void InitInterrupt(void);
void InitPCUart(void);
void InitPwmTimer(void);
void InitRpmTimer(void);
void InitPwmInputTimer(void);
void InitAc(void);
void InitAdc(void);

int main(void);

void ReadVoltage(void);
void ReadCurrent(void);

void Wait(uint16_t s);
void WaitMs(uint16_t ms);
void WaitUs(uint16_t us);

void SendPCUart(char data[], uint8_t crlf);

void Anlauf(void);

void ZustandStateMachine(void);



//Voltage ADC
int32_t VoltageLp;
int32_t VoltageV;


//Current ADC
int32_t CurrentLp;
int32_t CurrentA;


//Zustand
volatile uint8_t Zustand = 1;


volatile char debug1[20];
volatile char debug2[20];
volatile char debug3[20];


volatile uint16_t AcTimerDelay;


volatile int16_t PwmIn;

volatile int32_t SetPwm;


int32_t SollDrehzahl;
int32_t DrehzahlTmp;
int32_t DrehzahlLp;

int32_t DrehzahlOld;


//This parameters have to be adapted according to the actual motor!
int32_t kV = 1100;
int32_t NumberOfMagnets = 10;

int32_t PSet = 0;
int32_t DSet = 0;


int main(void)
{

InitClock();
InitPCUart();

InitPwmTimer();

//InitPwmInputTimer();

InitAc();

InitAdc();

//Init Pins
LedRedConfigPin;
LedGreenConfigPin;

PhaseASdConfigPin;
PhaseBSdConfigPin;
PhaseCSdConfigPin;
PhaseAPwmConfigPin;
PhaseBPwmConfigPin;
PhaseCPwmConfigPin;

PhaseAGnd;
PhaseBGnd;
PhaseCGnd;

LedRedOff;

//cut off MosFets
PhaseASdOff;
PhaseBSdOff;
PhaseCSdOff;


KommPinConfig;


//make sure to allways be able to programm the avr
Wait(2);

SendPCUart("Start",1);

WaitMs(500);

InitRpmTimer();

LedRedOn;
LedGreenOn;
WaitMs(500);
LedGreenOff;


Anlauf();
InitInterrupt();
while(1)
{
Zustand++;
if(Zustand>=7)
{
Zustand = 1;
}
ZustandStateMachine();
WaitUs((uint16_t)1000);
}

}

void InitAdc(void)
{
VoltagePinConfig;
CurrentPinConfig;
CurrentNegPinConfig;

ADCA.CTRLB = 0x18;
ADCA.REFCTRL = 0x11;
ADCA.EVCTRL = 0x40;
ADCA.PRESCALER = 0x03;

ADCA.CH0.CTRL = 0x01;
ADCA.CH0.MUXCTRL = 0x20;
ADCA.CH0.CTRL |= ADC_CH_START_bm;

ADCA.CH1.CTRL = 0b00001111;
ADCA.CH1.MUXCTRL = 0x30 | 0x03;
ADCA.CH1.CTRL |= ADC_CH_START_bm;

ADCA.CTRLA = 0x01;
}

void InitPwmInputTimer(void)
{
PwmInputPinConfig;

PwmInputTimer.CTRLA = 0x01; //Prescaler = 1
PwmInputTimer.CTRLB = 0x40; //CC C enabled , normal mode
PwmInputTimer.CTRLD = 0x20; //Event = input capture
}

void Anlauf(void)
{
SetPwm = AnlaufPwm;

for(uint16_t i=0;i<2000;i+=15) //2000
{
Zustand++;
if(Zustand>=7) { Zustand = 1; }
ZustandStateMachine();
WaitUs((uint16_t)3000-i);
}
}

void ZustandStateMachine(void)
{
if(SetPwm<MinPwm) { SetPwm = MinPwm; }
if(SetPwm>MaxPwm) { SetPwm = MaxPwm; }

if(Zustand==1)
{
PhaseASdOn;
PhaseBSdOff;
PhaseCSdOn;

PhaseAPwm = (uint16_t)SetPwm;
PhaseCGnd;

AcFalling;
PhaseBAcUse;
}else if(Zustand==2)
{
PhaseASdOff;
PhaseBSdOn;
PhaseCSdOn;

PhaseBPwm = (uint16_t)SetPwm;
PhaseCGnd;

AcRising;
PhaseAAcUse;
}else if(Zustand==3)
{
PhaseASdOn;
PhaseBSdOn;
PhaseCSdOff;

PhaseBPwm = (uint16_t)SetPwm;
PhaseAGnd;

AcFalling;
PhaseCAcUse;
}else if(Zustand==4)
{
PhaseASdOn;
PhaseBSdOff;
PhaseCSdOn;

PhaseCPwm = (uint16_t)SetPwm;
PhaseAGnd;

AcRising;
PhaseBAcUse;
}else if(Zustand==5)
{
PhaseASdOff;
PhaseBSdOn;
PhaseCSdOn;

PhaseCPwm = (uint16_t)SetPwm;
PhaseBGnd;

AcFalling;
PhaseAAcUse;
}else if(Zustand==6)
{
PhaseASdOn;
PhaseBSdOn;
PhaseCSdOff;

PhaseAPwm = (uint16_t)SetPwm;
PhaseBGnd;

AcRising;
PhaseCAcUse;
}
}

void InitAc(void)
{
PhaseAACConfigPin;
PhaseBACConfigPin;
PhaseCACConfigPin;
PhaseMittelConfigPin;

AcFalling;
Zustand = 1;
PhaseAAcUse;
}

void InitPwmTimer(void)
{
PwmPortPinConfig;

PwmTimer.CTRLA = 0x01; //Prescaler = 1
PwmTimer.CTRLB = 0x73; //CCA CCB CCC enabled , Single-Slop Pwm
PwmTimer.CTRLC = 0x00;
PwmTimer.CTRLD = 0x00;
PwmTimer.CTRLE = 0x00;

PwmTimer.PER = TimerPer;
PhaseAGnd;
PhaseBGnd;
PhaseCGnd;
}

void InitRpmTimer(void)
{
RpmTimer.CTRLA = 0x01; //Prescaler = 8 (0x04)
RpmTimer.INTCTRLA = 0x03;
}

void Wait(uint16_t s)
{
s*=1000;
for(s;s>=1;s--)
{
_delay_ms(1);
}
}

void WaitMs(uint16_t ms)
{
for(ms;ms>=1;ms--)
{
_delay_ms(1);
}
}

void WaitUs(uint16_t us)
{
for(us;us>=1;us--)
{
_delay_us(1);
}
}

void ReadVoltage(void)
{
uint16_t VoltageRead;
VoltageRead = ADCA.CH0.RES;
VoltageLp = (VoltageLp*31 + VoltageRead)>>5;
VoltageV = (VoltageLp * 1165) / 10000;
}

void ReadCurrent(void)
{
uint16_t CurrentRead;
CurrentRead = ADCA.CH1.RES;
CurrentLp = (CurrentLp* 31 + CurrentRead)>>5;
CurrentA = (CurrentLp);
}

void SendPCUart(char data[], uint8_t crlf)
{
char Counter = 0x00;
char lenght = 0x00;

lenght = strlen(data);

while(Counter < lenght)
{
while (!(PCUartPort.STATUS & USART_DREIF_bm));
PCUartPort.DATA = data[Counter];
Counter++;
}

Counter = 0x00;
if(crlf==1)
{
while (!( PCUartPort.STATUS & USART_DREIF_bm));
PCUartPort.DATA = 0x0D;
while (!( PCUartPort.STATUS & USART_DREIF_bm));
PCUartPort.DATA = 0x0A;
}
}

void InitClock(void)
{
OSC.CTRL |= OSC_RC32MEN_bm;
while(!(OSC.STATUS & OSC_RC32MRDY_bm));
CCP = CCP_IOREG_gc;
CLK.CTRL = CLK_SCLKSEL_RC32M_gc;
}

void InitPCUart(void)
{
PCUartPinConfig;
PCUartPort.BAUDCTRLB = 0;
PCUartPort.BAUDCTRLA = 0x11;
PCUartPort.CTRLB = USART_TXEN_bm | USART_RXEN_bm;
PCUartPort.CTRLC = 0x03;
PCUartPort.CTRLA = 0;
}

void InitInterrupt(void)
{
PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
sei();
}

ISR(ACA_AC0_vect)
{
//SetPwm = PwmIn;
KommPinTgl;
LedGreenTgl;
//Zustand++;
//if(Zustand>=7) { Zustand = 1; }
//ZustandStateMachine();
//ClearAcIntFlag;
WaitMs(100);
}


Wenn jemand ne Idee hat, was man testen könnte, wäre ich sehr dankbar!

Gruß
Chris

Che Guevara
06.02.2014, 10:54
Hi,

also ich den "Fehler" wohl jetzt gefunden:
Es ist das Fehlen / Auskommentiertsein der Timer-ISR?! Sobald diese im Programm steht (aber auch leer!), funktioniert der Komperator.
Kann mir das jemand erklären? Hab ich was verpasst?

Gruß
Chris

EDIT:
Vielen Dank an einen freundlichen User, er hat mir die Lösung per PN zukommen lassen. Es ist wohl in der Tat so, dass ein konfigurierter Timer ohne entsprechend definierte ISR einen Reset auslösen kann / wird.