Программирование передачи области памяти через UART с использованием DMA
#include "stm32f10x.h"
/*******************************************************************/
#define BAUDRATE 115200
#define DMA_BUFFER_SIZE 16
/*******************************************************************/
void initAll(void)
{
GPIO_InitTypeDef port;
USART_InitTypeDef usart;
DMA_InitTypeDef dma;
uint8_t dataBuffer[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/*******************************************************************/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//if ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != RCC_AHBENR_DMA1EN) RCC->AHBENR |= RCC_AHBENR_DMA1EN;
//при использовании для настройки CMSIS
DMA_StructInit(&dma);
dma.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);
dma.DMA_MemoryBaseAddr = (uint32_t)&dataBuffer[0];
dma.DMA_DIR = DMA_DIR_PeripheralDST;
dma.DMA_BufferSize = DMA_BUFFER_SIZE;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_Init(DMA1_Channel4, &dma);
GPIO_StructInit(&port);
port.GPIO_Mode = GPIO_Mode_AF_PP;
port.GPIO_Pin = GPIO_Pin_9;
port.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &port);
port.GPIO_Mode = GPIO_Mode_AF_PP;
port.GPIO_Pin = GPIO_Pin_10;
port.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &port);
USART_StructInit(&usart);
usart.USART_BaudRate = BAUDRATE;
USART_Init(USART1, &usart);
}
//==========================================================================
int main()
{
__enable_irq();
initAll();
USART_Cmd(USART1, ENABLE);
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
DMA_Cmd(DMA1_Channel4, ENABLE);
while(1)
{
__NOP();
DMA_Cmd(DMA1_Channel4, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel4,16);
DMA_Cmd(DMA1_Channel4, ENABLE);
}
}
Настройка DMA при использовании CMSIS
DMA1_Channel4->CMAR = (uint32_t) &text[0]; //адрес буфера передатчика
DMA1_Channel4->CPAR = (uint32_t) &USART1->DR; //адрес регистра данных передатчика
DMA1_Channel4->CNDTR = sizeof(text); //для передатчика
DMA1_Channel4->CCR = DMA_CCR4_DIR | DMA_CCR4_MINC; //чтение из памяти, инкремент указателя в памяти
DMA1_Channel4->CCR |= DMA_CCR4_TEIE; //канал 4
USART1->CR3 |= USART_CR3_DMAT; //разрешить передачу USART1 через DMA
Чтобы включить DMA набираем:
DMA1_Channel4->CCR |= DMA_CCR1_EN;
Для перезапуска DMA, придётся несколько усложнить функцию:
DMA1_Channel4->CCR &= (uint16_t)(~DMA_CCR1_EN); //Выключаем DMA.
DMA1_Channel4->CNDTR = sizeof(text); //Устанавливаем размер передаваемого буфера заново.
DMA1_Channel4->CCR |= DMA_CCR1_EN; //Включаем DMA
После этих строк DMA, будет работать и в конце выдаст прерывание вида:
void DMA1_Channel4_IRQHandler(void)
{
DMA1->IFCR |= DMA_ISR_TCIF4; //очистить флаг окончания обмена.
}
Флаг надо сбросить, иначе прерывания будут генерироваться бесконечно.
Другой вариант с SPL
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)text;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = sizeof(text);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
#include "stm32f10x.h"
/*******************************************************************/
#define BAUDRATE 115200
#define DMA_BUFFER_SIZE 16
/*******************************************************************/
void initAll(void)
{
GPIO_InitTypeDef port;
USART_InitTypeDef usart;
DMA_InitTypeDef dma;
uint8_t dataBuffer[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/*******************************************************************/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//if ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != RCC_AHBENR_DMA1EN) RCC->AHBENR |= RCC_AHBENR_DMA1EN;
//при использовании для настройки CMSIS
DMA_StructInit(&dma);
dma.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);
dma.DMA_MemoryBaseAddr = (uint32_t)&dataBuffer[0];
dma.DMA_DIR = DMA_DIR_PeripheralDST;
dma.DMA_BufferSize = DMA_BUFFER_SIZE;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_Init(DMA1_Channel4, &dma);
GPIO_StructInit(&port);
port.GPIO_Mode = GPIO_Mode_AF_PP;
port.GPIO_Pin = GPIO_Pin_9;
port.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &port);
port.GPIO_Mode = GPIO_Mode_AF_PP;
port.GPIO_Pin = GPIO_Pin_10;
port.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &port);
USART_StructInit(&usart);
usart.USART_BaudRate = BAUDRATE;
USART_Init(USART1, &usart);
}
//==========================================================================
int main()
{
__enable_irq();
initAll();
USART_Cmd(USART1, ENABLE);
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
DMA_Cmd(DMA1_Channel4, ENABLE);
while(1)
{
__NOP();
DMA_Cmd(DMA1_Channel4, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel4,16);
DMA_Cmd(DMA1_Channel4, ENABLE);
}
}
Настройка DMA при использовании CMSIS
DMA1_Channel4->CMAR = (uint32_t) &text[0]; //адрес буфера передатчика
DMA1_Channel4->CPAR = (uint32_t) &USART1->DR; //адрес регистра данных передатчика
DMA1_Channel4->CNDTR = sizeof(text); //для передатчика
DMA1_Channel4->CCR = DMA_CCR4_DIR | DMA_CCR4_MINC; //чтение из памяти, инкремент указателя в памяти
DMA1_Channel4->CCR |= DMA_CCR4_TEIE; //канал 4
USART1->CR3 |= USART_CR3_DMAT; //разрешить передачу USART1 через DMA
Чтобы включить DMA набираем:
DMA1_Channel4->CCR |= DMA_CCR1_EN;
Для перезапуска DMA, придётся несколько усложнить функцию:
DMA1_Channel4->CCR &= (uint16_t)(~DMA_CCR1_EN); //Выключаем DMA.
DMA1_Channel4->CNDTR = sizeof(text); //Устанавливаем размер передаваемого буфера заново.
DMA1_Channel4->CCR |= DMA_CCR1_EN; //Включаем DMA
После этих строк DMA, будет работать и в конце выдаст прерывание вида:
void DMA1_Channel4_IRQHandler(void)
{
DMA1->IFCR |= DMA_ISR_TCIF4; //очистить флаг окончания обмена.
}
Флаг надо сбросить, иначе прерывания будут генерироваться бесконечно.
Другой вариант с SPL
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)text;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = sizeof(text);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
Комментариев нет:
Отправить комментарий