STM32
登录
直播中
莫循虎
7年用户
889经验值
私信
关注
[问答]
怎样去使用STM32F1串口的DMA控制器呢
开启该帖子的消息推送
stm32f1
串口
控制器
怎样去使用
STM32
F1串口的DMA控制器呢?
串口接收完数据是要处理的,那么处理的步骤是怎么样呢?
回帖
(1)
刘瑞
2021-12-7 10:51:20
引言
常规串口接收数据使用的是串口接收中断,即串口每接收一个字符就进入中断,接收数据需要我们在中断里处理实现,然而大部分的场景是串口需要接收大量数据,频繁进入中断会导致程序时间开销大,cpu也需要花费大量算力取处理中断业务,所以一般都使用dma。
方法:
(空闲中断+DMA接收)
从系统结构可以看出,dma 有独立的总线连接外设abp总线与内部sarm 在传输数据的时候可以不由cpu处理。
传输动作本身是由 DMA 控制器来实现和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。这样的操作并没有让处理器参与处理,CPU可以干其他事情,当DMA传输完成的时候产生一个中断,告诉CPU我已经完成了,然后CPU知道了就可以去处理数据了,这样子提高了CPU的利用率。
STM32F1系列的MCU有两个DMA控制器(DMA2只存在于大容量产品中),DMA1有7个通道,DMA2有5个通道,每个通道专门用来管理来自于一个或者多个外设对存储器的访问请求。还有一个仲裁器来协调各个DMA请求的优先权。
串口配置成空闲中断,当数据传输的时候,总线慢,串口并不会产生中断。接收完后,总线会空闲,寄存器idle位就会被置1,产生中断事件。
实现思路:
采用串口1,并配置成
空闲中断
模式且使能DMA接收,并同时设置接收缓冲区和初始化DMA。
那么初始化完成之后,假设这帧数据长度是100个字节,那么在单片机接收到一个字节的时候(RXNE位被置位)并不会产生串口中断,而是DMA在后台把数据默默地搬运到你指定的缓冲区里面。当整帧数据发送完毕之后(接收停顿超过一字节时间)串口才会产生一次中断,此时可以利用DMA_GetCurrDataCounter();函数计算出本次的数据接受长度,从而进行数据处理。
就是在串口空闲中断中使用
Usart1RecLen = DMARecLen-DMA_GetCurrDataCounter(DMA1_Channel5); //算出接本帧数据长度 = DMA缓存的大小 - 剩余 DMA缓存大小
注意事项
串口接收完数据是要处理的,那么处理的步骤是怎么样呢?
暂时关闭串口接收DMA通道,有两个原因:1.防止后面又有数据接收到,产生干扰,因为此时的数据还未处理。2.DMA需要重新配置。
清DMA标志位。
从DMA寄存器中获取接收到的数据字节数(可有可无)。
重新设置DMA下次要接收的数据字节数,注意,数据传输数量范围为0至65535。这个寄存器只能在通道不工作(DMA_CCRx的EN=0)时写入。通道开启后该寄存器变为只读,指示剩余的待传输字节数目。寄存器内容在每次DMA传输后递减。数据传输结束后,寄存器的内容或者变为0;或者当该通道配置为自动重加载模式时,寄存器的内容将被自动重新加载为之前配置时的数值。当寄存器的内容为0时,无论通道是否开启,都不会发生任何数据传输。
给出信号量,发送接收到新数据标志,供前台程序查询。
开启DMA通道,等待下一次的数据接收,注意,对DMA的相关寄存器配置写入,如重置DMA接收数据长度,必须要在关闭DMA的条件进行,否则操作无效。
STM32的IDLE的中断在串口无数据接收的情况下,是不会一直产生的,产生的条件是这样的,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一断接收的数据断流,没有接收到数据,即产生IDLE中断。如果中断发送数据帧的速率很快,MCU来不及处理此次接收到的数据,中断又发来数据的话,这里不能开启,否则数据会被覆盖。有两种方式解决:
在重新开启接收DMA通道之前,将Rx_Buf缓冲区里面的数据复制到另外一个数组中,然后再开启DMA,然后马上处理复制出来的数据。
建立双缓冲,重新配置DMA_MemoryBaseAddr的缓冲区地址,那么下次接收到的数据就会保存到新的缓冲区中,不至于被覆盖。
引言
常规串口接收数据使用的是串口接收中断,即串口每接收一个字符就进入中断,接收数据需要我们在中断里处理实现,然而大部分的场景是串口需要接收大量数据,频繁进入中断会导致程序时间开销大,cpu也需要花费大量算力取处理中断业务,所以一般都使用dma。
方法:
(空闲中断+DMA接收)
从系统结构可以看出,dma 有独立的总线连接外设abp总线与内部sarm 在传输数据的时候可以不由cpu处理。
传输动作本身是由 DMA 控制器来实现和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。这样的操作并没有让处理器参与处理,CPU可以干其他事情,当DMA传输完成的时候产生一个中断,告诉CPU我已经完成了,然后CPU知道了就可以去处理数据了,这样子提高了CPU的利用率。
STM32F1系列的MCU有两个DMA控制器(DMA2只存在于大容量产品中),DMA1有7个通道,DMA2有5个通道,每个通道专门用来管理来自于一个或者多个外设对存储器的访问请求。还有一个仲裁器来协调各个DMA请求的优先权。
串口配置成空闲中断,当数据传输的时候,总线慢,串口并不会产生中断。接收完后,总线会空闲,寄存器idle位就会被置1,产生中断事件。
实现思路:
采用串口1,并配置成
空闲中断
模式且使能DMA接收,并同时设置接收缓冲区和初始化DMA。
那么初始化完成之后,假设这帧数据长度是100个字节,那么在单片机接收到一个字节的时候(RXNE位被置位)并不会产生串口中断,而是DMA在后台把数据默默地搬运到你指定的缓冲区里面。当整帧数据发送完毕之后(接收停顿超过一字节时间)串口才会产生一次中断,此时可以利用DMA_GetCurrDataCounter();函数计算出本次的数据接受长度,从而进行数据处理。
就是在串口空闲中断中使用
Usart1RecLen = DMARecLen-DMA_GetCurrDataCounter(DMA1_Channel5); //算出接本帧数据长度 = DMA缓存的大小 - 剩余 DMA缓存大小
注意事项
串口接收完数据是要处理的,那么处理的步骤是怎么样呢?
暂时关闭串口接收DMA通道,有两个原因:1.防止后面又有数据接收到,产生干扰,因为此时的数据还未处理。2.DMA需要重新配置。
清DMA标志位。
从DMA寄存器中获取接收到的数据字节数(可有可无)。
重新设置DMA下次要接收的数据字节数,注意,数据传输数量范围为0至65535。这个寄存器只能在通道不工作(DMA_CCRx的EN=0)时写入。通道开启后该寄存器变为只读,指示剩余的待传输字节数目。寄存器内容在每次DMA传输后递减。数据传输结束后,寄存器的内容或者变为0;或者当该通道配置为自动重加载模式时,寄存器的内容将被自动重新加载为之前配置时的数值。当寄存器的内容为0时,无论通道是否开启,都不会发生任何数据传输。
给出信号量,发送接收到新数据标志,供前台程序查询。
开启DMA通道,等待下一次的数据接收,注意,对DMA的相关寄存器配置写入,如重置DMA接收数据长度,必须要在关闭DMA的条件进行,否则操作无效。
STM32的IDLE的中断在串口无数据接收的情况下,是不会一直产生的,产生的条件是这样的,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一断接收的数据断流,没有接收到数据,即产生IDLE中断。如果中断发送数据帧的速率很快,MCU来不及处理此次接收到的数据,中断又发来数据的话,这里不能开启,否则数据会被覆盖。有两种方式解决:
在重新开启接收DMA通道之前,将Rx_Buf缓冲区里面的数据复制到另外一个数组中,然后再开启DMA,然后马上处理复制出来的数据。
建立双缓冲,重新配置DMA_MemoryBaseAddr的缓冲区地址,那么下次接收到的数据就会保存到新的缓冲区中,不至于被覆盖。
举报
更多回帖
rotate(-90deg);
回复
相关问答
stm32f1
串口
控制器
怎样
去
解决
STM32F1
串口
的最高波特率问题
呢
2021-12-14
2342
stm32f1
串口
DMA
接收定长数据总结,错过绝对后悔
2021-12-07
774
怎样
去
使用
STM32F1
的
串口
呢
2021-12-09
1395
怎样
去
判断
STM32F1
串口
接受不定长数据是否完成了
呢
2021-12-09
3997
STM32F1
的USB
串口
该
怎样
去
使用
呢
2021-12-06
1943
STM32F1
串口
如何使用
DMA
实现数据回传?
2021-12-08
866
请问大神
怎样
去
使用
STM32
串口
+
DMA
呢
2021-12-13
655
STM32F
103CBT6
串口
1
是如何利用
DMA
发送接收数据的
呢
2021-12-13
1361
怎样
去
使用
STM32F1
的CAN
控制器
呢
2021-11-01
1535
怎样
去
解决
STM32F
207
串口
有无校验时数据收发的问题
呢
2021-12-10
1017
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分