tier 0 4 мая, 2013 Опубликовано 4 мая, 2013 (изменено) · Жалоба Подскажите кто чем сможет, что-то бьюсь а результата нет. Есть 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; } в чем может быть проблема Изменено 5 мая, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 4 мая, 2013 Опубликовано 4 мая, 2013 (изменено) · Жалоба Независимо от подключенного измеряемого напряжения выдает 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 нет? Если есть, то может он разрешён? Изменено 5 мая, 2013 пользователем IgorKossak избыточное цитирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tier 0 5 мая, 2013 Опубликовано 5 мая, 2013 · Жалоба Вход на земле не сидит или может вообще оборван? Есть на нём напряжение? На входе контролирую мультиметром, напряжение есть 1.22В ADC_GetValue при разрешённых прерываниях измеряет? да , там где инициализация делаю разрешение уровней прывания PMIC.CTRL |= PMIC_MEDLVLEN_bm; PMIC.CTRL |= PMIC_HILVLEN_bm; JTAGa нет. Я уже пробовал и в дифференциальном режиме измерять подключая Negative Pin к земле. Ничего не меняется. Такое впечатление что АЦП вообще не работает, не пойму.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bob1 0 5 мая, 2013 Опубликовано 5 мая, 2013 (изменено) · Жалоба Попробуйте вот этот код под себя переделать: 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; }; Изменено 5 мая, 2013 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 5 мая, 2013 Опубликовано 5 мая, 2013 · Жалоба void ADC_Init(void) { ... } в чем может быть проблема Я не вдавался в подробности кода, но вот две ошибки, на мой взгляд, уже нашел. 1. На порту нужно отключить цифровой вход, который может влиять на результат измерений. Т.е. после настройки порта на вход, необходимо еще инициализировать регистр PIN6CTRL значением INTPUT_DISABLE. 2. Разрешать работу АЦП нужно после проведения всех настроек - т.е. строка ADCA.CTRLA |= ADC_ENABLE_bm; // Включаем АЦП должна быть самой последней в функции void ADC_Init(void) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 5 мая, 2013 Опубликовано 5 мая, 2013 · Жалоба 1. На порту нужно отключить цифровой вход, который может влиять на результат измерений. Т.е. после настройки порта на вход, необходимо еще инициализировать регистр PIN6CTRL значением INTPUT_DISABLE. Врядли это поможет. 2. Разрешать работу АЦП нужно после проведения всех настроек - т.е. строка ADCA.CTRLA |= ADC_ENABLE_bm; // Включаем АЦП должна быть самой последней в функции Тоже не принципиально. да , там где инициализация делаю разрешение уровней прывания Может прерывания от АЦП мешают работе ADC_GetValue? Такое впечатление что АЦП вообще не работает, не пойму.... В симуляторе (или отладчике) пробовали проверять? Лучше проект выложте, а то гадать можно долго. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tier 0 6 мая, 2013 Опубликовано 6 мая, 2013 · Жалоба 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 конечно большая, но не вообще ж не работать АЦП... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 6 мая, 2013 Опубликовано 6 мая, 2013 · Жалоба не пробовал, потому как тут непосредственно с перефирией работаю Попробуйте, хуже не будем - всёж равно не работает. кода мизер P.S. Непонятно как у вас чтение АЦП происходит - проде и прерывания по готовности результата АЦП разрешены и в функции АЦП по флагу готовноси читается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tier 0 6 мая, 2013 Опубликовано 6 мая, 2013 · Жалоба Попробуйте, хуже не будем - всёж равно не работает. да сейчас попробую.... оставлю в проекте только АЦП и USART, чтобы результаты видеть.... P.S. Непонятно как у вас чтение АЦП происходит - проде и прерывания по готовности результата АЦП разрешены и в функции АЦП по флагу готовноси читается. меня ввело в заблуждение, что если я не разрешу прерывания по готовности, то и флаг не будет устанавливаться, регистр то Interrupt Flag registers собственно мне что так, что так не помогает, я многое уже перепробовал... Чтение производится просто по готовности измерений, прерывания АЦП я нигде не использую..... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zombi 0 6 мая, 2013 Опубликовано 6 мая, 2013 · Жалоба На Си не пишу. С ацп не работал. Извиняюсь если бред напишу. Но, Вы правльно работаете с 16-ти битным результатом работы ацп? При сложении/делении результата ничего не теряется? Выводите/смотрите тоже все 16-ть бит? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tier 0 6 мая, 2013 Опубликовано 6 мая, 2013 (изменено) · Жалоба Но, Вы правльно работаете с 16-ти битным результатом работы ацп? При сложении/делении результата ничего не теряется? Выводите/смотрите тоже все 16-ть бит? использую 16-разрядный регистр, пробовал по отдельности младший и старший (складывая со сдвигом), безрезультатно Вот сделал отдельно проектик только для АЦП.... По прерыванию RTC (раз в секунду) вызывается функция ADC_GetValue, результат в USART, все время по нолям..... USART 9600bps, CPU clock 32MHz ADC_test.zip Изменено 6 мая, 2013 пользователем tier Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zombi 0 6 мая, 2013 Опубликовано 6 мая, 2013 · Жалоба Вот сделал отдельно проектик только для АЦП.... А здесь правильно сдвигаете? 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 разрешаете если только передаёте? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 6 мая, 2013 Опубликовано 6 мая, 2013 · Жалоба А здесь правильно сдвигаете? 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 0 7 мая, 2013 Опубликовано 7 мая, 2013 · Жалоба Не ту сторону. USARTD0.DATA = (uint8_t)(res >> 8); А здесь правильно сдвигаете? спасибо, это у меня повылазило....)))) И у Вас наблюдается постоянная тенденция разрешать работу внутр. устройств мк до полной инициализации всех регистров оного (о чём Вам уже писали). Это я про инит RTC. Может в данном случае это и не страшно но лично я не позволяю себе таких вольностей (рано или поздно обязательно где то да вылезет ... бяка). спасибо за советы.... исправил и исправлю.... кстати в апноте AVR1314 атмеловцы сначала запускают RTC, а потом настраивают регистры..... И попробуйте делать одно измерение (без суммирования и деления). делал.... не помогает А что показывает отладчик в ADCA.CH0.RES после завершения измерения? Может оно всё равно не меряет? так вот в том и проблема, что в отладчике то по нолям было.... Зачем RXD разрешаете если только передаёте? в основном проекте используется и прием, когда переносил не убрал.... тем более тут не принципиально, но убрал.... как бы АЦП вообще не хочет ничего измерять, хочу попробовать еще другие чипы, может что-то с чипами моими.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zombi 0 7 мая, 2013 Опубликовано 7 мая, 2013 · Жалоба кстати в апноте AVR1314 атмеловцы сначала запускают RTC, а потом настраивают регистры..... Ага. Советуют одно, делают по другому. И зачем то ждут готовности RTC при первом запуске. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться