|
SAM4S, Ничего не выходит |
|
|
|
 |
Ответов
(15 - 29)
|
Oct 15 2014, 12:50
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
а я бы сказал что так делать не надо, по описанной выше причине. Не надо делать своих дефайнов к ногам. Свои дефайны могу быть из раздела DIAGNOSTIC_LED_ON, DIAGNOSTIC_LED_OFF, за которыми скрыть работу с ножкой порта, но через стандартные дефайны из заголовочного файла. ИМХО конечно... Цитата , т.к. обращение напрямую к регистрам конечно не самый красивый способ не соглашусь. Это самый прямой и быстрый способ. Если не брать чужую библиотеку, надо писать свою, где функции настройки просто имеют внутри прямой доступ к регистрам. Это самый короткий, прямой путь без сюрпризов. Почему он не красив?
|
|
|
|
|
Oct 15 2014, 13:00
|

Частый гость
 
Группа: Свой
Сообщений: 78
Регистрация: 23-03-11
Из: Россия
Пользователь №: 63 824

|
Цитата(Golikov A. @ Oct 15 2014, 15:50)  а я бы сказал что так делать не надо, по описанной выше причине. Не надо делать своих дефайнов к ногам. Да дело же не в дефайнах - это идеология ASF от Атмела. А так, да - стоит использовать только дефайны для удобства чтения и создания переносимости. А по поводу скорости работы, кто же спорит. Напрямую всегда быстрее, чем окольными путями(ASF, STD Periph Lib и т.д, правда все зависит от реализации этих библиотек)
|
|
|
|
|
Oct 15 2014, 13:03
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Грендайзер @ Oct 15 2014, 13:55)  KnightIgor, спасибо, CMSIS обязательно изучу, т.к. обращение напрямую к регистрам конечно не самый красивый способ. Впрочем и работа с набором непонятных ф-ций то же не особо доставляет. Всегда пожалуйста, но мне кажется, Вы не совсем поняли: CMSIS не исключает обращения к регистрам напрямую. Она даже поощряет это, но вводит некоторые правила наименования тех самых регистров и битов в них, а также принцип доступа к периферийным регистрам как к полям некой структуры. Самих функций в CMSIS немного и касаются они только ядра и базовой периферии, то есть NVIC (контроллера прерываний), SYSTICK (генератора системных тиков) и некоторых других основ. Вам нужно, - и прислушайтесь к этому совету, - сначала изучить и применить периферийную библиотеку для Вашего процессора. Это надстройка над регистрами. Пусть многие ругают такие библиотеки и их индусских воплотителей, но они очень помогают для быстрого старта, потому что имеют сами за себя говорящие имена функций и параметры, скрывающие внутреннюю суть тех самых регистров и битов. И кстати, не все такие библиотеки плохи: для EFM32 они просто замечательны.
|
|
|
|
|
Oct 15 2014, 13:39
|
Местный
  
Группа: Участник
Сообщений: 368
Регистрация: 18-04-11
Из: Город-герой Москва
Пользователь №: 64 451

|
Цитата Это самый короткий, прямой путь без сюрпризов. Почему он не красив? А действительно, почему?! Наверное Вы правы!!! В конечном итоге можно будет процесс программирования сделать немного похожим на программирование тех же АВР Цитата А по поводу скорости работы, кто же спорит. Напрямую всегда быстрее, чем окольными путями(ASF, STD Periph Lib и т.д, правда все зависит от реализации этих библиотек) А вот этот момент мне критичен. Вообще работаю с ПЛИС поэтому всегда знаю, сколько тактов у меня на что уходит, и если такого понимания нет чувствую себя немного не уютно. Но создавать свои проекты с учётом временных особенностей кристалла крайне сложно и долго, поэтому, и решил где возможно использовать готовые решения (например тот же Nios), облегчает жизь, но не стоимость изделия. Так что чёткое понимание это есть хорошо, правда в этом случае, придётся перейти на ассемблер, но это уже черезчур. Времени конечно нет, но его никогда нет. Тут советывался с одним коллегой, он работает с ядром ARM где то пол года, говорит что даже не стал вникать в эти ф-ции. Начал сразу писать свои библиотеки (впрочем у него огромный опыт работы с АВР и чего он там для них токо не писал).
Сообщение отредактировал Грендайзер - Oct 15 2014, 13:43
|
|
|
|
|
Oct 15 2014, 14:17
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Правда как всегда по середине. Я всегда за то что нельзя использовать чужой код без проверки. Есть люди что верят библиотекам и даже не сморят что там внутри, а бывает всякое. Отрицать библиотеки тоже не правильно, часто они ускоряют процесс и делают код удобным для совместной работы, легче вникать что там понаделано.
Претензии у меня к ним такие. Библиотеки часто грешат, особенно те функции что настраивают сложную периферию тем что считают процессор в состоянии после ресета. А если есть бутлоадер и там уже что-то настроено? Пару раз так обсерался, не проверил и получил гемор и отладку...
А вот число тактов на команду - это суровый момент, процы имеют и схемы пред выбора команд, и конвейер и прерывания, и контроллер прерываний, не всегда у вас получится уследить за числом тактов%) да и компилятор помогает. А вот от Ассемблера я бы вас предостерег, мне кажется уже не того уровня техника. Только ассемблерные вставки в критических секциях не более, а то слишком дорого будет обслуживать проект.
Хотя все изложенное ИМХО
|
|
|
|
|
Jul 29 2015, 09:54
|
Местный
  
