[Решен] SPI раб с DMA

Vicolaships
Пт 20 апреля 2018 г., 16:50
Привет, я пытаюсь настроить раба SPI с полнодууплексными передачами DMA на синей таблетке.

Я хочу иметь возможность получать 2 байта (2x 8 бит), не управляя каждым байтом, я хочу, чтобы DMA сделал это для меня и вызвало прерывание, когда два байта переданы. Мне также нужно, чтобы передача была полной дуплексной, раб должен ответить на мастер (в этом примере должен получить мастер: 123 и 87).

С кодом ниже ничего не происходит, когда я передаю 2 байта, прерывание не стреляет. Мастер получает ответ, где все биты нули. Я уверен, что кабели правильно подключены, потому что простой раб SPI как ViewTopic.PHP?F = 18&T = 3525 Работа.
#include #include #include #define DATA_BUFFER_SIZE 2 // Tx / Rx buffer volatile uint8_t data_buffer[DATA_BUFFER_SIZE]; // If true a transfer is complete: data_bufer contains new and valid data volatile bool dma_transfer_complete(false); // DMA interrupt handler void rxDMAirq(void) { if (dma_get_irq_cause(DMA1, DMA_CH2) == DMA_TRANSFER_COMPLETE) dma_transfer_complete = true; } void setupDMA(void) { dma_init(DMA1); // DMA tube configuration for SPI1 Rx - channel 2 dma_tube_config tube_cfg = { &SPI1->regs->DR, // Source of data DMA_SIZE_8BITS, // Source transfer size &data_buffer, // Destination of data DMA_SIZE_8BITS, // Destination transfer size DATA_BUFFER_SIZE, // Number of data to transfer // Flags: auto increment destination address, circular buffer, set tube full IRQ, very high priority (DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE), // FIXME Do I need DMA_CCR_PL_VERY_HIGH? 0, // Un-used DMA_REQ_SRC_SPI1_RX, // Hardware DMA request source }; // Configure DMA channel // SPI1 Rx channel is nr. 2 const int ret(dma_tube_cfg(DMA1, DMA_CH2, &tube_cfg)); if (ret != DMA_TUBE_CFG_SUCCESS) { while (1) { Serial.print("DMA configuration error: "); Serial.println(ret, HEX); Serial.println("Reset is needed!"); delay(100); } } dma_attach_interrupt(DMA1, DMA_CH2, rxDMAirq); dma_enable(DMA1, DMA_CH2); } void setupSPI(void) { // MOSI, MISO, SCK PINs are set by the library pinMode(BOARD_SPI_DEFAULT_SS, INPUT); // SS // The clock value is not used // SPI1 is selected by default SPI.beginTransactionSlave(SPISettings(18000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT)); } void setup() { Serial.begin(115200); delay(100); // Data that will be sent data_buffer[0] = 123; data_buffer[1] = 87; setupSPI(); setupDMA(); } unsigned count_1(0); unsigned count_2(0); void loop() { if (dma_transfer_complete) { dma_transfer_complete = false; Serial.println("DMA transfer complete"); Serial.print("data_buffer[0] = "); Serial.println((unsigned)data_buffer[0]); Serial.print("data_buffer[1] = "); Serial.println((unsigned)data_buffer[1]); // Data that will be sent (for next transfer) // Assumes that a transfer has not yet been initiated data_buffer[0] = 123; data_buffer[1] = 87; } delayMicroseconds(10); if (++count_1 > 50000) { count_1 = 0; Serial.print("Waiting... "); Serial.println(++count_2); } }

