⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 51单片机用IO模拟串口通信,只占用一个定时器
💻 C
字号:
/*
IO 口模拟232通讯程序

使用两种方式的C程序 占用定时器0

**********************************************/
#include <reg51.h>
#include <string.h>
#define byte unsigned char


#define GPGLL		0
#define GPGSA		1
#define GPRMC		2
#define GPZDA		3
#define GPVTG		4
#define GPGGA		5


pdata byte pData[200];
sbit BT_SND =P3^1;
sbit BT_REC =P3^0;


byte	RxFlag=0;							
byte	RecTimeOut=0;	
byte	RecStatus=0;	
byte	RxCount=0;		
//byte    g_GPS;						//GPS数据状态.

extern void putch(byte ch);
#define F_TM F0

#define TIMER0_ENABLE  TL0=TH0; TR0=1;
#define TIMER0_DISABLE TR0=0;

sbit ACC0=   ACC^0;
sbit ACC1=   ACC^1;
sbit ACC2=   ACC^2;
sbit ACC3=   ACC^3;
sbit ACC4=   ACC^4;
sbit ACC5=   ACC^5;
sbit ACC6=   ACC^6;
sbit ACC7=   ACC^7;

//用IO模拟串口收,发数据占用定时器0
void IntTimer0() interrupt 1
{
  F_TM=1;
}

//模拟串口,发送一个字符
void PSendChar(unsigned char inch)
{			   	
	ACC=inch;	
	F_TM=0;
	BT_SND=0; //start bit
	TIMER0_ENABLE; //启动
	while(!F_TM);
	
	BT_SND=ACC0; //先送出低位
	F_TM=0;
	while(!F_TM);
	
	BT_SND=ACC1;
	F_TM=0;
	while(!F_TM);
	
	BT_SND=ACC2;
	F_TM=0;
	while(!F_TM);
	
	BT_SND=ACC3;
	F_TM=0;
	while(!F_TM);
	
	BT_SND=ACC4;
	F_TM=0;
	while(!F_TM);
	
	BT_SND=ACC5;
	F_TM=0;
	while(!F_TM);
	
	BT_SND=ACC6;
	F_TM=0;
	while(!F_TM);
	
	BT_SND=ACC7;
	F_TM=0;
	while(!F_TM);
	
	BT_SND=1;
	F_TM=0;
	while(!F_TM);
	TIMER0_DISABLE; //停止timer

}




//模拟串口,接收一个字符
unsigned char PGetChar()
{		
	
	TIMER0_ENABLE;
	F_TM=0;
	while(!F_TM); //等过起始位
	ACC0=BT_REC;
	
	TL0=TH0;
	
	F_TM=0;
	while(!F_TM);
	ACC1=BT_REC;
	
	F_TM=0;
	while(!F_TM);
	ACC2=BT_REC;
	
	F_TM=0;
	while(!F_TM);
	ACC3=BT_REC;
	
	F_TM=0;
	while(!F_TM);
	ACC4=BT_REC;
	
	F_TM=0;
	while(!F_TM);
	ACC5=BT_REC;
	
	F_TM=0;
	while(!F_TM);
	ACC6=BT_REC;
	
	F_TM=0;
	while(!F_TM);
	ACC7=BT_REC;
	
	F_TM=0;
	
	while(!F_TM)
	{
		if(BT_REC)
		{
		break;
		}
	}
	TIMER0_DISABLE; //停止timer
	return ACC;


}


//发送字符串
unsigned char send_str(unsigned char *str)
{
 unsigned char i;
 i=0;
 	while( str[i] != 0 ){
   	PSendChar(str[i]); 
	i++;	
	}
 
  return(0);
 }
 

// 发送AT指令. (返回接收到的数据长度.)

unsigned char SendAT(unsigned char *command,unsigned char *ACK)
{
  unsigned char i=0;  
  unsigned long m;
   
  if(strlen(command) > 0){ 	
    if( strlen(command) < 2) return(0); //  AT 命令格式错
    	while(command[i] != 0){  
        
		if( command[i] == '\n' )
	       {
			command[i] = 0;  // Remove the existing line terminating character (if any)
			break;
			}
		if( command[i] == '\r' ) {
			command[i] = 0;  // Remove the existing line terminating character (if any)
			break;
			}
		i++;
		}
	}
	    
	send_str(command);
	send_str("\x0D");   //

/*
三秒钟内无回复,认为超时退出.
*/
	m = 500000;
	i = 0;
	while(m--)
	{
	
	  if(BT_REC==0)
	  {
	  	ACK[i] =PGetChar();	
		i+=1;
		if(i>2 && (ACK[i-1]==0X0A && ACK[i-2]==0X0D))
		break;			
	  }	 
	
	}

 return(i);	  //回复收到的数据长度.

}


unsigned long delay;
void main()
{
	byte i,Len;

	SCON= 0X50;				//定议串口
	TMOD=0x22; 				/*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装) */
	PCON=0X80;				//波特率加倍
	
	TR0=0; 
	TF0=0;
	TH0 =256-80;			//用IO模拟的串口速率为 19200.
	TL0=TH0;
	ET0=1;					//允许定时器0中断
/*
	TH1 = 0XFB;			 	//单片机的串口速度为19200,测试用
	TL1 = 0XFB;
*/

   	TH1 = 0XF6;			 	//单片机的串口速度为9600,用于接收GPS数据.
	TL1 = 0XF6;					  
	TR1 = 1;				//启动定时器1
	ES = 1;					//允许串口中断


	EA=1;	  				//开总中断
  	delay = 0;
	REN = 1;

//	g_GPS =0;
	while(1)
	{   

		delay++;
		if(delay>=600000L)
		{
		    Len=0;
			Len =SendAT("ATE0",pData);
			for(i=0;i<Len;i++)
			PSendChar(pData[i]);		
			memset(pData,0,200);
			delay=0;
			RxFlag=0;
			
		
		}

	   if(RxFlag)
	   {	   							  
	   		for(i=0;i<RxCount;i++)
			putch(pData[i]);	  
//			g_GPS +=1;
//			if(g_GPS==6)  g_GPS=0;		
	   		RxFlag=0;
	   }

	}

}


void putch(byte ch)
{
  ES = 0;
  TI=0;
  SBUF =ch;
  while(!TI);
  TI = 0;
  ES = 1;	

}
//接收GPS模块数据.
void Com_Int(void) interrupt 4	using 1				// com interrupt routin
{

	RecTimeOut=120;								// byte timeout==20ms
	if(RI==1)									// recieved interrupt
	{
	   
		RI=0;	
		if(!RxFlag)
		{
			if(RecStatus==0)
			{			    
                 if(SBUF=='$')
				 {
					RxCount=1;
					pData[0]='$';
					RecStatus=1;
				  }         

			}
			else
			{

						if(RxCount>=120){RxCount=0;	RecStatus=0;return;}
						RxCount++;
						pData[RxCount-1]=SBUF;					                   
               			if(pData[RxCount-1]==0X0A && pData[RxCount-2]==0X0D)
                 		{	  				  		
						 /*
							switch(g_GPS)
							{
								case GPGLL:
									if(pData[3]=='G' && pData[4]=='L')
									RxFlag=1;
									break;

								case GPGSA:
									if(pData[3]=='G' && pData[4]=='S')
									RxFlag=1;
									break;

								case GPRMC:
									if(pData[3]=='R' && pData[4]=='M')
									RxFlag=1;
									break;

								case GPZDA:
									if(pData[3]=='Z' && pData[4]=='D')
									RxFlag=1;
									break;

								case GPVTG:
									if(pData[3]=='V' && pData[4]=='T')
									RxFlag=1;
									break;

								case GPGGA:
									if(pData[3]=='G' && pData[4]=='G')
									RxFlag=1;
									break;
								default:
									break;
														
							}
							*/
										//接收到GPS一个完整的数据包
							if(pData[3]=='R' && pData[4]=='M')		//徐工说只读这个数据就行了.
							RxFlag=1;
				  			RecStatus=0;
				 		}               	         
			}
		}		
	}

}

/*

//推荐最小明确数据: 纬度,经度,速度
$GPRMC,000000.000,V,0000.0000,S,00000.0000,W,0.00,0.00,220899,,,A*7E
UTC 时间
纬度,
经度
速度
高度
日,月,年

*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -