STM32L431RC(小熊派)使用HAL库和串口的空闲中断实现数据的整帧传输

初衷

因为学习的需要,需要使用LPUART串口实现数据的整帧传输,所以在网上找了很多的教程,都没有解决我的问题,大家使用的基本上都是DMA传输加空闲中断的方式实现整帧的传输,我跟着很多帖子做了实验,但是均未成功,后来直接使用串口的空闲中断不使用DMA也完成了数据的整帧传输,记录下来,用以复习。

代码思路

在这里插入图片描述

STM32CubeMX中的设置

串口使用了UART1和LPUART1,时钟使用了高速外部时钟和低速外部时钟

在这里插入图片描述

串口设置

串口1设置
在这里插入图片描述
LPUART1设置(此串口与我的NB模块相连接,实现AT指令的发送和模块回传数据的接收)
在这里插入图片描述
使能两个串口的中断
在这里插入图片描述
在这里插入图片描述

时钟频率的设置(重点是LPUART的时钟频率是32.768KHZ)

在这里插入图片描述
之后生成MDK5工程

MDK5中的代码

stm32l4xx_it.c

声明变量
#ifndef MAX_RCV_LEN
	#define MAX_RCV_LEN 1024
#endif
extern uint8_t LPUART1RECV[MAX_RCV_LEN];
extern void USART_IDLECallBack(void);
extern void LPUART_IDLECallBack(void);
在下面的代码中判断是否发生了空闲中断
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET)//判断此中断是否为空闲中断
	{		
		USART_IDLECallBack();//进入空闲中断处理函数,此函数我定义在main.c中
	}
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
	
  /* USER CODE END USART1_IRQn 1 */
}
void LPUART1_IRQHandler(void)
{
  /* USER CODE BEGIN LPUART1_IRQn 0 */
	if(__HAL_UART_GET_FLAG(&hlpuart1,UART_FLAG_IDLE)!=RESET)//判断此中断是否为空闲中断
	{		
		LPUART_IDLECallBack();//进入空闲中断处理函数,此函数我定义在main.c中		
	}
  /* USER CODE END LPUART1_IRQn 0 */
  HAL_UART_IRQHandler(&hlpuart1);
  /* USER CODE BEGIN LPUART1_IRQn 1 */

  /* USER CODE END LPUART1_IRQn 1 */
}

usart.c

声明变量
extern uint8_t Buftemp;
extern uint8_t Buftemp2;
在串口初始化的时候对串口使能第一次中断,就省下了在main.c中进行使能
void MX_LPUART1_UART_Init(void)
{

  hlpuart1.Instance = LPUART1;
  hlpuart1.Init.BaudRate = 9600;
  hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
  hlpuart1.Init.StopBits = UART_STOPBITS_1;
  hlpuart1.Init.Parity = UART_PARITY_NONE;
  hlpuart1.Init.Mode = UART_MODE_TX_RX;
  hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&hlpuart1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
	HAL_UART_Receive_IT(&hlpuart1,&Buftemp,1);//使能第一次中断
}
void MX_USART1_UART_Init(void)
{

  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;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
	HAL_UART_Receive_IT(&huart1,&Buftemp2,1);//使能第一次中断

}

main.c

声明变量
#define MAX_RCV_LEN 1024
uint8_t data[MAX_RCV_LEN];
uint8_t endflag=0;
uint8_t Buftemp;
uint8_t Buftemp2;
uint16_t lpuart1_recv_len=0;
uint16_t uart1_recv_len=0;
uint8_t data2[MAX_RCV_LEN];
uint8_t LPUART1RECV[MAX_RCV_LEN];
void USART_IDLECallBack(void);
void LPUART_IDLECallBack(void);
while循环
  while (1)
  {
		HAL_Delay(10000);
		HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
		uint8_t temp[]={"AT+NATSPEED?\r\n"};//NB模块的AT命令
		int len=sizeof(temp);
		HAL_UART_Transmit(&hlpuart1,temp,len,0xff);//通过LPUART1发送命令到NB模块
		HAL_UART_Receive_IT(&hlpuart1,&Buftemp,1);//避免LPUART串口在使用HAL_UART_Transmit函数后出现问题,再次使能中断接收
		
		HAL_Delay(10000);
		HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
		uint8_t temp1[]={"AT+CGATT?\r\n"};
		int len1=sizeof(temp1);
		HAL_UART_Transmit(&hlpuart1,temp1,len1,0xff);//通过LPUART1发送命令到NB模块
		HAL_UART_Receive_IT(&hlpuart1,&Buftemp,1);//避免LPUART串口在使用HAL_UART_Transmit函数后出现问题,再次使能中断接收
	}
其他函数定义在main.c最后
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
		//只有第一次中断会调用
		if(uart1_recv_len==0)
		{
			__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//使能空闲中断
		}
		data2[uart1_recv_len++]=Buftemp2;
		HAL_UART_Receive_IT(&huart1,&Buftemp2,1);
	}
	if(huart->Instance==LPUART1)
	{
		//只有第一次中断会调用
		if(lpuart1_recv_len==0)
		{
			__HAL_UART_ENABLE_IT(&hlpuart1,UART_IT_IDLE);//使能空闲中断
		}
		data[lpuart1_recv_len++]=Buftemp;
		HAL_UART_Receive_IT(&hlpuart1,&Buftemp,1);
		
	}
}
void LPUART_IDLECallBack()
{
	unsigned int temp;
  __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);//清除标志位
  temp = LPUART1->RDR;  //清除状态寄存器RDR
	temp = temp;
	HAL_UART_Transmit(&huart1,data,lpuart1_recv_len,0xff);
	memset(data,0,MAX_RCV_LEN);
	lpuart1_recv_len=0;
}

void USART_IDLECallBack()
{
	unsigned int temp;
  __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
  temp = USART1->RDR;  //清除状态寄存器RDR
	temp = temp;
	HAL_UART_Transmit(&hlpuart1,data2,uart1_recv_len,0xff);
	HAL_UART_Receive_IT(&hlpuart1,&Buftemp,1);
	memset(data2,0,MAX_RCV_LEN);
	uart1_recv_len=0;
}

实验成功截图

因为放上来的代码删除了无用的printf函数所以有些区别

在这里插入图片描述

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

渐寒去玩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值