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

[复制链接]
1758|9
 楼主| monkeypony 发表于 2015-5-26 15:04 | 显示全部楼层 |阅读模式
一、DMA请求映像
QQ截图20150526150331.png
 楼主| 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
  1. /**************************************************************************
  2. *函数名称:  Dma_Init
  3. *功能描述: 利用DMA 把内存的数据传输到串口发送达到高速传输的目的
  4. *  
  5. *输入参数:无
  6. *返回值  :无
  7. *其他说明:无
  8. *当前版本:v1.0
  9. *作者     :尹宣
  10. *完成时间:2013年12月1日
  11. *修改日期              版本号              修改人              修改内容
  12. *-----------------------------------------------------------------
  13. *
  14. ******************************************************************/
  15. #define UART_RX_LEN     5
  16. u8 Uart_Send_Buffer[UART_RX_LEN] = {0x12,0x34,0x56,0x78,0x90};
  17. u8 i=0;
  18. u8 Flag_Uart_Send=0;

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

  38.   /* Enable DMA Channel4Transfer Complete interrupt */
  39.   DMA_ITConfig(DMA1_Channel4,DMA_IT_TC, ENABLE);
  40. //
  41. // USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);                                                                    //串口接收器DMA
  42. //采用DMA方式发送
  43.        USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
  44.        //启动串口   
  45.        USART_Cmd(USART1,ENABLE);


  46.   DMA_ITConfig(DMA1_Channel4,DMA_IT_TC, ENABLE);
  47. 传输完成则进入DMA1_Channel4中断;
 楼主| 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请求
 楼主| monkeypony 发表于 2015-5-26 15:06 | 显示全部楼层
串口配置
  1. /*****************************************************************
  2. *函数名称: USART1_Init
  3. *功能描述:   配置串口1初始化
  4. *  
  5. *输入参数:无
  6. *返回值  :无
  7. *其他说明:无
  8. *当前版本:v1.0
  9. *作者     :尹宣
  10. *完成时间:2013年12月1日
  11. *修改日期              版本号              修改人              修改内容
  12. *-----------------------------------------------------------------
  13. *
  14. ******************************************************************/
  15. void USART1_Init(uint32 baud)
  16. {
  17.        GPIO_InitTypeDef       GPIO_InitStructure;
  18.        USART_InitTypeDef      USART_InitStructure;
  19.        USART_ClockInitTypeDefUSART_ClockInitStructure;
  20.       

  21.       
  22.        //使能串口1,PA,AFIO总线
  23.    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
  24.                           RCC_APB2Periph_AFIO |
  25.                           RCC_APB2Periph_USART1 ,
  26.                           (FunctionalState)ENABLE);
  27.       
  28.        // A9 USART1_Tx
  29.    GPIO_InitStructure.GPIO_Pin   =GPIO_Pin_9;
  30.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  31.    GPIO_InitStructure.GPIO_Mode  =GPIO_Mode_AF_PP;
  32.     GPIO_Init(GPIOA,&GPIO_InitStructure);

  33.     // A10 USART1_Rx
  34.    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_10;
  35.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  36.     GPIO_Init(GPIOA,&GPIO_InitStructure);
  37.       
  38.        USART_InitStructure.USART_BaudRate            = baud;
  39.        USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
  40.        USART_InitStructure.USART_StopBits            = USART_StopBits_1;
  41.        USART_InitStructure.USART_Parity              = USART_Parity_No;
  42.        USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
  43.        USART_InitStructure.USART_Mode= USART_Mode_Rx | USART_Mode_Tx;
  44.       
  45.        USART_ClockInitStructure.USART_Clock   = USART_Clock_Disable;
  46.        USART_ClockInitStructure.USART_CPOL    = USART_CPOL_Low;
  47.        USART_ClockInitStructure.USART_CPHA    = USART_CPHA_2Edge;
  48.        USART_ClockInitStructure.USART_LastBit= USART_LastBit_Disable;
  49.     USART_ClockInit(USART1,&USART_ClockInitStructure);
  50.       
  51.     USART_Init(USART1,&USART_InitStructure);
  52.     USART_Cmd(USART1,(FunctionalState)ENABLE);
  53. //  USART_ClearFlag(USART3, USART_FLAG_TC);  
  54.        //串口1使用接收中断
  55.        USART_ITConfig(USART1,USART_IT_RXNE,(FunctionalState)ENABLE);
  56. }


  57. 2.设置DMA优先级

  58. /*****************************************************************
  59. *函数名称:  NVIC_Config
  60. *功能描述:   配置DMA的中断优先级
  61. *  
  62. *输入参数:无
  63. *返回值  :无
  64. *其他说明:无
  65. *当前版本:v1.0
  66. *作者     :尹宣
  67. *完成时间:2013年12月1日
  68. *修改日期              版本号              修改人              修改内容
  69. *-----------------------------------------------------------------
  70. *
  71. ******************************************************************/
  72. void NVIC_Config(void)
  73. {
  74.          NVIC_InitTypeDefNVIC_InitStructure;  
  75.         
  76.          //DMA优先级        
  77.          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
  78.          NVIC_InitStructure.NVIC_IRQChannel= DMA1_Channel4_IRQn;
  79.          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2;
  80.          NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;
  81.          NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
  82.          NVIC_Init(&NVIC_InitStructure);
  83.         
  84.         
  85.          /*Configure one bit for preemption priority -------------------------------- */
  86.          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  87.         
  88.          /*UART1 -------------------------------------------------------------------- */
  89.          NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;
  90.          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;
  91.          NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;
  92.          NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
  93.          NVIC_Init(&NVIC_InitStructure);   
  94.         
  95. }
 楼主| monkeypony 发表于 2015-5-26 15:06 | 显示全部楼层
3.在stm3210x_it.c 文件中添加 DMA中断处理函数
  1. /*******************************************************************************
  2. * Function Name  : DMAChannel1_IRQHandler
  3. * Description    : This function handles DMA Stream 1interrupt request.
  4. * Input          : None
  5. * Output         : None
  6. * Return         : None
  7. *******************************************************************************/
  8. //串口1  DMA方式发送中断
  9. void DMA1_Channel4_IRQHandler(void)
  10. {
  11.         
  12.           //清除标志位
  13.    DMA_ClearFlag(DMA1_FLAG_TC4);
  14.    //关闭DMA
  15.    DMA_Cmd(DMA1_Channel4,DISABLE);
  16.           Flag_Uart_Send = 0;
  17.                   
  18. }
 楼主| 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);进行下一次的传输;
 楼主| 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};

当程序开始全速运行时,串口助手打印
QQ截图20150526150744.png
蜕变吧 发表于 2015-6-21 09:12 | 显示全部楼层
这个例程不错,有借鉴作用,省去了串口的发送时间,使得熟读变快了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

133

主题

715

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部