Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: АЦП в Xmega
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Nosaer
Здравствуйте.
Начал разбираться с АЦП в Xmega и столкнулся с проблемой в результате которой получаю не совсем корректные данные.
Собственно вот код инициализации АЦП:
Код
void ADC_init()
{    
    //ADCA.CAL=0xff;                                            // Значение для калибровки АЦП
    ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc;                     // 12 бит дескретизация
    ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02;                // Опорное напряжение 1 В.
    ADCA.PRESCALER = ADC_PRESCALER_DIV256_gc;                    // Переферийная частота работы АЦП
    ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;        // CH0 настроен на внешний несимметричный вход
    ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN3_gc;                 // Настраиваем как положительный вывод порта для АЦП
    ADCA.CTRLA|= ADC_ENABLE_bm;                                // Активирую АЦП
    ADCA.CTRLB|=(1<<3);                                        // Старт  автоматического преобразования АЦП
}


На 3 пин порта А, подаю напряжение заведомо выше 1В, ожидая получить с АЦП максимальное значение, что то в районе 4095(судя по даташиту для безнакового вывода)
В результате получаю значение в районе 2700.
Вроде бы все регистры уже перепроверил, никак не могу понять в чем проблема.
Надеюсь на Вашу помощь)
Александр1
Цитата(Nosaer @ Jan 13 2016, 17:30) *
Код
void ADC_init()
{    
    //
    ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02;                // Опорное напряжение 1 В.
    
}


На 3 пин порта А, подаю напряжение заведомо выше 1В, ожидая получить с АЦП максимальное значение, что то в районе 4095(судя по даташиту для безнакового вывода)
В результате получаю значение в районе 2700.

Я так понял, что опорное напряжение для АЦП 1 В, а на вход АЦП подаете "заведомо выше 1 В"?
В этом случае результат преобразования будет некорректен. На вход АЦП должно подаваться напряжение не более опорного напряжения. Опорное напряжение соответствует максимальному значению преобразования.
Nosaer
Александр1, мне казалось, что даже если превысить, то АЦП должно было вывести максимальное свое значение.

Прошу прощения за неточность, сразу как то не доглядел.
АЦП выводит мне это значение при подаче абсолютно любого значения поданного на его вход, даже если 0. То есть число в районе 2700, и периодически плавает плюс минус несколько единиц.

Приведу код, возможно у кого будет время и желание глянуть:
CODE
#include <avr/io.h>
#include <avr/interrupt.h>

#define ENABLE_BIT_DEFINITIONS
#define HI(x) ((x)>>8)
#define LO(x) ((x)& 0xFF)

unsigned char i,cnt,y;
long int DataADC;
volatile int Voltage = 0x00;

// Настройка на работу от внешнего кварца в 4 МГц
void ClockExt4MHz()
{
OSC.XOSCCTRL = 0x4B;
OSC.CTRL = 0x08;
while((OSC.STATUS & 0x08) == 0);
OSC_PLLCTRL = 0xC1;
OSC_CTRL = OSC_CTRL | 0x10;
while((OSC_STATUS & 0x10) == 0 );
CCP = CCP_IOREG_gc;
CLK.CTRL = CLK_SCLKSEL_XOSC_gc;
OSC_CTRL = OSC_CTRL & 0xFE;
}

// UART для связи на 9600 bod для 4 МГц
void StartUsartD1()
{
USARTD1_CTRLC= USART_CHSIZE0_bm | USART_CHSIZE1_bm;
USARTD1_BAUDCTRLB = 0;
USARTD1_BAUDCTRLA = 0x19;
USARTD1_CTRLB = USART_TXEN_bm | USART_RXEN_bm;
USARTD1_CTRLA=USART_RXCINTLVL0_bm;
PORTD_OUTSET = PIN7_bm;
PORTD_DIRSET = PIN7_bm;
PORTD_OUTCLR = PIN6_bm;
PORTD_DIRCLR = PIN6_bm;
}

// Функция получения данных
char getChar1(void)
{
while(1){
char buffer1;
buffer1=USARTD1_DATA;
if ((USARTD1_STATUS & (USART_FERR_bm | USART_PERR_bm | USART_BUFOVF_bm))==0)
return buffer1;
}
}

// Функция передачи данных
void sendChar1(char d1)
{
while( !(USARTD1_STATUS & USART_DREIF_bm) );
USARTD1_DATA = d1;
while( !(USARTD1_STATUS & USART_TXCIF_bm) );
}

// Прерывание по получению данных с UART
ISR(USARTD1_RXC_vect)
{
PORTA.OUTTGL =0x20;
DataADC = ADCA.CH0RES;
cnt = getChar1();
if (cnt != 0) {
if (cnt == 0x4F)
{
sendChar1(HI(DataADC));
sendChar1(LO(DataADC));
}
else for (i=0;i<5;i++) sendChar1(0x55);
}
cnt = 0;
}

// Функция инициализации АЦП
void ADC_init()
{
ADCA.CAL=0xff; // Значение для калибровки АЦП
ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc; // 12 бит дескретизация
ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02; // Опорное напряжение 1 В.
ADCA.PRESCALER =ADC_PRESCALER_DIV512_gc; // Переферийная частота работы АЦП
ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; // CH0 настроен на внешний нессимметричный вход
ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN3_gc; // Настраиваем как положительный вывод порта для АЦП
ADCA.CTRLA = ADC_ENABLE_bm; // Активирую АЦП
ADCA.CTRLB|=(1<<3); // старт автоматического преобразования АЦП
}

// Функция инициализации ЦАП
void DAC_init()
{
DACB.CTRLC = ( DACB.CTRLC & ~DAC_REFSEL_gm) | DAC_REFSEL_AVCC_gc;
DACB.CTRLB = ( DACB.CTRLB & ~DAC_CHSEL_gm ) | DAC_CHSEL_SINGLE_gc;
PORTB.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc;
DACB.CTRLA = DAC_CH0EN_bm | DAC_ENABLE_bm;
}

// Функция выдачи напряжения с ЦАП
void DACB_out(int Voltage)
{
DACB.CH0DATA = Voltage;
while (!DACB.STATUS & DAC_CH0DRE_bm);
}


int main(void)
{
ClockExt4MHz();

PORTA.DIR = 0x20;
PORTC.DIR = 0x02;
StartUsartD1();
ADC_init();
DAC_init();
DACB_out(Voltage);

PORTD.PIN4CTRL = PORT_OPC_PULLDOWN_gc | PORT_ISC_FALLING_gc;

sei();
PMIC.CTRL|=PMIC_HILVLEN_bm|PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm;

while (1)
{

asm("NOP");

}
}


По задумке должен получать значение АЦП по UART. Напряжение выставляю с помощью ЦАПа.
Еще заметил, что при изменении регистра ADCA.PRESCALER =ADC_PRESCALER_DIV512_gc; почему то изменяется получаемое значение с АЦП, то есть изменил скорость преобразование, и значение АЦП изменилось где то на 200 единиц при том же напряжении.
Или же буду рад хотя бы рабочему примеру работы с АЦП для этого контроллера.
__Alexander
А где старт преобразования и ожидание его завершения?
Nosaer
Код
ADCA.CTRLB|=(1<<3);                                    // старт  автоматического преобразования АЦП


Постоянное работает автоматическое преобразование
SpyBot
Цитата(Nosaer @ Jan 14 2016, 16:34) *
Код
ADCA.CTRLB|=(1<<3);                                    // старт  автоматического преобразования АЦП


Постоянное работает автоматическое преобразование

Не у всех МК такое прокатывает. Например, у старых мег работало, но и то с оговорками. А у стм32 - нет.
Лучше для начала использовать однократное преобразование с ожиданием результата поллингом.
(а потом уже когда заработает сделать как удобно)
Nosaer
Всем спасибо. Проблему решил заменой контроллера. Видимо выбило чего
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.