Jump to content

    
Sign in to follow this  
tier

ATxMega32D4

Recommended Posts

Подскажите кто чем сможет, что-то бьюсь а результата нет.

Есть ATxMega32D4, на начальном этапе пытаюсь просто измерить постоянное напряжение (~1.2В) которое подается к Pin2.

Ф-я ADC_GetValue() вызывается по требованию программы (необходимость измерения в данный момент)

 

Независимо от подключенного измеряемого напряжения выдает 0xC0...0xC3 в случае

UnsignedMode и 0x02...0x06 в случае SignedMode (ADC_CONMODE_bm)

 

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; 
}

 

в чем может быть проблема

Edited by IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Share this post


Link to post
Share on other sites
Независимо от подключенного измеряемого напряжения выдает 0xC0...0xC3 в случае

UnsignedMode

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

 

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 нет? Если есть, то может он разрешён?

Edited by IgorKossak
избыточное цитирование

Share this post


Link to post
Share on other sites
Вход на земле не сидит или может вообще оборван? Есть на нём напряжение?

 

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

 

ADC_GetValue при разрешённых прерываниях измеряет?

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

 

PMIC.CTRL |= PMIC_MEDLVLEN_bm;
PMIC.CTRL |= PMIC_HILVLEN_bm;

JTAGa нет. Я уже пробовал и в дифференциальном режиме измерять подключая Negative Pin к земле. Ничего не меняется.

Такое впечатление что АЦП вообще не работает, не пойму....

Share this post


Link to post
Share on other sites

Попробуйте вот этот код под себя переделать:

SLEEP.CTRL=1;

 

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;
};

Edited by IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Share this post


Link to post
Share on other sites
void ADC_Init(void)
{
...
}

в чем может быть проблема

Я не вдавался в подробности кода, но вот две ошибки, на мой взгляд, уже нашел.

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

 

2. Разрешать работу АЦП нужно после проведения всех настроек - т.е. строка

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

должна быть самой последней в функции

void ADC_Init(void)

Share this post


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

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

 

2. Разрешать работу АЦП нужно после проведения всех настроек - т.е. строка

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

должна быть самой последней в функции

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

 

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

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

 

Такое впечатление что АЦП вообще не работает, не пойму....

В симуляторе (или отладчике) пробовали проверять?

Лучше проект выложте, а то гадать можно долго.

Share this post


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

сделал, в ADC_Init добавил

PORTA.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc;

 

2. Разрешать работу АЦП нужно после проведения всех настроек - т.е. строка

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

должна быть самой последней в функции

void ADC_Init(void)

 

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

 

В симуляторе (или отладчике) пробовали проверять?

не пробовал, потому как тут непосредственно с перефирией работаю, кода мизер

у кого-нибудь есть эта самая 32d4 ревизии A, просто errata конечно большая, но не вообще ж не работать АЦП...

 

Share this post


Link to post
Share on other sites
не пробовал, потому как тут непосредственно с перефирией работаю

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

 

кода мизер

P.S. Непонятно как у вас чтение АЦП происходит - проде и прерывания по готовности результата АЦП разрешены и в функции АЦП по флагу готовноси читается.

Share this post


Link to post
Share on other sites
Попробуйте, хуже не будем - всёж равно не работает.

 

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

 

P.S. Непонятно как у вас чтение АЦП происходит - проде и прерывания по готовности результата АЦП разрешены и в функции АЦП по флагу готовноси читается.

 

меня ввело в заблуждение, что если я не разрешу прерывания по готовности, то и флаг не будет устанавливаться, регистр то Interrupt Flag registers

собственно мне что так, что так не помогает, я многое уже перепробовал... Чтение производится просто по готовности измерений, прерывания АЦП я нигде не использую.....

Share this post


Link to post
Share on other sites

На Си не пишу. С ацп не работал.

Извиняюсь если бред напишу.

Но, Вы правльно работаете с 16-ти битным результатом работы ацп?

При сложении/делении результата ничего не теряется?

Выводите/смотрите тоже все 16-ть бит?

Share this post


Link to post
Share on other sites
Но, Вы правльно работаете с 16-ти битным результатом работы ацп?

При сложении/делении результата ничего не теряется?

Выводите/смотрите тоже все 16-ть бит?

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

 

Вот сделал отдельно проектик только для АЦП....

По прерыванию RTC (раз в секунду) вызывается функция ADC_GetValue, результат в USART, все время по нолям.....

USART 9600bps, CPU clock 32MHz

ADC_test.zip

Edited by tier

Share this post


Link to post
Share on other sites
Вот сделал отдельно проектик только для АЦП....

А здесь правильно сдвигаете?

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 разрешаете если только передаёте?

Share this post


Link to post
Share on other sites
А здесь правильно сдвигаете?

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 после завершения измерения? Может оно всё равно не меряет?

Share this post


Link to post
Share on other sites
Не ту сторону.

USARTD0.DATA = (uint8_t)(res >> 8);

 

А здесь правильно сдвигаете?

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

 

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

Это я про инит RTC.

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

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

 

И попробуйте делать одно измерение (без суммирования и деления).

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

 

А что показывает отладчик в ADCA.CH0.RES после завершения измерения? Может оно всё равно не меряет?

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

 

Зачем RXD разрешаете если только передаёте?

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

 

как бы АЦП вообще не хочет ничего измерять, хочу попробовать еще другие чипы, может что-то с чипами моими....

Share this post


Link to post
Share on other sites
кстати в апноте AVR1314 атмеловцы сначала запускают RTC, а потом настраивают регистры.....

Ага.

Советуют одно, делают по другому. :biggrin:

И зачем то ждут готовности RTC при первом запуске.

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this