CH5-IDLE

IDLE原理

在使用串口接受字符串时,可以使用空闲中断(IDLEIE置1,即可使能空闲中断),这样在接收完一个字符串,进入空闲状态时(IDLE置1)便会激发一个空闲中断。在中断处理函数,我们可以解析这个字符串。

接受完一帧数据,触发中断

STM32的IDLE的中断产生条件:
在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断

CubeMX配置

image-20240331235446386
下载线配置
image-20240401000353599
RTC配置
image-20240401000547320
USART配置
image-20240401010952869
USART DMA配置
image-20240401000843198
USER按键中断配置
image-20240401001127070
NVIC配置
image-20240401001317678
时钟树配置

MDK程序编写

function.c

fputc函数

1
2
3
4
5
6
7
8
int fputc(int ch,FILE *f)
{
extern UART_HandleTypeDef huart2;
HAL_UART_Transmit(&huart2,(const uint8_t *)&ch,1,0xffff);
while(__HAL_UART_GET_IT(&huart2,UART_IT_TC){};

return ch;
}

串口接收函数组

流程
image-20240401021434982
接收流程图

1.初始化:打开IDLE中断打开DMA接收,当MCU通过USART接收外部发来的数据时,在进行第①②③步的时候,DMA直接将接收到的数据写入缓存rx_buffer[100] //接收数据缓存数组,程序此时也不会进入接收中断,在软件上无需做任何事情,要在初始化配置的时候设置好配置就可以了。

2.中断处理:当数据接收完成之后产生接收空闲中断④ 在中断服务函数中做这几件事:

  • 判断是否为IDLE接受空闲中断
  • 在中断服务函数中将接收完成标志位置1
  • 关闭DMA防止在处理数据时候接收数据,产生干扰。
  • 计算出接收缓存中的数据长度,清除中断位,

3.接收处理函数(放入while循环中,主程序)

  • 主程序中检测到接收完成标志被置1
  • 进入数据处理程序,现将接收完成标志位置0,将接收到的数据长度清零
  • 根据要求自定义函数
  • 重新设置DMA下次要接收的数据字节数,使能DMA进入接收数据状态。

定义接收变量

1
2
3
4
5
6
7
#define Usart_RX_len 100 //宏定义一个允许串口接收的最大数据个数
unsigned char Usart_RX_sec_flag;//定义了一帧串口接收完成的标志位
unsigned char Usart_RX_sec_len;//定义了一帧串口接收数据的实际个数
unsigned char Usart_RX_mess[Usart_RX_len];//定义了用于存储接收到的数据的一个数组

extern UART_HandleTypeDef huart2;//外部调用串口的结构体
extern DMA_HandleTypeDef hdma_usart2_rx;//外部调用串口DMA的结构体

初始化函数

1
2
3
4
5
6
void USART_RX_IDLE_Init(void)
{
__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);//使能IDLE的接收中断
HAL_UART_Receive_DMA(&huart2,Usart_RX_mess,Usart_RX_len);//打开DMA串口接收函数,第一个变量为串口2结构体,第二
//个变量为接收的存储数组,第三个为接收数据的大小
}

IDLE中断函数

==注:1.需要将USART_RX_IDLE_EXTI()放进stm32l0xx_it.c中的void USART2_IRQHandler(void)中==

==2.中断一定是UART_FLAG_IDLE==

1
2
3
4
5
6
7
8
9
10
11
void USART_RX_IDLE_EXTI(void)
{
if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE)==SET)//判断IDLE的接收是否产生中断,如果接收到一帧数据,那么就会触发中断,FLAG被置1
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除中断标志位
HAL_UART_DMAStop(&huart2);//关闭DMA防止在处理数据时候接收数据,产生干扰

Usart_RX_sec_flag=1;//将检测接收完成的标志位置1
Usart_RX_sec_len=Usart_RX_len-__HAL_DMA_GET_COUNTER(&hdma_usart2_rx);//计算出接收缓存中的数据长度
}
}

接收处理函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void USART_RX_IDLE_DEAL(void)
{
if(Usart_RX_sec_flag==1)//判断接收完成标志位是否置1
{

if((Usart_RX_mess[0]=='L') && (Usart_RX_mess[1]=='E') && (Usart_RX_mess[2]=='D'))//用户自定义的函数,在这里我们可以根据需要,设置我们输入特定指令所触发的功能
{
HAL_UART_Transmit_DMA(&huart2,Usart_RX_mess,Usart_RX_sec_len);//
}

Usart_RX_sec_flag=0;//将接收完成标志位置0
Usart_RX_sec_len=0;//将接收到的数据清零
HAL_UART_Receive_DMA(&huart2,Usart_RX_mess,Usart_RX_len);//重新设置DMA下次要接收的数据字节数,使能DMA进入接收数据状态
}
}