Перейти к содержанию
    

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

Есть 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; 
}

 

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

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Независимо от подключенного измеряемого напряжения выдает 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 нет? Если есть, то может он разрешён?

Изменено пользователем IgorKossak
избыточное цитирование

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

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

 

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

void ADC_Init(void)
{
...
}

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

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

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

 

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

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

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

void ADC_Init(void)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

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

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

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

 

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

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

 

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 конечно большая, но не вообще ж не работать АЦП...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

кода мизер

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

 

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

 

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

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

USART 9600bps, CPU clock 32MHz

ADC_test.zip

Изменено пользователем tier

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не ту сторону.

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

 

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

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

 

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

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

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

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

 

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

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

 

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

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

 

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Ага.

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

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...