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

 
 
 
Reply to this topicStart new topic
> АЦП в 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
Александр1
сообщение Jan 14 2016, 05:45
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 465
Регистрация: 13-05-15
Из: Запорожье
Пользователь №: 86 663



Цитата(Nosaer @ Jan 13 2016, 17:30) *
Код
void ADC_init()
{    
    //
    ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02;                // Опорное напряжение 1 В.
    
}


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

Я так понял, что опорное напряжение для АЦП 1 В, а на вход АЦП подаете "заведомо выше 1 В"?
В этом случае результат преобразования будет некорректен. На вход АЦП должно подаваться напряжение не более опорного напряжения. Опорное напряжение соответствует максимальному значению преобразования.
Go to the top of the page
 
+Quote Post
Nosaer
сообщение Jan 14 2016, 09:16
Сообщение #3


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

Группа: Свой
Сообщений: 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
__Alexander
сообщение Jan 14 2016, 13:20
Сообщение #4


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

Группа: Участник
Сообщений: 76
Регистрация: 18-07-07
Из: Киев
Пользователь №: 29 202



А где старт преобразования и ожидание его завершения?
Go to the top of the page
 
+Quote Post
Nosaer
сообщение Jan 14 2016, 13:34
Сообщение #5


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

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



Код
ADCA.CTRLB|=(1<<3);                                    // старт  автоматического преобразования АЦП


Постоянное работает автоматическое преобразование
Go to the top of the page
 
+Quote Post
SpyBot
сообщение Jan 14 2016, 14:38
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 285
Регистрация: 5-11-05
Пользователь №: 10 491



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


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

Не у всех МК такое прокатывает. Например, у старых мег работало, но и то с оговорками. А у стм32 - нет.
Лучше для начала использовать однократное преобразование с ожиданием результата поллингом.
(а потом уже когда заработает сделать как удобно)
Go to the top of the page
 
+Quote Post
Nosaer
сообщение Jan 15 2016, 08:12
Сообщение #7


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

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



Всем спасибо. Проблему решил заменой контроллера. Видимо выбило чего
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 18th July 2025 - 03:07
Рейтинг@Mail.ru


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