【嵌入式知识10】分别采用串口中断方式和串口DMA方式进行串口通信
本文学习使用串口中断方式和串口DMA方式进行串口通信,用115200bps或更高速率向上位机连续发送数据。
一、串口通信概述
1.通信方式
同步串行:数据传输以数据块(一组字符)为单位,在一个数据块内,字符与字符间无间隔,收发双方依靠独立的时钟线进行信号的同步。适用于大批量的数据传输。
异步串行:数据传输以单个字符为单位,字符和字符之间的间隙任意,字符内部每一位持续的时间相同。收发双方没有专门的时钟信号,而是依靠事先约定的字符格式和通信速率来完成通信。
2.异步串行通信的字符格式
常用字符格式: 1位起始位+8位数据位+无奇偶校验+1位停止位

3.通信速率
**波特率:**每秒钟传送二进制数码的位数,以==bit/s(bps)==为单位。
- 常用的波特率有:9600、19200、38400、57600和115200;
- 波特率为115200,表示每秒传输115200位,且每一位数据在数据线上持续时间为Tbit= 1/115200 = 8.68us。
4.串口通信工作方式
三种工作方式:
- 轮询方式
- 中断方式
- DMA方式

二、串口中断通信
1.串口中断方式的特点
- 发送数据时,将一字节数据放入数据寄存器DR;接收数据时,将DR的内容存放到用户存储区;
- 中断方式不必等待数据的传输过程,只需要在每字节数据收发完成后,由中断标志位触发中断,在中断服务程序中放入新的一字数据或者读取接收到 的一字节数据;
- 在传输数据量较大,且通信波特率较高(大于38400)时,如果采用中断方式,每收发一个字节的数据,CPU都会被打断,造成CPU无法处理其他事务。因此在批量数据传输,通信波特率较高时,建议采用DMA方式。
2.串口发送/接收函数
- HAL_UART_Transmit();串口发送数据,使用超时管理机制
- HAL_UART_Receive();串口接收数据,使用超时管理机制
- HAL_UART_Transmit_IT();串口中断模式发送
- HAL_UART_Receive_IT();串口中断模式接收
- HAL_UART_Transmit_DMA();串口DMA模式发送
- HAL_UART_Transmit_DMA();串口DMA模式接收
串口发送数据:
HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
参数:
- UART_HandleTypeDef *huart UATR的别名 如 : UART_HandleTypeDef huart1;
- *pData 需要发送的数据
- Size 发送的字节数
- Timeout 最大发送时间,发送数据超过该时间退出发送
3.串口中断函数
- HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //串口中断处理函数
- HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //串口发送中断回调函数
- HAL_UART_RxCpltCallback(UART_HandleTypeDef
*huart); //串口接收中断回调函数- HAL_UART_ErrorCallback();串口接收错误函数
串口接收中断回调函数:
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
参数:
- UART_HandleTypeDef *huart UATR的别名
- 如 : UART_HandleTypeDef huart1;别名就是huart1
串口中断处理函数:
HAL_UART_IRQHandler(UART_HandleTypeDef *huart);
功能:对接收到的数据进行判断和处理 判断是发送中断还是接收中断,然后进行数据的发送和接收,在中断服务函数中使用,如果接收数据,则会进行接收中断处理函数。
三、中断方式的串口通信
1.实验要求
实现以下功能:
1)当stm32接收到字符“s”时,停止持续发送“hello windows!”; 当接收到字符“t”时,持续发送“hello windows!”。
2)当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”。
2.CubeMX初始配置
1.RCC时钟配置
设置高速外部时钟HSE,选择外部时钟源

2.USART1配置使能
注意:选择异步通信模式

3.串口中断使能

配置好之后,导出文件。
3.串口中断通信程序编写
相关标志位及发送接收字符串变量的定义
uint8_t RX_str; //串口接收变量
uint8_t flag=0; //串口发送的全局标志位
uint8_t Uart1_TXBuff[]="hello windows!\r\n";
uint8_t STOP[]="stop stm32!";
uint8_t START[]="go stm32!";
USART1初始化配置函数
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
main函数
在main函数中写入下列程序,将目标字符串发送至PC端的上位机,while语句中,满足条件则发送“hello windows!"
HAL_UART_Receive_IT(&huart1, (uint8_t *)&RX_str, 1); //打开串口接收中断
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
if(flag==0)
{
HAL_UART_Transmit(&huart1, (uint8_t*)Uart1_TXBuff, sizeof(Uart1_TXBuff), 100); //发送"hello windows!"
}
HAL_Delay(500);
/* USER CODE BEGIN 3 */
}
串口中断服务函数
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1); //串口接收中断服务函数入口
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
回调函数
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(RX_str=='s'||RX_str==*STOP)
{
flag=1;
}
else if(RX_str =='t'||RX_str==*START)
{
flag=0;
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&RX_str, 1); //重新打开串口接收中断
}
/* USER CODE END 4 */
四、使用串口通信助手进行串口通信
实现功能
1)当stm32接收到字符“s”时,停止持续发送“hello windows!”; 当接收到字符“t”时,持续发送“hello windows!”
2)当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”

采用串口中断方式的串口通信成功。
五、DMA概述
1.直接存储访器问(DMA)的基本概念
用于在外设与存储器之间以及存储器与存储器之间进行高速数据传输。DMA传输过程的初始化和启动由CPU完成,传输过程由DMA控制器来执行,无需CPU参与,从而节省CPU资源,提高利用率。

DMA数据传输方式
| 普通模式 | 循环模式 |
|---|---|
| 传输结束后(即要传输数据的数量达到零),将不再产生DMA操作。若开始新的DMA传输,需在关闭DMA通道情况下,重新启动DMA传输。 | 可用于处理环形缓冲区和连续数据流(例如ADC扫描模式)。当激活循环模式后,每轮传输结束时,要传输的数据数量将自动用设置的初始值进行加载, 并继续响应DMA请求。 |
DMA数据传输的四个要素:
- 传输源:DMA数据传输的来源
- 传输目标:DMA数据传输的目的
- 传输数量:DMA传输数据的数量
- 触发信号:启动一次DMA数据传输的动作
DMA框图

2.DMA方式的接口函数
1.串口DMA方式发送函数:HAL_UART_Transmit_DMA

2.串口DMA方式接收函数:HAL_UART_Receive_DMA

3.获取未传输数据个数函数:_HAL_DMA_GET_COUNTER(HANDLE)

3.DMA方式串口通信的CubeMX配置初始化
实验目的
STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据。
RCC时钟配置

USART1配置

使能中断

DMA设置
点击DMA Settings的Add添加通道,传输速率设置为中速Medium,模式设置为Normal,勾选Memory

点击System Core下的DMA,添加MEMTOMEN,

时钟树配置

六、程序编写
1.main.c文件中编写
uint8_t Senbuff[] = "Hello world!"; //定义数据发送数组

2.while语句中编写
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
HAL_Delay(1000);

七、使用串口助手进行DMA串口通信
连接好电路后,将代码下载到C8T6中,打开串口助手,选择好串口:COM4和波特率115200后,打开串口。

八、总结
本文主要学习了采用串口中断方式和串口DMA方式进行串口通信,通过本次实验,我实实在在地学会了不同的串口通信方法,对串口通信知识也有了进一步的认识。
串口中断方式在触发中断时才转到处理中断函数,这毫无疑问提高了芯片运算效率;但DMA传输过程不占用CPU资源,可以在DMA串口通信的同时,执行其他的任务,这也更加的高效。
九、参考资料
https://blog.csdn.net/qq_46467126/article/details/121076618?spm=1001.2014.3001.5502
https://blog.csdn.net/as480133937/article/details/104827639/
https://blog.csdn.net/qq_52791446/article/details/127449558?spm=1001.2014.3001.5502
更多推荐




所有评论(0)