STM32F103ZET6【标准库函数开发】------正点原子串口中断服务函数简介

一、首先上代码,正点原子的串口中断服务函数如下

#define USART_REC_LEN  	200  	//定义最大接收字节数 200
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
u16 USART_RX_STA=0;       //接收状态标记	
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
void USART1_IRQHandler(void)//串口1中断服务程序
{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
        } 
} 

可以看到代码后面虽然都有注释,但是初看起来还是比较绕的,下面对其运行逻辑简单介绍下。
一、0d0a是什么意思,以及由来
我们打开原子给的串口调试助手,勾选“发送新行”,然后点击发送,如下图可以看到TX:0D0A,所以0d0a代表的是回车和换行。串口调试助手发送的数据不分大小写。
在这里插入图片描述
二、USART_RX_STA代表的意思
USART_RX_STA是定义的一个16位接收状态寄存器,其结构如下:

bit15tin14bit13-0
接收完成标志接受到了0x0d接收到的有效数据个数

所以可以通过读USART_RX_STA来判断数据是否发送完全,以及数据有多少个

三、USART_RX_BUF和USART_REC_LEN
USART_RX_BUF[]表示的是缓存数据
USART_REC_LEN表示最大缓存数据个数

四、串口接收数据步骤,假如接受到的数据是0x11 0x22 0x33
首先进入串口中断,数据是一个一个读取的,第一个数据0x11来了

Res =USART_ReceiveData(USART1);	//读取接收到的数据

此时Res =0x11USART_RX_STA=0
然后进行第一个判断,USART_RX_STA&0x4000等效于0000 0000 0000 0000&0x0100 0000 0000 0000等效于0,所以应该执行下图中的oooo语句

if(USART_RX_STA&0x4000)//接收到了0x0d
	{
	xxxx
	}
else //还没收到0X0D
	{	
	oooo
	}		 

然后进行第二个判断,从上面的分析可知,Res ==0x11,所以要执行else里面的语句,首先USART_RX_STA&0X3FFF等效于0000 0000 0000 0000&0011 1111 1111 1111等效于0,即USART_RX_BUF[0]=Res,即USART_RX_BUF[0]=0x11
至此我们将第一个数据0x11保存至数组USART_RX_BUF[0]中

if(Res==0x0d)	USART_RX_STA|=0x4000;
else
	{
		USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
		USART_RX_STA++;
		if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
	}		 
}		 

然后执行USART_RX_STA++,即USART_RX_STA变为0+11。然后执行最后一个判断if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;,由于,USART_REC_LEN-1等效于(200-1)为199,而USART_RX_STA==1,所以这个判断为假,后面的USART_RX_STA=不会执行。
至此串口中断服务函数执行完毕,其实只执行了下图框框里面的函数。
Res==0x11
USART_RX_BUF[0]==0x11
USART_RX_STA==1
在这里插入图片描述
—————————————————————————————
然后第二个数据0x22来了,Res =0x22USART_RX_STA=1,然后进行第一个判断,USART_RX_STA&0x4000等效于0000 0000 0000 0001&0x0100 0000 0000 0000等效于0,所以应该执行下图中的oooo语句

if(USART_RX_STA&0x4000)//接收到了0x0d
	{
	xxxx
	}
else //还没收到0X0D
	{	
	oooo
	}		 

然后进行第二个判断,从上面的分析可知,Res ==0x22,所以要执行else里面的语句,首先USART_RX_STA&0X3FFF等效于0000 0000 0000 0001&0011 1111 1111 1111等效于1,即USART_RX_BUF[1]=Res,即USART_RX_BUF[1]=0x22
至此我们将第二个数据0x22保存至数组USART_RX_BUF[1]中

if(Res==0x0d)	USART_RX_STA|=0x4000;
else
	{
		USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
		USART_RX_STA++;
		if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
	}		 
}		 

