wifi模块_esp工作在路由模式遇到的问题及解决

文章描述了一个在单片机中使用UART通信时遇到的问题,主要集中在中断服务函数中缓冲区索引管理的不当导致的接收数据异常。作者指出,白盒测试时由于接收的特定字串限制,问题未显现,但在实际应用中,缓冲区溢出可能引发数据丢失或混乱。
摘要由CSDN通过智能技术生成
#include "reg52.h"
#include "intrins.h"
#include "string.h"
#define SIZE 12

sfr AUXR = 0x8E;
sbit D5  = P3^7;
sbit D6  = P3^6;

char buffer[SIZE];

char LYMS[] =  "AT+CWMODE=2\r\n";
char DLJ[] = "AT+CIPMUX=1\r\n";
char JLFW[] = "AT+CIPSERVER=1\r\n";
char FSSJ[] = "AT+CIPSEND=0,5\r\n";

char AT_OK_Flag      = 0;
char Client_Connect_Flag = 0;

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void UartInit()
{
	//相关寄存器的配置
	AUXR 	= 0x01;
	SCON 	= 0x50;
	TMOD &= 0x0F;
	TMOD |= 0x20;
	TH1 	= 0xFD;
	TL1 	= 0xFD;
	TR1   = 1;
	EA    = 1;
	ES    = 1;
}

void sendByte(char data_msg)
{
	SBUF = data_msg;
	while(!TI);
	TI   = 0;
}

void sendString(char *data_msg)
{
	while(*data_msg != '\0'){
		sendByte(*data_msg);
		data_msg++;
	}
}

void main()
{
	//每隔一秒发送一串字符	
	UartInit();
	Delay1000ms();
	
	sendString(LYMS);
	Delay1000ms();
	Delay1000ms();
	Delay1000ms();
	while(!AT_OK_Flag);
	AT_OK_Flag = 0;
	
	sendString(DLJ);
	Delay1000ms();
	Delay1000ms();
	Delay1000ms();
	while(!AT_OK_Flag);
	AT_OK_Flag = 0; 

	sendString(JLFW);
	Delay1000ms();
	Delay1000ms();
	Delay1000ms();
	while(!Client_Connect_Flag);
	AT_OK_Flag = 0;
	
	if(Client_Connect_Flag){
	D5 = 0;//点亮D5,代表有客户端接入
	D6 = 0;
	}
	while(1){
	//4 发送数据
		sendString(FSSJ);
		Delay1000ms();
		Delay1000ms();
		sendString("Hello");
		Delay1000ms();
		Delay1000ms();
	}
}

void UART_Handler() interrupt 4
{
	static int i;
	char tmp;
	
	if(RI){
		RI = 0;
		tmp = SBUF;
		if(tmp == 'O' || tmp == '0' || tmp == ':'){
			i = 0;
		}
		buffer[i++] = tmp;

		if(buffer[0] == 'O' && buffer[1] == 'K'){
			AT_OK_Flag = 1;
			i = 0;
			memset(buffer,'\0',SIZE);
		}
		
		if(buffer[0] == '0' && buffer[2] == 'C'){
			Client_Connect_Flag = 1;
			i = 0;
			memset(buffer,'\0',SIZE);
		}
		
		if(buffer[0] == ':' && buffer[1] == 'o' && buffer[2] == 'p'){
			D5 = 0;//点亮D5
			i = 0;
			memset(buffer, '\0', SIZE);
		}
		if(buffer[0] == ':' && buffer[1] == 'c' && buffer[2] == 'l'){
			D5 = 1;//熄灭D5
			i = 0;
			memset(buffer, '\0', SIZE);
		}
		if(i == 12){
				i = 0;
		}
	}
	
	if(TI);
}

在做白盒测试时,功能完全正常。但是直接连接到单片机时就没用了,是为什么呢?

原因:在中断服务函数中的最后面部分,没有在当i = 12时,对i清零,让i回到初始的位置。

为什么做白盒测试的时候有用呢,是因为做白盒测试时,单片机接收到的只有OK和0,Connect这两种字串,而直接连接单片机时,接受到的字串不止这两种,在没有判断到OK和0,Connect这两种关键字时,索引i就不会清0,反而会一直递增,导致后面关键字符来了,单片机也找不到。

在这种特定的情况下,少了这段代码可能导致问题的原因如下:

  1. 缓冲区溢出问题:如果没有在中断服务函数中检查缓冲区索引 i 是否达到最大值,当接收到连续的字符时,i 会继续递增,直到超出缓冲区的大小。这可能导致数组越界,破坏其他重要的数据,或者导致程序的其他部分无法正常工作。

  2. 正确清除缓冲区:当缓冲区索引 i 达到最大值时,需要将其重置为0,以便缓冲区可以重新使用。如果不进行这样的重置,缓冲区可能会在达到其容量上限后无法继续接收数据,从而导致接收到的数据丢失或覆盖。

问:你的意思时i超出了缓冲区12的大小,就会导致缓冲区无法继续使用吗?

答:

是的,您理解得很正确。

在这种特定情况下,缓冲区大小被定义为 12,表示它最多可以容纳 12 个字符。如果 i 的值超过了缓冲区的大小,即 i 变为了 12,这意味着缓冲区已经填满了。此时如果没有将 i 重置为 0,那么当再次接收到新的字符时,将无法将其放入缓冲区中,因为 i 已经达到了其最大值,超出了缓冲区的范围。这样的话,新接收到的字符将会丢失或覆盖掉之前缓冲区中的数据,导致接收到的数据不完整或混乱。

因此,确保在缓冲区填满时重置 i 为 0 是十分必要的,这样可以确保缓冲区能够循环使用,而不会因为达到最大容量而导致数据丢失或错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值