初衷
因为学习的需要,需要使用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?rn"};//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?rn"};
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函数所以有些区别
初衷
因为学习的需要,需要使用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?rn"};//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?rn"};
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函数所以有些区别
举报