|
|
  |
ATxmega |
|
|
|
Aug 9 2009, 13:29
|
Частый гость
 
Группа: Участник
Сообщений: 90
Регистрация: 7-05-06
Пользователь №: 16 862

|
Попался сборник статей сотрудников ЭФО: ftp://ftp.efo.ru/pub/efo/Efo_publish-2008-IIsogl.pdfСреди прочих там есть три статьи по XMEGA. В общем-то они представляют собой перекомпилированные атмеловские даташиты. Но написаны на нормальном техническом русском языке. Я думаю многим будут полезны для начального ознакомления.
|
|
|
|
|
Aug 10 2009, 18:42
|
Частый гость
 
Группа: Участник
Сообщений: 90
Регистрация: 7-05-06
Пользователь №: 16 862

|
Цитата(Piter_Korn @ Aug 10 2009, 17:40)  Так на ЭФФО прямо раздел есть и про Х-мега 3 (тры) полезных статьи Да, это те же самые статьи. Но для их скачивания нужна регистрация. Я такие скачивания недолюбливаю. Одна из причин в том, что запрашивающий не всегда следит за конфедициальностью предоставленных данных. Ваша ссылка тому яркая иллюстрация - по ней под Вашим логином можно скачать любую статью, при этом на странице видны Ваши регистрационные данные, в частности e-mail как подарок для спамеров  . Впрочем здесь есть и Ваш недосмотр...
|
|
|
|
|
Aug 11 2009, 06:12
|

Мастер-фломастер
   
Группа: Свой
Сообщений: 611
Регистрация: 29-12-05
Пользователь №: 12 700

|
Цитата(xelax @ Aug 6 2009, 17:35)  Отключите disasm. что значит отключите дизасм? пыс: исходники на асм.
--------------------
Вон ПОПОВ, клоун клоуном, а радио изобрел!!
|
|
|
|
|
Aug 21 2009, 17:15
|
Участник

Группа: Участник
Сообщений: 44
Регистрация: 24-11-07
Пользователь №: 32 645

|
Народ привет. Может не в тему, но меня мучит вот что. Значит девайс хмега128а1. Значит первый вопрос: при определении вот таким кодом Код void adc_init(void) { // ADC_CalibrationValues_Set(&ADCA); /* откалибруем ADC A. */ offset = ADC_Offset_Get(&ADCA); /* Получим смещение для ADC A. */ ADC_ConvMode_and_Resolution_Config(&ADCA, false, ADC_RESOLUTION_8BIT_gc); /* Сконфигурим ADC A для беззнакового преобразования 8 бит*/ ADC_Prescaler_Config(&ADCA, ADC_PRESCALER_DIV128_gc);/* Частота преобразования CPUFREQ/128. */ ADC_Referance_Config(&ADCA, ADC_REFSEL_INT1V_gc);/* установим опорное напряжение ADC A to be VCC 1 V.*/ /* Настроим каналы 0, 1, 2 and 3 на single ended input. */ // ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH0,ADC_CH_INPUTMODE_SINGLEENDED_gc,ADC_CH_GAINFAC_1X_gc); // ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH1,ADC_CH_INPUTMODE_SINGLEENDED_gc,ADC_CH_GAINFAC_1X_gc); //ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH2,ADC_CH_INPUTMODE_SINGLEENDED_gc,ADC_CH_GAINFAC_1X_gc); ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH3,ADC_CH_INPUTMODE_SINGLEENDED_gc,ADC_CH_GAINFAC_1X_gc);
/* Настроим входы на ADC A ножки 4, 5, 6 and 7. */ //ADC_Ch_InputMux_Config(&ADCA.CH0, ADC_CH_MUXPOS_PIN4_gc, ADC_CH_MUXNEG_PIN0_gc); //ADC_Ch_InputMux_Config(&ADCA.CH1, ADC_CH_MUXPOS_PIN5_gc, ADC_CH_MUXNEG_PIN0_gc); //ADC_Ch_InputMux_Config(&ADCA.CH2, ADC_CH_MUXPOS_PIN6_gc, ADC_CH_MUXNEG_PIN0_gc); ADC_Ch_InputMux_Config(&ADCA.CH3, ADC_CH_MUXPOS_PIN7_gc, ADC_CH_MUXNEG_PIN0_gc);
/* настроим sweep всех 4х каналов. */ ADC_SweepChannels_Config(&ADCA, ADC_SWEEP_0123_gc); ADC_Enable(&ADCA); ADC_Wait_32MHz(&ADCA); ADC_FreeRunning_Enable(&ADCA);
} Собственно при настройке канала на ногу ADC_CH_MUXPOS_PIN7_gc почему то опрашивается нога рядом, так и не понял почему. Если кто нибудь работал с ацп, объясните, как заставить работать заремаренную верхнюю строчку. Компилер кроет матом, говорит не найти подпрограммы, хотя в оригинале(апноуте) все компилится нормально. Второй вопрос, подскажите как настраивать каналы, не врубаюсь. третий вопрос, как заставить работать одиночное преобразование. Но главное не пойму почему канал опрашивается не тот.
|
|
|
|
|
Aug 21 2009, 17:45
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686

