|
Xmega АЦП |
|
|
|
Mar 11 2012, 07:26
|
Частый гость
 
Группа: Участник
Сообщений: 140
Регистрация: 21-04-11
Пользователь №: 64 524

|
Сначала приведу код , а потом расскажу в чём проблема: Хэдер для АЦП: Код #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
|
|
|
|
|
 |
Ответов
|
Mar 11 2012, 08:34
|
Частый гость
 
Группа: Участник
Сообщений: 140
Регистрация: 21-04-11
Пользователь №: 64 524

|
Цитата(Палыч @ Mar 11 2012, 10:40)  Вероятно, не хватает volatile при описании Flags А зачем? это же просто переменная в которой я храню текущее состояние АЦП и все...
|
|
|
|
|
Mar 11 2012, 09:24
|
Частый гость
 
Группа: Участник
Сообщений: 140
Регистрация: 21-04-11
Пользователь №: 64 524

|
Цитата(Палыч @ Mar 11 2012, 11:54)  Поскольку значение этого поля структуры может измениться "вдруг" при наступлении прерывания А можно по подробней... просто я считал что volatile используется для гарантирования, что что-то запишется во флэш (например volatile asm("cli"))!!!!! Поставил volatile помогло БОЛЬШУЩЕЕ СПАСИБО Палыч!!!!!!!!
|
|
|
|
|
Mar 11 2012, 09:42
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Xeon @ Mar 11 2012, 13:24)  А можно по подробней... Выполнение цикла в ADC_wait() выполняется следующим образом: 1. Взять значение Flags на регистр Temp 2. Сравнить значение регистра Temp со значением ADC_CONVERSION_COMPLETE 3. Если условие не выполняется то выход из цикла и функции 4. В противном случае - переход: а) при отсутствии volatile - значение Flags не изменилось в теле цикла и находится в регистре Temp, то переход на п.2 (впадаем в бесконечный цикл) б) с volatile - значение Flags могло быть изменено где-то (не важно где), то на п.1
|
|
|
|
|
Mar 11 2012, 12:58
|
Частый гость
 
Группа: Участник
Сообщений: 140
Регистрация: 21-04-11
Пользователь №: 64 524

|
Цитата(Палыч @ Mar 11 2012, 13:42)  Выполнение цикла в ADC_wait() выполняется следующим образом: 1. Взять значение Flags на регистр Temp 2. Сравнить значение регистра Temp со значением ADC_CONVERSION_COMPLETE 3. Если условие не выполняется то выход из цикла и функции 4. В противном случае - переход: а) при отсутствии volatile - значение Flags не изменилось в теле цикла и находится в регистре Temp, то переход на п.2 (впадаем в бесконечный цикл) б) с volatile - значение Flags могло быть изменено где-то (не важно где), то на п.1 Если я правельно понил: получается, что без volatile зайдя в цикл копируется Flags в temp регистр один раз и потом проверяется при этом нового копирования не происходит...а в случае присутствия volatile значение Flags копируется в temp на каждой итерации?????
|
|
|
|
|
Mar 11 2012, 16:53
|
Частый гость
 
Группа: Участник
Сообщений: 140
Регистрация: 21-04-11
Пользователь №: 64 524

|
Цитата(Палыч @ Mar 11 2012, 19:37)  Да, это - "гримаса" оптимизатора. Спецификатор volatile "подсказывает" оптимизатору, что значение Flags может изменяться в любой момент времени, и заставляет генерить код, который "достаёт" значение переменной из памяти всякий раз, когда её значение используется в неком выражении. Помимо того, что volatile используется для того что бы гарантировать, что какая либо команда будет точно вставленна компилятором и "доставать значение всякий раз когда пытаемся изменить его, для чего ещё может быть использованна volatile?"
|
|
|
|
Сообщений в этой теме
Xeon Xmega АЦП Mar 11 2012, 07:26 Xeon И снова Всем привет! Ситуация следующая нужно ... Mar 28 2012, 10:39 ASDFG123 Как у Xmega 32 A4 дела с ацп ? померить нужно импу... Apr 5 2013, 06:19 Herz Цитата(ASDFG123 @ Apr 5 2013, 09:19) Как ... Apr 5 2013, 06:36 ASDFG123 почитал отзывы по ней, и ацп в пред. ревизиях не р... Apr 5 2013, 07:11 _Артём_ Цитата(ASDFG123 @ Apr 5 2013, 10:11) дата... Apr 5 2013, 08:10 Herz Цитата(ASDFG123 @ Apr 5 2013, 10:11) Нужн... Apr 5 2013, 10:46 vitas56 Цитата(ASDFG123 @ Apr 5 2013, 11:11) почи... Apr 27 2013, 04:13 ASDFG123 да 6 мс, ну вольтметр это я очень упрощенно сказал... Apr 26 2013, 16:24
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|