285686334 发表于 2018-12-4 14:25:59

HAL_DMA_USARAT 普通模式只能发送一次数据,不知如何再次启DMA

#include"stm32l0xx_hal.h"

UART_HandleTypeDef   USART2_Handler ;
DMA_HandleTypeDef    DMA1_Handler ;

uint8_tDMA1_USART2_TxDat = 0xaa ;

void USARTx_Initialization(void)
{
        __HAL_RCC_USART2_CLK_ENABLE();
       
        USART2_Handler.Instance             = USART2 ;
        USART2_Handler.Init.BaudRate      = 9600 ;
      USART2_Handler.Init.Mode            = UART_MODE_TX ;
      USART2_Handler.Init.WordLength      = UART_WORDLENGTH_8B ;
       USART2_Handler.Init.StopBits      = UART_STOPBITS_1 ;
       USART2_Handler.Init.Parity          = UART_PARITY_NONE ;
       USART2_Handler.Init.HwFlowCtl       = UART_HWCONTROL_NONE ;

      while(HAL_UART_Init(&USART2_Handler)!=HAL_OK);
}

void DMA1_Initialization(void)
{
        __HAL_RCC_DMA1_CLK_ENABLE() ;
       
        DMA1_Handler.Instance                   = DMA1_Channel4 ;
        DMA1_Handler.Init.Direction             = DMA_MEMORY_TO_PERIPH ;
      DMA1_Handler.Init.Mode                  = DMA_NORMAL ;
       DMA1_Handler.Init.MemDataAlignment      = DMA_MDATAALIGN_BYTE ;
      DMA1_Handler.Init.PeriphDataAlignment   = DMA_PDATAALIGN_BYTE ;
      DMA1_Handler.Init.MemInc                = DMA_MINC_DISABLE ;
      DMA1_Handler.Init.PeriphInc             = DMA_PINC_DISABLE ;
   DMA1_Handler.Init.Priority            = DMA_PRIORITY_HIGH ;
   DMA1_Handler.Init.Request               = DMA_REQUEST_4 ;       
   while(HAL_DMA_Init(&DMA1_Handler)!=HAL_OK);
       
   __HAL_LINKDMA(&USART2_Handler,hdmatx,DMA1_Handler);
       
//        HAL_UART_Transmit_DMA(&USART2_Handler,&DMA1_USART2_TxDat,1);
}

intmain(void)
{
       
        HAL_Init();
        USARTx_Initialization();
        DMA1_Initialization();
       
        while(1)
        {               
                HAL_UART_Transmit_DMA(&USART2_Handler,&DMA1_USART2_TxDat,1);       //第一次发送数据成功
               
/*以下是再次使能DMA与重启DAM ,但是不行 ,不知道是地址不对,还是我定义的数据类型为 uint8_t 错误 **/
                __HAL_DMA_ENABLE(&DMA1_Handler);
                HAL_DMA_Start( &DMA1_Handler,(uint32_t)DMA1_USART2_TxDat,(uint32_t)USART2_Handler.Instance ->TDR ,1);       
        }
}


285686334 发表于 2018-12-4 14:29:56

补充一下 :
   1、 自己判断是 HAL_DMA_Start(); 错误 ,但是本人不知道如何填写这个函数的源地址与目标地址 。
   2 、 我用 USART2 发送一个 byte ,所以定义的数据类型为 uint8_t ,是否要更改为 uint32_t 。

jeffhe1 发表于 2018-12-4 16:24:21

傳送資料長度要一樣 , DMA1_Handler.Init.MemDataAlignment      = DMA_MDATAALIGN_BYTE ;
                              DMA1_Handler.Init.PeriphDataAlignment   = DMA_PDATAALIGN_BYTE ;
MemInc 應該要 Enable      , DMA1_Handler.Init.MemInc                = DMA_MINC_DISABLE ;
                                       DMA1_Handler.Init.PeriphInc             = DMA_PINC_DISABLE ;
內到外 方向應該沒錯         DMA1_Handler.Init.Direction             = DMA_MEMORY_TO_PERIPH ;
可能還要再試看看 , 對 HAL 庫的函數 還不是很熟:L


285686334 发表于 2018-12-4 16:47:36

DMA1_Handler.Init.MemDataAlignment      = DMA_MDATAALIGN_BYTE ;
DMA1_Handler.Init.PeriphDataAlignment   = DMA_PDATAALIGN_BYTE ;
长度是一样的啊 。
uint8_tDMA1_USART2_TxDat = 0xaa ;数据我只是 定义了一个变量 ,也要 递增吗 ? 递增就跑飞啦 ?

285686334 发表于 2018-12-4 16:48:31

HAL_DMA_Start( &DMA1_Handler,(uint32_t)DMA1_USART2_TxDat,(uint32_t)USART2_Handler.Instance ->TDR ,1);    自己感觉应该是这个 启动函数没写对,不会写了。

andrewsss 发表于 2018-12-4 18:12:27

HAL_DMA_Start里包含了 __HAL_DMA_ENABLE,不需要写两次,你应该去看看HAL的串口标准库文件,里面有几个串口操作的函数HAL_UART_Receive_DMA和HAL_UART_DMAStop应该要用到的

xmshao 发表于 2018-12-5 16:48:07

285686334 发表于 2018-12-4 14:29
补充一下 :
   1、 自己判断是 HAL_DMA_Start(); 错误 ,但是本人不知道如何填写这个函数的源地址与目标 ...

HAL_DMA_Start (DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); 这是函数原型。
注意变量类型要一致。你说的传输数据是字节,在这个函数调用过程中没关系,你给的只是地址和
数据个数。

下面的配置才跟你传输数据宽度有关系。
DMA1_Handler.Init.MemDataAlignment      = DMA_MDATAALIGN_BYTE ;
DMA1_Handler.Init.PeriphDataAlignment   = DMA_PDATAALIGN_BYTE ;

另外 注意你定义变量数据类型也跟上面配置一致,即字节,半字、字要对应。

nanguofenghuo 发表于 2018-12-5 22:02:32

DMA需要配置中断的, __HAL_DMA_ENABLE(&DMA1_Handler)跟 HAL_DMA_Start重复了吧,都不需要的,已经包含在发送函数中了。
另外如果想开始后,DMA自己不停的发,DMA1_Handler.Init.Mode= DMA_NORMAL ;这里要改成循环模式,正常模式只会发送一次的。

285686334 发表于 2018-12-7 14:27:09

循环发送,这样写没有问题,我的意思是 用 普通模式 ,发送一次数据后,再发送一次数据 ,应该这么改 ,据说是要重新启动一下 DMA函数, 我的判断是HAL_DMA_Start这个函数没写对。
      函数的原型是这样HAL_DMA_Start (DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
      uint8_tDMA1_USART2_TxDat = 0xaa ;但是我定义的 发送 数据类型是 uint8_t , 应该也是 8bit 的吧。是不是这个地方 有问题?

wh8 发表于 2018-12-7 17:04:24

直接用HAL_UART_Transmit_DMA(&USART2_Handler,&DMA1_USART2_TxDat,1);这个是HAL的API帮你做好了,只要初始化设置没错DMA自动帮你发送1字节不用再调用HAL_DMA_Start的。
且发送完成后DMA是用中断通知CPU的。中断的回调函数接口HAL库也做好了是 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
页: [1]
查看完整版本: HAL_DMA_USARAT 普通模式只能发送一次数据,不知如何再次启DMA