Группа: Участник
Сообщений: 368
Регистрация: 18-04-11
Из: Город-герой Москва
Пользователь №: 64 451

|
Здравствуйте! Продолжаю мучить ATSAM4S32C. Дошёл до ЦАП и возникло 2 вопроса. 1) В электрических параметрах на встроенный ЦАП указан параметр Startup Time - что это? 2) В этих же электрических данных указано, что максимальная тактовая частота ЦАП составляет 50МГц. Но максимальная частота ядра достигает 120МГц. Частота ядра, как собственно и переферии есть Master Clock (MCK) которая ирёт с контроллера управления питанием Power Management Controller (PMC). В описаниии на ЦАП указано: The DACC uses the master clock (MCK) divided by two to perform conversions. Т.о. если я правильно понимаю, либо частота ядра не должна превышать 100МГц (что на 20МГц ниже чем максимальная) либо отказаться от использования встроенного ЦАП?  С АЦП у меня такой проблемы не возникло, т.к. тот имеет свой собственный делитель частоты. Но вот в ЦАПе я такого не обнаружл  Как быть? Что делать? Кто виноват?
|
|
|
|
|
Aug 5 2015, 10:10
|
Местный
  
Группа: Участник
Сообщений: 368
Регистрация: 18-04-11
Из: Город-герой Москва
Пользователь №: 64 451