Vicolaships
Вт 24 апреля 2018 г., 19:40
Я хочу вернуться к своему базовому примеру: ViewTopic.PHP?P = 13036#P13036
Я только изменил длину буфера (records_per_buffer = 2, records_per_block = 8) и размер данных передачи SPI от 16 битов до 8 бит, передача никогда не завершается, у вас есть идея, почему? Мастер отправил 8 раз 8 -битный кадр SPI.
/* Storage of multiple 8bit data received over SPI1 to SD card over SPI2. */ #include #include // SD card chip select pin #define CHIP_SELECT PB12 #define TOTAL_BLOCKS 10 // number of blocks to record // size of data block which will be written in one shot to card #define BLOCK_SIZE 512 // bytes // size of data buffer where the ADC sampled data will be transferred over DMA #define DATA_BUFFER_SIZE (2*BLOCK_SIZE) // bytes #define RECORD_SIZE 2 // 8 bits #define RECORDS_PER_BLOCK 8 // uint8_t #define RECORDS_PER_BUFFER 2 // uint8_t // the data buffer to store values uint8_t data_buffer[RECORDS_PER_BUFFER]; uint32_t total_blocks; uint32_t total_records; uint8_t * pCache; // set by HW when a complete DMA transfer was finished. volatile uint8_t dma_irq_full_complete; // set by HW when a DMA transfer is at its half. volatile uint8_t dma_irq_half_complete; // set by SW when overrun occurs volatile uint8_t overrun; // signalling for lower and upper buffer status volatile uint8_t buff0_stored, buff1_stored, buff_index; void setupParameters(void) { // init some relevant values total_blocks = TOTAL_BLOCKS; // the SW can only record an even number of blocks, so we need to adjust it if ( (total_blocks&1) ) total_blocks++; total_records = (total_blocks*RECORDS_PER_BLOCK); } void DMA_Init(void) { dma_irq_full_complete = 0; dma_irq_half_complete = 0; overrun = 0; buff0_stored = buff1_stored = 1; // avoid overrun detection buff_index = 0; dma_clear_isr_bits(DMA1, DMA_CH2); // for test only: fill ADC buffer with dummy data for (int i = 0; iregs->DR, // data source address DMA_SIZE_8BITS, // source transfer size &data_buffer, // data destination address DMA_SIZE_8BITS, // destination transfer size RECORDS_PER_BUFFER, // nr. of data to transfer // tube flags: auto increment dest addr, circular buffer, set tube full IRQ, very high prio: ( DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_HALF_CMPLT_IE | DMA_CFG_CMPLT_IE | DMA_CCR_PL_VERY_HIGH ), 0, // unused DMA_REQ_SRC_SPI1_RX, // Hardware DMA request source }; // configure DMA channel int ret = dma_tube_cfg(DMA1, DMA_CH2, &my_tube_cfg); // SPI1 Rx channel is nr. 2 if (ret > 0) { Serial1.print("DMA configuration error: "); Serial1.println(ret,HEX); Serial1.println("Stopped, reset is needed!"); while (1); } dma_attach_interrupt(DMA1, DMA_CH2, DMA_Rx_irq); // attach an interrupt handler. dma_enable(DMA1, DMA_CH2); // Enable the DMA tube. It will now begin serving requests. } /*****************************************************************************/ SPIClass SPI_2(2); uint32_t app_cr1; /*****************************************************************************/ void SPI_setup(void) { // use SPI 1 for recording, SPI 2 is used by SD card SPI.setModule(1); SPI.beginTransactionSlave(SPISettings(18000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT)); SPI.setModule(2); // FIXME Remove? } void setup() { Serial.begin(115200); Serial.println("8bit data received over SPI1 in slave mode is stored to SD-card over SPI2."); delay (10); } void setupModules() { // Set-up involved hardware modules SPI_setup(); DMA_Setup(); } void loop() { setupParameters(); setupModules(); Serial1.print("Total_blocks = "); Serial1.println(total_blocks); uint32_t t_out; // time-out uint32_t bl, val = 0; for( bl = 0; bl < total_blocks; ++bl) { // time-out to avoid hangup if something goes wrong t_out = 1000000; // each ADC sequence is sampled triggered by TIMER3 event. while ( (--t_out)>0 ) { // check DMA recording status and push data to card if either half buffer is full if ( dma_irq_half_complete ) { dma_irq_half_complete = 0; buff0_stored = 1; break; } if ( dma_irq_full_complete ) { dma_irq_full_complete = 0; buff1_stored = 1; break; } //if ( spi_is_rx_nonempty(SPI1) ) { spi_rx_reg(SPI1); val++; } } // only for debug purposes: if ( t_out==0 ) { Serial1.println(F("\n!!!! TIME_OUT !!!")); break; } } }

