打印

STM32 DMA 应用之(二) DMA 串口 数据传输--发送

[复制链接]
1481|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
一、DMA请求映像

沙发
monkeypony|  楼主 | 2015-5-26 15:04 | 只看该作者

使用特权

评论回复
板凳
monkeypony|  楼主 | 2015-5-26 15:04 | 只看该作者
由此我们知道如果需要使用串口1的发送功能需要用到的是DMA1_Channel4

使用串口1的接收功能需要用到的是DMA1_Channel5

使用特权

评论回复
地板
monkeypony|  楼主 | 2015-5-26 15:05 | 只看该作者
二、怎样配置软件来使用DMA  把数据传到串口发送?

(1)配置dma
/**************************************************************************
*函数名称:  Dma_Init
*功能描述: 利用DMA 把内存的数据传输到串口发送达到高速传输的目的
*  
*输入参数:无
*返回值  :无
*其他说明:无
*当前版本:v1.0
*作者     :尹宣
*完成时间:2013年12月1日
*修改日期              版本号              修改人              修改内容
*-----------------------------------------------------------------
*
******************************************************************/
#define UART_RX_LEN     5
u8 Uart_Send_Buffer[UART_RX_LEN] = {0x12,0x34,0x56,0x78,0x90};
u8 i=0;
u8 Flag_Uart_Send=0;

void Dma_Init(void)
{
  DMA_InitTypeDef  DMA_InitStructure;
      
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
       /* DMA channel6configuration */
  DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr       = (u32)(&USART1->DR);  //外设地址
DMA_InitStructure.DMA_MemoryBaseAddr                    =(u32)Uart_Send_Buffer;
  DMA_InitStructure.DMA_DIR                                      =DMA_DIR_PeripheralDST;   //外设作为目的地址   //DMA_DIR_PeripheralSRC;   //外设作为DMA的源端
DMA_InitStructure.DMA_BufferSize                          =5; //BufferSize;      //传输大小
  DMA_InitStructure.DMA_PeripheralInc                   =DMA_PeripheralInc_Disable; //外设递增模式禁止   DMA_PeripheralInc_Enable;            //外设地址增加
DMA_InitStructure.DMA_MemoryInc                       =DMA_MemoryInc_Enable;   //内存地址自增
DMA_InitStructure.DMA_PeripheralDataSize         = DMA_PeripheralDataSize_Byte; //传输方式:字节   DMA_PeripheralDataSize_Word;    //字(32位)
DMA_InitStructure.DMA_MemoryDataSize            =DMA_PeripheralDataSize_Byte;  //内存存储方式:字节  DMA_MemoryDataSize_Word;
  DMA_InitStructure.DMA_Mode                                  =DMA_Mode_Circular;  //DMA_Mode_Normal 正常模式,只传送一次;  DMA_Mode_Circular:循环模式,不停的传送;
DMA_InitStructure.DMA_Priority                      =DMA_Priority_High;
  DMA_InitStructure.DMA_M2M                                   =DMA_M2M_Disable;             //DMA_M2M_Enable;   
  DMA_Init(DMA1_Channel4,&DMA_InitStructure);

  /* Enable DMA Channel4Transfer Complete interrupt */
  DMA_ITConfig(DMA1_Channel4,DMA_IT_TC, ENABLE);
//
// USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);                                                                    //串口接收器DMA
//采用DMA方式发送
       USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
       //启动串口   
       USART_Cmd(USART1,ENABLE);


  DMA_ITConfig(DMA1_Channel4,DMA_IT_TC, ENABLE);
传输完成则进入DMA1_Channel4中断;

使用特权

评论回复
5
monkeypony|  楼主 | 2015-5-26 15:05 | 只看该作者
注意这句话:USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  这是使能指定USART的DMA请求;(不同的外设都有这个  xxx_DMACmd()请求;)

USART_DMAReq_Tx:发送DMA请求

USART_DMAReq_Rx:接收DMA请求

使用特权

评论回复
6
monkeypony|  楼主 | 2015-5-26 15:06 | 只看该作者
串口配置
/***************************************************************** 
*函数名称: USART1_Init
*功能描述:   配置串口1初始化
*  
*输入参数:无
*返回值  :无
*其他说明:无
*当前版本:v1.0
*作者     :尹宣
*完成时间:2013年12月1日
*修改日期              版本号              修改人              修改内容
*-----------------------------------------------------------------
*
******************************************************************/
void USART1_Init(uint32 baud)
{
       GPIO_InitTypeDef       GPIO_InitStructure;
       USART_InitTypeDef      USART_InitStructure;
       USART_ClockInitTypeDefUSART_ClockInitStructure;
      

      
       //使能串口1,PA,AFIO总线
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
                          RCC_APB2Periph_AFIO |
                          RCC_APB2Periph_USART1 ,
                          (FunctionalState)ENABLE);
      
       // A9 USART1_Tx
   GPIO_InitStructure.GPIO_Pin   =GPIO_Pin_9;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode  =GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA,&GPIO_InitStructure);

    // A10 USART1_Rx
   GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_10;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
      
       USART_InitStructure.USART_BaudRate            = baud;
       USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
       USART_InitStructure.USART_StopBits            = USART_StopBits_1;
       USART_InitStructure.USART_Parity              = USART_Parity_No;
       USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
       USART_InitStructure.USART_Mode= USART_Mode_Rx | USART_Mode_Tx;
      
       USART_ClockInitStructure.USART_Clock   = USART_Clock_Disable;
       USART_ClockInitStructure.USART_CPOL    = USART_CPOL_Low;
       USART_ClockInitStructure.USART_CPHA    = USART_CPHA_2Edge;
       USART_ClockInitStructure.USART_LastBit= USART_LastBit_Disable;
    USART_ClockInit(USART1,&USART_ClockInitStructure);
      
    USART_Init(USART1,&USART_InitStructure);
    USART_Cmd(USART1,(FunctionalState)ENABLE);
//  USART_ClearFlag(USART3, USART_FLAG_TC);  
       //串口1使用接收中断
       USART_ITConfig(USART1,USART_IT_RXNE,(FunctionalState)ENABLE);
}


2.设置DMA优先级

/*****************************************************************
*函数名称:  NVIC_Config
*功能描述:   配置DMA的中断优先级
*  
*输入参数:无
*返回值  :无
*其他说明:无
*当前版本:v1.0
*作者     :尹宣
*完成时间:2013年12月1日
*修改日期              版本号              修改人              修改内容
*-----------------------------------------------------------------
*
******************************************************************/
void NVIC_Config(void)
{
         NVIC_InitTypeDefNVIC_InitStructure;  
        
         //DMA优先级        
         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
         NVIC_InitStructure.NVIC_IRQChannel= DMA1_Channel4_IRQn;
         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2;
         NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;
         NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
         NVIC_Init(&NVIC_InitStructure);
        
        
         /*Configure one bit for preemption priority -------------------------------- */
         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
        
         /*UART1 -------------------------------------------------------------------- */
         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);   
        
}

使用特权

评论回复
7
monkeypony|  楼主 | 2015-5-26 15:06 | 只看该作者
3.在stm3210x_it.c 文件中添加 DMA中断处理函数
/*******************************************************************************
* Function Name  : DMAChannel1_IRQHandler
* Description    : This function handles DMA Stream 1interrupt request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
//串口1  DMA方式发送中断
void DMA1_Channel4_IRQHandler(void)
{
        
          //清除标志位
   DMA_ClearFlag(DMA1_FLAG_TC4);
   //关闭DMA
   DMA_Cmd(DMA1_Channel4,DISABLE);
          Flag_Uart_Send = 0;
                  
}

使用特权

评论回复
8
monkeypony|  楼主 | 2015-5-26 15:07 | 只看该作者
如果DMA是正常模式DMA_Mode_Normal时,传输结束后将不再产生DMA操作;所以需要在传输完成的中断中暂时把DMA关闭—即:DMA_Cmd(DMA1_Channel4,DISABLE);

之后在main函数的while(1)循环中打开DMA_Cmd(DMA1_Channel4,ENABLE);进行下一次的传输;

使用特权

评论回复
9
monkeypony|  楼主 | 2015-5-26 15:08 | 只看该作者
测试:



数据源地址为数组Uart_Send_Buffer ,它的定义如下:

#define UART_RX_LEN     5

u8 Uart_Send_Buffer[UART_RX_LEN] ={0x12,0x34,0x56,0x78,0x90};

当程序开始全速运行时,串口助手打印

使用特权

评论回复
10
蜕变吧| | 2015-6-21 09:12 | 只看该作者
这个例程不错,有借鉴作用,省去了串口的发送时间,使得熟读变快了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

133

主题

715

帖子

0

粉丝