原创 【博客大赛】STM32学习笔记之DMA传输串口数据

2013-7-6 00:46 5299 29 29 分类: MCU/ 嵌入式 文集: C

 

前言:

        最近项目中需要用到串口及网口输出大量的数据给上位机,先调试串口。发现CPU花蛮多时间来传输数据,太浪费了。所以想到了用DMA来传输串口数据,一搜资料,库函数里还真的有DMA来实现USART数据的传输的,真的。遂有以下学习笔记:

      我以前使用串口都是简单的通过重构putchar函数,调用printf函数来给上位机PC传输数据的,数据格式通常是ASCII码,然而这次数据帧格式是十六进制,所以得用USART_SendData()函数了,由于数据量大,有3000多字节数据,除了发送数据外,CPU还得做其他事情,所以这里用DMA来传数据。

 

1)建立发送数据缓冲区:uint32_t SendBuff[3000];

2)宏定义串口的DMA基地址:#define USART1_DR_Base  0x40013804

3)开启USART1GPIOAAFIODMA1的时钟,并且初始化USARTGPIO:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

 

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;         //tx

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

 

GPIO_Init(GPIOA,&GPIO_InitStructure);

 

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;          //rx

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA,&GPIO_InitStructure);

 

USART_InitStructure.USART_BaudRate=256000; //波特率256000bit/s

USART_InitStructure.USART_WordLength=USART_WordLength_8b;        //8 bit data

USART_InitStructure.USART_StopBits=USART_StopBits_1;                // stop bit 1

USART_InitStructure.USART_Parity=USART_Parity_No;                        //no  parity bit

USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;

USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;          //双工模式

USART_Init(USART1,&USART_InitStructure);

 

4)使能串口1的发送和接收中断;使能串口1

//enable USART1's interruput

USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);

//enable USART1

USART_Cmd(USART1,ENABLE);

 

5USART中断优先级配置:

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

 

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

  

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

 

6DMAUSART1的配置:

void DMA_Configuration(void)

{

    DMA_InitTypeDef DMA_InitStructure;

 

    DMA_DeInit(DMA1_Channel4);

    DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;//在(2)中已经宏定义了,内存地址&串口数据寄存器地址

    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;           //要发送的数组,注意此处发送的是32位的, 即四个字节的数据。

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

    DMA_InitStructure.DMA_BufferSize = 3000; //传输数据大小

    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模式一次传输,不循环

    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//优先级中

    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

    DMA_Init(DMA1_Channel4, &DMA_InitStructure);

}

 

 

7)主函数:

int main(void)

{

  SystemInit();

USART_Config();

NVIC_Configuration();

  DMA_Configuration();

  LED_Config();

 

     Data_init();

 

  USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);//USART1配置成DAM方式工作,

 

 DMA_Cmd(DMA1_Channel4, ENABLE);//使能DMA通道,开始传输数据

 

    while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET)//此时DMA正在传输数据,传输结束则跳出while

 {

     LED1_ON;  //DMA在传输数据时,CPU在此可以干其他事情,这里是举例点灯

  LED2_OFF;

  delay_ms(50);

  LED1_OFF;

  LED2_ON;

  delay_ms(50);

   }

 printf("\r\nDMA transmission successful!\r\n");

 

 while(1);

}

 

8)还有USART中断尚未弄明白,后续补充。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
29
关闭 站长推荐上一条 /3 下一条