文章目录
- DMA简介
- STM32的DMA
- DMA中断
- 全局中断
- 使用串口DMA发送数据(实验1)
- Cube设置
- 代码修改
- 空闲中断
- 串口通讯协议的数据包
- 使用串口空闲中断接收数据(实验2)
- 编写代码
- 参考资料
DMA简介
- Direct Memony Access,直接内存访问
- 可以不经过CPU,直接将某一地址的数据复制到另一地址
- 节省CPU时间
- DMA实质上相当于不经过CPU自动完成* p1=* p2
STM32的DMA
- STM32具有数个DMA,每个DMA具有多个通道
- 同一时间每个DMA只能有一个通道在复制数据
- 类似中断,DMA的通道之间也有优先级的设置
- 每个通道可以在外设和内存之间交换数据,或者内存和内存之间交换数据
- DMA的传输可以由其他外设触发或由软件触发
- 每次传输之后,内存的地址可以自动+1
DMA中断
- 当DMA传输完成或传输错误时可以产生中断
- HAL库会自动启动并处理DMA中断,无需自行配置
全局中断
- 点开 USART3 的设置页面,打开DMA Settings 的标签页,点击 Add,于select处选择USART3_RX,将优先级(priority)配置为非常高,再将mode配置为循环模式(circular)
最后最后开启USART3的全局中断
使用串口DMA发送数据(实验1)
-
UART1使用DMA发送数据
-
UART6使用中断接收数据
Cube设置
在之前串口实验基础上打开Cube,在Connectivity的USART1中的DMA Settings中
添加一个DMA Request,选择TX
然后就很之前设置一样,生成代码
代码修改
把代码中的HAL_UART_Transmit_IT改为HAL_UART_Transmit_DMA即可
空闲中断
- 串口处于空闲状态,即连续一个字节的时间RX处于高电平触发
- 可以使用空闲中断配合DMA接收不定长的数据
串口通讯协议的数据包
- 串口是一种接口,在这个接口是可以实现通讯协议
- 常见的串口通信协议的一个数据包一般可以包含以下部分
- 一个固定值起始字节
- 接收方地址(仅用于大于2个设备时)
- 数据量
- 实际数据
- 校验字节(例如CRC8检验)
- 一个固定值结束字节
- 有时数据量是不确定的,需要接收方进行处理
- 如果数据包没有结束字节和数据量字节,一般需要利用空闲中断
- 一般使用空闲中断接收数据
使用串口空闲中断接收数据(实验2)
- UART1使用DMA发送不定长的数据
- UART6使用DMA接收数据
- 接收使用空闲中断函数
- 添加UART6的DMA
编写代码
首先,编写一个不定长的数据,把txDataBuffer和rxDataBuffer的容量扩大,把4改为10
同时定义两个uint8_t类型的数据长度
/* USER CODE BEGIN PV */
uint8_t txDataBuffer[10],rxDataBuffer[10];//unsign char类型
uint32_t rxDate;//unsign int类型
uint8_t txDatelen,rxDatelen;//长度为一个字节,使用uint8_t类型
/* USER CODE END PV */
这里我们可以引入随机数来定义这个数据的长度或者使用一个循环队列来生成这个不定长数据
在STM32Cube中也可以在Security的RNG中进行勾选来产生一个硬件随机数
这里我们使用循环队列来生成随机数,更改原来的回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==GPIO_PIN_0)
{
uint32_t temp =HAL_GetTick();
*((uint32_t*)txDataBuffer) = temp;
//循环队列来使数据长度变化(不定长数据)
txDatelen++;//数据长度进行递增
if(txDatelen==5)
{
txDatelen =0;
}//即数据长度从1~4进行变化
while(huart1.gState !=HAL_UART_STATE_READY);//保护数据程序
HAL_UART_Transmit_DMA(&huart1,txDataBuffer,txDatelen +4);//使用DMA通道
}
}
然后把我们之前写的接收函数注释掉
/* USER CODE BEGIN 2 */
//HAL_UART_Receive_IT(&huart6,txDataBuffer,sizeof(rxDataBuffer));
/* USER CODE END 2 */
然后调用一个UARTEx函数
/* USER CODE BEGIN 2 */
//HAL_UART_Receive_IT(&huart6,txDataBuffer,sizeof(rxDataBuffer));
HAL_UARTEx_ReceiveToIdle_DMA(&huart6,rxDataBuffer,sizeof(rxDataBuffer));//串口6的DMA通道的接收函数
/* USER CODE END 2 */
把原来接收的回调函数注释掉
然后编写UARTEx的回调函数
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef*huart,uint16_t size)
{
if(huart == &huart6)
{
rxDate =*((uint32_t*)rxDataBuffer);
rxDatelen=size;
HAL_UARTEx_ReceiveToIdle_DMA(&huart6,rxDataBuffer,sizeof(rxDataBuffer));//进行重复调用接收函数
}
};
然后编译烧录。
本文介绍了STM32的DMA技术,如何通过DMA实现串口发送和接收数据,并详细讲解了如何配置CubeMX以及编写相关代码。实验中,使用串口DMA发送不定长数据,并通过空闲中断接收,确保了数据包的完整性和效率。
270

被折叠的 条评论
为什么被折叠?



