stm32 文件系统dma大小_请教DMA缓冲区大小修改

STM32的UART在使用DMA接收数据时,若数据长度不固定,可通过结合定时器复位模式实现动态调整接收长度。通过设置定时器为复位模式,监测UART接收中断,当数据帧结束时,定时器超时中断提供数据长度信息,从而实现灵活的串口通信。
摘要由CSDN通过智能技术生成

好像是在运行中更改可能不好实现,串口通信是经常使用到的功能,在STM32中UART具有DMA功能,并且收发都可以使用DMA,使用DMA发送基本上大家不会遇到什么问题,因为发送的时候会告知DMA发送的数据长度,DMA按照发送的长度直接发送就OK了,但是使用DMA接收时候就不同了,因为有时候数据接收并不是每一次都是定长的,但是DMA只在接收数据长度和设定数据长度相同的时候才可以触发中断,告诉MCU数据接收完毕,针对这个问题,解决方法如下,有一点复杂,但是很管用。首先要了解一下串口数据传输格式,UART在传输一个字节的时候,首先拉低,传输起始位,然后在是LSB –MSB,最后是停止位,停止位是高电平。

2、        超时时间

搞过串口通信的都知道,如果串口有协议,一般都是有个超时时间的,超时时间是定义两个帧之间的间隔的,如果串口接收到一个字节后,在规定的超时时间内没有接收到其他数据,我们则认为前面接收的数据位一帧。

3、        定时器复位复位模式

STM32定时器功能比较强大,其中有一种模式为复位模式,

整体的思路是这样的,一开始设置好DMA接收,可以把缓冲区长度设置为帧最大长度,我们可以把RX连接到定时器的管脚输入端,并且一开始设置输入并且使能引脚下降沿中断,当帧的第一个字节发送时,因为起始位为低电平,空闲时UART为高电平,满足条件,进入中断,禁止中断,并且在中断中开启定时器,该定时器工作在复位模式,上升沿复位,并且设置好定时器输出比较值为超时时间,比如20ms,这样,在传输后面字节时,肯定会有高低电平出现,即便是传输的是0x00,0xFF,虽然UART数据区不变,但是都为1,或都为0,但是因为起始位为低电平,停止位是高电平,所以肯定会有上升沿,定时器会一直复位,输出定时器的计数器一直到达不了输出比较值,当一帧传输结束后,定时在最后一个字节复位后,由于没有数据继续到达,无法复位,则计数器就能计到输出比较值,这时发出中断,在定时器中断中可以计算出接收数据的长度,并且通知外部数据已经接收完毕。

4、        功能实现

实现的步骤:

1、硬件连接:UART的RX线在连接外部的同时,还需要连接到一个定时器的输入端TIMx_CHx,定时器可以为任意定时器,但是CHx,只能为CH1或CH2,具体的需要看STM32的定时器逻辑图,以STM32F101CB为例

STM32中,DMA的双缓冲模式可以通过配置DMA的通道控制寄存器来实现。下面是一个示例代码,可以帮助你理解如何使用STM32DMA双缓冲模式。 首先,需要定义两个缓冲区,用于DMA的读写操作。在本示例中,我们假设缓冲区大小为16字节。 ```c #define BUFFER_SIZE 16 uint8_t buffer1[BUFFER_SIZE]; uint8_t buffer2[BUFFER_SIZE]; ``` 然后,需要配置DMA通道的控制寄存器。在本示例中,我们使用DMA1通道1,并启用双缓冲模式。 ```c DMA_HandleTypeDef hdma; hdma.Instance = DMA1_Channel1; hdma.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma.Init.PeriphInc = DMA_PINC_DISABLE; hdma.Init.MemInc = DMA_MINC_ENABLE; hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma.Init.Mode = DMA_CIRCULAR; hdma.Init.Priority = DMA_PRIORITY_HIGH; hdma.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma.Init.MemBurst = DMA_MBURST_SINGLE; hdma.Init.PeriphBurst = DMA_PBURST_SINGLE; HAL_DMA_Init(&hdma); __HAL_DMA_DISABLE(&hdma); hdma.Instance->CR |= DMA_SxCR_DBM; ``` 接下来,需要启动DMA传输。 ```c HAL_DMA_Start(&hdma, (uint32_t)&peripheral_device, (uint32_t)buffer1, BUFFER_SIZE); ``` 在DMA传输期间,当缓冲区1已经被填满时,DMA会自动切换到缓冲区2进行数据传输。当缓冲区2也被填满时,DMA会再次切换回缓冲区1。 当需要读取DMA传输的数据时,可以通过检查DMA传输期间使用的缓冲区来获取传输的数据。 ```c uint8_t* buffer = (hdma.Instance->CR & DMA_SxCR_CT) ? buffer2 : buffer1; ``` 最后,在传输完成后,需要停止DMA传输并释放DMA通道。 ```c HAL_DMA_Stop(&hdma); HAL_DMA_DeInit(&hdma); ``` 以上就是一个基本的DMA双缓冲模式的示例代码。需要注意的是,在使用DMA双缓冲模式时,需要保证缓冲区大小足够大,以避免数据溢出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值