XMEGA interrupts question

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

gentlemen,

 

I have been working on the software part and I wanted to consult your expertise, once more. I noticed that the interrupts generated by the XMEGA A for the analog comparators AC0 and AC1 do not have the event that I need. I wanted an AC to trigger interrupt for the output levels of the analog comparators. for example, if the output of AC1 is HIGH, the module should keep triggering interrupts until the output goes LOW. However, the XMEGA A manual indicates that the interrupts are generated for the following transitions: BOTHEDGES, FALLING, and RISING. Is there a way to force the XMEGA controller to trigger interrupts on the high or low levels? 

 

Due to the extremely amount of work at my job, it has been kind of slow progress with my personal project. Below, I am posting the C-code that I have drafted so far. If I cannot force the XMEGA A controller to constantly generate interrupts based on the level of the comparators' output, I will have to modify the code to perform the actions in the while loop of the main.

/* The goal is to maintain the array current (Ia) within a lower limit of
* about 100 ma and an upper current limit of about 200 ma. When the output
voltage
* of the current sensor ACS722 outputs 1.6764 volts, the corresponding array
current
* (Ia) is about 100 ma. When the output voltage of the current sensor ACS722 is
* 1.7028 volts, the corresponding array current (Ia) is about 200 ma.
* The voltage reference for the lower current limit will be provided by the
internal
* voltage reference using a scale factor of 32 (0x20) which corresponds to about
1.7015625v,
* which also corresponds to the output from the current sensor ACS722 of
195.3125 ma (Ia),
* approximately 200 ma.
*
* The reference voltage for the lower current limit of 100 ma will be provided
by the reference
* voltage (Vr) represented by the voltage divider network which includes the
potentiometers. When
* the output from the current sensor is 1.6764v, the array current (Ia) is about
100 ma.
*

* AC0 is configured to detect the lower current limit and ACA1 to detect the
upper current limit.
* The software allows to connect the (+) positive input of ACA1 and the (-)
negative input from
* AC0 to the current sensor through the pin PA3. The (-) negative input from AC1
is connected
* to the internal reference voltage and the (+) positive input from AC0 is
connected to the
* external reference voltage (Vr) formed by the potentiometers through the pin
PA4.
*
* The lower current limit event is detected by the falling edge interrupt of
ACA0
* and the upper current limit by the falling edge of ACA1 because of the
swapping of the
* inputs of the comparator ACA1.
*
* The interrupt from AC0 is configured for medium priority level and AC1 will be
given a high
* priority level.
*
*/

