Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ATxMega32D4
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
tier
Подскажите кто чем сможет, что-то бьюсь а результата нет.
Есть ATxMega32D4, на начальном этапе пытаюсь просто измерить постоянное напряжение (~1.2В) которое подается к Pin2.
Ф-я ADC_GetValue() вызывается по требованию программы (необходимость измерения в данный момент)

Независимо от подключенного измеряемого напряжения выдает 0xC0...0xC3 в случае
UnsignedMode и 0x02...0x06 в случае SignedMode (ADC_CONMODE_bm)

CODE
void ADC_Init(void)
{
PORTA.DIRCLR = PIN6_bm; // Настраиваем нужный вход
// Устанавливаем разрядность и режим Signed Mode
ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc | ADC_CONMODE_bm;
ADCA.REFCTRL = ADC_REFSEL_AREFB_gc; // Внешний ИОН 2,36В, подключен к PB0 Pin4

// Настраиваем мультиплексор - Канал 0 ADCA настроен на внешний несимметричный вход
ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;

ADCA.CH0.MUXCTRL |= ADC_CH_MUXPOS_PIN6_gc; // Positive Input ADC6 PA6 Pin2

ADCA.CTRLA |= ADC_ENABLE_bm; // Включаем АЦП

ADCA.PRESCALER = ADC_PRESCALER_DIV256_gc; // Делитель частоты (32МГц/256=125кГц)
// Прерывание по завершению преобразования, уровень прерываний - средний
ADCA.CH0.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_MED_gc;
}

uint16_t ADC_GetValue(void)
{
uint16_t i, tmp, sum = 0;

for (i=0; i<16; i++) // Number of samples
{
ADCA.CTRLA |= ADC_CH0START_bm; // ADC Start Conversion

while(ADCA.CH0.INTFLAGS & ADC_CH_CHIF_bm);
ADCA.CH0.INTFLAGS |= ADC_CH_CHIF_bm; // Clear interrupt flag

tmp = ADCA.CH0RES;
sum += tmp;
}

sum /= 16;

return sum;
}


в чем может быть проблема
_Артём_
Цитата(tier @ May 4 2013, 20:57) *
Независимо от подключенного измеряемого напряжения выдает 0xC0...0xC3 в случае
UnsignedMode

Вход на земле не сидит или может вообще оборван? Есть на нём напряжение?

Цитата(tier @ May 4 2013, 20:57) *
Код
void ADC_Init(void)
{
...
}

Калибровки не хватает, но вряд ли она так сильно влияет. Так всё вроде правильно.

Цитата
ADCA.PRESCALER = ADC_PRESCALER_DIV256_gc; // Делитель частоты (32МГц/256=125кГц)

Не 125кГц, а 125/8, но это не так важно.

Цитата
Код
// Прерывание по завершению преобразования, уровень прерываний - средний
    ADCA.CH0.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_MED_gc;

ADC_GetValue при разрешённых прерываниях измеряет?
JTAG-а в D4 нет? Если есть, то может он разрешён?
tier
Цитата(_Артём_ @ May 4 2013, 22:26) *
Вход на земле не сидит или может вообще оборван? Есть на нём напряжение?


На входе контролирую мультиметром, напряжение есть 1.22В

Цитата(_Артём_ @ May 4 2013, 22:26) *
ADC_GetValue при разрешённых прерываниях измеряет?

да , там где инициализация делаю разрешение уровней прывания

Код
PMIC.CTRL |= PMIC_MEDLVLEN_bm;
PMIC.CTRL |= PMIC_HILVLEN_bm;

JTAGa нет. Я уже пробовал и в дифференциальном режиме измерять подключая Negative Pin к земле. Ничего не меняется.
Такое впечатление что АЦП вообще не работает, не пойму....
bob1
Попробуйте вот этот код под себя переделать:
Код
SLEEP.CTRL=1;


CODE
int16_t ADC_U(uint8_t MUX,uint8_t IN,uint8_t REF)
{
PR.PRPA=PR_AC_bm;
ADCA.CH0.CTRL =IN;
ADCA.CH0.MUXCTRL=MUX;
ADCA.REFCTRL=REF;

if(MUX==ADC_CH_MUXINT_TEMP_gc)
{
ADCA.PRESCALER=ADC_PRESCALER_DIV256_gc;
ADCA.CTRLB=0;
}
else
{
ADCA.PRESCALER=ADC_PRESCALER_DIV256_gc;
ADCA.CTRLB=ADC_CONMODE_bm;
};
ADCA.EVCTRL=0;
ADCA.CTRLA=ADC_ENABLE_bm|ADC_FLUSH_bm; // очистка конвеера

int16_t u=0;

ADCA.CH0.INTCTRL=ADC_CH_INTLVL_LO_gc;
ADCA.CTRLA=ADC_ENABLE_bm|ADC_CH0START_bm;
__sleep();
for(uint8_t i=0;i<16;i++)
{
ADCA.CTRLA=ADC_ENABLE_bm|ADC_CH0START_bm;
__sleep();
int16_t w=ADCA.CH0RES;
u=u+w;
};
ADCA.CH0.INTCTRL=ADC_CH_INTLVL_OFF_gc;
ADCA.REFCTRL=0;
ADCA.CTRLA=0;
PR.PRPA=PR_ADC_bm|PR_AC_bm;
return u;
};
prottoss
Цитата(tier @ May 4 2013, 23:57) *
Код
void ADC_Init(void)
{
...
}

