Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR...

 
Опции темы
Непрочитано 29.01.2013, 12:45  
Fogtech
Частый гость
 
Регистрация: 29.01.2013
Сообщений: 31
Сказал спасибо: 13
Сказали Спасибо 2 раз(а) в 2 сообщении(ях)
Fogtech на пути к лучшему
Печаль ADC для ATXmega128A1 - помогите найти ошибку в коде

Здравствуйте, уважаемые посетители форума!

Передо мной стоит задача настроить АЦП для мк ATXmega128A1 (доска Xmega128-A1 Xplained) таким образом, чтобы через потенциометр задавать значания для внутренних переменных. Используя наброски с этой страницы у меня получился ниже приведенный код. Программа должа анализировать напряжение исходящее с потенциометра и выдавать сигнал на LED в зависимости от измерянных данных.
Просьба помочь найти ошибку в коде. Пробовал разные комбинации. Предполагаю, что ошибка банальная, так как я только начинаю заниматься подобного рода мк. Пользуюсь CodeVisionAVR. Компаратор не ругается на синтаксис, но плата молчит. Программирую через Flip. АЦП - 12 бит.

Код:
//I/O Registersdefinition:
#include ‹xmega128a1.h› //Xmega-A1-Xplained development board
#define LED PORTE// LED as PORT E.

volatile int Result;

void main()
{
LED.DIR = 0b00001111;  //E0 - E3 - outputs.

PORTA.DIR = 0;                                  // configure PORTA as input
ADCA.CTRLA |= 0x1;                              // enable adc
ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc;           // 12 bit conversion
ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02;      // internal 1V bandgap reference
ADCA.PRESCALER = ADC_PRESCALER_DIV8_gc;         // peripheral clk/8 (2MHz/16=250kHz)
ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;// single ended
ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN0_gc; 	    // PORTA:0 

ADCA.CH0.CTRL |= ADC_CH_START_bm; // start conversion on channel 0

    while(1)  // cycle
    { 

        while(!ADCA.CH0.INTFLAGS);
        Result = ADCA.CH0RES;
    
        if (Result › 1000) //
        {
            LED.OUTSET = (1 ‹‹ 0); // output E0 High.
        } //if
        if (Result › 2000) //
        {
            LED.OUTSET = (1 ‹‹ 1); // output E1 High.
        } //if        
        if (Result › 3000) //
        {
            LED.OUTSET = (1 ‹‹ 2); // output E2 High.
        } //if        
        if (Result › 4000) //
        {
            LED.OUTSET = (1 ‹‹ 3); // output E3 High.
        } //if      
    }//while(1)
}//main
Подключение потенциометра:
---VCC
|
|
|-/
|/|--ADC0
/-|
|
|
----GND
Реклама:

Последний раз редактировалось Fogtech; 29.01.2013 в 12:50.
Fogtech вне форума  
Непрочитано 29.01.2013, 12:59  
Wiza_
Почётный гражданин KAZUS.RU
 
Регистрация: 29.12.2012
Адрес: Питер
Сообщений: 982
Сказал спасибо: 131
Сказали Спасибо 230 раз(а) в 157 сообщении(ях)
Wiza_ на пути к лучшему
По умолчанию Re: ADC для ATXmega128A1 - помогите найти ошибку в коде.

На вскидку:
Код:
ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02;      // internal 1V bandgap reference
Меряете относительно 1в а резистор прикручиваете к питанию.

Код:
ADCA.CH0.CTRL |= ADC_CH_START_bm; // start conversion on channel 0
Сработает только один раз т.к. не находится в теле цикла
Wiza_ вне форума  
Сказали "Спасибо" Wiza_
Fogtech (29.01.2013)
Непрочитано 29.01.2013, 13:12  
Fogtech
Частый гость
 
Регистрация: 29.01.2013
Сообщений: 31
Сказал спасибо: 13
Сказали Спасибо 2 раз(а) в 2 сообщении(ях)
Fogtech на пути к лучшему
По умолчанию Re: ADC для ATXmega128A1 - помогите найти ошибку в коде.

Сообщение от Wiza_ Посмотреть сообщение
На вскидку:
Код:
ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02;      // internal 1V bandgap reference
Меряете относительно 1в а резистор прикручиваете к питанию.

Код:
ADCA.CH0.CTRL |= ADC_CH_START_bm; // start conversion on channel 0
Сработает только один раз т.к. не находится в теле цикла
Спасибо большое за быструю подсказку. Изменил эти части кода:

Код:
ADCA.REFCTRL = ADC_REFSEL_VCC_gc | 0x02;  // internal 1V bandgap reference
Теперь подключение к VCC соответствует действительности.

Код:
ADCA.CH0.CTRL |= ADC_CH_START_bm; // start conversion on channel 0
Спустил под while(1)

Когда включаю плату все отлично показывает, когда потенциометр уменьшает напряжение, диоды также последовательно отключаются. Но не включаются при повышении напряжении. Видимо цикл неправильно задан.
Второй вопрос. Параметр ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02; значит настраевает плату на внешний источник напряжения 1В?
Fogtech вне форума  
Непрочитано 29.01.2013, 13:12  
Wiza_
Почётный гражданин KAZUS.RU
 
Регистрация: 29.12.2012
Адрес: Питер
Сообщений: 982
Сказал спасибо: 131
Сказали Спасибо 230 раз(а) в 157 сообщении(ях)
Wiza_ на пути к лучшему
По умолчанию Re: ADC для ATXmega128A1 - помогите найти ошибку в коде.

Вдогонку: если хотите читать данные АЦП в цикле - не забудьте обнулять ADCA.CH0.INTFLAGS ручками

Сообщение от Fogtech Посмотреть сообщение
Второй вопрос. Параметр ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02; значит настраевает плату на внешний источник напряжения 1В?
0х02 = External reference from AREF pin on PORT A

Последний раз редактировалось Wiza_; 29.01.2013 в 13:15.
Wiza_ вне форума  
Сказали "Спасибо" Wiza_
Fogtech (29.01.2013)
Непрочитано 29.01.2013, 13:17  
Wiza_
Почётный гражданин KAZUS.RU
 
Регистрация: 29.12.2012
Адрес: Питер
Сообщений: 982
Сказал спасибо: 131
Сказали Спасибо 230 раз(а) в 157 сообщении(ях)
Wiza_ на пути к лучшему
По умолчанию Re: ADC для ATXmega128A1 - помогите найти ошибку в коде.

Сообщение от Fogtech Посмотреть сообщение
Видимо цикл не правильно задан.
LED.OUTSET = 0
после
Result = ADCA.CH0RES;
добавте
Wiza_ вне форума  
Сказали "Спасибо" Wiza_
Fogtech (29.01.2013)
Непрочитано 29.01.2013, 13:37  
Fogtech
Частый гость
 
Регистрация: 29.01.2013
Сообщений: 31
Сказал спасибо: 13
Сказали Спасибо 2 раз(а) в 2 сообщении(ях)
Fogtech на пути к лучшему
По умолчанию Re: ADC для ATXmega128A1 - помогите найти ошибку в коде.

Сообщение от Wiza_ Посмотреть сообщение
LED.OUTSET = 0
после
Result = ADCA.CH0RES;
добавте
Все таки еще чего-то не хватает. LED.OUTSET = 0 установил на свое место.
Только что поигрался с выражением ADCA.CH0.INTFLAGS=ADC_CH_CHIF_bm; согласно комментарию "// clear int flags (cleared by writing 1)" должен при записи очищать ADCA.CH0.INTFLAGS, но не удалось. Как только что-то получится, сразу отпишусь.
Fogtech вне форума  
Непрочитано 29.01.2013, 14:10  
Fogtech
Частый гость
 