|
Всем доброго времени суток. Опять столкнулся с проблемой, точнее с двумя. Первое - никак не могу победить оптимизатор в AtmelStudio. Это сволочь помоиму мне палки в колёса тычит. А именно: написал программку которая принимает данные с АЦП, пропускает через ФВЧ и кладёт в ЦАП. CODE #include "sam.h" int din = 0; int dout = 0; int dacc_in = 0; int din_1 = 0; volatile int flag = 0;
int main(void) { SystemInit(); //--------------- Включение глобальных прерываний ----------------------------- __enable_irq (); //--------------- Enable Interrupts in NVIC ---------------------------- NVIC_EnableIRQ(DACC_IRQn); NVIC_EnableIRQ(ADC_IRQn); //--------------- Приоритет прерывания ЦАП ниже чем у АЦП NVIC_SetPriority (DACC_IRQn, 2); //----------- далее настройка переферии------------------------ . . . //---------------------------------------------------------------------- int main(void) { switch(flag) { case 0: // если прерывание от АЦП не произошло, моргать светодиодами { {PIOA -> PIO_CODR = PIO_CODR_P19 | PIO_CODR_P20;} for (int i = 0; i < 1000000; i ++){} {PIOA -> PIO_SODR = PIO_SODR_P19 | PIO_SODR_P20;} for (int i = 0; i < 1000000; i ++){} break; } case 1: // Если прерывание от АЦП было - гнать данные через ФВЧ { dacc_in = dout + din - din_1; dout = dacc_in * 0.9 + 600; din_1 = din; break; } default : {break;} } return 0; }
\\ Подпрограммы прерываний \\------------ АЦП---------------- void ADC_Handler( void ) { volatile int IRQ_sense = 0; IRQ_sense = ADC -> ADC_ISR & (ADC_IER_EOCAL | ADC_IER_EOC5); switch(IRQ_sense) { case ADC_IER_EOCAL : // автокалибровка АЦП { {PIOA -> PIO_CODR = PIO_CODR_P19 | PIO_CODR_P20;} {PIOA -> PIO_SODR = PIO_SODR_P19 | PIO_SODR_P20;} ADC -> ADC_IER = ADC_IER_EOC5; ADC -> ADC_CR = ADC_CR_START; return; } case ADC_IER_EOC5 : { flag = 1; // Говорим что было прерывание от АЦП din = ADC -> ADC_CDR[5] & ADC_CDR_DATA_Msk; // Данные с АЦП ADC -> ADC_CR = ADC_CR_START; // Вновь запускаем АЦП return; } default : {return;} } }
//-------------------------- ЦАП -------------------------------- void DACC_Handler( void ) { volatile int IRQ_sense = 0; IRQ_sense = DACC -> DACC_ISR;// & (DACC_ISR_EOC); DACC -> DACC_CDR = DACC_CDR_DATA(dout); return; } Так вот у меня программа лишь могргает светодиодами... Тупо.. В пошаговой отладке оказывается, что din меняет свое значение, а вот dout просто проскакивается, процессор его не замечая выполнят команду flag = 0 и всё. При этом если формулу фильтра вписать в функцию прерывания от АЦП то всё работает. В чём дело?
Сообщение отредактировал IgorKossak - Aug 5 2015, 19:37
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Aug 5 2015, 11:56
|
Местный
  
Группа: Участник
Сообщений: 368
Регистрация: 18-04-11
Из: Город-герой Москва
Пользователь №: 64 451

|
Цитата Не грех посмотреть в сгенерённый код: куда dout там делся… А кто ж его знает... оптимизировался б...  Приведу кусочек дизассемблированного кода на рисуночке. P.S. Попробовал везде volatile напихать... амплитуда на выходе ЦАПа уменьшилась почти в 10 раз по сравнению с тем, что без волатиле, при том осциллограма сильно дёргается... Вообщем жесть какая то...
Сообщение отредактировал Грендайзер - Aug 5 2015, 11:57
Эскизы прикрепленных изображений
|
|
|
|
|
Aug 5 2015, 12:40
|
Местный
  
Группа: Участник
Сообщений: 368
Регистрация: 18-04-11
Из: Город-герой Москва
Пользователь №: 64 451

|
прошу прощения за ошибки допущенные при копировании. вот поправленный вариант CODE #include "sam.h"
int din = 0; int dout = 0; int dacc_in = 0; int din_1 = 0; volatile int flag = 0;
int main(void) { SystemInit(); //--------------- Enable Global Interrupts ----------------------------- __enable_irq (); //--------------- Enable Interrupts in NVIC ---------------------------- NVIC_EnableIRQ(DACC_IRQn); NVIC_EnableIRQ(ADC_IRQn); NVIC_SetPriority (DACC_IRQn, 2); while (1) { switch(flag) { case 0:// если прерывание от АЦП не произошло, моргать светодиодами { {PIOA -> PIO_CODR = PIO_CODR_P19 | PIO_CODR_P20;} for (int i = 0; i < 1000000; i ++){} {PIOA -> PIO_SODR = PIO_SODR_P19 | PIO_SODR_P20;} for (int i = 0; i < 1000000; i ++){} break; } case 1: // Если прерывание от АЦП было - гнать данные через ФВЧ { dacc_in = dout + din - din_1; dout = dacc_in * 0.9 + 600; din_1 = din; flag = 0; break; } default : {break;} } } return 0; }
\\ Подпрограммы прерываний \\------------ АЦП---------------- void ADC_Handler( void ) { volatile int IRQ_sense = 0; IRQ_sense = ADC -> ADC_ISR & (ADC_IER_EOCAL | ADC_IER_EOC5); switch(IRQ_sense) { case ADC_IER_EOCAL : // автокалибровка АЦП { {PIOA -> PIO_CODR = PIO_CODR_P19 | PIO_CODR_P20;} {PIOA -> PIO_SODR = PIO_SODR_P19 | PIO_SODR_P20;} ADC -> ADC_IER = ADC_IER_EOC5; ADC -> ADC_CR = ADC_CR_START; return; } case ADC_IER_EOC5 : { flag = 1; // Говорим что было прерывание от АЦП din = ADC -> ADC_CDR[5] & ADC_CDR_DATA_Msk; ADC -> ADC_CR = ADC_CR_START; return; } default : {return;} } }
//-------------------------- ЦАП -------------------------------- void DACC_Handler( void ) { volatile int IRQ_sense = 0; IRQ_sense = DACC -> DACC_ISR; DACC -> DACC_CDR = DACC_CDR_DATA(dout); return; } P.S. Процесс настройки переферии указывать не стал
Сообщение отредактировал IgorKossak - Aug 5 2015, 19:37
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Aug 5 2015, 13:14
|
Местный
  
Группа: Участник
Сообщений: 368
Регистрация: 18-04-11
Из: Город-герой Москва
Пользователь №: 64 451

|
Цитата какая там у вас битность ЦАП? не переполнится ли он таким макаром? 12 бит. Нет, не переполнится. Как я уже писал, всё работает если данный кусок кода поместить в ф-цию обработчика прерываний. Цитата Прерывания кстати где сбрасываются? В смысле? Прерывания срабатывают следующим образом 1) В процессе настройки переферии запускается ЦАП; 2) Когда завершается автокалибровка; 3) После автокалибровки запускается ЦАП; Все прерывания отрабатывают. И ещё пробовал отключать оптимизацию, код выполнялся правильно, но работал оооочень медленно.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|