Arlleex 183 30 октября, 2022 Опубликовано 30 октября, 2022 · Жалоба Где настройка GPIO, где хоть какие-то барьеры между разрешением клоков и доступом к регистрам периферии, где нормальная обработка флагов DMA? К тому же, корректная настройка будет в порядке DMA -> SPI -> GPIO, но не наоборот. Выкладывайте минимальный проект, раз уж мистика происходит, плюс укажите проц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reystlin 0 30 октября, 2022 Опубликовано 30 октября, 2022 (изменено) · Жалоба Проц STM32f407IGT6 Поместил весь код, касающийся SPI3, DMA1 и нужных GPIO в одну функцию, вызываю её один раз перед основным циклом. Проект большой, больше нигде ничего не трогается из этой периферии void SPI3_Send() { //DMA1 Stream 5 SPI3_TX channel 0 RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // GPIO GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; GPIO_InitStruct.Alternate = GPIO_AF6_SPI3; // PC10 - SCK - Выход GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // PC11 - MISO - Вход GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // PC12 - MOSI - Выход GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); uint8_t data[] = {1,2,3}; uint8_t len = 3; DMA1_Stream5->CR = 0; DMA1_Stream5->PAR = (uint32_t)(&SPI3->DR); DMA1_Stream5->M0AR = (uint32_t)data; DMA1_Stream5->NDTR = len; DMA1_Stream5->FCR = 0; // Настройка FIFO буфера DMA1_Stream5->CR = (0x00) << DMA_SxCR_CHSEL_Pos // Выбор канала |(0x00) << DMA_SxCR_MBURST_Pos // |(0x00) << DMA_SxCR_PBURST_Pos // |0 << DMA_SxCR_CT_Pos // Текущий буфер |0 << DMA_SxCR_DBM_Pos // Двойной буфер |(0x03) << DMA_SxCR_PL_Pos // Приоритет |0 << DMA_SxCR_PINCOS_Pos // Инкремент адреса периферии |(0x00) << DMA_SxCR_MSIZE_Pos // Размер данных в памяти 8 бит |(0x00) << DMA_SxCR_PSIZE_Pos // Размер данных в периферии 8 бит |1 << DMA_SxCR_MINC_Pos // Инкремент адреса памяти |0 << DMA_SxCR_PINC_Pos // Инкремент адреса периферии |0 << DMA_SxCR_CIRC_Pos // Циркуляционный режим |(0x01) << DMA_SxCR_DIR_Pos // Направление данных из памяти в периферию |0 << DMA_SxCR_PFCTRL_Pos // DMA управляет процессом |0 << DMA_SxCR_TCIE_Pos // Прерывание по окончанию передачи |0 << DMA_SxCR_HTIE_Pos // Прерывание по половине передачи |0 << DMA_SxCR_TEIE_Pos // Прерывание по ошибке передачи |0 << DMA_SxCR_DMEIE_Pos // Прерывание по |1 << DMA_SxCR_EN_Pos; // Активация DMA SPI3->CR2 = 1<<SPI_CR2_TXDMAEN_Pos | 1<<SPI_CR2_SSOE_Pos; SPI3->CR1 = 0<<SPI_CR1_DFF_Pos //Размер кадра 8 бит | 0<<SPI_CR1_LSBFIRST_Pos //MSB first | 1<<SPI_CR1_SSM_Pos //Программное управление SS | 1<<SPI_CR1_SSI_Pos //SS в высоком состоянии | 0x04<<SPI_CR1_BR_Pos //Скорость передачи: F_PCLK/32 | 1<<SPI_CR1_MSTR_Pos //Режим Master (ведущий) | 0<<SPI_CR1_CPOL_Pos | 0<<SPI_CR1_CPHA_Pos //Режим работы SPI: 0 | 1<<SPI_CR1_SPE_Pos; //Включаем SPI } Нужно ли обработчик прерывания делать если оно у меня не используется? Изменено 30 октября, 2022 пользователем Reystlin Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 30 октября, 2022 Опубликовано 30 октября, 2022 · Жалоба Еще замечу сразу, пока не забыл - локальные данные data[] делайте либо глобальными, либо удерживайте CPU от выхода из функции до окончания отправки (последнее - костыль). Прерывания - не знаю, Вам виднее, нужны они Вам или нет. Лично я не совсем понимаю, зачем тогда Вам DMA без прерываний по нему. Дальше. Что рапортуют статусные регистры DMA после включения потока? Чем контролируете "отправляется / не отправляется"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AVI-crak 0 30 октября, 2022 Опубликовано 30 октября, 2022 (изменено) · Жалоба Spoiler #include "gpio_one.h" /// https://github.com/AVI-crak/gpio_one void SPI3_Init() { RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; gpio_one_pin(zap_gpio.C.pin10.v_af06_i2s3_ck_spi3_sck.speed4.lock_on); gpio_one_pin(zap_gpio.C.pin11.v_af06_spi3_miso.speed4.lock_on); gpio_one_pin(zap_gpio.C.pin12.v_af06_i2s3_sd_spi3_mosi.speed4.lock_on); gpio_one_pin(zap_gpio.A.pin15.v_af06_i2s3_ws_spi3_nss.speed4.lock_on); SPI3->CR1 = 0x0; SPI3->CR2 = SPI_CR2_SSOE | //Вывод NSS - выход управления SPI_CR2_TXDMAEN; SPI3->CR1 = _VAL2FLD(SPI_CR1_BR, 2)| // Baud rate control /8 SPI_CR1_MSTR | // Режим Master SPI_CR1_BIDIMODE | // 1 линия SPI_CR1_BIDIOE | // только передача SPI_CR1_SPE; // вкл }; void SPI3_Send(volatile uint8_t *data, uint16_t len) { DMA1->LIFCR = (DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0); DMA1_Stream5->CR = 0; DMA1_Stream5->FCR = 0; DMA1_Stream5->NDTR = len; DMA1_Stream5->M0AR = (uint32_t)data; DMA1_Stream5->PAR = (uint32_t)(&SPI3->DR); DMA2_Stream5->CR = _VAL2FLD(DMA_SxCR_CHSEL, 0)| /// channe - tmigger _VAL2FLD(DMA_SxCR_DIR, 1)| /// memory_to_peripheral _VAL2FLD(DMA_SxCR_MBURST, 1)| /// incremental_burst_of_4_beats DMA_SxCR_MINC| /// memory increment mode DMA_SxCR_EN; while(!(DMA1->LISR & DMA_LISR_TCIF0 )); while((SPI3->SR & (SPI_SR_BSY | SPI_SR_TXE)) != SPI_SR_TXE); }; Изменено 30 октября, 2022 пользователем AVI-crak Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reystlin 0 31 октября, 2022 Опубликовано 31 октября, 2022 · Жалоба Флаги Transfer error и FIFO error устанавливаются после запуска DMA Я пытаюсь сейчас в простом виде запустить SPI+DMA чтобы что-нибудь выдало а дальше буду накручивать функционал т.к. не понятно чего оно не работает Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reystlin 0 31 октября, 2022 Опубликовано 31 октября, 2022 · Жалоба 22 часа назад, AVI-crak сказал: Скрыть контент #include "gpio_one.h" /// https://github.com/AVI-crak/gpio_one void SPI3_Init() { RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; gpio_one_pin(zap_gpio.C.pin10.v_af06_i2s3_ck_spi3_sck.speed4.lock_on); gpio_one_pin(zap_gpio.C.pin11.v_af06_spi3_miso.speed4.lock_on); gpio_one_pin(zap_gpio.C.pin12.v_af06_i2s3_sd_spi3_mosi.speed4.lock_on); gpio_one_pin(zap_gpio.A.pin15.v_af06_i2s3_ws_spi3_nss.speed4.lock_on); SPI3->CR1 = 0x0; SPI3->CR2 = SPI_CR2_SSOE | //Вывод NSS - выход управления SPI_CR2_TXDMAEN; SPI3->CR1 = _VAL2FLD(SPI_CR1_BR, 2)| // Baud rate control /8 SPI_CR1_MSTR | // Режим Master SPI_CR1_BIDIMODE | // 1 линия SPI_CR1_BIDIOE | // только передача SPI_CR1_SPE; // вкл }; void SPI3_Send(volatile uint8_t *data, uint16_t len) { DMA1->LIFCR = (DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0); DMA1_Stream5->CR = 0; DMA1_Stream5->FCR = 0; DMA1_Stream5->NDTR = len; DMA1_Stream5->M0AR = (uint32_t)data; DMA1_Stream5->PAR = (uint32_t)(&SPI3->DR); DMA2_Stream5->CR = _VAL2FLD(DMA_SxCR_CHSEL, 0)| /// channe - tmigger _VAL2FLD(DMA_SxCR_DIR, 1)| /// memory_to_peripheral _VAL2FLD(DMA_SxCR_MBURST, 1)| /// incremental_burst_of_4_beats DMA_SxCR_MINC| /// memory increment mode DMA_SxCR_EN; while(!(DMA1->LISR & DMA_LISR_TCIF0 )); while((SPI3->SR & (SPI_SR_BSY | SPI_SR_TXE)) != SPI_SR_TXE); }; DMA2_Stream5->CR заменил на DMA1_Stream5->CR так-же у DMA1->HISR TEIF5 и FEIF5 = 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AVI-crak 0 31 октября, 2022 Опубликовано 31 октября, 2022 · Жалоба Извиняюсь, f407 нету, проверить не смог. Но IDE весело собирает код без ошибок. Исправил. Spoiler void SPI3_Send(volatile uint8_t *data, uint16_t len) { DMA1->HIFCR = (DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5); DMA1_Stream5->CR = 0; DMA1_Stream5->NDTR = len; DMA1_Stream5->M0AR = (uint32_t)data; DMA1_Stream5->PAR = (uint32_t)(&SPI3->DR); DMA1_Stream5->CR = _VAL2FLD(DMA_SxCR_CHSEL, 0)| /// channe - tmigger _VAL2FLD(DMA_SxCR_DIR, 1)| /// memory_to_peripheral DMA_SxCR_MINC| /// memory increment mode DMA_SxCR_EN; while(!(DMA1->HISR & DMA_HISR_TCIF5 )); while((SPI3->SR & (SPI_SR_BSY | SPI_SR_TXE)) != SPI_SR_TXE); }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reystlin 0 1 ноября, 2022 Опубликовано 1 ноября, 2022 · Жалоба При компиляции то ошибок нет, но при исполнении в статус регистрах появляются Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 1 ноября, 2022 Опубликовано 1 ноября, 2022 · Жалоба В 30.10.2022 в 22:14, Reystlin сказал: Проц STM32f407IGT6 Поместил весь код, касающийся SPI3, DMA1 и нужных GPIO в одну функцию, вызываю её один раз перед основным циклом. Проект большой, больше нигде ничего не трогается из этой периферии Спойлер void SPI3_Send() { //DMA1 Stream 5 SPI3_TX channel 0 RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // GPIO GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; GPIO_InitStruct.Alternate = GPIO_AF6_SPI3; // PC10 - SCK - Выход GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // PC11 - MISO - Вход GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // PC12 - MOSI - Выход GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); uint8_t data[] = {1,2,3}; uint8_t len = 3; DMA1_Stream5->CR = 0; DMA1_Stream5->PAR = (uint32_t)(&SPI3->DR); DMA1_Stream5->M0AR = (uint32_t)data; DMA1_Stream5->NDTR = len; DMA1_Stream5->FCR = 0; // Настройка FIFO буфера DMA1_Stream5->CR = (0x00) << DMA_SxCR_CHSEL_Pos // Выбор канала |(0x00) << DMA_SxCR_MBURST_Pos // |(0x00) << DMA_SxCR_PBURST_Pos // |0 << DMA_SxCR_CT_Pos // Текущий буфер |0 << DMA_SxCR_DBM_Pos // Двойной буфер |(0x03) << DMA_SxCR_PL_Pos // Приоритет |0 << DMA_SxCR_PINCOS_Pos // Инкремент адреса периферии |(0x00) << DMA_SxCR_MSIZE_Pos // Размер данных в памяти 8 бит |(0x00) << DMA_SxCR_PSIZE_Pos // Размер данных в периферии 8 бит |1 << DMA_SxCR_MINC_Pos // Инкремент адреса памяти |0 << DMA_SxCR_PINC_Pos // Инкремент адреса периферии |0 << DMA_SxCR_CIRC_Pos // Циркуляционный режим |(0x01) << DMA_SxCR_DIR_Pos // Направление данных из памяти в периферию |0 << DMA_SxCR_PFCTRL_Pos // DMA управляет процессом |0 << DMA_SxCR_TCIE_Pos // Прерывание по окончанию передачи |0 << DMA_SxCR_HTIE_Pos // Прерывание по половине передачи |0 << DMA_SxCR_TEIE_Pos // Прерывание по ошибке передачи |0 << DMA_SxCR_DMEIE_Pos // Прерывание по |1 << DMA_SxCR_EN_Pos; // Активация DMA SPI3->CR2 = 1<<SPI_CR2_TXDMAEN_Pos | 1<<SPI_CR2_SSOE_Pos; SPI3->CR1 = 0<<SPI_CR1_DFF_Pos //Размер кадра 8 бит | 0<<SPI_CR1_LSBFIRST_Pos //MSB first | 1<<SPI_CR1_SSM_Pos //Программное управление SS | 1<<SPI_CR1_SSI_Pos //SS в высоком состоянии | 0x04<<SPI_CR1_BR_Pos //Скорость передачи: F_PCLK/32 | 1<<SPI_CR1_MSTR_Pos //Режим Master (ведущий) | 0<<SPI_CR1_CPOL_Pos | 0<<SPI_CR1_CPHA_Pos //Режим работы SPI: 0 | 1<<SPI_CR1_SPE_Pos; //Включаем SPI } Вот прям скопировал весь приведенный исходник, стер только настройку пинов, залил в F407 и никаких ошибок в DMA - рапортует, что все отправил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
0men 2 1 ноября, 2022 Опубликовано 1 ноября, 2022 · Жалоба если устроит HAL, могу скинуть сою инициализацию Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reystlin 0 1 ноября, 2022 Опубликовано 1 ноября, 2022 · Жалоба Методом тыка выяснил, что LWIP не дает работать, когда комментирую инициализацию LWIP то SPI через DMA заводится... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reystlin 0 2 ноября, 2022 Опубликовано 2 ноября, 2022 · Жалоба Организовал в итоге работу SPI через DMA вот таким образом #include "SPI3.h" uint8_t SPI3_buff[1024]; uint8_t Empty_Flag = 1; int rxCounter = 0; void SPI3_Init(void) { //DMA1 Stream 5 SPI3_TX channel 0 RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; RCC->APB1ENR |= RCC_APB1ENR_SPI3EN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOCEN; // GPIO GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; GPIO_InitStruct.Alternate = GPIO_AF6_SPI3; // PA10 - SS - Выход GPIOA->MODER |= GPIO_MODER_MODE10_0; // PC10 - SCK - Выход GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // PC11 - MISO - Вход GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // PC12 - MOSI - Выход GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); SPI3->CR2 = SPI_CR2_RXDMAEN| // Получение через DMA SPI_CR2_TXDMAEN; // Отправка через DMA SPI3->CR1 = 0 << SPI_CR1_DFF_Pos // Размер кадра 8 бит | 1<<SPI_CR1_SSM_Pos // Программное управление SS | 1<<SPI_CR1_SSI_Pos // SS в высоком состоянии | 0x02<<SPI_CR1_BR_Pos // Скорость передачи | 1<<SPI_CR1_MSTR_Pos // Режим Master | 0<<SPI_CR1_CPOL_Pos | 0<<SPI_CR1_CPHA_Pos | SPI_CR1_SPE; DMA1_Stream5->CR = 0; DMA1_Stream5->FCR = 0; DMA1_Stream5->PAR = (uint32_t)(&SPI3->DR); DMA1_Stream0->CR = 0; DMA1_Stream0->FCR = 0; DMA1_Stream0->PAR = (uint32_t)(&SPI3->DR); DMA1_Stream0->NDTR = 1024; DMA1_Stream0->M0AR = (uint32_t)SPI3_buff; DMA1_Stream0->CR = _VAL2FLD(DMA_SxCR_CHSEL, 0)| /// channe - tmigger _VAL2FLD(DMA_SxCR_DIR, 0)| /// peripheral to memory DMA_SxCR_MINC| /// memory increment mode DMA_SxCR_EN; } void SPI3_Send(uint8_t *data, uint16_t len) { while ((SPI3->SR & SPI_SR_BSY) | !(SPI3->SR & SPI_SR_TXE)) {} Empty_Flag = 1; GPIOA->BSRR = GPIO_BSRR_BS_10; // На прием DMA1_Stream0->CR &=~(DMA_SxCR_EN); DMA1_Stream0->NDTR = 1024; DMA1_Stream0->M0AR = (uint32_t)SPI3_buff; DMA1_Stream0->CR |=(DMA_SxCR_EN); // На передачу DMA1->HIFCR = (DMA_HIFCR_CTCIF5| DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5); DMA1_Stream5->NDTR = len; DMA1_Stream5->M0AR = (uint32_t)data; DMA1_Stream5->CR = _VAL2FLD(DMA_SxCR_CHSEL, 0)| /// channe - tmigger _VAL2FLD(DMA_SxCR_DIR, 1)| /// memory_to_peripheral DMA_SxCR_MINC| /// memory increment mode DMA_SxCR_TCIE| DMA_SxCR_EN; NVIC_EnableIRQ(SPI3_IRQn); NVIC_EnableIRQ(DMA1_Stream5_IRQn); } void DMA1_Stream5_IRQHandler(void) { if (DMA1->LISR & DMA_LISR_TCIF0) { DMA1->LIFCR = DMA_LIFCR_CTCIF0; // сброс флага события TCIF DMA1_Stream5->CR = 0; SPI3->CR2 |= SPI_CR2_TXEIE; //GPIOA->BSRR = GPIO_BSRR_BR_10; } } uint8_t SPI3_Is_Empty(void) { return Empty_Flag; } volatile uint8_t ssss; void SPI3_IRQHandler(void) { const uint32_t sr = SPI3->SR; const uint32_t cr2 = SPI3->CR2; if(READ_BIT(sr, SPI_SR_TXE)) { SPI3->SR = sr &(~SPI_SR_TXE); SPI3->CR2 = cr2 &(~SPI_CR2_TXEIE); Empty_Flag = 0; GPIOA->BSRR = GPIO_BSRR_BR_10; } else if(READ_BIT(sr, SPI_SR_OVR)) { __NOP(); } } Не могу добиться правильного варианта с опусканием вывода PA10. В прерыварии по DMA срабатывает рано, что понятно почему Прерывание по TXE не срабатывает... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
deni 6 2 ноября, 2022 Опубликовано 2 ноября, 2022 (изменено) · Жалоба TXE тоже ничего не даст, он также выставляется по опустошению буфера, для отслеживания опустошения передатчика надо мониторить BSY: Busy flag, но от него нет прерывания. Изменено 2 ноября, 2022 пользователем deni Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tgruzd 11 2 ноября, 2022 Опубликовано 2 ноября, 2022 · Жалоба 39 минут назад, deni сказал: но от него нет прерывания. зато есть прерывание от RXNE Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 2 ноября, 2022 Опубликовано 2 ноября, 2022 · Жалоба В прерывании по завершению передачи DMA разрешаете прерывание RXNE SPI, в его обработчике блокируете это прерывание и опускаете PA10. Здесь на электрониксе была тема, когда путем экспериментов было установлено, что для некоторых режимов SPI ни RXNE, ни BSY не обеспечивают должного времени после передачи последнего бита. Так что - делете так, как, например, я только что написал, а дальше осциллом смотрите, как далеко от последнего бита опустился CS. В крайнем случае можно в прерывании TC DMA запускать таймер, который через какое-то время опустит ногу. 100500 способов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться