使用DMA发送数据时应将数据块定义为静态

DMA的非阻塞特性

在使用DMA进行发送时,应该额外注意时间的问题。DMA是一个外设,其发送时CPU是非阻塞式的,可以说DMA的发送根本不占用CPU的时间。那么问题就可能存在:

  • 当DMA发送正在执行时,数据已经被销毁
  • 当DMA接收正在执行时,数据还未接收完整就已经被使用;

以上两个问题都是由于DMA的非阻塞特性造成的。DMA在运作时,与CPU并行,这一点是特别需要注意的。

void printf_tjc(const char *fmt, ...)
{
    va_list args;
    size_t length;
    static char buf[TJC_SINGLE_MESSAGE_SIZE];
    /** 先等待DMA为空闲,否则数据可能被迅速覆盖 2024-12-17 Tuesday 23:07:14*/
    while(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TC)==RESET);

    va_start(args, fmt);
    /* the return value of vsnprintf is the number of bytes that would be
     * written to buffer had if the size of the buffer been sufficiently
     * large excluding the terminating null byte. If the output string
     * would be larger than the rt_log_buf, we have to adjust the output
     * length. */
    length = vsnprintf(buf, sizeof(buf) - 1, fmt, args);
    if (length > TJC_SINGLE_MESSAGE_SIZE - 1)
        length = TJC_SINGLE_MESSAGE_SIZE - 1;
    va_end(args); 
    /** 打印到特定页面 2024-12-14 Saturday 00:25:58 */
	/** 将显示信息修改为追加模式:+= 2024-12-14 Saturday 10:44:40 */
    /** 使用DMA发送的数据内存段应该定义为静态 2024-12-17 Tuesday 21:03:46*/
    static char buff_send[TJC_SINGLE_MESSAGE_SIZE];
    /** 因为strcat的存在,这里需要先清除缓存 2024-12-17 Tuesday 22:40:10 */
    memset(buff_send,0,sizeof(buff_send));
    /** strcat将源字符串拼接到目标字符串上
     * 其与静态变量相互作用又会出问题,因此使用memset清除一下变量
     *  2024-12-17 Tuesday 22:42:01 */
    strcat(buff_send,TJC_TEXT_PAGE1);
	strcat(buff_send,buf);
    strcat(buff_send,"\"\xff\xff\xff");
    /* 使用USART2 DMA模式进行输出 2024/05/15 Wednesday 23:24:28 */  
    HAL_UART_Transmit_DMA(&huart2,(uint8_t *)buff_send,strlen(buff_send));
    
}

以上代码可以正常运作。如果把buff_send的static修饰去掉,就不正常了。理解了DMA的非阻塞特性就能够明白这一点。那么为了解决这个问题,除了将该内存块定义为静态意外,可以在启动了DMA之后加一定延时,防止在DMA发送完成之前就清除局部变量,这个方式也测试可行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值