然后执行USART_RX_STA++,即USART_RX_STA变为1+12。然后执行最后一个判断if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;,由于,USART_REC_LEN-1等效于(200-1)为199,而USART_RX_STA==2,所以这个判断为假,后面的USART_RX_STA=不会执行。
至此串口中断服务函数执行完毕,其实只执行了下图框框里面的函数。
在这里插入图片描述
Res==0x22--------有变化
USART_RX_BUF[1]==0x22--------有变化
USART_RX_STA==2--------有变化
—————————————————————————————
然后第三个数据0x33来了,Res =0x33USART_RX_STA=2,然后进行第一个判断,USART_RX_STA&0x4000等效于0000 0000 0000 0010&0x0100 0000 0000 0000等效于0,所以应该执行下图中的oooo语句

if(USART_RX_STA&0x4000)//接收到了0x0d
	{
	xxxx
	}
else //还没收到0X0D
	{	
	oooo
	}		 

然后进行第二个判断,从上面的分析可知,Res ==0x33,所以要执行else里面的语句,首先USART_RX_STA&0X3FFF等效于0000 0000 0000 0010&0011 1111 1111 1111等效于0000 0000 0000 0010等效于十进制的2,即USART_RX_BUF[2]=Res,即USART_RX_BUF[2]=0x33
至此我们将第三个数据0x33保存至数组USART_RX_BUF[2]中

if(Res==0x0d)	USART_RX_STA|=0x4000;
else
	{
		USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
		USART_RX_STA++;
		if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
	}		 
}		 

然后执行USART_RX_STA++,即USART_RX_STA变为2+13。然后执行最后一个判断if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;,由于,USART_REC_LEN-1等效于(200-1)为199,而USART_RX_STA==3,所以这个判断为假,后面的USART_RX_STA=不会执行。
至此串口中断服务函数执行完毕,其实只执行了下图框框里面的函数。
在这里插入图片描述
Res==0x33--------有变化
USART_RX_BUF[2]==0x33--------有变化
USART_RX_STA==3--------有变化
—————————————————————————————
五、数据发送完毕,发送回车和换行
数据发送完毕后会发送回车和换行,即0x0d0x0a
首先回车符0x0d来了,Res =0x0dUSART_RX_STA=3,然后进行第一个判断,USART_RX_STA&0x4000等效于0000 0000 0000 0011&0x0100 0000 0000 0000等效于0,所以应该执行下图中的oooo语句

if(USART_RX_STA&0x4000)//接收到了0x0d
	{
	xxxx
	}
else //还没收到0X0D
	{	
	oooo
	}		 

然后进行第二个判断,从上面的分析可知,Res ==0x0d,所以要执行USART_RX_STA|=0x40000000 0000 0000 0011|0100 000 0000 00000100 0000 0000 0011,所以此时USART_RX_STA==0100 0000 0000 0011==0x4003

if(Res==0x0d)	USART_RX_STA|=0x4000;
else
	{
		USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
		USART_RX_STA++;
		if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
	}		 
}		 

至此串口中断服务函数执行完毕,其实只执行了下图框框里面的函数。
在这里插入图片描述
Res==0x0d--------有变化
USART_RX_BUF[2]==0x33--------没变化
USART_RX_STA==0x4003--------有变化
—————————————————————————————
然后换行符0x0a来了,Res =0x0aUSART_RX_STA=0x4003,然后进行第一个判断,USART_RX_STA&0x4000等效于0100 0000 0000 0011&0x0100 0000 0000 0000等效于0100 0000 0000 0000等效于0x4000为真,所以应该执行下图中的xxxx语句

if(USART_RX_STA&0x4000)//接收到了0x0d
	{
	xxxx
	}
else //还没收到0X0D
	{	
	oooo
	}		 

然后进行第二个判断,从上面的分析可知,Res ==0x0a,所以要执行USART_RX_STA|=0x80000100 0000 0000 0000|1000 000 0000 00001100 0000 0000 0000,所以此时USART_RX_STA==1100 0000 0000 0000==0xB000

if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x8000;	//接收完成了 		 

至此串口中断服务函数执行完毕,其实只执行了下图框框里面的函数。
在这里插入图片描述

Res==0x0a--------有变化
USART_RX_BUF[2]==0x33--------没变化
USART_RX_STA==0xB000--------有变化
—————————————————————————————
至此,所有的数据包括停止数据都发送完毕,分为普通数据和标志
三个数据:0x11、0x22、0x33
两个停止的标志:0x0d、0x0a