в чем может быть проблема
Я не вдавался в подробности кода, но вот две ошибки, на мой взгляд, уже нашел.
1. На порту нужно отключить цифровой вход, который может влиять на результат измерений. Т.е. после настройки порта на вход, необходимо еще инициализировать регистр PIN6CTRL значением INTPUT_DISABLE.

2. Разрешать работу АЦП нужно после проведения всех настроек - т.е. строка
ADCA.CTRLA |= ADC_ENABLE_bm; // Включаем АЦП
должна быть самой последней в функции
void ADC_Init(void)
_Артём_
Цитата(prottoss @ May 5 2013, 13:19) *
1. На порту нужно отключить цифровой вход, который может влиять на результат измерений. Т.е. после настройки порта на вход, необходимо еще инициализировать регистр PIN6CTRL значением INTPUT_DISABLE.

Врядли это поможет.

Цитата(prottoss @ May 5 2013, 13:19) *
2. Разрешать работу АЦП нужно после проведения всех настроек - т.е. строка
ADCA.CTRLA |= ADC_ENABLE_bm; // Включаем АЦП
должна быть самой последней в функции

Тоже не принципиально.

Цитата(tier @ May 5 2013, 09:13) *
да , там где инициализация делаю разрешение уровней прывания

Может прерывания от АЦП мешают работе ADC_GetValue?

Цитата(tier @ May 5 2013, 09:13) *
Такое впечатление что АЦП вообще не работает, не пойму....

В симуляторе (или отладчике) пробовали проверять?
Лучше проект выложте, а то гадать можно долго.
tier
Цитата(prottoss @ May 5 2013, 13:19) *
1. На порту нужно отключить цифровой вход, который может влиять на результат измерений. Т.е. после настройки порта на вход, необходимо еще инициализировать регистр PIN6CTRL значением INTPUT_DISABLE.

сделал, в ADC_Init добавил
Код
PORTA.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc;


Цитата(prottoss @ May 5 2013, 13:19) *
2. Разрешать работу АЦП нужно после проведения всех настроек - т.е. строка
ADCA.CTRLA |= ADC_ENABLE_bm; // Включаем АЦП
должна быть самой последней в функции
void ADC_Init(void)


тоже не помогает

Цитата(_Артём_ @ May 5 2013, 14:09) *
В симуляторе (или отладчике) пробовали проверять?

не пробовал, потому как тут непосредственно с перефирией работаю, кода мизер
у кого-нибудь есть эта самая 32d4 ревизии A, просто errata конечно большая, но не вообще ж не работать АЦП...
_Артём_
Цитата(tier @ May 6 2013, 15:36) *
не пробовал, потому как тут непосредственно с перефирией работаю

Попробуйте, хуже не будем - всёж равно не работает.

Цитата(tier @ May 6 2013, 15:36) *
кода мизер

P.S. Непонятно как у вас чтение АЦП происходит - проде и прерывания по готовности результата АЦП разрешены и в функции АЦП по флагу готовноси читается.
tier
Цитата(_Артём_ @ May 6 2013, 16:09) *
Попробуйте, хуже не будем - всёж равно не работает.


да сейчас попробую.... оставлю в проекте только АЦП и USART, чтобы результаты видеть....

Цитата(_Артём_ @ May 6 2013, 16:09) *
P.S. Непонятно как у вас чтение АЦП происходит - проде и прерывания по готовности результата АЦП разрешены и в функции АЦП по флагу готовноси читается.


меня ввело в заблуждение, что если я не разрешу прерывания по готовности, то и флаг не будет устанавливаться, регистр то Interrupt Flag registers
собственно мне что так, что так не помогает, я многое уже перепробовал... Чтение производится просто по готовности измерений, прерывания АЦП я нигде не использую.....
zombi
На Си не пишу. С ацп не работал.
Извиняюсь если бред напишу.
Но, Вы правльно работаете с 16-ти битным результатом работы ацп?
При сложении/делении результата ничего не теряется?
Выводите/смотрите тоже все 16-ть бит?
tier
Цитата(zombi @ May 6 2013, 18:33) *
Но, Вы правльно работаете с 16-ти битным результатом работы ацп?
При сложении/делении результата ничего не теряется?
Выводите/смотрите тоже все 16-ть бит?

