Harry_wu 发表于 2020-5-3 19:56:52

HAL_UART_Transmit_DMA函数在循环前正常,放入while(1)循环不正常

尝试使用HAL_UART_Transmit_DMA进行发送数据到串口上位机。main()函数的代码主要为如下三段:
1. 用printf打印一些字符串到PC-----------运行正常
2. 用HAL_UART_Transmit_DMA打印一段字符串到PC---故意打印两遍均正常
3. 将HAL_UART_Transmit_DMA放在while(1)循环中每隔2s打印------不正常,PC端未见输出
不清楚什么影响了HAL_UART_Transmit_DMA在while(1)的正常运行? 在做debug时将断点设置到while(1)中的HAL_UART_Transmit_DMA行,再单步运行又可以打印出来字符串,不知道如何分析,求指点。

int main(void)
{
***
uint8_t aTxMessage[] = "\r\n**** UART-Hyperterminal communication based on DMA ***\r\n    The 2nd line with DMA \r\n";

        /* RS485发送前才使能发送模式,发送完毕马上转为接收模式 */
        HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_SET);//RS485输出使能
        printf("***************************************************\r\n\r\n");
        printf("*                                                 *\r\n");
        printf("************* 测试一下中文字符 ********************\r\n");
        printf("*                                                 *\r\n");
        printf("***************************************************\r\n\r\n");
        HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_RESET);//RS485输入使能
        HAL_Delay(1000);


        HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_SET);//RS485输出使能
        HAL_Delay(1000);
        HAL_UART_Transmit_DMA(&huart1, (uint8_t *)aTxMessage, sizeof(aTxMessage)-1);
        HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_RESET);//RS485输入使能
        HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_SET);//RS485输出使能
        HAL_Delay(1000);
        HAL_UART_Transmit_DMA(&huart1, (uint8_t *)aTxMessage, sizeof(aTxMessage)-1);
        HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_RESET);//RS485输入使能
        HAL_Delay(1000);
/* USER CODE END 2 */


/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
                HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_SET);//RS485输出使能
                HAL_Delay(1000);
                HAL_UART_Transmit_DMA(&huart1, (uint8_t *)aTxMessage, sizeof(aTxMessage)-1);
                HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_RESET);//RS485输入使能
    HAL_Delay(1000);

}
/* USER CODE END 3 */
}



byronsong 发表于 2020-5-3 19:56:53


      HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_SET);//RS485输出使能
      HAL_Delay(1000);
      HAL_UART_Transmit_DMA(&huart1, (uint8_t *)aTxMessage, sizeof(aTxMessage)-1);

把上述代码改为:

      HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_SET);//RS485输出使能
      HAL_Delay(5);
      HAL_UART_Transmit_DMA(&huart1, (uint8_t *)aTxMessage, sizeof(aTxMessage)-1);
      HAL_Delay(995);
      HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_RESET);

应该就可以了。


原因是串口数据未发送完成,就将RS485输出使能关闭了。采用延时后关闭,或者发送完成回调中开启RS485输入使能开启。

烟花绽放 发表于 2020-5-3 21:45:06

判断下是否发送完成呢

Harry_wu 发表于 2020-5-4 10:34:53

songshiqun2010 发表于 2020-5-4 08:00
把上述代码改为:

应该就可以了。


你说的完全正确:DMA串口发送数据需要时间,而我马上下一句我就关闭了RS485的输出,导致数据没有发出去。所以昨天我将while(1)循环前的代码改成了下面这样:
HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_SET);//RS485输出使能
        HAL_UART_Transmit_DMA(&huart1, (uint8_t *)aTxMessage, sizeof(aTxMessage)-1);
        HAL_Delay(500);
        HAL_GPIO_WritePin(DMX_DIR_GPIO_Port, DMX_DIR_Pin, GPIO_PIN_SET);//RS485输出使能
        HAL_UART_Transmit_DMA(&huart1, (uint8_t *)aTxMessage, sizeof(aTxMessage)-1);将开启RS485输入使能放入回调函数,在Transmit_DMA和RS485输出使能之间加了延时。也是因为开头的原因:防止先执行开启了RS485的输出使能,然后回调函数后运行关闭了RS485输出使能,导致下一个Transmit_DMA发送失败。

while(1)循环中也必须留意Transmit_DMA和RS485输出使能之间增加延时。


非常感谢!

Harry_wu 发表于 2020-5-4 10:37:01

烟花绽放 发表于 2020-5-3 21:45
判断下是否发送完成呢

思路对的,确实是DMA搬运和下一句关RS485输出会“同时”进行,我还是按先执行DMA,再执行关RS485的想法去查问题了,导致一开始没考虑到此原因。

李康1202 发表于 2020-5-4 18:53:06

检查一下发完没有

yzz163 发表于 2020-12-10 17:47:39

HAL_Delay(995); 是关键。。没发完就开始干其他事情了。。
页: [1]
查看完整版本: HAL_UART_Transmit_DMA函数在循环前正常,放入while(1)循环不正常