STM32-HAL库(快速入门)-4-UART-不定长收发最终解决版(DMA)

一、DMA实现不定长接收字符串原理

DMA,可以看作一个CPU的秘书,可以在程序配置好后,不经过CPU的干预,直接做数据搬移的操作,来大大节省CPU的资源消耗

原理:

我们知道,串口通信开始为空闲位,然后发送方先发送起始位,再发送字符,最后发送校验位和停止位,最后再变为空闲位,那么当数据连续收发时,如果我们像上一篇文章一样,接收一个字符就触发一次中断,那是不是中断的太频繁了呢?就像你对妹子说I love you,可是你每说一个字母就摇动对方一下,确认对方听清了没,我估计你没说到第5个字符对方就扭头走了吧。所以,这篇文章实现了DMA+串口ilde中断(空闲中断)的方式来实现不定长接收,类似于,你一次性说出i love you然后再确认对方有没有听到。

空闲中断:当串口连续通信时,每发送两个字符之间是没有空闲位的,只有当全部字符发送完毕才进入空闲位,然后触发空闲中断。

同样,我们先定义一个数组,如rx_buffer[100],已知,当触发DMA接收时,DMA计数器自动设置为100,每收到一个字节,计数器减1,所以,我们可以获取这个计数器数a,然后100-a,就是已经接收到的字符了。再把数据从数组中拿出来,这样就实现了不定长收发功能。

二、cubemx配置

第一步:打开串口,设置为异步模式

第二步:配置串口参数

第三步:打开串口中断 

第四步:打开DMA 

三、keil代码编写

    #define MAX_Size_rx_buffer 100
    uint8_t rx_buffer[MAX_Size_rx_buffer];
    uint8_t rx_error[] = "The data is too long\r\n";

    HAL_UART_Receive_DMA(&huart1,rx_buffer,MAX_Size_rx_buffer);//开启串口DMA接收
    __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//开启空闲中断

    extern uint8_t rx_buffer[MAX_Size_rx_buffer];
    uint16_t len = 0;

    void USART1_IRQHandler(void)
    {
       /* USER CODE BEGIN USART1_IRQn 0 */
    if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET)
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);
        HAL_UART_DMAStop(&huart1);
        len = MAX_Size_rx_buffer - __HAL_DMA_GET_COUNTER(huart1.hdmarx);
        if(len>=MAX_Size_rx_buffer)
        {
            HAL_UART_Transmit_DMA(&huart1,rx_error,22);
        }
        else
        {   
            HAL_UART_Transmit_DMA(&huart1,rx_buffer,len);
        }
        
        HAL_UART_Receive_DMA(&huart1,rx_buffer,100);
    }

第一步:定义接收缓存区

main.h

main.c

第二步:while前开启DMA接收和空闲中断

第三步:由于工程没有空闲中断的回调函数,所以我们要在串口1的中断服务函数来编写

先外部声明一下主函数用到的接收缓存区数组,再定义一下用来记录接收数据长度的变量len

stm32f4_it.c

第四步:在串口1中断服务函数编写不定长收发代码

先获取空闲中断标志位是否发生了,若发生则先清楚标志位再停止DMA,然后判断出来接受了多少字符串,判断长度是否大于等于最大数量,100个字符的最大数量,若点击了发送新行,则还会有\R和\N,最后,重新开启DMA接收

四、现象

注意:

由于hal库bug,第一次发送时候不要超过max_size,因为程序第一次启动后,第一次暂停DMA之后,使用dma模式发出字符串

有任何bug请直接发在评论区我会第一时间更改

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值