victor_pv
Вт 24 апреля 2018 г., 21:29
Я не мог видеть в коде, что вы включите просьбы о периферийном DMA SPI.
Помимо настройки контроллера DMA, вам необходимо настроить периферийную систему SPI для генерации запросов DMA.
Если вы проверите библиотеку SPI, имя функции для этого есть, я забыл имя.

Vicolaships
Ср 25 апреля 2018 г., 16:50
[victor_pv - Вт 24 апреля 2018 г., 21:29] - Я не мог видеть в коде, что вы включите просьбы о периферийном DMA SPI.
dma_init(DMA1); // DMA tube configuration for SPI1 Rx - channel 2 dma_tube_config tube_cfg = { &SPI1->regs->DR, // Source of data DMA_SIZE_8BITS, // Source transfer size &data_buffer, // Destination of data DMA_SIZE_8BITS, // Destination transfer size DATA_BUFFER_SIZE, // Number of data to transfer // Flags: auto increment destination address, circular buffer, set tube full IRQ, very high priority (DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE), // FIXME Do I need DMA_CCR_PL_VERY_HIGH? 0, // Un-used DMA_REQ_SRC_SPI1_RX, // Hardware DMA request source }; // Configure DMA channel // SPI1 Rx channel is nr. 2 const int ret(dma_tube_cfg(DMA1, DMA_CH2, &tube_cfg)); if (ret != DMA_TUBE_CFG_SUCCESS) { while (1) { Serial.print("DMA configuration error: "); Serial.println(ret, HEX); Serial.println("Reset is needed!"); delay(100); } }

victor_pv
Чт 26 апреля 2018 11:14
Периферийное устройство DMA будет выполнять передачу только тогда, когда периферийная передача SPI запрашивает передачу DMA, поэтому, помимо установки контроллера DMA, в SPI CR есть флаг, чтобы включить запросы SPI с периферийного устройства SPI. Как только этот флаг будет установлен, периферийное устройство SPI запрашивает новую передачу контроллеру DMA каждый раз, когда устанавливаются флаги RXNE или TXE.

Стивестронг
Пт 27 апреля 2018 г. 8:26 утра
Чтобы настроить доступ DMA, вам лучше взглянуть на эти строки: https: // github.com/rogerclarkmelbourne/ ... #L396-L421.
Конечно, часть RX должна работать в рабов.

Vicolaships
Пт 27 апреля 2018 г. 13:00
Спасибо за любезную помощь, я получил это работает благодаря вашим двум сообщениям! Были очевидно, что я не понимал, теперь я думаю, что знаю достаточно ;)

