Ликбез для Arduino DUE
- Войдите на сайт для отправки комментариев
Ср, 21/03/2018 - 09:30
Добрый день, форумчане.
Предлагаю тему про изучение Arduino DUE (sam3x8e) не на уровне Arduino IDE, а с пониманием регистров...
Обращаюсь к знатокам программирования (и кто уже разобрался с Atmel sam3x8e) помогите разобраться.. сам переключился на изучение sam3x8e т.к. на Arduino MEGA не стало хватать ресурсов и так вопрос:
1. стандартная функция digitalWrite требует порядка 2 мксек времени, это ОЧЕНЬ расточительно (168 тактов!!)
как выполнить данную функцию на уровне регистров?? (как было у MEGA, например PORTC |= (1 << 0))
Чукча не читатель, чукча - писатель?
http://arduino.ru/forum/programmirovanie/arduino-due-neponyatki-pri-popy...
Большое спасибо за наводку..
2. можно так же подробно про настройку таймеров? (кое что нашел, но хотелось поподробнее...)
Уважаемые знатоки!
Помогите разобраться с настройками АЦП на arduinoDUE. Стандартная функция analogRead не вариант - очень долго!
Много уважаемые зубры программирования: "dimax", "ЕвгенийП", "andriano" и другие ..
Уделите свое внимание!
Ни как не могу разобраться в datasheet, выложите, пожалуста, пример настройки АЦП на arduino DUE (работа по прерыванию)!!!
AntonULN, я АЦП в дуе не использовал, так что готовых "шапок" нет. А что гугль, разве ничего не предлагает на эту тематику?
в google не нашел примерного кода, для arduino ... пытался разобраться в asf AtmelStudio, но там вроде через подключаемые библиотеки в самой студии, т.е. это надо разбираться "внутрях" библиотеки :-( это пока не для меня..
кое что нашел.. и так кому нужно ускорить ADC в arduinoDUE до 1мкс вам сюда...
http://forum.arduino.cc/index.php?topic=156849.0
http://www.djerickson.com/arduino/due_adc.html
http://frenki.net/2013/10/fast-analogread-with-arduino-due/
Вот пример, делал разгон АЦП на 42 МГц ( /21 -> 2 мегасэмпла/сек). Скетч даст вам идею, как в некоторых моментах разбираться самому, потому что врут все, даташиты и интернет. Не обязательно намерено, просто у кого то действительно работало, а потом компилёр поменялся и бац. Идея простая, используйте Сериал по максимуму, ставите непонятные биты через команды по сериал порту, сбрасываете, и смотрите разницу. Для этого ардуино ИДЕ и нужна, собственно. Если есть осцилоскоп то ещё лучше, нет и так можно. Да, и просматривайте что биты выставились как было запрошено, ардуино очень своенравна, и допускать что она сделает как велено - очень большая недальновидность.
#define SMP_RATE 233000UL #define CLK_MAIN 84000000UL #define TMR_CNTR CLK_MAIN / (2 *SMP_RATE) #define FFT_SIZE 64 #define INP_BUFF FFT_SIZE * 4 /* 4 Mikrofona */ int16_t in[2][INP_BUFF] = { 0}; /* 2x2x4x2028 = 32k */ volatile uint16_t sptr = 0 ; volatile int16_t flag = 0 ; uint32_t lowres = 0; uint32_t ovrclk = 0; const int16_t dc_offst = 2047; void setup() { Serial.begin (115200) ; adc_setup (); tmr_setup (); pinMode ( 2, INPUT); pinMode ( 13, OUTPUT); digitalWrite( 13, LOW); } void loop() { volatile uint32_t reg; volatile uint32_t reg_val1, reg_val2; char in_Byte; if (Serial.available() > 0) { in_Byte = Serial.read(); if (in_Byte == 'z') { //debug tmr_adjust(-10); } if (in_Byte == 'c') { //debug tmr_adjust( 10); } if (in_Byte == 'l') { //debug lowres = 1 - lowres; adc_setup(); } if (in_Byte == 'o') { //debug ovrclk = 1 - ovrclk; adc_setup(); } if (in_Byte == 'x') { //debug uint16_t indx_a = flag -1; Serial.print("\n buff: "); Serial.print(indx_a, DEC); for ( uint32_t y = 0; y < 4; y++){ Serial.print("\n\tInput - "); Serial.print( y, DEC); Serial.print("\n\t"); for ( uint32_t i = y; i < INP_BUFF; i += 4) { Serial.print(in[indx_a][i] - dc_offst, DEC); Serial.print("\t"); if ((i + 4 - y) % 64 == 0) Serial.print("\n\t"); } } Serial.println("\n\t"); /* Serial.print("\n\t"); for ( int i = 0; i < INP_BUFF; i++) { Serial.print(in[indx_a][i]); Serial.print("\t"); if ((i+1)%16 == 0) Serial.print("\n\t"); } */ } if (in_Byte == 'd') { //debug unsigned long reg; reg = REG_ADC_MR; Serial.print("\n\tREG_ADC_MR = "); Serial.println(reg, HEX); reg = adc_get_actual_adc_clock(ADC, SystemCoreClock); Serial.print("\n\tADC Clock = "); Serial.println(reg, DEC); reg = SystemCoreClock; Serial.print("\n\tSystemCoreClock = "); Serial.println(reg, DEC); } } } void tmr_adjust (int delta) { REG_TC0_RC0 += delta; REG_TC0_RA0 = REG_TC0_RC0 /2; Serial.print("\n TC_RC = \t"); Serial.print(REG_TC0_RC0, DEC); Serial.print("\t TC_RA = \t"); Serial.print(REG_TC0_RA0, DEC); } void tmr_setup () { pmc_enable_periph_clk(TC_INTERFACE_ID + 0 *3 + 0); // clock the TC0 channel 0 TcChannel * t = &(TC0->TC_CHANNEL)[0] ; // pointer to TC0 registers for its channel 0 t->TC_CCR = TC_CCR_CLKDIS ; // disable internal clocking while setup regs t->TC_IDR = 0xFFFFFFFF ; // disable interrupts t->TC_SR ; // read int status reg to clear pending t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // use TCLK1 (prescale by 2, = 42MHz) TC_CMR_WAVE | // waveform mode TC_CMR_WAVSEL_UP_RC | // count-up PWM using RC as threshold TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output) TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR | TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR ; t->TC_RC = TMR_CNTR; // counter resets on RC, so sets period in terms of 42MHz clock t->TC_RA = TMR_CNTR /2; // roughly square wave t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET ; // set clear and set from RA and RC compares t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ; // re-enable local clocking and switch to hardware trigger source. } void adc_setup () { pmc_enable_periph_clk(ID_ADC); if (ovrclk == 0) adc_init(ADC, SystemCoreClock, 21000000UL, ADC_STARTUP_FAST); if (ovrclk == 1) adc_init(ADC, SystemCoreClock, 42000000UL, ADC_STARTUP_FAST); NVIC_EnableIRQ (ADC_IRQn); // enable ADC interrupt vector adc_disable_all_channel(ADC); adc_enable_interrupt(ADC, ADC_IER_RXBUFF); ADC->ADC_RPR = (uint32_t) in[0]; // DMA buffer ADC->ADC_RCR = INP_BUFF; ADC->ADC_RNPR = (uint32_t) in[1]; // next DMA buffer ADC->ADC_RNCR = INP_BUFF; ADC->ADC_PTCR = 1; adc_set_bias_current(ADC, 0x01); if (lowres == 1) { // adc_set_resolution(ADC, ADC_10_BITS); REG_ADC_MR |= 0x00000010; } if (lowres == 0) { //? adc_set_resolution(ADC, ADC_MR_LOWRES_BITS_12); // adc_set_resolution(ADC, ADC_12_BITS); REG_ADC_MR &= ~0x00000010; } adc_enable_channel(ADC, ADC_CHANNEL_7); // AN0 adc_enable_channel(ADC, ADC_CHANNEL_6); // AN1 adc_enable_channel(ADC, ADC_CHANNEL_5); // AN2 adc_enable_channel(ADC, ADC_CHANNEL_4); // AN3 adc_configure_trigger(ADC, ADC_TRIG_TIO_CH_0, 0); } void ADC_Handler (void) { if((adc_get_status(ADC) & ADC_ISR_RXBUFF) == ADC_ISR_RXBUFF) { flag = ++sptr; sptr &= 0x01; ADC->ADC_RNPR = (uint32_t) in[sptr]; ADC->ADC_RNCR = INP_BUFF; } }Регистры можно и подругому твикать, прямой записью, но скетч более ранний чем я это выяснил.
Спасибо большое "Волшебник" за приведенный пример, но если можно, прошу пояснить..
вообще на данном этапе требуется считать 4-аналоговых сигнала, мне удалось реализовать переодическое считывание через таймер ТС0, я понимаю, что это не правильно...пытаюсь запустить прерывание ADC, в примере "Волшебника" это есть, но там много лишнего... можно пояснить строки:
}
происходить проверка не переполнение буфера?
Я так думаю в моем случае можно и не использовать буфер...
adc_set_bias_current(ADC, 0x01); - что это? конроль тока? экономичный режим?
1. можно пояснить строки:
void ADC_Handler (void) { if((adc_get_status(ADC) & ADC_ISR_RXBUFF) == ADC_ISR_RXBUFF) { flag = ++sptr; sptr &= 0x01; ADC->ADC_RNPR = (uint32_t) in[sptr]; ADC->ADC_RNCR = INP_BUFF; }происходить проверка не переполнение буфера?
2. Я так думаю в моем случае можно и не использовать буфер...
3. adc_set_bias_current(ADC, 0x01); - что это? конроль тока? экономичный режим?
Поясню, Вам бы на Уно поиграть пару месяцев, а потом уж на Дуэ. Буду краток, не обессудьте. Логика предельно проста: Если сэмплировать надо под 1 МГц, то цепочка АЦП->ДМА->Буффер Обязательна, просто потому что ардуина не успеваеет прыгать в прерывание за каждым сэмплом и обратно. Вариант когда самплирование это всё что она делает я вообще не рассматриваю. Если прыгать в прерывание раз на 1000 сэмплов, тогда накладные расходы времени на переходы минимальны, почти всё идёт за сценой.
3. adc_set_bias_current и другие ляповатые функции, это части ASF, атмеловская попытка создать свой CMSIS, т.е упорядочить обращение к регистрам /битам процессора и периферии через "вреперы" - функции обёртки.
http://asf.atmel.com/docs/3.17.0/asf_drivers.html
http://asf.atmel.com/docs/3.5.1/sam.drivers.tc.tc_capture_waveform_example.sam4l_ek/html/tc__capture__waveform__example_8c_source.html
Попытка не удачная (личное мнение), там полный бардак. Не удалось толком и другим, Кортекс-3 сложноват, процессоры разные с разным набором периферии и методами, поэтому ни ЭсТиЭм ни другие Филипсы этот бардак так и не разрулили.
Пользователю остаётся открывать дата шит на процессор, (скачать если ещё не сделали), смотреть регистры и битовые поля, потом искать в установленных директориях ардуино ИДЕ а есть ли там похожая функция и использовать её. Если нет, или она меняет не то или не так, тогда Хрень1->Биты7 = (* uint32_t) (ставим что надо).
Сам пользуюсь нортом-командером, ну типа, в строку поиска имя регистра, раздел - ардуино15, Дуе ставится на диске в другой директории чем Уно (и др. АВР).
"Волшебник"
На DUE пришлось перейти с MEGA, не хватало скорости (требуется управлять 4-мя ШД).. пытаюсь переделать проект с MEGA на DUE сохранив концепцию.. решение считывание ADC на прерывание таймера ТС0, по временным затратам проходит (в прерывание ADC выполняется менее 1мкс), но хотелось все-таки разобраться с вызовом прерывания самого ADC..
Взял код из ASF, но он почему-то не работает.. помогите найти ошибку
И еще, в UNO, MEGA описывалась проблема, что при переключении с канала на канал ADC при первом преобразовании идут шумы, в DUE есть такие проблемы??
Работая с UNO, MEGA очень удобно, при каких либо непонятках в коде, прогонять код в симуляторе (использую AtmelStudio), нигде не нашел симулятор для DUE, он вообще есть?
Вопрос по скетчу из поста #8 к Волшебнику? Загрузил скетч ADC->DMA в Arduino DUE и вижу вот такую некрасивую картинку, не подскажите в каком направлении копать?
...вижу вот такую некрасивую картинку, не подскажите в каком направлении копать?
Отфотошопить, чтобы была красивая.
Кто объяснит такую вещь. Было подключено в adc_setup два канала измерения АN0 и АN1, шла штриховка по обоим каналам. После отключения канала AN1 картинка приняла нормальный вид, без штриховки.
Мальтиплексор переключает каналы. Если выходное сопротивление источника сигнала высокое, то накопительный конденсатор не успевает зарядиться нормально и имеем случайный уровень. Подключите две пальчиковые батарейки с разными напряжениями и штриховки не будет.
добрый день
под рабочий проек, решил набросать "карту портов" и столкнулся с некоторым несответствием имен портов контроллера и ардуино
кратко, выкус из "последних" зарисовок, надеюсь, кому надо - пригодится :о)
1 - datasheet sam3x8e 2 - pdf A-Due 3 - на плате A-Due (обозначение пинов краской) ------------------------------------------------------ port pin (1) (2) (3) ------------------------------------------------------ PA9 2 UTXD TX PA8 27 URXD RX PA11 4 TXD0 TXD2 TX1 !!! несоответствие на плате и pdf-схеме Due PA10 3 RXD0 RXD2 RX1 !!! несоответствие на плате и pdf-схеме Due PA13 6 TXD1 TXD1 TX2 !!! несоответствие на плате и pdf-схеме Due PA12 5 RXD1 RXD1 RX2 !!! несоответствие на плате и pdf-схеме Due B20 91 TXD2 TXD3 A11 !!! A11 на ADCH 4pin B21 92 RXD2 RXD3 D52 !!! D52 на DIGITAL PD4 17 TXD3 TXD0 TX3 !!! (TXDO - обозначение на схеме, но подключен TXD3) PD5 18 RXD3 RXD0 RX3 !!! (RXDO - обозначение на схеме, но подключен RXD3) + (*) доп. - несоответствие названий пинов у мандарины и datasheet-pdf ----------------------------------- DUE CHIP_PDF ----------------------------------- 18 PA11 TX1 -> TX0 19 PA10 RX1 -> RX0 6 PA13 TX2 -> TX1 5 PA12 RX2 -> RX1 17 PD4 TX3 -> TX3 18 PD5 RX3 -> RX3 ----------------------------------- итого ___ ___ --------|---|----|---|-------------- | COM COM | * | | | A-Due Board Reset | | | | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | ADCH Communication | | x <- key key --> x | TX3/14 | -> TXD3 <- реальные пина на контроллере | x x | RX3/15 | -> RXD3 | x x | TX2/16 | -> TXD1 | * A11/TXD2 x | RX2/17 | -> RXD1 | x x | TX1/18 | -> TXD0 | x x | RX1/19 | -> RXD0 | x x | SDA/20 | -> | x x | SCL/21 | -> | DIGITAL connected | ^ | A52/RXD2 | | | x*xxxxxxxxxxxxxxxxxxxxxxxxxxxxx | Due обозначение | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ------------------------------------дополнительно, есть "некоторая" непонятка с портами A11/TXD2, A52/RXD2 (из головы вылетело, но задокументалировал, значит была причина :о)
возможно, допускаю, что где-то я ошибся, недоглядел итд (недосып, недоед, итд)... спасибо
sunjob, это разные системы счислений. Вызвал путаницу видимо тот факт, что изначально в камне 2 типа портов: 1UART и 4 USART (Usart0-Usart3). В схеме уже нумерация своя (нулевым портом стал UART, а нулевой USART стал tx2) , а в нумерации на плате уже третья система (Нулевой и первый USART сдвинулись на единицу, став первым и вторым, а UART нулевым) . Ну если по-человечески, то конечно это косяк. Ничто не мешало на схеме и в распиновке на плате придерживаться одной системы счисления.
Вопрос к знатокам.
Прикрутил к ARDUINO DUE АЦП AD9280, но из-за того что опрос шины происходит последовательно снижается скорость.
Кто нибудь пробовал параллельный ввод информации на DUE, в MEGA2560 есть, но код от MEGA не работает на DUE?
К даташиту не отсылать, переводил на русский, читал, но ни хрена не понял, осталось его только курить.
это косяк. Ничто не мешало на схеме и в распиновке на плате придерживаться одной системы счисления.
конечно-же это косяк, потому как в хедерах/библиотеках сделан (пришлось сделать) такой выкид шухерной с переименованием... добавив неслабую неразбериху (по законам военного времени за такое в расход пускали :о)
конечно-же это косяк
ну это чисто эстетический косяк, не более. Перепутаны ведь не номера пинов и портов, а лишь символьные синонимы типа TX1 или RX3. Зачем они вообще вам понадобились, непонятно, пользуйтесь вместо них обозначениями пинов типа PA11 или PB6 - они во всех трех системах обозначают одно и тоже.
Я, честно говоря. вообще не знал. что существуют имена типа TX2 . всегда пользуюсь только явно указанными пинами
to dimax, добрый день, еще раз :о)
есть некий код инициализации пина
как в "данном" случае отработает код? сделает подтяжку на землю (arm архитектура) или оставит болтаться в воздухе (ардуино совместимость)
Arduino Due / SAM3X8E
как в "данном" случае отработает код? сделает подтяжку на землю (arm архитектура) или оставит болтаться в воздухе (ардуино совместимость)
что мешает открыть исходник и посмотреть самому?
Arduino Due / ATSAM3X8EA + сетевой шильд W5500 KeyEStudio - проблемы с питанием
Arduino Due / ATSAM3X8EA + сетевой шильд W5500 KeyEStudio - проблемы с питанием
sunjob - продолжаете отжигать?
Вы описание шилда читали?
Keyestudio W5500 network shield comes with W5500 network module as core.
It is compatible with both keyestudio UNO R3 and Mega 2560 R3 development board.
Так какого же фига вы его в Дуе втыкаете?
Что, с первого раза и даже со второго - не дошло? :)))
а вы, сударь, продолжаете идиотничать?! :о) и в школу не ходили и читать не умеете?!... сам себе плюсики ставите? ну-ну, продолжайте :о)
> дурины были сожжены до меня
сударь, если хотите общаться, научитесь слушать и уважительно относиться к собеседнику! а лучше еще и думать! удачи
сударь, если хотите общаться, научитесь слушать и уважительно относиться к собеседнику!
общаться с вами? уважительно относится - к вам? Вы пока не написали ничего такого, чтобы обусловило первое или второе.
Я комментирую ваши сообщения ИСКЛЮЧИТЕЛЬНО для того, чтобы вы своими невежественными замечаниями не пудрили мозг новичкам.
не напрягайте... пролетайте... :о)
по сути возражения есть? - похоже нет
предполагаю, что коротышь 3.3 и 5В происходит в разьеме ISP, т.к. у шильда "питание" 5В и оно идет на пин питания разьема ISP, а у "дурины" питание 3.3В и оно так-же идет на этот самый пин
###!!! UPDATE !!!###
коротыш питания 5 на 3 вольта идет по двум направлениям:
гланды через Ж.
Прерывание SAM3x8E / datasheet
Table 10-28 / page 154 показано, как прерывания или номера IRQ отображаются на регистры прерываний и соответствующие переменные CMSIS, которые имеют один бит на прерывание.
------------------------------------------------------------- Table 10-28/page154 Mapping of interrupts to var ------------------------------------------------------------- ISR | CMSIS array elements (1) |----------|----------|----------|----------|--------- | Set-enbl | Clr-enbl | Set-pend | Clr-pend | Act Bit ------------------------------------------------------------- 0-29 | ISER[0] | ICER[0] | ISPR[0] | ICPR[0] | IABR[0] 30-63 | ISER[1] | ICER[1] | ISPR[1] | ICPR[1] | IABR[1] -------------------------------------------------------------судя по формуле NVIC_EnableIRQ()
~/.arduino15/packages/arduino/hardware/sam/1.6.12/system/CMSIS/CMSIS/Include/core_cm3.h
line: 940 static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) { NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); // enable interrupt }Table10-28 содержит ошибку, а именно распределение номера прерываний
+
так-же есть непонимание по кол-ву прерываний
10.20 Nested Vectored Interrupt Controller
судя по Table10-28 их чуток немного ... поболее :о)
а судя по
// // Interrupt Number Definition // typedef enum IRQn { // // Cortex-M3 Processor Exceptions Numbers // NonMaskableInt_IRQn = -14, /**< 2 Non Maskable Interrupt */ MemoryManagement_IRQn = -12, /**< 4 Cortex-M3 Memory Management Interrupt */ BusFault_IRQn = -11, /**< 5 Cortex-M3 Bus Fault Interrupt */ UsageFault_IRQn = -10, /**< 6 Cortex-M3 Usage Fault Interrupt */ SVCall_IRQn = -5, /**< 11 Cortex-M3 SV Call Interrupt */ DebugMonitor_IRQn = -4, /**< 12 Cortex-M3 Debug Monitor Interrupt */ PendSV_IRQn = -2, /**< 14 Cortex-M3 Pend SV Interrupt */ SysTick_IRQn = -1, /**< 15 Cortex-M3 System Tick Interrupt */ // // SAM3X8E specific Interrupt Numbers // SUPC_IRQn = 0, /**< 0 SAM3X8E Supply Controller (SUPC) */ RSTC_IRQn = 1, /**< 1 SAM3X8E Reset Controller (RSTC) */ RTC_IRQn = 2, /**< 2 SAM3X8E Real Time Clock (RTC) */ ... EMAC_IRQn = 42, /**< 42 SAM3X8E Ethernet MAC (EMAC) */ CAN0_IRQn = 43, /**< 43 SAM3X8E CAN Controller 0 (CAN0) */ CAN1_IRQn = 44, /**< 44 SAM3X8E CAN Controller 1 (CAN1) */ PERIPH_COUNT_IRQn = 45 /**< Number of peripheral IDs */ }их 45 + 8 "исключительных" прерываний
+
typedef struct { ... __IO uint32_t IABR[8]; // Offset: 0x200 (R/W) Interrupt Active bit Register ... } NVIC_Type;судя по даташиту должно быть R/O (описание, но все-таки...)
убрал
ерунду написал
день добрей!
есть у кого схема "Arduino-Due ch340 mod" (может не умею искать :о)
интересует именно блок ch340 (понятно, что "оно там и так понятно/аналогично как у других/не тупи... итд" ...
без комментариев, просто нужна схема :о)
спасибо