/* Header Files */
#include <avr/io.h>
#include <avr/interrupt.h>
//#define F_CPU 32000000UL
//#include <util/delay.h>
//#include <pmic.h>
/* GLOBAL DATA DECLARATION */
#define SCALEFACT 0x20 //Reference voltage scale factor for 1.7016v (approx.
200ma)
#define TOTALEDPAIRS 10 /* The total number of LED pairs in the array of the
prototype
* is 32. The total number of LEDs in the prototype is
100.
* If Vin is 120 vac, make TotalLedPairs = 20 for a
total number
* of LEDs equals 60 (=20*3).
* 10 = 9 LPairs and 3 series connected LEDs for a
total of 30 LEDs */
/* Definition of LED Pair Masks*/
#define LP01M (1 << 0) /* Mask for digital output PA0 at pin #40 */
#define LP02M (1 << 1) /* Mask for digital output PA1 at pin #41 */
#define LP03M (1 << 2) /* Mask for digital output PA2 at pin #42 */
#define LP04M (1 << 5) /* Mask for digital output PA5 at pin #1 */
#define LP05M (1 << 6) /* Mask for digital output PA6 at pin #2 */
#define LP06M (1 << 7) /* Mask for digital output PA7 at pin #3 */
#define LP07M (1 << 0) /* Mask for digital output PB0 at pin #4 */
#define LP08M (1 << 1) /* Mask for digital output PB1 at pin #5 */
#define LP09M (1 << 2) /* Mask for digital output PB2 at pin #6 */
#define LP10M (1 << 3) /* Mask for digital output PB3 at pin #7 */
#define LP11M (1 << 0) /* Mask for digital output PC0 at pin #10 */
#define LP12M (1 << 1) /* Mask for digital output PC1 at pin #11 */
#define LP13M (1 << 2) /* Mask for digital output PC2 at pin #12 */
#define LP14M (1 << 3) /* Mask for digital output PC3 at pin #13 */
#define LP15M (1 << 4) /* Mask for digital output PC4 at pin #14 */
#define LP16M (1 << 5) /* Mask for digital output PC5 at pin #15 */
#define LP17M (1 << 6) /* Mask for digital output PC6 at pin #16 */
#define LP18M (1 << 7) /* Mask for digital output PC7 at pin #17 */
#define LP19M (1 << 0) /* Mask for digital output PD0 at pin #20 */
#define LP20M (1 << 1) /* Mask for digital output PD1 at pin #21 */
#define LP21M (1 << 2) /* Mask for digital output PD2 at pin #22 */
#define LP22M (1 << 3) /* Mask for digital output PD3 at pin #23 */
#define LP23M (1 << 4) /* Mask for digital output PD4 at pin #24 */
#define LP24M (1 << 5) /* Mask for digital output PD5 at pin #25 */
#define LP25M (1 << 6) /* Mask for digital output PD6 at pin #26 */
#define LP26M (1 << 7) /* Mask for digital output PD7 at pin #27 */
#define LP27M (1 << 0) /* Mask for digital output PE0 at pin #28 */
#define LP28M (1 << 1) /* Mask for digital output PE1 at pin #29 */
#define LP29M (1 << 2) /* Mask for digital output PE2 at pin #32 */
#define LP30M (1 << 3) /* Mask for digital output PE3 at pin #33 */
#define LP31M (1 << 0) /* Mask for digital output PR0 at pin #36 */
#define LP32M (1 << 1) /* Mask for digital output PR1 at pin #37 */

typedef struct ledType { volatile uint8_t *pPort; volatile uint8_t mask; };

volatile uint8_t ledPairNum = 0; /* Global counter variable keeps track of the
* configuration of the LED PAIRS. */

/* Function prototypes to reset all digital outputs and counter variable to zero
* for unwanted events */
volatile void resetLP(void);
void setup(void);
void setup_clock(void);
void setup_PMIC(void);
void setup_GPIO(void);
void setup_AC0(void);

/* This structure allows to operate the I/O pins of the ports
* in a sequential manner */

struct ledType ledPairPins[32] = {
/* Array of structures containing the output ports and corresponding 
* pin positions (LED Pairs - digital I/Os) */
{ &PORTA.OUT, LP01M }, { &PORTA.OUT, LP02M },
{ &PORTA.OUT, LP03M }, { &PORTA.OUT, LP04M },
{ &PORTA.OUT, LP05M }, { &PORTA.OUT, LP06M },
{ &PORTB.OUT, LP07M }, { &PORTB.OUT, LP08M },
{ &PORTB.OUT, LP09M }, { &PORTB.OUT, LP10M },
{ &PORTC.OUT, LP11M }, { &PORTC.OUT, LP12M },
{ &PORTC.OUT, LP13M }, { &PORTC.OUT, LP14M },
{ &PORTC.OUT, LP15M }, { &PORTC.OUT, LP16M },
{ &PORTC.OUT, LP17M }, { &PORTC.OUT, LP18M },
{ &PORTD.OUT, LP19M }, { &PORTD.OUT, LP20M },
{ &PORTD.OUT, LP21M }, { &PORTD.OUT, LP22M },
{ &PORTD.OUT, LP23M }, { &PORTD.OUT, LP24M },
{ &PORTD.OUT, LP25M }, { &PORTD.OUT, LP26M },
{ &PORTE.OUT, LP27M }, { &PORTE.OUT, LP28M },
{ &PORTE.OUT, LP29M }, { &PORTE.OUT, LP30M },
{ &PORTR.OUT, LP31M }, { &PORTR.OUT, LP32M }
};