Вот самый простой пример, который я мог бы приступить к работе: #include #include #include #define DATA_BUFFER_SIZE 2 // Rx and Tx buffers volatile uint8_t rx_buffer[DATA_BUFFER_SIZE]; volatile uint8_t tx_buffer[DATA_BUFFER_SIZE]; // If true a transfer is complete: rx_bufer contains new and valid data // tx_buffer has been completely sent volatile bool dma_transfer_complete(false); // DMA interrupt handler void rxDMAirq(void) { if (dma_get_irq_cause(DMA1, DMA_CH2) == DMA_TRANSFER_COMPLETE) dma_transfer_complete = true; } void setupDMA(void) { // SPI is on DMA1 dma_init (DMA1); // DMA tube configuration for SPI1 Rx dma_tube_config rx_tube_cfg = { &SPI1->regs->DR, // Source of data DMA_SIZE_8BITS, // Source transfer size &rx_buffer, // Destination of data DMA_SIZE_8BITS, // Destination transfer size DATA_BUFFER_SIZE, // Number of data to transfer // Flags: auto increment destination address, circular buffer, set tube full IRQ, very high priority (DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE | DMA_CCR_PL_VERY_HIGH), 0, // Un-used DMA_REQ_SRC_SPI1_RX, // Hardware DMA request source }; // SPI1 Rx is channel 2 const int ret_rx(dma_tube_cfg(DMA1, DMA_CH2, &rx_tube_cfg)); if (ret_rx != DMA_TUBE_CFG_SUCCESS) { while (1) { Serial.print("Rx DMA configuration error: "); Serial.println(ret_rx, HEX); Serial.println("Reset is needed!"); delay(100); } } // DMA tube configuration for SPI1 Tx dma_tube_config tx_tube_cfg = { &tx_buffer, // Source of data DMA_SIZE_8BITS, // Source transfer size &SPI1->regs->DR, // Destination of data DMA_SIZE_8BITS, // Destination transfer size DATA_BUFFER_SIZE, // Number of data to transfer // Flags: auto increment source address, circular buffer, set tube full IRQ, low priority (DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE | DMA_CCR_PL_LOW), 0, // Un-used DMA_REQ_SRC_SPI1_TX, // Hardware DMA request source }; // SPI1 Tx is channel 3 const int ret_tx(dma_tube_cfg(DMA1, DMA_CH3, &tx_tube_cfg)); if (ret_tx != DMA_TUBE_CFG_SUCCESS) { while (1) { Serial.print("Tx DMA configuration error: "); Serial.println(ret_tx, HEX); Serial.println("Reset is needed!"); delay(100); } } // Clear RX register in case we already received SPI data spi_rx_reg(SPI.dev()); // SPI DMA requests for Rx and Tx spi_rx_dma_enable(SPI.dev()); spi_tx_dma_enable(SPI.dev()); // Attach interrupt to catch end of DMA transfer dma_attach_interrupt(DMA1, DMA_CH2, rxDMAirq); // Enable DMA configurations dma_enable(DMA1, DMA_CH2); // Rx dma_enable(DMA1, DMA_CH3); // Tx } void setupSPI(void) { // MOSI, MISO, SCK PINs are set by the library pinMode(BOARD_SPI_DEFAULT_SS, INPUT); // SS // The clock value is not used // SPI1 is selected by default SPI.beginTransactionSlave(SPISettings(0, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT)); } void setup() { Serial.begin(115200); delay(100); // Data that will be sent tx_buffer[0] = 20; tx_buffer[1] = 18; setupSPI(); setupDMA(); } unsigned count_1(0); unsigned count_2(0); void loop() { if (dma_transfer_complete) { dma_transfer_complete = false; Serial.println("DMA transfer complete"); Serial.print("data_buffer[0] = "); Serial.println((unsigned)rx_buffer[0]); Serial.print("data_buffer[1] = "); Serial.println((unsigned)rx_buffer[1]); // Data that will be sent (for next transfer) // Assumes that a transfer has not yet been initiated tx_buffer[0] = 20; tx_buffer[1] = 18; } delayMicroseconds(10); if (++count_1 > 50000) { count_1 = 0; Serial.print("Waiting... "); Serial.println(++count_2); } }

Rogerclark
Пт 27 апреля 2018 г., 21:35
Спасибо..


Если несколько человек могут проверить это, подумайте, что это должно быть включено в примеры...

victor_pv
SAT 28 апреля 2018 г. 12:55 утра
Отличная работа.
Я думаю, было бы хорошо, если бы функция Dmatransfer, уже в ядре, может быть проверена и сделана совместимой с режимом подчинения, если это не так, это еще больше упростит использование.

AG123
SAT 28 апреля 2018 г., 3:53 утра
+5 Это довольно хорошо, спасибо! Теперь STM32duino Blue Pills / Maple Mini может удвоиться как ADC и больше для других досок, таких как R-Pi
:)

Стивестронг
Сб 28 апреля 2018 г. 10:37
У меня есть только одно замечание, не проверяя его: эти строки // enable SPI DMA requests for Rx and Tx spi_rx_dma_enable(SPI.dev()); spi_tx_dma_enable(SPI.dev());

Vicolaships
Солнце 29 апреля 2018 г., 7:49
[Стивестронг - Сб 28 апреля 2018 г. 10:37] - У меня есть только одно замечание, не проверяя его: эти строки // enable SPI DMA requests for Rx and Tx spi_rx_dma_enable(SPI.dev()); spi_tx_dma_enable(SPI.dev());

Стивестронг
Пн 30 апреля 2018 г., 18:23
Если вы используете два разных буфера, вы должны изменить адрес буфера.
Я предлагаю не устанавливать DMA в круглом режиме.

Обычно я использую один круглый буфер, размер вдвое больше одного буфера.
В этом случае нет необходимости менять адрес буфера.
Я проверяю основной цикл полного полного и передаю полные флаги DMA и выполняю процесс завершенной половины: когда DMA передает половину, основной уровень обрабатывает дополнительную половину буфера.

