Страницы

воскресенье, 13 июля 2014 г.

DMA to USART

Программирование передачи области памяти через 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);

Комментариев нет:

Отправить комментарий

ваше мнение...