ResUSART_RX_STAUSART_RX_BUF[ ]
发送0x11Res =0x11USART_RX_STA=1USART_RX_BUF[0]=0x11
发送0x22Res =0x22USART_RX_STA=2USART_RX_BUF[1]=0x22
发送0x33Res =0x33USART_RX_STA=3USART_RX_BUF[2]=0x33
发送0x0dRes =0x0dUSART_RX_STA=0x4003/
发送0x0aRes =0x0aUSART_RX_STA=0xB003/
  • 4
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
//出入均设有缓冲区,大小可任意设置。 //可供使用的函数名: //char getbyte(void);从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。 //getline(char idata *line, unsigned char n); 获取一行数据回车结束,必须定义最大输入字符数 //putbyte(char c);放入一个字节到发送缓冲区 //putbytes(unsigned char *outplace,j);放一串数据到发送缓冲区,自定义长度 //putstring(unsigned char code *puts);发送一个定义在程序存储区的字符串到串口 //puthex(unsigned char c);发送一个字节的hex码,分成两个字节发。 //putchar(uchar c,uchar j);输出一个无符号字符数的十进制表示,必须标示小数点的位置,自动删除前面无用的零 //putint(uint ui,uchar j);输出一个无符号整型数的十进制表示,必须标示小数点的位置,自动删除前面无用的零 //delay(unsigned char d); 延时n x 100ns //putinbuf(uchar c);人工输入一个字符到输入缓冲区 //CR;发送一个回车换行 //************************************************************************* #include <w77e58.h> #define uchar unsigned char #define uint unsigned int #define OLEN 32 /* size of serial transmission buffer */ idata unsigned char outbuf[OLEN]; /* storage for transmission buffer */ unsigned char idata *outlast=outbuf; //最后由中断传输出去的字节位置 unsigned char idata *putlast=outbuf; //最后放入发送缓冲区的字节位置 #define ILEN 12 /* size of serial receiving buffer */ idata unsigned char inbuf[ILEN]; unsigned char idata *inlast=inbuf; //最后由中断进入接收缓冲区的字节位置 unsigned char idata *getlast=inbuf; //最后取走的字节位置 bit outbufsign0; //最后一个数据覵BUF发完标志 发完=0 bit outbufsign; //输出缓冲区非空标志 有=1 bit inbufsign; //接收缓冲区非空标志 有=1 bit inbufful; //输入缓冲区满标志 满=1 #define CR putstring("\r\n") //CR=回车换行 //***************************** //延时n x 100ns void delay(unsigned char d) //在源程序开头定义是否用w77e58或22。1184M晶振 {unsigned char j; do{ d--; //110592 & 89c52 #ifndef cpuw77e58 #ifndef xtal221184 j=21; //k=38 cpu80320 100us k="21" cpu 8052 #else j=42; #endif #else #ifndef xtal221184 j=38; #else j=76;
STM32的UART中,空闲中断是一种比较常用的中断方式,它可以用来判断数据是否接收完成,以及处理接收到的数据。下面详细介绍一下STM32空闲中断的实现方法和注意事项。 1. 实现方法 (1)开启空闲中断 在STM32的UART中,开启空闲中断需要配置CR1寄存器的IDLEIE位。具体实现方法如下: ```c USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); ``` (2)中断服务程序 当UART接收到数据后,在一段时间内没有再次接收到数据,就会触发空闲中断,并进入中断服务程序中执行相应的操作。中断服务程序的实现方法如下: ```c void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) { // 处理接收到的数据 USART_ClearITPendingBit(USART1, USART_IT_IDLE); // 清除中断标志位 } } ``` 在中断服务程序中,我们可以读取接收缓冲区中的数据,并进行处理。需要注意的是,在处理完中断服务程序后,必须清除中断标志位,否则会一直触发中断。 2. 注意事项 (1)开启空闲中断前,必须先开启接收中断。 (2)在处理完中断服务程序后,必须清除中断标志位,否则会一直触发中断。 (3)在处理接收到的数据时,需要判断接收缓冲区中的数据是否已经接收完成。 (4)在使用空闲中断时,需要合理设置接收数据的超时时间,以避免因数据接收不完整而出现错误。 以上就是关于STM32空闲中断的详细介绍,希望对您有所帮助。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值