Vicolaships
Сб 30 июня 2018 г., 13:52
[Стивестронг - Пн 30 апреля 2018 г. 18:23] - Если вы используете два разных буфера, вы должны изменить адрес буфера.
Я предлагаю не устанавливать DMA в круглом режиме.

Обычно я использую один круглый буфер, размер вдвое больше одного буфера.
В этом случае нет необходимости менять адрес буфера.
Я проверяю основной цикл полного полного и передаю полные флаги DMA и выполняю процесс завершенной половины: когда DMA передает половину, основной уровень обрабатывает дополнительную половину буфера.
Для этого вы должны использовать двойной буферный режим DMA, он использует 2 Adreses и Memords Adress and Mogs. Пользователи каждый раз, когда передача завершается (см AN4031 Страница 13, режим двойного буфера).


Сейчас я сталкиваюсь с новой проблемой. Иногда по неизвестной причине (я думаю, электрический импеданс и тому подобное) моя периферия получает еще одно слово, которое должно. Я могу обнаружить его, потому что я вычисляю суммы Флехтера с обеих сторон (мастер/раб), поэтому я знаю сообщение, если плохо сформировано.

Но как я могу исправить это автоматически? Одним из решений было бы доступ к индексу буфера DMA, и если он не изменяется в течение определенного периода времени (дольше одной полной передачи), сбросьте DMA.

Ты знаешь, как я мог это сделать?

Вот псевдо -код того, что я хотел бы сделать:
uint32_t last(0); uint32_t dma_check_time(0); bool dma_check(false); unsigned dma_check_buffer_id(0); void loop() { // Count time (usec) elapsed since last time uint32_t right_now(micros()); uint32_t elapsed(right_now - last); if (last == 0) elapsed = 0; last = right_now; // In case DMA buffer index is not zero: reset DMA buffer index if the DMA buffer index // do not change after 150 microseconds // // This is useful when the peripheral received one word more than expected for whatever reason and // all messages gets shifted because of that. if (dma_check) { if (right_now - dma_check_time > 150) { dma_check = false; if (dma_check_buffer_id == dma_index) { // Reset DMA index } } } else if (dma_index != 0) { dma_check_buffer_id = dma_index; dma_check_time = right_now; dma_check = true; } }

Стивестронг
SAT 30 июня 2018 г. 16:46
Что касается примечания к заявлению, на которую вы указали, это для F2, F4 и F7, как вы, вероятно, заметили.
Здесь мы говорим о синей таблетке (F1), верно? F1 и F3 не имеют этой функции.

Не зная вашего кода, трудно оценить, что может быть неправильно.
Кстати, я опубликовал здесь несколько рабочих магистра/рабов примеров: http: // stm32duino.com/viewtopic.PHP?f = 9 ... 878#P45041

РЕДАКТИРОВАТЬ
Можно проверить, сколько переводов имеет DMA еще для завершения: dma_get_count(,);

Vicolaships
Пн, 2 июля 2018 г. 8:19
[Стивестронг - Сб 30 июня 2018 г., 16:46] - Что касается примечания к заявлению, на которую вы указали, это для F2, F4 и F7, как вы, вероятно, заметили.
Здесь мы говорим о синей таблетке (F1), верно? F1 и F3 не имеют этой функции.

Не зная вашего кода, трудно оценить, что может быть неправильно.
Кстати, я опубликовал здесь несколько рабочих магистра/рабов примеров: http: // stm32duino.com/viewtopic.PHP?f = 9 ... 878#P45041

РЕДАКТИРОВАТЬ
Можно проверить, сколько переводов имеет DMA еще для завершения: dma_get_count(,);

Стивестронг
Пн, 02 июля 2018 г. 8:28 утра
UPS, извините, кажется, что это только в моем репо: https: // github.com/stevstrong/arduino_s ... #L541-L543
Вы можете импортировать эту часть в своих файлах.

Я только что сделал пиар: https: // github.com/rogerclarkmelbourne/ ... 2/Pull/534

Стивестронг
Вт. 3 июля 2018 г. 9:31
PR был совершен, поэтому вы можете использовать эту функцию.

Vicolaships
SAT 07 июля 2018 г., 17:31
Большое спасибо, я получил его работу благодаря этому дополнению 8-)
Я до сих пор не знаю, почему это происходит, но, по крайней мере, я могу обнаружить его и сбросить SPI / DMA, тогда все снова работает нормально.