Регистрация: 29.01.2013
Сообщений: 31
Сказал спасибо: 13
Сказали Спасибо 2 раз(а) в 2 сообщении(ях)
Fogtech на пути к лучшему
По умолчанию Re: ADC для ATXmega128A1 - помогите найти ошибку в коде.

Сообщение от Wiza_ Посмотреть сообщение
Вдогонку: если хотите читать данные АЦП в цикле - не забудьте обнулять ADCA.CH0.INTFLAGS ручками
Скажите, пожалуйста, каким образом можно обнулить этот параметр в цикле... Банальное "= 0" не работает, а "=ADC_CH_CHIF_bm" вообще обнуляет значение вне зависимости от места написания и Result всегда равен 0.
И еще личный вопрос, изучали ли вы Xmega по каким-то конкретным книгам или практическим методом, так как я не могу найти более менее нормально собранной информации для начинающих по данному типу микроконтроллеров. А синтаксис у них немного отличается от классических mega или tiny.
Fogtech вне форума  
Непрочитано 29.01.2013, 14:43  
Wiza_
Почётный гражданин KAZUS.RU
 
Регистрация: 29.12.2012
Адрес: Питер
Сообщений: 982
Сказал спасибо: 131
Сказали Спасибо 230 раз(а) в 157 сообщении(ях)
Wiza_ на пути к лучшему
По умолчанию Re: ADC для ATXmega128A1 - помогите найти ошибку в коде.

ADCA.CH0.INTFLAGS &= ADC_CH_CHIF_bm
должно быть перед
ADCA.CH0.CTRL |= ADC_CH_START_bm; // start conversion on channel 0

Сообщение от Fogtech Посмотреть сообщение
И еще личный вопрос, изучали ли вы Xmega по каким-то конкретным книгам или практическим методом, так как я не могу найти более менее нормально собранной информации для начинающих по данному типу микроконтроллеров. А синтаксис у них немного отличается от классических mega или tiny.
Начинал с AVR. Код для XMega - вообще первый раз вижу
Wiza_ вне форума  
Сказали "Спасибо" Wiza_
Fogtech (29.01.2013)
Непрочитано 29.01.2013, 21:53  
Fogtech
Частый гость
 
Регистрация: 29.01.2013
Сообщений: 31
Сказал спасибо: 13
Сказали Спасибо 2 раз(а) в 2 сообщении(ях)
Fogtech на пути к лучшему
Радость Re: ADC для ATXmega128A1 - помогите найти ошибку в коде.

@Wiza_
Спасибо за помощь. Нашел ошибку. Перепутал комманды PORTA.OUTSET и
PORTA.OUTCLR. Теперь программа работает на ура.

Код:
//I/O Registersdefinition:
#include ‹xmega128a1.h› //Xmega-A1-Xplained development board
#include ‹delay.h›

#define LED PORTE// LED as PORT E.

volatile int Result;

void main()
{
LED.DIR = 0b00001111;  //E0 - E3 - outputs.

PORTA.DIR = 0;                                  // configure PORTA as input
ADCA.CTRLA |= 0x1;                              // enable adc
ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc;           // 12 bit conversion
ADCA.REFCTRL = ADC_REFSEL_VCC_gc | 0x02;        // internal 1.6V bandgap reference
ADCA.PRESCALER = ADC_PRESCALER_DIV8_gc;         // peripheral clk/8 (2MHz/16=250kHz)
ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;// single ended
ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN0_gc; 	    // PORTA:0 

    while(1)  // cycle
    { 
        ADCA.CH0.CTRL |= ADC_CH_START_bm; // start conversion on channel 0
        while(!ADCA.CH0.INTFLAGS);
        Result = ADCA.CH0RES;
        
        if (Result ›= 0 && Result ‹ 1000) //
        {
            LED.OUTCLR = (1 ‹‹ 0); // output E0 High.
        } //if
        if (Result ›= 1000 && Result ‹ 2000) //
        {
            LED.OUTCLR = (1 ‹‹ 1); // output E1 High.
        } //if        
        if (Result ›= 2000 && Result ‹ 3000) //
        {
            LED.OUTCLR = (1 ‹‹ 2); // output E2 High.
        } //if        
        if (Result ›= 3000 && Result ‹ 4096) //
        {
            LED.OUTCLR = (1 ‹‹ 3); // output E3 High.
        } //if
        delay_ms(50);
        LED.OUTSET = 0b00001111;
       }//while(1)
}//main

