Посоветуйте как оптимальней (по скорости исполнения) реализовать алгоритм для xmega256A3:
Обрабатываются 8 каналов ацп A и 8 каналов ацп B.
Каждый канал ацп суммируется 16 раз в прерывании таймера, кроме того каналы ацп а могут использоваться как логические входы (пороги задаются), и также перепады могут фиксироваться (инкремент счётчика). В каждом прерывании считываются и запускается 4 преобразования ацп а и 4 ацп Б.
CODE
#ifndef adc_h__
#define adc_h__
#include "avr_compiler.h"
#include "adc_driver.h"
#include "adc_driver.h"
struct TADC_AChannel {// данные канала на АЦП А
unsigned char Cnt;// счётчик передов
unsigned char CntUp;// считать фронт
unsigned char CntDown;// считать срез
unsigned char State;// состояние входа
unsigned char NextMux;// значение MUX
unsigned short LvlH, LvlL;// уровни 1 и 0
unsigned short Sum;// накопленная сумма
void Init(
unsigned short level_h, // уровень 1
unsigned short level_l, // уровень 0
unsigned char cnt_mode, // счёт. импульсов/ аналоговый вход
unsigned char state // начальное логическое состояние
) {
Cnt=0;
LvlH=level_h;
LvlL=level_l;
CntUp = (cnt_mode&1) ? (1) : (0);
CntDown = (cnt_mode&2) ? (1) : (0);
State=state;
}
void Exec(unsigned short new_value) {
if (Cnt) {
// режим счёта импульсов
if (State) {
if (new_value<LvlL) {
State=0;
if (CntDown)
Cnt++;
}
}
else {
if (new_value>LvlH) {
State=1;
if (CntUp)
Cnt++;
}
}
}
Sum+=new_value;
}
};
struct TADC_BChannel {// данные канала на АЦП А
unsigned short Sum;// накопление суммы
unsigned char NextMux;
void Exec(unsigned short new_value) {
Sum+=new_value;
}
};
class TAdc {
unsigned char ADCAMode;
volatile unsigned char ActiveArray;
volatile unsigned char SumReady;
struct TADC_AChannel AdcA[2][8];
struct TADC_BChannel AdcB[2][8];
volatile unsigned char ADCReady;
unsigned char CycleCnt;
public:
void StartNextConvervion()
{
TADC_AChannel *adc_ptr;
// определение текущего блока памяти для записи
unsigned char active_block = (ActiveArray) ? (1) : (0);
adc_ptr= (active_block) ? (&AdcA[1][0]) : (&AdcA[0][0]);
if (CycleCnt&1)
adc_ptr+=4; // чтение каналов 4-7
unsigned short adc_result;
// виртуальный канал 0 АЦП А
adc_result=ADCA.CH0.RES;
adc_ptr->Exec(adc_result);
ADCA.CH0.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;
// виртуальный канал 1 АЦП А
adc_result=ADCA.CH1.RES;
adc_ptr->Exec(adc_result);
ADCA.CH1.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;
// виртуальный канал 2 АЦП А
adc_result=ADCA.CH2.RES;
adc_ptr->Exec(adc_result);
ADCA.CH2.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;
// виртуальный канал 3 АЦП А
adc_result=ADCA.CH3.RES;
adc_ptr->Exec(adc_result);
ADCA.CH3.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;
struct TADC_BChannel *adcb_ptr=(active_block) ? (&AdcB[1][0]) : (&AdcB[0][0]);
// виртуальный канал 1 АЦП B
adc_result=ADCB.CH0.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH0.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;
// виртуальный канал 2 АЦП B
adc_result=ADCB.CH1.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH1.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;
// виртуальный канал 3 АЦП B
adc_result=ADCB.CH2.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH2.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;
// виртуальный канал 4 АЦП B
adc_result=ADCB.CH3.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH3.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;
// запуск преобразования
ADC_Conversions_Start(&ADCA, 0xF<<2);
ADC_Conversions_Start(&ADCB, 0xF<<2);
if (++CycleCnt>=16) {
// накоплено 16 отсчётов
CycleCnt=0;
adc_ptr= (active_block) ? (&AdcA[0][0]) : (&AdcA[1][0]);
TADC_AChannel *adc_ptr2= (active_block) ? (&AdcA[1][0]) : (&AdcA[0][0]);
for (char i=0; i<16; i++) {
adc_ptr->Cnt=0;
adc_ptr->Sum=0;
adc_ptr->State=adc_ptr2->State;
adc_ptr++;
adc_ptr2++;
}
adcb_ptr=(active_block) ? (&AdcB[0][0]) : (&AdcB[1][0]);
for (char i=0; i<16; i++) {
adcb_ptr->Sum=0;
}
SumReady=1;
}
}
};
extern TAdc Adc;
void InitADC();
#endif // adc_h__
#define adc_h__
#include "avr_compiler.h"
#include "adc_driver.h"
#include "adc_driver.h"
struct TADC_AChannel {// данные канала на АЦП А
unsigned char Cnt;// счётчик передов
unsigned char CntUp;// считать фронт
unsigned char CntDown;// считать срез
unsigned char State;// состояние входа
unsigned char NextMux;// значение MUX
unsigned short LvlH, LvlL;// уровни 1 и 0
unsigned short Sum;// накопленная сумма
void Init(
unsigned short level_h, // уровень 1
unsigned short level_l, // уровень 0
unsigned char cnt_mode, // счёт. импульсов/ аналоговый вход
unsigned char state // начальное логическое состояние
) {
Cnt=0;
LvlH=level_h;
LvlL=level_l;
CntUp = (cnt_mode&1) ? (1) : (0);
CntDown = (cnt_mode&2) ? (1) : (0);
State=state;
}
void Exec(unsigned short new_value) {
if (Cnt) {
// режим счёта импульсов
if (State) {
if (new_value<LvlL) {
State=0;
if (CntDown)
Cnt++;
}
}
else {
if (new_value>LvlH) {
State=1;
if (CntUp)
Cnt++;
}
}
}
Sum+=new_value;
}
};
struct TADC_BChannel {// данные канала на АЦП А
unsigned short Sum;// накопление суммы
unsigned char NextMux;
void Exec(unsigned short new_value) {
Sum+=new_value;
}
};
class TAdc {
unsigned char ADCAMode;
volatile unsigned char ActiveArray;
volatile unsigned char SumReady;
struct TADC_AChannel AdcA[2][8];
struct TADC_BChannel AdcB[2][8];
volatile unsigned char ADCReady;
unsigned char CycleCnt;
public:
void StartNextConvervion()
{
TADC_AChannel *adc_ptr;
// определение текущего блока памяти для записи
unsigned char active_block = (ActiveArray) ? (1) : (0);
adc_ptr= (active_block) ? (&AdcA[1][0]) : (&AdcA[0][0]);
if (CycleCnt&1)
adc_ptr+=4; // чтение каналов 4-7
unsigned short adc_result;
// виртуальный канал 0 АЦП А
adc_result=ADCA.CH0.RES;
adc_ptr->Exec(adc_result);
ADCA.CH0.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;
// виртуальный канал 1 АЦП А
adc_result=ADCA.CH1.RES;
adc_ptr->Exec(adc_result);
ADCA.CH1.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;
// виртуальный канал 2 АЦП А
adc_result=ADCA.CH2.RES;
adc_ptr->Exec(adc_result);
ADCA.CH2.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;
// виртуальный канал 3 АЦП А
adc_result=ADCA.CH3.RES;
adc_ptr->Exec(adc_result);
ADCA.CH3.MUXCTRL=adc_ptr->NextMux;
adc_ptr++;
struct TADC_BChannel *adcb_ptr=(active_block) ? (&AdcB[1][0]) : (&AdcB[0][0]);
// виртуальный канал 1 АЦП B
adc_result=ADCB.CH0.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH0.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;
// виртуальный канал 2 АЦП B
adc_result=ADCB.CH1.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH1.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;
// виртуальный канал 3 АЦП B
adc_result=ADCB.CH2.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH2.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;
// виртуальный канал 4 АЦП B
adc_result=ADCB.CH3.RES;
adcb_ptr->Exec(adc_result);
ADCB.CH3.MUXCTRL=adcb_ptr->NextMux;
adcb_ptr++;
// запуск преобразования
ADC_Conversions_Start(&ADCA, 0xF<<2);
ADC_Conversions_Start(&ADCB, 0xF<<2);
if (++CycleCnt>=16) {
// накоплено 16 отсчётов
CycleCnt=0;
adc_ptr= (active_block) ? (&AdcA[0][0]) : (&AdcA[1][0]);
TADC_AChannel *adc_ptr2= (active_block) ? (&AdcA[1][0]) : (&AdcA[0][0]);
for (char i=0; i<16; i++) {
adc_ptr->Cnt=0;
adc_ptr->Sum=0;
adc_ptr->State=adc_ptr2->State;
adc_ptr++;
adc_ptr2++;
}
adcb_ptr=(active_block) ? (&AdcB[0][0]) : (&AdcB[1][0]);
for (char i=0; i<16; i++) {
adcb_ptr->Sum=0;
}
SumReady=1;
}
}
};
extern TAdc Adc;
void InitADC();
#endif // adc_h__
Прерывание:
Код
TAdc Adc;
ISR(TCC0_OVF_vect)
{
Adc.StartNextConvervion();
}
ISR(TCC0_OVF_vect)
{
Adc.StartNextConvervion();
}
IAR выдал код с временем выполнения 450-550 циклов в зависимости от настроек оптимизации, что не есть гуд.
Из интереса создал проект для GCC, проверил в симуляторе ~320-350 тактов (не ожидал такого результата - удивлён).
Как получить от IAR похожий результат?
P.S. Проект сначала не компилился для GCC:
Код
In file included from ../../avr_compiler.h:132:0,
from ../task1.cpp:2:
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h: In function 'void _delay_ms(double)':
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:149:42: error: 'fabs' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:149:43: error: 'ceil' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h: In function 'void _delay_us(double)':
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:226:42: error: 'fabs' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:226:43: error: 'ceil' was not declared in this scope
make: *** [task1.o] Ошибка 1
from ../task1.cpp:2:
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h: In function 'void _delay_ms(double)':
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:149:42: error: 'fabs' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:149:43: error: 'ceil' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h: In function 'void _delay_us(double)':
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:226:42: error: 'fabs' was not declared in this scope
c:\avr_toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h:226:43: error: 'ceil' was not declared in this scope
make: *** [task1.o] Ошибка 1
Что за ...?
Прект:Нажмите для просмотра прикрепленного файла
Закоментировал delay.h. Тогда откомпилировалось.