int main(void) {
/* initialization code */
setup();
resetLP();
while (1)
{
}
return 0;
}

ISR(ACA_AC0_vect) {
/* The array current has moved below the allowable lower limit */
if (ledPairNum > (TOTALEDPAIRS)) { /* Illegal values of ledPairNum */
/* if ledPairNum > 32, call resetLP(). Illegal value of ledPairNum Something
* went wrong */
resetLP();
}
else if (ledPairNum == (TOTALEDPAIRS)) {
/* if ledPairNum == 32 do nothing. All 32 LPairs are already ON
* and configured in parallel. This is the event when the input
* voltage is in the zone of zero voltage crossing */
}
else { //0 =< ledPairNum < TOTALEDPAIRS-1. legal value of ledPairNum
/* Allowable value of the counter variable. Set an output to turn ON an
LED

* Pair and increase counter variable */
/* Turn ON a LED pair */
*(ledPairPins[ledPairNum].pPort) |= ledPairPins[ledPairNum].mask;
ledPairNum++; /* increment counter variable to point to the next inactive
LED pair */
}
}
ISR(ACA_AC1_vect) {
/* The array current has moved above the allowable upper limit */
if (ledPairNum > (TOTALEDPAIRS)) { // ledPairNum > 32 Illegal values of
ledPairNum.
/* or if ledPairNum = 31 - all 32 LPs are already ON and something went
wrong */
resetLP();
}
else if (ledPairNum == 0) { // All LED pairs are reconfigured in series
/* DO NOTHING */
}
else { // 0 < ledPairNum =< TOTALEDPAIRS
/* Allowable value of the counter variable. Turn OFF an output to turn
OFF
* an LED Pair and decrease counter variable */
ledPairNum--; /* Decrement counter variable to point to the LED pair to
* be deactivated or turned off */
/* Turn OFF a LED pair */
*(ledPairPins[ledPairNum].pPort) &= ~ledPairPins[ledPairNum].mask;
}
}

void setup(void) {
setup_clock();
setup_PMIC();
setup_GPIO();
setup_AC0();
}

void setup_clock(void) {
/* Configure system clock for 32 MHz*/
OSC.CTRL |= OSC_RC32KEN_bm; // Enable the 32.768KHz internal
oscillator
while(!(OSC.STATUS & OSC_RC32KRDY_bm)); //Wait for 32.768KHz internal OSC to
be ready
OSC.CTRL |= OSC_RC32MEN_bm; // Enable the 32MHz internal
oscillator
CPU_CCP = CCP_IOREG_gc; //Allow to write protected clock
register
CLK.PSCTRL = ((CLK.PSCTRL &
(~(CLK_PSADIV_gm | //Reset prescaler A group division
factor
CLK_PSBCDIV_gm | //Reset prescaler B bit 1 division
factor
CLK_PSBCDIV0_bm))) | //Reset prescaler C bit 0 division
factor
CLK_PSADIV_1_gc | //Set prescaler A with division
factor 1
CLK_PSBCDIV_1_1_gc); //Set prescaler B & C with division
factor 1
OSC.DFLLCTRL = ((OSC.DFLLCTRL &
(~(OSC_RC32MCREF_gm | //Reset 32MHz OSC reference Selection
OSC_RC2MCREF_bm))) | //An error?
OSC_RC32MCREF_RC32K_gc); //Set 32.768 KHz CAL reference from
the 32.768KHz
DFLLRC32M.CTRL |= DFLL_ENABLE_bm; //Enable DFLL and auto-calibration
OSC
while(!(OSC.STATUS & OSC_RC32MRDY_bm)); //Wait for 32MHz internal oscillator
to be ready
CPU_CCP = CCP_IOREG_gc; //Allow to write protected clock
register
CLK.CTRL = ((CLK.CTRL &
(~CLK_SCLKSEL_gm)) | //Reset system clock selection group
CLK_SCLKSEL_RC32M_gc); //Set system clock to 32MHz
OSC.CTRL &= (~(OSC_RC2MEN_bm | //Disable 2MHz OSC
OSC_XOSCEN_bm | //Disable external OSC
OSC_PLLEN_bm)); //Disable PLL for no FREQ
multiplication factor
PORTCFG.CLKEVOUT = 0x00; //Disable Event and Clock output
ports
}

void setup_PMIC(void) { /* Programmable Multi-level Interrupt Controller */
sei(); // Enable global interrupts
//PMIC.CTRL |= PMIC_HILVLEN_bm; //Enable HIGH level interrupts in the
PMIC
/* Enable high and medium level interrupts */
PMIC_CTRL |= ( PMIC_CTRL & ~(PMIC_RREN_bm |
PMIC_IVSEL_bm |
PMIC_LOLVLEN_bm )) | //Reset RREN, IVSEL, and LOLVLEN
( PMIC_HILVLEN_bm | //Configure HILVLEN and MEDLVLEN
PMIC_MEDLVLEN_bm );
}

void setup_GPIO(void) { /* General Purpose I/Os */
/* CONFIGURE PORTA */
PORTA.DIR = 0xE7; /* PA3 and PA4 configured as input, the rest
* or the PORTA I/Os as digital output */
PORTA.OUT &= ~(0xE7); /* Reset digital output I/Os of PORTA */
PORTCFG.MPCMASK = 0xE7; /* Group digital outputs I/Os of PORTA */
/* Configure digital output I/Os to push/pull and because of two
* analog input, disable the input register */
PORTA.PIN0CTRL |= PORT_OPC_TOTEM_gc; //PORTA I/Os in push/pull mode
PORTCFG.MPCMASK = 0x18; /* Group pins PA3 and PA4 */
PORTA.PIN3CTRL |= PORT_ISC_INPUT_DISABLE_gc; //Disable interrupt sensing
// for pins PA3 and PA4
/* CONFIGURE PORTB */
PORTB.DIR = 0x0F; /* Configure first four I/Os of PORTB as
* as digital output */
PORTB.OUT &= ~(0x0F); // Reset PORTB first four output pins
PORTCFG.MPCMASK = 0x0F; /* Group first four digital outputs I/Os
* of PORTB */
/* Configure digital output I/Os to push/pull */
PORTB.PIN0CTRL |= PORT_OPC_TOTEM_gc;
/* CONFIGURE PORTC */
PORTC.DIR = 0xFF; /* Configure PORTC as digital output */
PORTC.OUT = 0x00; /* Reset PORTC I/Os output pins */
PORTCFG.MPCMASK = 0xFF; /* Group all digital outputs I/Os s
* of PORTC */
/* Configure digital output I/Os to push/pull */
PORTC.PIN0CTRL |= PORT_OPC_TOTEM_gc;
/* CONFIGURE PORTD */
PORTD.DIR = 0xFF; /* Configure PORTD as digital output */
PORTD.OUT = 0x00; /* Reset PORTD I/Os output pins */
PORTCFG.MPCMASK = 0xFF; /* Group all digital outputs I/Os
* of PORTD */
/* Configure digital output I/Os to push/pull */
PORTD.PIN0CTRL |= PORT_OPC_TOTEM_gc;
/* CONFIGURE PORTE */
PORTE.DIR = 0x0F; /* Configure first four I/Os of PORTE as
* as digital output */
PORTE.OUT &= ~(0x0F); /* Reset PORTE first four output pins */
PORTCFG.MPCMASK = 0x0F; /* Group first four digital outputs I/Os
* of PORTE */
/* Configure digital output I/Os to push/pull */
PORTE.PIN0CTRL |= PORT_OPC_TOTEM_gc;
/* CONFIGURE PORTR */
PORTR.DIR = 0x03; /* Configure first two I/Os of PORTR as
* as digital output */
PORTR.OUT &= ~(0x03); /* Reset PORTR first four output pins */
PORTCFG.MPCMASK = 0x03; /* Group first two digital outputs I/Os
* of PORTR */
/* Configure digital output I/Os to push/pull */
PORTR.PIN0CTRL |= PORT_OPC_TOTEM_gc;
/* Enable Port Interrupt n and select interrupt level */
// PORTA_INTCTRL = ((PORTA_INTCTRL & (~(PORT_INT1LVL_gm | PORT_INT0LVL_gm |
// PORT_INT1LVL_OFF_gc | PORT_INT0LVL_OFF_gc);
}

void setup_AC0(void) { /* Configure analog Comparators ACA0 and ACA1 */

/* CONFIGURE ANALOG COMPARATOR ACA0 FOR LOWER CURRENT LIMIT INTERRUPT */
/* Enable interrupt for rising edge, medium priority, high-speed, and
* large hysteresis mode */
ACA.AC0CTRL = AC_INTMODE_RISING_gc | //Interrupt on rising edge
AC_INTLVL_MED_gc | //Medium interrupt level
AC_HSMODE_bm | //High speed mode
AC_HYSMODE_LARGE_gc | //60mv hysteresis
AC_ENABLE_bm; //Enable ACA0

/* Configure V+ input to connect to pin PA4 for the external reference volt
* and V- to PA3 connect to the current sensor for lower current limit
* AC0 MONITORS THE LOWER CURRENT LIMIT */
ACA.AC0MUXCTRL |= AC_MUXPOS_PIN4_gc | //(+) input to PA4 external ref volt
AC_MUXNEG_PIN3_gc; //(-) input to PA3 for current
Sensing

/* CONFIGURE ANALOG COMPARATOR ACA1 FOR UPPER CURRENT LIMIT INTERRUPT */
/* Enable interrupt for rising edge, high priority, high-speed, and
* large hysteresis mode */
ACA.AC1CTRL = AC_INTMODE_RISING_gc | //Interrupt on rising edge
AC_INTLVL_HI_gc | //High interrupt level
AC_HSMODE_bm | //High speed mode
AC_HYSMODE_LARGE_gc | //60mv hysteresis
AC_ENABLE_bm; //Enable ACA1
/* Configure V+ input to connect to pin PA3 for current sensing
* and V- to connect to internal reference voltage

* AC1 MONITORS THE UPPER CURRENT LIMIT WITH INVERTED LOGIC */
ACA.AC1MUXCTRL |= AC_MUXPOS_PIN3_gc | //(-) input to PA3 for current
Sensing

AC_MUXNEG_SCALER_gc; //(-) input to PA to internal ref.
Voltage

/* Disable analog comparator window mode */
ACA.WINCTRL &= ~AC_WEN_bm;

/* Disable analog comparator output pins */
ACA.CTRLA &= ~AC_AC0OUT_bm;

/* Configure the scale factor for internal voltage reference to 32
* Vscale OF 1.7075625V FOR 195.3125 ma ARRAY CURRENT*/
ACA.CTRLB = (ACA.CTRLB & ~0b00111111) | SCALEFACT;
}

volatile void resetLP(void) { /* Reset all digital outputs and counter variable
*/
PORTA.OUT &= ~(0xE7); // Reset port A output pins, except PA3, PA4
PORTB.OUT &= ~(0x0F); // Reset port B first four output pins
PORTC.OUT = 0x00; // Reset all port C output pins
PORTD.OUT = 0x00; // Reset all port D output pins
PORTE.OUT &= ~(0x0F); // Reset port E first four output pins
PORTR.OUT &= ~(0x03); // Reset port R first two output pins
ledPairNum = 0; // Reset counter variable, all LEDs connected in
series
}

 

 

 

Common Sense is Not That Common And When Used It Could Get You Into Troubles!!!
If used in politics, people may call you CRAZY!
If used in religion, people may call you ATHEIST!
And when used in science, you may be known as a GENIUS!
It all happened to Nikolai Tesla....

Last Edited: Mon. Mar 5, 2018 - 08:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Post split as it deals with another topic now.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there a way to force the XMEGA controller to trigger interrupts on the high or low levels? 

Only for specific interrupts, but not for the Analog Comparator.

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW, if you are using an XMEGA A rather than an XMEGA AU, you should know that the analog portions of the A chips have issues.  Have you read the Errata?

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!