Последний раз редактировалось Fogtech; 30.01.2013 в 12:09.
Fogtech вне форума  
Непрочитано 30.01.2013, 10:18  
whoim
Почётный гражданин KAZUS.RU
 
Аватар для whoim
 
Регистрация: 26.11.2011
Адрес: Анапа
Сообщений: 1,620
Сказал спасибо: 284
Сказали Спасибо 129 раз(а) в 111 сообщении(ях)
whoim на пути к лучшему
По умолчанию Re: ADC для ATXmega128A1 - помогите найти ошибку в коде.

Не забудьте загрузить калиброванные значения для повышения точности


Код:
//загрузка калибровочных данных
uint8_t ReadCalibrationByte( uint8_t index )
{
	uint8_t result;
	/* Load the NVM Command register to read the calibration row. */
	NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
	result = pgm_read_byte(index);
	/* Clean up NVM Command register. */
	NVM_CMD = NVM_CMD_NO_OPERATION_gc;
	return( result );
}

Код:
	ADCA.CALL = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0) );
	ADCA.CALH = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1) );
ну и у меня работает так

Код:
float get_ADC(uint8_t _ch)
{
	float Result;
	
	ADCA.CTRLA = ADC_ENABLE_bm;// enable adc
	
	ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc; // 12 bit conversion
	ADCA.REFCTRL = ADC_REFSEL_VCC_gc;
	ADCA.PRESCALER = ADC_PRESCALER_DIV128_gc; // peripheral clk/128 (32MHz/128=250kHz)
	ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;	 // single ended
	
	//выбор пина
	switch (_ch)
	{
		case 0:
			ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN0_gc;
			break;
		
		case 1:
			ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN1_gc;
			break;

		case 2:
			ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN2_gc;
			break;

		case 3:
			ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN3_gc;
			break;
		
		case 4:
			ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN4_gc;
			break;
	}
	//цикл с усреднением
	for(uint8_t _x=0; _x‹10; _x++)
	{
		ADCA.CH0.CTRL |= ADC_CH_START_bm;  // Start conversion
		while(!(ADCA.CH0.INTFLAGS));
		ADCA.CH0.INTFLAGS=ADC_CH_CHIF_bm;
		Result += ADCA.CH0RES;
	}	
	
	Result = Result / 10;	
	return (Result * 20.6 / 4096 - ADC_GND_OFFSET);
}
где ADC_GND_OFFSET подобрал ручками. Если заюзать два пина и один из них на землю - оффсет можно вычислять также.

ADCA.REFCTRL = ADC_REFSEL_VCC_gc; - это VCC-0.6v, в моем случае 3.3 - 0.6 = 2.7 в, что побольше 1в

Последний раз редактировалось whoim; 30.01.2013 в 10:21.
whoim вне форума  
Сказали "Спасибо" whoim
Fogtech (25.02.2013)
 

Закладки

Метки
adc, atxmega128a1, xmega128-a1 xplained, ацп, код
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите найти ошибку barbuss Микроконтроллеры, АЦП, память и т.д 9 16.10.2013 18:05
Помогите найти ошибку AVR asm sibiryak983 AVR 46 04.02.2013 16:58
Помогите найти ошибку в моделировании 172senator Proteus 0 22.12.2010 14:18
Помогите найти ошибку в исходнике (+) Don_Ambrosio Микроконтроллеры, АЦП, память и т.д 1 29.04.2008 18:30
Помогите найти ошибку в PROTEUS maxNTF Proteus 2 29.11.2007 10:26


Часовой пояс GMT +4, время: 11:36.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot