[STM32F1] 串口DMA接收的问题

[复制链接]
2231|27
 楼主| djz1992 发表于 2020-8-28 15:15 | 显示全部楼层 |阅读模式
用HTTP下载bin文件,服务器不分段,一下子几十k的文件就下发过来。
现在是DMA+串口空闲中断。问题来了。
接收是来连续的,串口不会空闲,远超缓冲区大小的数据,怎么办 ?
想用双缓冲区来切换接收,然后接受完一部分立马处理,避免数据被覆盖。
但是问题是中间不停顿,空闲中断会触发吗?DMA完成中断会触发吗?

如果DMA的接收BUF长度是1024。当接收满1024后会不会触发完成中断?
@dirtwillfly @m564522634 @xyz549040622
gyh974 发表于 2020-8-28 15:25 | 显示全部楼层
这么大的文件传输数据,最终你是要保存文件在哪里?还是收完再作处理?
xyz549040622 发表于 2020-8-28 15:31 | 显示全部楼层
只要DMA传输完成中断使能,满1024肯定会触发中断的。
双缓存区是软件机制,和硬件没关系的。你需要做的是两种接收方式配合使用。
 楼主| djz1992 发表于 2020-8-28 15:42 | 显示全部楼层
xyz549040622 发表于 2020-8-28 15:31
只要DMA传输完成中断使能,满1024肯定会触发中断的。
双缓存区是软件机制,和硬件没关系的。你需要做的是两 ...

我现在想的是串口空闲中断负责接收处理一些短的数据。DMA完成中断负责接收处理那些超长内容。但是最后一帧肯定又不会正好是1024,还得靠空闲中断来?

好麻烦啊,直接1字节1字节接收得了,简单方便。
 楼主| djz1992 发表于 2020-8-28 15:43 | 显示全部楼层
gyh974 发表于 2020-8-28 15:25
这么大的文件传输数据,最终你是要保存文件在哪里?还是收完再作处理?

收完一帧就写到flash里,OTA升级么
 楼主| djz1992 发表于 2020-8-28 16:19 | 显示全部楼层
  1. void UsartReceive_IDLE(UART_HandleTypeDef *huart,UartBufferTypedef *UartxRT )
  2. {
  3.         uint32_t temp;
  4.         if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))                                //获取IDLE标志位,如果idle标志被置
  5.         {
  6.                 __HAL_UART_CLEAR_IDLEFLAG(huart);                                                                        //清除标志
  7.                 HAL_UART_DMAStop(huart);
  8.                 temp=__HAL_DMA_GET_COUNTER(huart->hdmarx);                                                        //获取DMA中未传输的数据个
  9.                 UartxRT->RxLen =  MAX_UART_BUFFER - temp;                                                        //总计数减去未传输的数据个数,得到已经接收的数据个
  10.                 memcpy(UartxRT->RxBuf ,UartxRT->RxDMA_Buf ,UartxRT->RxLen );
  11.                 UartxRT->rx_idle_flag=1;                                                                                        //接受完成标志位置1
  12.                 HAL_UART_Receive_DMA(huart,UartxRT->RxDMA_Buf,MAX_UART_BUFFER);                //重新启串口DMA接收
  13.         }
  14. }

  15. void DMA1_Channel5_Receive_Complete(UART_HandleTypeDef *huart,UartBufferTypedef *UartxRT)
  16. {
  17.         static uint8_t witchbuf=1;

  18.         if(        __HAL_DMA_GET_FLAG(&hdma_usart1_rx,DMA_FLAG_TC5)!= RESET)                                //DMA接收完成标志
  19.         {
  20.                 __HAL_DMA_CLEAR_FLAG(&hdma_usart1_rx,DMA_FLAG_TC5);                                                //清除中断标志
  21.                 HAL_UART_DMAStop(huart);
  22.                 if(witchbuf==1)                                                                                                //之前用的buf1,切换为2
  23.                 {
  24.                         memcpy(UartxRT->RxBuf ,UartxRT->RxDMA_Buf ,MAX_UART_BUFFER);
  25.                         UartxRT->rx_idle_flag=1;               
  26.                         witchbuf=2;                                                                                            
  27.                         HAL_UART_Receive_DMA(huart,UartxRT->RxDMA_Buf2,MAX_UART_BUFFER);        //重启串口DMA接收到buf2
  28.                 }
  29.                 else if(witchbuf==2)                                                                             //之前用的buf2,切换为buf1
  30.                 {
  31.                         memcpy(UartxRT->RxBuf ,UartxRT->RxDMA_Buf2 ,MAX_UART_BUFFER);
  32.                         UartxRT->rx_idle_flag=1;               
  33.                         witchbuf=1;                                                                                            
  34.                         HAL_UART_Receive_DMA(huart,UartxRT->RxDMA_Buf,MAX_UART_BUFFER);                //重启串口DMA接收到buf1
  35.                 }
  36.         }
  37. }
@xyz549040622 以上这样写,好像每次收完复制到一个地方,会很慢吧。是不是应该传递指针?不复制又容易丢
 楼主| djz1992 发表于 2020-8-28 16:43 | 显示全部楼层
xyz549040622 发表于 2020-8-28 15:31
只要DMA传输完成中断使能,满1024肯定会触发中断的。
双缓存区是软件机制,和硬件没关系的。你需要做的是两 ...

双缓冲区的时候,dma设置成normal还是循环?
 楼主| djz1992 发表于 2020-8-28 17:12 | 显示全部楼层
xyz549040622 发表于 2020-8-28 15:31
只要DMA传输完成中断使能,满1024肯定会触发中断的。
双缓存区是软件机制,和硬件没关系的。你需要做的是两 ...

memcpy(UartxRT->RxBuf ,UartxRT->RxDMA_Buf ,UartxRT->RxLen );
HAL_UART_Receive_DMA(huart,UartxRT->RxDMA_Buf2,MAX_UART_BUFFER);        //重启串口DMA接收到buf2


HAL_UART_Receive_DMA(huart,UartxRT->RxDMA_Buf2,MAX_UART_BUFFER);        //重启串口DMA接收到buf2
memcpy(UartxRT->RxBuf ,UartxRT->RxDMA_Buf ,UartxRT->RxLen );


这两句的前后关系影响接收吗?
如果执行完HAL_UART_Receive_DMA,DMA就立马开始工作,cpu可以自己copy自己的,不用管串口,那就应该先打开dma,再开始复制,然后处理。

其实最好是配置完dma为buf2后,直接用buf1进行处理,都不需要复制。但是其他c文件里也有调用buf的处理部分。
要么用if来控制处理的buf还是buf2,要么传递指针过去。
传递指针的话,像buf[2]这种该怎么写?*(p+2)?
C语言差。。。
zchong 发表于 2020-8-28 21:24 | 显示全部楼层
HTTP,串口,具体是啥过程,没看明白
dirtwillfly 发表于 2020-8-29 12:42 | 显示全部楼层
不懂,这个数据传输过程,是服务器端控制传输的,还是下位机控制传输的?
这样一下子传输那么多,中间没有验证,很容易出错的
cooldog123pp 发表于 2020-8-29 21:38 | 显示全部楼层
默默的围观吧,是不是数据量传输太大了,缓存不够?不懂,不敢瞎哔哔。
cooldog123pp 发表于 2020-8-29 21:38 | 显示全部楼层
默默的围观吧,是不是数据量传输太大了,缓存不够?不懂,不敢瞎哔哔。
 楼主| djz1992 发表于 2020-8-30 07:29 | 显示全部楼层
dirtwillfly 发表于 2020-8-29 12:42
不懂,这个数据传输过程,是服务器端控制传输的,还是下位机控制传输的?
这样一下子传输那么多,中间没有 ...

http下载文件,就是直接在tcp的连接基础上,按http的请求格式去get文件。
没有做相应的上位机,所以没有分包和校验。
bald 发表于 2020-8-31 00:24 | 显示全部楼层
可以用定时中断。读取指针与DMA传输指针之间够一帧即转存一次。这样根本不需要关注串口的传输,只要监视缓冲区里的内容即可。这里主要问题是巡查窗口周期的选择。
 楼主| djz1992 发表于 2020-8-31 17:11 | 显示全部楼层
STM32串口空闲中断,接收一帧数据,会进两次空闲中断。数据乱了,这咋整啊@dirtwillfly @m564522634 @xyz549040622
 楼主| djz1992 发表于 2020-8-31 17:12 | 显示全部楼层
@xyz549040622
 楼主| djz1992 发表于 2020-8-31 21:11 | 显示全部楼层
bald 发表于 2020-8-31 00:24
可以用定时中断。读取指针与DMA传输指针之间够一帧即转存一次。这样根本不需要关注串口的传输,只要监视缓 ...

假设dma读取长度设置的是128。现在还没读取完,怎么查看DMA已经读取到哪个位置了?
bald 发表于 2020-8-31 22:05 | 显示全部楼层
djz1992 发表于 2020-8-31 21:11
假设dma读取长度设置的是128。现在还没读取完,怎么查看DMA已经读取到哪个位置了? ...

DMA本身有一个传输指针,自己在缓冲区设置一个读取指针,两个指针之差大于等于128进行一次存储操作。DMA传输指针是工作在循环模式的。读取指针当然也要进行循环操作
 楼主| djz1992 发表于 2020-9-1 08:17 | 显示全部楼层
bald 发表于 2020-8-31 22:05
DMA本身有一个传输指针,自己在缓冲区设置一个读取指针,两个指针之差大于等于128进行一次存储操作。DMA ...

DMA传输指针是
HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
这个里面的*pData吗?
天意无罪 发表于 2020-9-1 08:20 | 显示全部楼层
STM32做主还是从啊,如果做主,直接get或定时get数据,还不用开buffer,数据校验也好做。如果STM32是做从,你靠DMA中断来接收数据,数据正确率不好控制吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:人生苦短,冬日苦长,正是青葱,却无骄阳

115

主题

620

帖子

5

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