Сначала приведу код , а потом расскажу в чём проблема:
Хэдер для АЦП:
Код
#define ADC_BUFFER_SIZE 256
/*
AdcConvertionMode - режим преобразования, знаковый или без знаковый (см. в даташите на странице )
== 0 - беззнаковый режим
== 1 - знаковый режим
Resolution - разрядность
== 00 - 12 бит выравнивание справа
== 01 - зарезервированно
== 10 - 8 бит выравневание справа
== 11 - 12 бит выравнивание слева
Reference - опорное напряжения
== 00 - внутреннее 1.00V
== 01 - внешнее VCC/1.6
== 10 - внешнее на порту A.
== 11 - внешнее на порту B.
Prescaler - делитель частоты АЦП
== 000 - 4
== 001 - 8
== 010 - 16
== 011 - 32
== 100 - 64
== 101 - 128
== 110 - 256
== 111 - 512
AdcPin - Вход АЦП
== 000 - ADC0 pin
== 001 - ADC1 pin
== 010 - ADC2 pin
== 011 - ADC3 pin
== 100 - ADC4 pin
== 101 - ADC5 pin
== 110 - ADC6 pin
== 111 - ADC7 pin
Values[ADC_BUFFER_SIZE] - буфер в котором хранятся преобразованные значения
CurVal - текущее количество значений в буфере
ConversionCnt - количество измерений которые надо сделать
Flags - текущее состояние АЦП
*/
struct ADC_cfg
{
unsigned char AdcConvertionMode;
unsigned char Resolution;
unsigned char Reference;
unsigned char Prescaler;
unsigned char AdcPin;
unsigned short Values[ADC_BUFFER_SIZE];
unsigned short CurVal;
unsigned short ConversionCnt;
unsigned char Flags;
} ADC_config;
#define ADC_STOPED 0
#define ADC_STARTED 1
#define ADC_CONVERSION_COMPLETE 2
void ADC_init();
void ADC_deinit();
void ADC_flush();
void ADC_start();
void ADC_wait();
Соурс для АЦП:Код
void ADC_init()
{
// нужную ногу настраиваем на вход
PORTA.DIRCLR = 1 << ADC_config.AdcPin;
// CTRLA - ADC Control Register A (см. в даташите на странице 302)
// здесь просто включаем АЦП выставляя нуливой бит
ADCA.CTRLA = 1;
// CTRLB - ADC Control Register B
// здесь в зависимосте от настроек выставляем знак, режим, разрядность
ADCA.CTRLB = ((ADC_config.AdcConvertionMode << ADC_CONMODE_bp) | (ADC_config.Resolution << 1));
// REFCTRL - ADC Reference Control register
// выставляем опорное напряжение
ADCA.REFCTRL = (ADC_config.Reference << 4) | 2;
// делитель частоты АЦП, по даташиту максимальная частота 2 МГц
ADCA.PRESCALER = ADC_config.Prescaler;
// Настраиваем мультиплексор
ADCA.CH0.CTRL = 1;
ADCA.CH0.MUXCTRL = ADC_config.AdcPin << 3;
ADCA.CH0.INTCTRL = 3;
ADC_config.CurVal = 0;
ADC_config.Flags = ADC_STOPED;
}
void ADC_deinit()
{
// отключаем АЦП
ADCA.CTRLA = 0;
ADC_config.Flags = ADC_STOPED;
}
void ADC_flush()
{
// очистить АЦП
ADCA.CTRLA |= 2;
ADC_config.CurVal = 0;
ADC_config.Flags = ADC_STOPED;
}
void ADC_start()
{
// начать преобразование
//ADCA.CH0.CTRL |= 128;
ADCA.CTRLA |= 4; // start channel 0
ADC_config.Flags = ADC_STARTED;
}
void ADC_wait()
{
do {} while(ADC_config.Flags != ADC_CONVERSION_COMPLETE);
}
ISR(ADCA_CH0_vect)
{
ADC_config.Values[ADC_config.CurVal] = ADCA.CH0.RES;
//ADCA.CH0.INTFLAGS = ADC_CH_CHIF_bm;
ADC_config.CurVal++;
ADC_config.ConversionCnt--;
if(ADC_config.ConversionCnt != 0)
{
ADC_start();
}
else
{
ADC_config.Flags = ADC_CONVERSION_COMPLETE;
}
}
И как пользуюсь: Код
// заполняем конфигурационную структуру
ADC_config.AdcConvertionMode = 0; // без знаковый
ADC_config.Resolution = 0; // 12 бит, выравневание справа
ADC_config.Reference = 0; // внутрений источник опорного напряжения 1 В
ADC_config.Prescaler = 2; // делитель частоты 64 (частота АЦП получается 2 МГц при тактовой частоте камня 500 КГц)
ADC_config.AdcPin = 0; // выбираем ногу ADC0
// инициализируем АЦП
ADC_init();
// устанавляваем количество преобразований
ADC_config.ConversionCnt = ((unsigned short) ParseBuf[1]) << 8;
ADC_config.ConversionCnt |= (unsigned short) ParseBuf[0];
// запускаем цикл измерений
ADC_flush();
ADC_start();
// ожидаем завершения цикла измерений
[color="#FF0000"]_delay_us(50); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!![/color]
ADC_wait();
// отключаем АЦП
ADC_deinit();
Проблема в следующем: если есть строка
_delay_us(50); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! то всё работает норм, делаются нужное количество преобразований и отсылаются мне на комп... А вот если я убираю данную строку то программа зависает в функции ADC_wait(); (там цикл выполняется пока все преобразования не выполнятся). Флаг выставляется в прерывании АЦП (строчка ADC_config.Flags = ADC_CONVERSION_COMPLETE;)... Без вот этой задержки почему то не каких преобразований не делается, может конечно они делаются но прерывание не срабатывает!!!
Люди, может я что то упускаю из особенностей работы с данным АЦП?
Вот если нужно проект для AVR Studio 5:
ADC.rar ( 290.39 килобайт )
Кол-во скачиваний: 106