|
Ответ на второй вопрос по АЦП: я вот такой код написал (на основе даташита): Код //Инициализация АЦП - канал CH0 void init_ADC (void) { // Конфигурируем канал CH0 на работу в несимметричном включении ADCA.CH0.MUXCTRL|=ADC_CH_INPUTMODE_SINGLEENDED_gc; // В несимметричном режиме подключением к положительному входу АЦП линию 1 порта PORTA ADCA.CH0.MUXCTRL|=ADC_CH_MUXPOS_PIN1_gc; // Подключаем внешний источник опорного напряжения ADCA.REFCTRL|=0x20; // Устанавливаем частоту тактирования АЦП: тактовая частота делиться на число N // при N=32, F=29,491200 МГц - частота тактирования - 921,6 кГц ADCA.PRESCALER|=ADC_PRESCALER_DIV32_gc; // Разрешаем работу АЦП ADCA.CTRLA|=ADC_ENABLE_bm; }
// Измерение на АЦП канал CH0; unsigned int adc_rez (void) { unsigned int ADC_result; ADCA.CTRLA|=ADC_CH0START_bm; // запускаем одиночное преобразование do{}while((ADCA.INTFLAGS&ADC_CH0IF_bm)==0x00); // Ждет флага CH0IF об окончании преобразования ADCA.INTFLAGS=ADC_CH0IF_bm; // сбрасываем флаг CH0IF записью в него "1" ADC_result=ADCA.CH0RES.i; // считываем результат преобразования в канале CH0 return ADC_result; // Возвращение результата преобразования }
// Функция измерения напряжения - 30 измерений unsigned int usmer (void) { unsigned int j,F; double value=0, temp; init_ADC(); for (j=1; j<31; j++) { F=adc_rez(); value=value+F; } temp=(value/30); F=(unsigned int)(temp); return F; } Как видно - работает в единичном преобразовании, функции легко переделать по любой вывод (добавляем переменную в вызов функции). А вот насчет - калибровки - пока не знаю (нашел по даташитам что калибровка АЦП происходит при производстве и дальше можно зашивать значения при программировании (и они не изменяются пока программатором не сотрешь) - так что пока разбираюсь что и как калибровать и надо ли на 12 -бит это делать?? (тем более внутренний ИОН всего 1 %).[/quote]
Сообщение отредактировал Leonmezon - Aug 21 2009, 17:47
|
|
|
|
|
Aug 21 2009, 19:05
|
Участник

Группа: Участник
Сообщений: 44
Регистрация: 24-11-07
Пользователь №: 32 645

|
Вроде как разобрался, спасибо.. Что самое обидное нет толкового описания. Смотрел на гаве описалово на русском, но оно противоречит по регистрам даташита, иар тоже разницу в названиях регистров имеет, вот и спрашиваю. У меня ацп врет в районе 10ти значений, что вполне приемлимо при 12ти битном преобразовании при своем внутреннем опорном. А вот 8ми битное не понравилось совсем. Очень шумно. По схеме все расключено в порядке, осциллом смотрел AVCC, более менее в поряде.
Сообщение отредактировал ведущий_специалист - Aug 21 2009, 19:33
|
|
|
|
|
Aug 21 2009, 19:37
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686

