STM32.USART Использование DMA

Если вам нужно передавать (или принимать) через USART массыв данных, тогда есть смысл использовать DMA.

USART1 «сидит» на контроллере DMA1: передатчик можно подключить к четвертому каналу, а приемник — к пятому.

Настроим прием и передачу данных с использованием DMA. Прием будет осуществляться в массив RxBuff[64], передача — из массива TxBuff[64].

Создаем функцию-обработчик прерываний DMA канала 4:

void DMA1_Channel4_IRQHandler (void)
{
  //Если обмен завершен
  if(DMA1->ISR & DMA_ISR_TCIF4) { }      //что-то делаем
 
  //Если передана половина буфера
  if(DMA1->ISR & DMA_ISR_HTIF4) { }      //что-то делаем
 
  //Если произошла ошибка при обмене
  if(DMA1->ISR & DMA_ISR_TEIF4) { }      //что-то делаем
}

Создаем функцию-обработчик прерываний DMA канала 5:

void DMA1_Channel5_IRQHandler (void)
{
 //Если обмен завершен
 if(DMA1->ISR & DMA_ISR_TCIF5) { }      //что-то делаем
 
 //Если передана половина буфера
 if(DMA1->ISR & DMA_ISR_HTIF5) { }      //что-то делаем
 
 //Если произошла ошибка при обмене
 if(DMA1->ISR & DMA_ISR_TEIF5) { }      //что-то делаем
}

Выполним настройку контроллера DMA.
Подаем тактовые импульсы на DMA:

if ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != RCC_AHBENR_DMA1EN) RCC->AHBENR |=RCC_AHBENR_DMA1EN;

Указываем область памяти, с которой будем работать:

DMA1_Channel4->CMAR = (uint32_t) &TxBuff[0];       //адрес буфера передатчика
DMA1_Channel5->CMAR = (uint32_t) &RxBuff[0];       //адрес буфера приемника

Определяемся с устройствами, которые будут подключены к каналам 4 и 5:

DMA1_Channel4->CPAR = (uint32_t) &USART1->DR;      //адрес регистра данных передатчика 
DMA1_Channel5->CPAR = (uint32_t) &USART1->DR;      //адрес регистра данных приемника

Задаем количество данных для обмена:

DMA1_Channel4->CNDTR = 64;                         //для передатчика
DMA1_Channel5->CNDTR = 64;                         //для приемника

Настраиваем управляющие регистры:

DMA1_Channel4->CCR = DMA_CCR4_DIR | DMA_CCR4_MINC; //чтение из памяти, инкремент указателя в памяти
DMA1_Channel5->CCR = DMA_CCR4_MINC;                //запись в память, инкремент указателя в памяти

Разрешить прерывание по завершении обмена:

DMA1_Channel4->CCR |= DMA_CCR4_TEIE;               //канал 4
DMA1_Channel5->CCR |= DMA_CCR5_TEIE;               //канал 5

Разрешаем прерывания от каналов 4 и 5 модуля DMA1:

NVIC_EnableIRQ (DMA1_Channel4_IRQn);              //Разрешить прерывания от DMA канал №4
NVIC_EnableIRQ (DMA1_Channel5_IRQn);              //Разрешить прерывания от DMA канал №5

Конфигурируем USART1 для работы через DMA:

USART1->CR3 |= USART_CR3_DMAT;                    //разрешить передачу USART1 через DMA
USART1->CR3 |= USART_CR3_DMAR;                    //разрешить прием USART1 через DMA

О первоисточнике можете узнать тут