基于STM32G0,使用DMA方式,实现串口接收不定长的数据
目录
- 基于STM32G0,使用DMA方式,实现串口接收不定长的数据
- 1.图形化操作
- 1.1.配置串口基本参数
- 1.2.增加发送和接收DMA
- 1.3.开启中断
- 1.4.配置时钟树
- 1.5.生成代码
- 2.用户代码
- 2.1.usart修改
- 2.2.修改串口中断函数
- 3.结果测试
- 4.实验结果
优质博文,求个赞不过分吧。
单片只因图镇贴!
1.图形化操作
1.1.配置串口基本参数
使能串口,异步模式,参数:115200,8,None,1。io为默认引脚。
1.2.增加发送和接收DMA
点击ADD
1.3.开启中断
NVIC中勾选使能中断
1.4.配置时钟树
g0支持64m。
1.5.生成代码
勾选生成独立的.c和h文件
点击生成代码
2.用户代码
2.1.usart修改
注意: 用户一定要放置在CUBE IDE生成的代码,指定注释的下面。如:/* USER CODE END 0 */
usart.c如下位置定义变量。
代码:
volatile uint8_t USART1_RX_LEN = 0; // 接收一帧数据的长度
volatile uint8_t USART1_RECV_CPLT_FLAG = 0; // 一帧数据接收完成标志
uint8_t USART1_RX_BUF[USART1_RX_BUF_SIZE]={0}; // 接收数据缓冲区
在MX_USART1_UART_Init函数的末尾,写入如下代码。
代码:
/* 使能空闲中断 */
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart1,USART1_RX_BUF,USART1_RX_BUF_SIZE);
usart.h 修改如下
代码如下:
包括头文件
#include "stdio.h"
声明
#define USART1_RX_BUF_SIZE 512
extern volatile uint8_t USART1_RX_LEN; // 接收一帧数据的长度
extern volatile uint8_t USART1_RECV_CPLT_FLAG; // 一帧数据接收完成标志
extern uint8_t USART1_RX_BUF[USART1_RX_BUF_SIZE]; // 接收数据缓冲区
2.2.修改串口中断函数
stm32g0xx_it.c文件中先添加头文件
#include "usart.h"
然后,USART1_IRQHandler函数修改如下:
代码:
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
uint32_t tmp_flag = 0;
uint32_t temp;
/* USER CODE END USART1_IRQn 0dr&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
if(USART1 == huart1.Instance)
{
tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
if((tmp_flag != RESET))//idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
HAL_UART_DMAStop(&huart1);
temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数
USART1_RX_LEN = USART1_RX_BUF_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
USART1_RECV_CPLT_FLAG = USART1_RX_LEN?1:0; // 如果接收到数据,设置完成标志
HAL_UART_Receive_DMA(&huart1,USART1_RX_BUF,USART1_RX_BUF_SIZE);//重新打开DMA接收
}
}
/* USER CODE END USART1_IRQn 1 */
}
3.结果测试
main.c包括头文件:
#include <string.h>
main.c串口printf重定向
代码:
#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART3 and Loop until the end of transmission */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
main函数的while(1)测试代码如下:
/* USER CODE BEGIN WHILE */
printf("hello world\r\n");
while (1)
{
if(USART1_RECV_CPLT_FLAG ==1)
{
printf("rx_len=%d\r\n",USART1_RX_LEN);//打印接收长度
HAL_UART_Transmit(&huart1,USART1_RX_BUF, USART1_RX_LEN,200);//接收数据打印出来
// 清除数据
memset(USART1_RX_BUF,0,USART1_RX_BUF_SIZE);
USART1_RX_LEN=0;//清除计数
USART1_RECV_CPLT_FLAG=0;//清除接收结束标志位
}
HAL_UART_Receive_DMA(&huart1,USART1_RX_BUF,USART1_RX_BUF_SIZE);//重新打开DMA接收
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
烧录程序:
4.实验结果
打开串口工具。单片机复位上电后,先打印hello world
发送hi,显示如下
因为勾选了发送新行所以,len会加上回车换行这俩个字符。
到此实验结束。
如果没有数据,请检查串口连接及串口重定向。
用爱发电,真的很详细了。