|
Цитата(ведущий_специалист @ Aug 21 2009, 23:05)  Интересно, с какой ноги сигнал снимать? Я совсем запутался. К примеру CH0, его ведь нужно определить на какую либо ножку ацп физически, или по умолчанию как то разводится внутри проца? Что самое обидное нет толкового описания. Смотрел на гаве описалово на русском, но оно противоречит по регистрам даташита, иар тоже разницу в названиях регистров имеет, вот и спрашиваю. У меня ацп врет в районе 10ти значений, что вполне приемлимо при 12ти битном преобразовании при своем внутреннем опорном. А вот 8ми битное не понравилось совсем. Очень шумно. По схеме все расключено в порядке, осциллом смотрел AVCC, более менее в поряде. Вот этой командой ADCA.CH0.MUXCTRL|=ADC_CH_MUXPOS_PIN1_gc; - т.е. получаем измерение напряженя на 1 ножке порта А. Вот *.h файл с ICC AVR 7.22B (они очень близко написали к Atmel) - вобщем все понятно - каждое ADC_CH_MUXPOS_PIN*_gc соотвествует своей ножке * порта А или B (задаеться в начале). (причем если надо использовать разные ножки- то лучше передовать число (понятнее вроде будет). - Код #define ADC_MUXPOS_PIN0_gc (0x00<<4) /* Input pin 0 */ #define ADC_MUXPOS_PIN1_gc (0x01<<4) /* Input pin 1 */ #define ADC_MUXPOS_PIN2_gc (0x02<<4) /* Input pin 2 */ #define ADC_MUXPOS_PIN3_gc (0x03<<4) /* Input pin 3 */ #define ADC_MUXPOS_PIN4_gc (0x04<<4) /* Input pin 4 */ #define ADC_MUXPOS_PIN5_gc (0x05<<4) /* Input pin 5 */ #define ADC_MUXPOS_PIN6_gc (0x06<<4) /* Input pin 6 */ #define ADC_MUXPOS_PIN7_gc (0x07<<4) /* Input pin 7 */ Если кто знает, вот с чем помочь: написал код и как его прогнать (так чтоб не часы ждать) в AVR Studio, т.е. надо убедиться что работает (пока макетки нет)? причем Tmax от 100 до 10000 Код // Прерывание по окончанию счета #pragma interrupt_handler iv_TCE0_OVF_isr:48 void iv_TCE0_OVF_isr(void) { TCE0.CTRLA=0x00; // stop Timer 1 порта Е TCE0.CNT.i=0xFF8C; // установка значения для счета 115 значений - 0x73 T=T+1; TCE0.CTRLA|=0x06; //start Timer 1 порта Е }
//TIMER0 initialize - prescale: 256, actual value: 1.001739130435 мс // Тактовая частота таймера 29491200 Гц void timerE0_init(void) { TCE0.CTRLA=0x00; // stop Timer 1 порта Е TCE0.CNT.i=0xFF8C; // установка значения для счета 115 значений - 0x73 TCE0.INTCTRLA = 0x01; // Разрешение прерывания по переполнению - уровень низкий. TCE0.CTRLA|=0x06; //start Timer 1 порта Е }
//Функция задежки управляемая от таймера-счетчика void delayT (unsigned int Tmax) { T=0; timerE0_init(); while (T<Tmax) { NOP(); } TCE0.CTRLA=0x00; // stop Timer 1 порта Е }
Сообщение отредактировал Leonmezon - Aug 21 2009, 19:32
|
|
|
|
|
Aug 22 2009, 01:13
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Цитата как его прогнать (так чтоб не часы ждать) в AVR Studio, т.е. надо убедиться что работает (пока макетки нет)? причем Tmax от 100 до 10000 А чего тут отлаживать? работу nop()? Если в прерывание заходит - значит работает. Только вот не пойму, зачем столько мороки с таймером в прерывании. Во-первых останавливать таймер при смене CNT не обязательно. А во-вторых в данном случае логичнее было бы использовать Period Register Тогда Код void iv_TCE0_OVF_isr(void) { TCE0.CTRLA=0x00; // stop Timer 1 порта Е TCE0.CNT.i=0xFF8C; // установка значения для счета 115 значений - 0x73 T=T+1; TCE0.CTRLA|=0x06; //start Timer 1 порта Е } Превращается в Код T++;
|
|
|
|
|
Aug 25 2009, 18:07
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686

|
Запустил АЦП - есть смещение на 100 мВ+ шумы, рещил запустить калибровку. Просьба помочь разобраться: Файлы для калибровки по даташитам Atmel: Код // Из файла adc_driver.с от Atmel void ADC_CalibrationValues_Load(ADC_t * adc) { if(&ADCA == adc){ /* Get ADCACAL0 from production signature . */ adc->CALL = SP_ReadCalibrationByte( PROD_SIGNATURES_START + ADCACAL0_offset ); adc->CALH = SP_ReadCalibrationByte( PROD_SIGNATURES_START + ADCACAL1_offset ); }else { /* Get ADCBCAL0 from production signature */ adc->CALL = SP_ReadCalibrationByte( PROD_SIGNATURES_START + ADCBCAL0_offset ); adc->CALH = SP_ReadCalibrationByte( PROD_SIGNATURES_START + ADCACAL1_offset ); } }
uint8_t SP_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; }
#define PROD_SIGNATURES_START 0x0000 #define pgm_read_byte(x) *(x) Написал собственную для ICCAVR: Код // Функция калибровки АЦП порта А void ADC_CalibrationValues_Load(void) { unsigned char ADCACAL0_offset, ADCACAL1_offset; unsigned int value; /* Load the NVM Command register to read the calibration row. */ NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc; ADCACAL0_offset = (*(volatile unsigned char *)0x20); // младший калибровочный байт /* Clean up NVM Command register. */ NVM.CMD = NVM_CMD_NO_OPERATION_gc; /* Load the NVM Command register to read the calibration row. */ NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc; ADCACAL1_offset = (*(volatile unsigned char *)0x21); // старший калибровочный байт /* Clean up NVM Command register. */ NVM.CMD = NVM_CMD_NO_OPERATION_gc; value= (ADCACAL1_offset<<8)+ADCACAL0_offset; ADCA.CAL.i = value; // установка данных в регистр калибровка АЦП } 1. Зачем надо писать (*(volatile unsigned char *)0x20)?? (только просьба просто объяснить). 2. Надо ли после считывания младшего калибровочного байта писать в NVM Command register или можно подрят считать оба байта? 3. Просьба - может кто уже разобрался с структурой из файла xmstructs.h мы можем сразу получить доступ ко всем калибровочным данным? Если да - то как это сделать (примеров с этой структорой нет). Код #ifndef ___xmstructs_h #define ___xmstructs_h * * * /* NVM signature row registers */ typedef struct NVM_SIG_struct { unsigned char RCOSC2MCAL; unsigned char reserved_0x01; unsigned char RCOSC32KCAL; unsigned char RCOSC32MCAL; unsigned char reserved_0x04; unsigned char reserved_0x05; unsigned char reserved_0x06; unsigned char reserved_0x07; unsigned char LOTNUMBYTE0; unsigned char LOTNUMBYTE1; unsigned char LOTNUMBYTE2; unsigned char LOTNUMBYTE3; unsigned char LOTNUMBYTE4; unsigned char LOTNUMBYTE5; unsigned char reserved_0x0E; unsigned char reserved_0x0F; unsigned char WAFERNUM; unsigned char reserved_0x11; unsigned char WAFERX0; // jph unsigned char WAFERX1; // jph unsigned char WAFERY0; // jph unsigned char WAFERY1; // jph unsigned char reserved_0x16; unsigned char reserved_0x17; unsigned char reserved_0x18; unsigned char reserved_0x19; unsigned char reserved_0x1A; unsigned char reserved_0x1B; unsigned char reserved_0x1C; unsigned char reserved_0x1D; unsigned char reserved_0x1E; unsigned char reserved_0x1F; unsigned char ADCACAL0; unsigned char ADCACAL1; unsigned char ADCACAL2; unsigned char ADCACAL3; unsigned char ADCBCAL0; unsigned char ADCBCAL1; unsigned char ADCBCAL2; unsigned char ADCBCAL3; unsigned char reserved_0x28; unsigned char reserved_0x29; unsigned char reserved_0x2A; unsigned char reserved_0x2B; unsigned char reserved_0x2C; unsigned char reserved_0x2D; unsigned char TEMPSENSE0; unsigned char TEMPSENSE1; unsigned char DACACAL0; unsigned char DACACAL1; unsigned char DACBCAL0; unsigned char DACBCAL1; } NVM_SIG_t;
|
|
|
|
|
Sep 2 2009, 13:49
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Цитата(Duhas @ Sep 2 2009, 14:28)  решил наваять макетку для Хмеги128А1 и что-то терюсь где искать распиновку периферии.. уарты там и прочее как по портам раскидано? иль я туплю ?) См. раздел 29.2 Alternate Pin Functions в ATxmega64A1/128A1/192A1/256A1/384A1 Preliminary (rev.I). Там в виде таблицы все сведено
|
|
|
|
|
Sep 24 2009, 11:07
|
Группа: Участник
Сообщений: 4
Регистрация: 22-07-09
Пользователь №: 51 458

|
Всем привет! Тут поднимали тему про АЦП Xmega. Может кто-то тоже сталкивался с подобной проблемой: Я пыталась добиться точного измерения на 12-битном разрешении. Все настроила, сделала калибровку (переписала калибровочные значения в регистры CAL).В бесконечном цикле запускаю функцию:
void ADC__read(ADC_t * adc, int countOfMeasure, countOfMeasure) { ADC_Enable(adc); ADC_Wait_8MHz(adc); // запуск преобразования на канале CH3 ADC_Ch_Conversion_Start(&adc->CH3); // ожидание завершения преобразования do{} while(!ADC_Ch_Conversion_Complete(&adc->CH3)); adc->INTFLAGS=ADC_CH3IF_bm; // считываем результат преобразования с канала CH3 ADC_result[countOfMeasure]=ADC_ResultCh_GetWord(&adc->CH3, 0); ADC_Disable(adc); } Полученные значения в массиве ADC_result[countOfMeasure] сильно нестабильны, разница между соседними отсчетами достигает 40 единиц. Даже не понятно какое из значений использовать.
Может это нормально для XMEga, но все-таки хотелось большей точности от 12-разрядного АЦП
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|