Функции setupdma и setupspi: void setupDMA(void) { // SPI is on DMA1 dma_init(DMA1); // Disable in case already enabled spi_tx_dma_disable(SPI.dev()); spi_rx_dma_disable(SPI.dev()); // Disable in case it was already enabled dma_disable(DMA1, DMA_CH2); dma_disable(DMA1, DMA_CH3); dma_detach_interrupt(DMA1, DMA_CH2); // DMA tube configuration for SPI1 Rx dma_tube_config rx_tube_cfg = { &SPI1->regs->DR, // Source of data DMA_SIZE_8BITS, // Source transfer size &rx_buffer, // Destination of data DMA_SIZE_8BITS, // Destination transfer size BUFFER_SIZE, // Number of data to transfer // Flags: auto increment destination address, circular buffer, set tube full IRQ, very high priority (DMA_CFG_DST_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE | DMA_CCR_PL_VERY_HIGH), 0, // Un-used DMA_REQ_SRC_SPI1_RX, // Hardware DMA request source }; // SPI1 Rx is channel 2 const int ret_rx(dma_tube_cfg(DMA1, DMA_CH2, &rx_tube_cfg)); if (ret_rx != DMA_TUBE_CFG_SUCCESS) { while (1) { #ifdef SERIAL_DEBUG Serial.print("Rx DMA configuration error: "); Serial.println(ret_rx, HEX); Serial.println("Reset is needed!"); #endif delay(500); } } // DMA tube configuration for SPI1 Tx dma_tube_config tx_tube_cfg = { &tx_buffer, // Source of data DMA_SIZE_8BITS, // Source transfer size &SPI1->regs->DR, // Destination of data DMA_SIZE_8BITS, // Destination transfer size BUFFER_SIZE, // Number of data to transfer // Flags: auto increment source address, circular buffer, set tube full IRQ, very high priority (DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE | DMA_CCR_PL_VERY_HIGH), 0, // Un-used DMA_REQ_SRC_SPI1_TX, // Hardware DMA request source }; // SPI1 Tx is channel 3 const int ret_tx(dma_tube_cfg(DMA1, DMA_CH3, &tx_tube_cfg)); if (ret_tx != DMA_TUBE_CFG_SUCCESS) { while (1) { #ifdef SERIAL_DEBUG Serial.print("Tx DMA configuration error: "); Serial.println(ret_tx, HEX); Serial.println("Reset is needed!"); #endif delay(500); } } // Attach interrupt to catch end of DMA transfer dma_attach_interrupt(DMA1, DMA_CH2, rxDMAirq); // Enable DMA configurations dma_enable(DMA1, DMA_CH2); // Rx dma_enable(DMA1, DMA_CH3); // Tx // SPI DMA requests for Rx and Tx spi_rx_dma_enable(SPI.dev()); spi_tx_dma_enable(SPI.dev()); #ifdef SERIAL_DEBUG Serial.print("setupDMA | Rx count = "); Serial.print((unsigned) dma_get_count(DMA1, DMA_CH2)); Serial.print(" | Tx DMA count = "); Serial.println((unsigned) dma_get_count(DMA1, DMA_CH3)); #endif } void setupSPI(void) { // MOSI, MISO, SCK PINs are set by the library pinMode(BOARD_SPI_DEFAULT_SS, INPUT); // SS // The clock value is not used // SPI1 is selected by default SPI.beginTransactionSlave(SPISettings(0, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT)); // Clear RX register in case we already received SPI data spi_rx_reg(SPI.dev()); }

Rogerclark
Вторник 04 декабря 2018 г., 19:23
Спасибо, что опубликовали это.

Я пытаюсь изменить работу радио-радио UHF (BAOFENG UV-82) для получения цифровых сигналов, и мне нужно перехватить команды SPI, отправляемые в чип, через SPI.

Этот код выглядит действительно полезным для этого проекта.

На самом деле я, наверное, выиграл’T Используйте версию DMA, так как мне нужно слушать каждую отдельную команду, и немедленно отвечать .

Но функциональность SPI подчинка - действительно полезная функция.