serial.c

来自「功能非常完善的51串口程序包」· C语言 代码 · 共 213 行

C
213
字号
#include "Serial.h"

Packet comm;

//******************数据通讯初始化函数**********************//
//输入:无
//输出:无
//说明:初始化包括定时器和中断的初始化
//      配置为使用定时器1,开串口中断,允许接收
//      波特率等参数在serial.h中设置,无需改动此函数
//********************************************************//
void Serial_Init()
{
 TMOD=0x20;
 SCON=0x50;
 
#ifdef BOUND_RATE_DOUBLE	//波特率加倍时的参数
 TL1=0;
 TH1=256.5-CLK_FRE/(BOUND_RATE*16.0*CLK_DIV);
 PCON=0x80;
#else						//波特率不加倍时的参数
 TL1=0;
 TH1=256.5-CLK_FRE/(BOUND_RATE*32.0*CLK_DIV);
 PCON=0x00;
#endif

 TR1=1;
 ES=1;
 EA=1;
 comm.rflag=COMM_IDLE;
 comm.tflag=COMM_IDLE;
 comm.time=COMM_TIME;
 comm.rcount=0;
 comm.tcount=0;

}

//******************数据接收中断函数**********************//
//输入:无
//输出:无
//说明:此函数完成数据的接收和发送功能,无需调用
//      要获取通讯接收状态可监视comm.rflag
//      COMM_IDLE  0  时为空闲等待状态
//		COMM_ACK   1  时为接收完成
//		COMM_REING 2  时为正在接收
//      接收数据将在接收完成后更新,读取comm,dat[]即可获取数据

//      要获取通讯接收状态可监视comm.tflag
//      COMM_IDLE  0  时为空闲等待状态
//		COMM_ACK   1  时为发送完成
//		COMM_TEING 2  时为正在发送
//		要发送数据调用Serial_Send()函数
//********************************************************//
void Serial_Int() interrupt 4
{
 if (RI)
 {
  RI=0;

  if (comm.rcount>=PACKET_LEN-1)	//本次数据包接收完毕
  	{
	 uchar i;

	 comm.dat[PACKET_LEN-1]=SBUF;	//保存最后一个接收到的数据
	 for (i=0;i<PACKET_LEN-1;i++)
	 	{
		 comm.dat[i]=comm.temp[i];	//转存以前的接收数据
		}
	 comm.rflag=COMM_ACK;		//接收完毕标志
	 comm.rcount=0;				//下次重新开始接收
	}
   else
   	{
	 comm.temp[comm.rcount]=SBUF;	//保存接收数据
  	 comm.rcount++;
	 comm.rflag=COMM_REING;		//正在接收标志
	 comm.time=COMM_TIME;		//重置接收计时 
	}
 }

 if (TI)
 {
  TI=0;

  if (comm.tcount>=comm.len)	//发送完毕
  	{
	 comm.tflag=COMM_IDLE;
	}
   else
   	{
	 SBUF=*comm.pdat;
	 comm.pdat++;
	 comm.tcount++;
	}
 }


}


//******************数据接收计时函数**********************//
//输入:无
//输出:无
//说明:此函数负责监视一个数据包中各数据的接收,若数据包接收
//      超时则重新启动数据接收
//      若要使用数据接收监视功能,需在主函数中循环调用此函数
//********************************************************//
void Serial_Timer()
{
 if (comm.rflag==COMM_REING)
 	{
	 if (comm.time)
	 	{
		 comm.time--;
		}
	   else
	   	{
	 	 comm.rflag=COMM_IDLE;
		 comm.time=COMM_TIME;
		 comm.rcount=0;
		}
	}
}

//******************数据接收状态函数**********************//
//输入:无
//输出:COMM_DATA_NOTRDY  0    数据未准备好,未接收到数据或正在接收
//		COMM_DATA_ACK	  1    数据接收完成,效验正确
//		COMM_DATA_ERROR   2    数据接收完成,效验错误或无效验位
//说明:调用此函数后,接收状态被自动清为空闲(仅对接收完成的状态)
//********************************************************//
uchar Serial_GetDataState()
{
 uchar i,a=0;
 if (comm.rflag==COMM_IDLE || comm.rflag==COMM_REING)
 	return COMM_DATA_NOTRDY;

 for (i=0;i<PACKET_LEN-1;i++)			//数据效验,数据包中最后一字节为效验位,应等于包中其他数据之和(不计溢出)
 	{
	 a+=comm.dat[i];
	}
 if (a==comm.dat[PACKET_LEN-1])
 	{
	 comm.rflag=COMM_IDLE;
 	 return COMM_DATA_ACK;
	}
   else
	{
	 comm.rflag=COMM_IDLE;
   	 return COMM_DATA_ERROR;
	}
}

//******************数据发送函数**************************//
//输入:发送数据缓冲区指针 *pdat
//      发送数据长度       len
//输出:COMM_SENT_OK     0   数据发送正常
//      COMM_SENT_BUSY   1   发送忙,需稍后重发
//说明:此函数将缓冲区内len长度的数据发送出去
//********************************************************//
uchar Serial_Sent(uchar *pdat,uchar len)
{
 if (comm.tflag==COMM_TEING)
 	return COMM_SENT_BUSY;

 comm.tflag=COMM_TEING;	//开始发送,置标志
 comm.len=len;
 SBUF=*pdat;			//发送第一个数据启动发送
 comm.pdat=pdat+1;
 comm.tcount=1;

 return COMM_SENT_OK;
}

//*****************带效验位生成的数据发送函数*******************//
//输入:发送数据缓冲区指针 *pdat
//      发送数据长度       len
//输出:COMM_SENT_OK     0   数据发送正常
//      COMM_SENT_BUSY   1   发送忙,需稍后重发
//说明:此函数自动计算效验位,将其放在缓冲区末端再将数据发送出去
//      总共发送数据长度为len+1
//注:  缓冲区的有效长度应至少为len+1,否则会产生不可知后果
//********************************************************//
uchar Serial_ValidateSent(uchar *pdat,uchar len)
{
 uchar i,a=0;
 if (comm.tflag==COMM_TEING)
 	return COMM_SENT_BUSY;

 comm.pdat=pdat;
 comm.tflag=COMM_TEING;	//开始发送,置标志
 comm.len=len+1; 

 for (i=0;i<len;i++)
 	{
	 a+=*pdat;
	 pdat++;
	}
 *pdat=a;

 SBUF=*comm.pdat;		//发送第一个数据启动发送
 comm.pdat++;
 comm.tcount=1;

 return COMM_SENT_OK;
}






⌨️ 快捷键说明

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