использую 16-разрядный регистр, пробовал по отдельности младший и старший (складывая со сдвигом), безрезультатно

Вот сделал отдельно проектик только для АЦП....
По прерыванию RTC (раз в секунду) вызывается функция ADC_GetValue, результат в USART, все время по нолям.....
USART 9600bps, CPU clock 32MHz
Нажмите для просмотра прикрепленного файла
zombi
Цитата(tier @ May 6 2013, 21:42) *
Вот сделал отдельно проектик только для АЦП....

А здесь правильно сдвигаете?
Код
ISR(RTC_OVF_vect)
...
      while( (USARTD0.STATUS & USART_DREIF_bm) == 0);
      USARTD0.DATA = (uint8_t)(res << 8);
      
      while( (USARTD0.STATUS & USART_DREIF_bm) == 0);
      USARTD0.DATA = (uint8_t)(res);
...

И попробуйте делать одно измерение (без суммирования и деления).
И у Вас наблюдается постоянная тенденция разрешать работу внутр. устройств мк до полной инициализации всех регистров оного (о чём Вам уже писали).
Это я про инит RTC.
Может в данном случае это и не страшно но лично я не позволяю себе таких вольностей (рано или поздно обязательно где то да вылезет ... бяка).

Код
Инициализация (RTC, не запущен)
1.Запишите значение периода в регистр периода PER.
2.Запишите значения величины сравнения и счетчика в регистры COMP и CNT.
3.Установите уровень прерывания для прерываний по сравнению и переполнению RTC.
4.Установите выбранный коэффициент предмасштабирования в регистре CTRL.


Зачем RXD разрешаете если только передаёте?
_Артём_
Цитата(zombi @ May 7 2013, 00:18) *
А здесь правильно сдвигаете?
Код
ISR(RTC_OVF_vect)
...
      while( (USARTD0.STATUS & USART_DREIF_bm) == 0);
      USARTD0.DATA = (uint8_t)(res << 8);
      
      while( (USARTD0.STATUS & USART_DREIF_bm) == 0);
      USARTD0.DATA = (uint8_t)(res);
...

Не ту сторону.
Код
USARTD0.DATA = (uint8_t)(res >> 8);


А что показывает отладчик в ADCA.CH0.RES после завершения измерения? Может оно всё равно не меряет?
tier
Цитата(_Артём_ @ May 7 2013, 01:04) *
Не ту сторону.
Код
USARTD0.DATA = (uint8_t)(res >> 8);


Цитата(zombi @ May 7 2013, 00:18) *
А здесь правильно сдвигаете?

спасибо, это у меня повылазило....))))

Цитата(zombi @ May 7 2013, 00:18) *
И у Вас наблюдается постоянная тенденция разрешать работу внутр. устройств мк до полной инициализации всех регистров оного (о чём Вам уже писали).
Это я про инит RTC.
Может в данном случае это и не страшно но лично я не позволяю себе таких вольностей (рано или поздно обязательно где то да вылезет ... бяка).

спасибо за советы.... исправил и исправлю.... кстати в апноте AVR1314 атмеловцы сначала запускают RTC, а потом настраивают регистры.....

Цитата(zombi @ May 7 2013, 00:18) *
И попробуйте делать одно измерение (без суммирования и деления).

делал.... не помогает

Цитата(_Артём_ @ May 7 2013, 01:04) *
А что показывает отладчик в ADCA.CH0.RES после завершения измерения? Может оно всё равно не меряет?

так вот в том и проблема, что в отладчике то по нолям было....

Цитата(zombi @ May 7 2013, 00:18) *
Зачем RXD разрешаете если только передаёте?

в основном проекте используется и прием, когда переносил не убрал.... тем более тут не принципиально, но убрал....

как бы АЦП вообще не хочет ничего измерять, хочу попробовать еще другие чипы, может что-то с чипами моими....
zombi
Цитата(tier @ May 7 2013, 10:11) *
кстати в апноте AVR1314 атмеловцы сначала запускают RTC, а потом настраивают регистры.....

Ага.
Советуют одно, делают по другому. biggrin.gif
И зачем то ждут готовности RTC при первом запуске.
tier
Все заработало, скомпилировал другой студией и все измеряет...
У меня была 4.18 поставил 4.19 с тулчейном на другой машине, скомпилировал, прошил и все измеряет....
Тот же код компилю в 4.18 - не работает.......
Всем спасибо......
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.