SPI с DMA в Arduino Due
У меня есть проект, в котором мне нужно хранить данные (~ 16 месяцев) в памяти и иметь возможность быстро извлекать данные (<36000 бит/с) с помощью DMA, поскольку у меня есть другие сигналы, о которых нужно заботиться.
>В настоящее время я использую SD-карту с библиотекой SD, но, похоже, она не использует DMA из-за задержки между отправкой.
Многие люди говорили мне, что это не должно быть так уж сложно, и я так думаю. Я предполагаю, что я не могу правильно настроить DMA и/или SPI.
Я давно пробовал кое-что: Отправить данные через SPI с DMA
Может ли кто-нибудь показать мне пример SPI с DMA или советы по настройке обоих.
Еще раз спасибо
@Vlad, 👍-1
1 ответ
#include <dmac.h>
#include <SPI.h>
#include <Arduino.h>
#include <sam.h>
uint8_t sourceBuffer[256];
void setup() {
SPI.begin();
SPI.setClockDivider(21); // тактовая частота 4 МГц (при условии, что системная тактовая частота 84 МГц)
setupDMA();
}
void loop() {
for(int i = 0; i < sizeof(sourceBuffer); i++) {
sourceBuffer[i] = i;
}
startDMATransfer();
delay(1000);
}
void setupDMA() {
// Включаем контроллер DMA
PMC->PMC_PCER1 |= PMC_PCER1_PID34; // Идентификатор DMA для срока — 34
// Отключаем SPI DMA TX и RX
SPI0->SPI_PTCR = SPI_PTCR_RXTDIS | SPI_PTCR_TXTDIS;
// Настраиваем канал DMA для передачи (в данном примере канал 1)
DmacChannel* channel = &(DMAC->DMAC_CH_NUM[1]);
// Отключаем канал DMA
channel->DMAC_CHDR = DMAC_CHDR_DIS;
// Очистим все флаги и сбросим статус
channel->DMAC_CHDR = DMAC_CHDR_RES;
// Устанавливаем указатели источника и назначения
channel->DMAC_SADDR = (uint32_t) sourceBuffer;
channel->DMAC_DADDR = (uint32_t) &(SPI0->SPI_TDR);
// Настраиваем указатели источника и назначения: источник увеличивается, пункт назначения нет
channel->DMAC_CTRLA = DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE;
// Устанавливаем рукопожатие источника и назначения (связанное с SPI0 Tx)
channel->DMAC_CTRLB = DMAC_CTRLB_SRC_DSCR_FETCH_DISABLE | DMAC_CTRLB_DST_DSCR_FETCH_DISABLE |
DMAC_CTRLB_FC_MEM2PER_DMA_FC | DMAC_CTRLB_SRC_INCR_INCREMENTING |
DMAC_CTRLB_DST_INCR_FIXED;
channel->DMAC_CFG = DMAC_CFG_SRC_PER(1) | DMAC_CFG_DST_PER(1) | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG;
}
void startDMATransfer() {
// Предполагаем, что используется канал 1
DmacChannel* channel = &(DMAC->DMAC_CH_NUM[1]);
// Устанавливаем размер буфера
channel->DMAC_CUBC = sizeof(sourceBuffer);
// Включаем SPI DMA для TX
SPI0->SPI_PTCR = SPI_PTCR_TXTEN;
// Включаем канал DMA, чтобы начать передачу
channel->DMAC_CHER = DMAC_CHER_ENA;
}
Если вы хотите отправить данные через SPI с использованием DMA, вы можете заполнить sourceBuffer
и вызвать startDMATransfer()
.
Не забывайте всегда обращаться к техническому описанию Atmel SAM3X8E и схеме Arduino Due, когда вы работаете на этом уровне, поскольку они предоставляют подробную информацию о том, как работает оборудование. Я не могу запустить код или протестировать его. Но я считаю, что логика кода правильная. Обработка ошибок зависит от вас.
- устаревшее преобразование из строковой константы в 'char*'
- Регистры ввода-вывода SAM3X8E (Arduino Due)
- как быстро loop() работает в Arduino
- Построение графика на Python с использованием Tkinter Canvas
- Программирование ведомого SPI для Arduino
- как отправить аргумент объектам ESP8266WebServer в функции
- Использование экрана SD-карты на Arduino Due
- Arduino синтаксический анализ строки с использованием sscanf