реклама на сайте
подробности

 
 
> АЦП в Xmega
Nosaer
сообщение Jan 13 2016, 14:30
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 85
Регистрация: 6-02-15
Пользователь №: 84 967



Здравствуйте.
Начал разбираться с АЦП в 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.
Вроде бы все регистры уже перепроверил, никак не могу понять в чем проблема.
Надеюсь на Вашу помощь)
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Nosaer
сообщение Jan 14 2016, 09:16
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 85
Регистрация: 6-02-15
Пользователь №: 84 967



Александр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 единиц при том же напряжении.
Или же буду рад хотя бы рабочему примеру работы с АЦП для этого контроллера.

Сообщение отредактировал IgorKossak - Jan 14 2016, 19:29
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 31st July 2025 - 10:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01367 секунд с 7
ELECTRONIX ©2004-2016