STM32CubeMX基础例程(小熊派):03.串口收发(DMA+空闲中断)

1、准备开发板

这里我选用了一块网红开发板:”小熊派“,这款板子的人气比较高,还是全国大学生物联网设计竞赛(华为杯)的华为竞赛开发板,我个人也比较喜欢用这款板子,这款板子在放在纸箱吃灰半年之后,被我重新拿了起来,并想借此写博客的机会,整理一下自己的代码。

开发板功能区分布图

在这里插入图片描述

开发板俯视图

在这里插入图片描述

2、STM32CubeMX生成代码

在这里插入图片描述

搜索并选择芯片型号

在这里插入图片描述

配置系统时钟

在这里插入图片描述

配置时钟树

STM32L4的最高主频可达到80M,最后使HCLK = 80Mhz即可:

在这里插入图片描述
在这里插入图片描述

配置串口

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

生成工程设置在这里插入图片描述

代码生成配置

在这里插入图片描述

生成代码

在这里插入图片描述

生成成功

在这里插入图片描述

3、在MDK中编写代码

在usart.h下的用户代码区编写以下代码

/* USER CODE BEGIN Includes */
#if defined ( __CC_ARM  )
#pragma anon_unions
#endif
/* USER CODE END Includes */

/* USER CODE BEGIN Private defines */

#define RX_BUF_MAX_LEN 256		  //最大接收缓存字节数

typedef struct 
{
	
	unsigned short dataLenPre;		//上一次的长度数据,用于比较
	
	union{
		unsigned short InfAll;
		struct 
		{
			unsigned short dataLen : 15;			//接收数据长度
			unsigned short finishFlag : 1;		//接收完成标志
		}InfBit;
	};
	unsigned char rxBuf[RX_BUF_MAX_LEN];			//接收缓存

} USART_INFO_STRUCT;


#define REC_OK		1	//接收完成标志
#define REC_WAIT	0	//接收未完成标志

extern USART_INFO_STRUCT usart1Info;

/* USER CODE END Private defines */

/* USER CODE BEGIN Prototypes */

void USART_Interupt_Enable(void);
void USER_UartDMAHandler(UART_HandleTypeDef* huart,USART_INFO_STRUCT* usartInfo);

/* USER CODE END Prototypes */

在usart.c下的用户代码区编写以下代码

/* USER CODE BEGIN 0 */

#include <stdio.h>

USART_INFO_STRUCT usart1Info;

int fputc(int ch, FILE *stream)
{
    /* 堵塞判断串口是否发送完成 */
    while((USART1->ISR & 0X40) == 0);

    /* 串口发送完成,将该字符发送 */
    USART1->TDR = (uint8_t) ch;

    return ch;
}

/* USER CODE END 0 */

/* USER CODE BEGIN 1 */

void USART_Interupt_Enable(void)
{
	
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);                //空闲中断使能
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE); 							//接收中断使能
	__HAL_UART_CLEAR_IDLEFLAG(&huart1);       //清除串口空闲中断标志位
	
}


void USER_UartDMAHandler(UART_HandleTypeDef* huart,USART_INFO_STRUCT* usartInfo)
{
	uint32_t ucCh;
	if(huart->Instance == USART1)
	{
			if(__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET)  //触发空闲中断
			{
					__HAL_UART_CLEAR_IDLEFLAG(huart);       //清除串口2空闲中断标志位
					HAL_UART_DMAStop(huart);                //关闭DMA
					ucCh = huart->Instance->ISR;              //清除SR状态寄存器
					ucCh = huart->Instance->RDR;              //读取DR数据寄存器     用来清除中断
					ucCh = hdma_usart1_rx.Instance->CNDTR;      //获取DMA中未传输的数据个数
					usartInfo->InfBit.dataLen = RX_BUF_MAX_LEN - ucCh;           //总计数减去未传输的数据个数,得到已经接收的数据个数
					usartInfo->InfBit.finishFlag = REC_OK;			//标志接收成功
			}
	}
		
	HAL_UART_Receive_DMA(huart,usartInfo->rxBuf,RX_BUF_MAX_LEN);  //使能DMA接收到buf1
	
}


/* USER CODE END 1 */


在stm32l4xx_it.c中的USART1_IRQHandler函数的用户代码区编写以下代码

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
  USER_UartDMAHandler(&huart1,&usart1Info);	//用户中断代码
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

在main.c下的main函数下的用户代码区编写以下代码

/* USER CODE BEGIN 2 */
  USART_Interupt_Enable();	//使能串口接收中断和空闲中断
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	 if(usart1Info.InfBit.finishFlag == REC_OK)		//如果接收成功
		{
				usart1Info.rxBuf[usart1Info.InfBit.dataLen++] = '\0';	//在数组最后添加\0,这样可以截断字符串
				printf("usart1Info.rxBuf:%s\r\n",usart1Info.rxBuf);		//打印字符串
				usart1Info.InfBit.finishFlag = REC_WAIT;				//将标志位设置成等待接收状态
				usart1Info.InfBit.dataLen = 0;							//将接收的数据长度设置为0
		}

  }
  /* USER CODE END 3 */

4、配置烧录器

在这里插入图片描述
在这里插入图片描述

5、烧录代码

在这里插入图片描述

6、实验现象

串口助手向单片机发送数据,单片机会将接收到的数据再发送到串口助手
在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值