51单片机串口2的RS485通信调试总结

过完年,一到公司主管就催我赶紧把这个项目的PC和单片机的RS485通信给调通。这几天,一直在实验室度过的。开始我从单片机简单发送一串数据,用串口调试助手测试。上位机根本没有接收到数据,用示波器测了发送管脚和接收管脚都没有波形,查看了下波特率也是对的。所以初步断定是否硬件电路有问题,检查了ADM2483的DE端初始化时是低电平,我在程序里把这个位置为高电平,再用万用表测量还是低电平。原来DE和RE和地线是连到一块的,问其他同事,原来他们前面把这个地方拉低为了让485模块一直处于接收状态,测试测试能否接收到上位机数据。把这个地方改过来后,继续测试。还是用简单的串口收发数据测试通信,上位机发送数据,下位机接收到数据后紧接着把接收到的数据发给上位机。测试的时候,发送55和00是正确的,但是其他数据都发生了改变。后面用示波器测试单片机TXD2和RXD2的波形,发现下位机发出的数据在RXD2上显示波形,初步断定是否设计原理图的时候这两个引脚是否反了,把电路板割线,重新跳线调换两个引脚后再测试下位机往上位机发送数据,上位机接收正常。紧接着,发送和接收一起测,发送和接收都正常了。调了几天,原来电路板出问题了,可主管一来就说硬件是没有问题的,让我检查软件。哎,干软件的就是弱势群体,特别在我们公司真是这样。所以搞嵌入式开发的最好要软硬件都懂。最后,我把我以前写的程序下载到板子上,发现仍然和上位机不能通信。最后我想是不是在接收中断函数里通信协议解析不对,通过查阅资,改用另一种方式解析,结果可以通过上位机控制下位机输出显示了。最后把自己些调试用的程序附上:

简单的串口2收发程序

#include <reg52.h>

/*******************宏定义***********************/
#define uchar unsigned char
#define	uint unsigned int
/*****************串口2特殊功能的声明*************/
sfr AUXR=0x8e;  // 辅助寄存器,用于设定串口2工作波特率、独立波特率发生器的选择
sfr S2CON=0x9a; //串口2串行控制器
sfr S2BUF=0x9b; //串口2数据缓冲寄存器
sfr BRT=0x9c;  //独立波特率产生器,重装数
sfr IE2=0xaf; //串口2中断寄存器
sfr AUXR1=0xa2;// 辅助寄存器1,用于切换端口。以后用,切记!
#define	S2RI  0x01 // 串口2接收标志位
#define S2TI  0x02 // 串口2发送标志位
sfr WDT_CONTR = 0xc1;//看门狗
/*******************位定义声明*****************/
sbit EN1=P3^3;//485通信使能端
bit flag = 0;
/********************数据存储、数据缓冲器声明*************/

/**************************************************************/
//++++++++++++++++++++++++++++++++++++++++//
//名称:delay_ms
//作用:延时time毫秒
//说明:延时函数
//输入参数:time
//输出参数:
//++++++++++++++++++++++++++++++++++++++++//
void delay_ms(unsigned int time)
{
   unsigned int i,j;
   for(i=time;i>0;i--)
     for(j=112;j>0;j--)
	   {;}
}

uint num;
void UartInit(void)  //[email protected]
{
	 AUXR &= 0xf7;  //波特率不倍速
	 S2CON = 0x50;  //8位数据,可变波特率
	 BRT = 0xFD;      //设定独立波特率发生器重装值
	 AUXR &= 0xfb;  //独立波特率发生器时钟为Fosc/12,即12T
	 AUXR |= 0x10;  //启动独立波特率发生器
	 EA=1;
	 IE2=0x01;
}  
void send(uint ch)
{
	EN1 = 1;
	IE2=0x00;   	
	S2CON&=~S2TI;  
	S2BUF=ch;      
	while(!(S2CON&S2TI));  
	S2CON &=~S2TI; 
	IE2=0x01;
	EN1 = 0;    
}

void main()
{
	EN1 = 0;
	UartInit();
    send(0x55);
	delay_ms(1);
	send(0xaa);
	delay_ms(1);
	send(0xff);
	delay_ms(1);
	while(1);
 
}
void Uart2() interrupt 8        
{ 
	if(S2CON&S2RI)
	{
		S2CON&=~S2RI;
		delay_ms(1);
		num=S2BUF;
		send(num);
	}
}
通信协议解析部分程序

void Data_analysis(void)
{
	static unsigned int check_sum = 0;  //存放校验和
	static unsigned char lencnt = 0;  //数据长度计数器
	switch (state_flag)
	{
		case 0:
        {
			if(recdata == 0xaa)     // 是否帧头第一个数据
				state_flag = 1;
			else
				state_flag = 0;    // 标志复位 
			break;      
        }
       case 1:
       {
			if(recdata == 0x55)     //是否帧头第二个数据
				state_flag = 2;
			else
				state_flag = 0;    // 标志复位
			break;
       }
       case 2:
       {
			if(recdata == addr)     //判断目的地址是否正确
			{
				state_flag = 3;
				check_sum = recdata;
			}
			else
				state_flag = 0;    // 标志复位
			break;
       }
       case 3:
       {
			state_flag = 4;
            cmd = recdata;  //指令码
            check_sum ^= recdata;  //校验和累加 
            break;
       } 
       case 4: 
       {
			lencnt = 0;  //数据长度计数器清零
			data_count = recdata;  //存储数据长度
			check_sum ^= recdata;  //累加
			if(data_count != 0)  //后面有数据码
				state_flag = 5;
			else 
				state_flag = 7;
			break;
       }        
	   case 5: 
       case 6: 
       {
			dat[lencnt++] = recdata;  //存储数据码
			check_sum ^= recdata;   //累加
			if(lencnt == data_count)
			{
				state_flag = 7;
				lencnt = 0;        
			}  				
			else
				state_flag = 6;
			break;
       }
       case 7:
       {
			if(check_sum == recdata)   //数据校验,判断累加和是否正确
				state_flag = 8;
			else
			{
			  retval = 1;   //置错误标志,数据传输不正确
			  state_flag=0;   
			}
			check_sum=0;//累加和清0
			break;
       }
       case 8:
       {
			if (recdata==0x0d)
			{
				retval = 2;   //置接收一帧数据成功标志
				state_flag=0;
			}
			else
				state_flag=0; 
			break; 
       }
	   default:
			break;
	}
// 	if(timeOutFlag == 1)	//超时判断
// 	{
// 		timeOutFlag = 0;
// 		state_flag=0;
// 		retval = 1;   //置错误标志,数据传输不正确
// 		recdata = 0x00;
// 	}
}


你可能感兴趣的:(调试,单片机,串口通信,嵌入式开发)