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

📄 uart_new.c

📁 KEIL C上的门禁控制器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////////////////////////////////////////////////////
// 门禁终端与上位服务器通信
// 门禁终端与上位服务器通信采用RS485总线方式连接,每台门禁终端分配固定设备
// 地址。
// 需要注意的是在处理串行通信的时候,可以关闭其它中断
// idata=19
///////////////////////////////////////////////////////////////////////////////

#include "Global.h"


///////////////////////////////////////////////////////////////////////////////
// 内部存储区变量	0~128字节
extern data uchar cur_time[15];			// 系统当前时间显示存储区 XXXX年XX月XX日XX时XX分XX秒星期X

extern data uchar pulse;				// 蜂鸣
extern data uint  time_out;				// 通用超时定时器

extern data uint  recv_ctr;				// 接收数据指针
extern data uint  trans_time;			// 发送数据超时保护
extern data uint  trans_ctr;			// 发送数据指针
extern data uint  trans_size;			// 发送数据大小

extern idata char  wieformat;			// 韦根通信格式

extern bdata bit maxtrans;				// 大/小数据量传输状态
extern bdata bit SerialFlag;			// 串口通信状态
extern idata uchar baudrate;			// 波特率

extern idata uchar laddr;				// 地址低字节ASC码
extern idata uchar haddr;				// 地址高字节ASC码
extern idata uchar currecno;			// 当前已读取的实时记录索引
extern idata uchar sumrecno;			// 所有实时记录索引

extern data  uchar checksum;			// 校验和
extern data  uchar testchecksum;		// 接收到的校验和

///////////////////////////////////////////////////////////////////////////////
// 中断4服务列程
// 串行中断服务
///////////////////////////////////////////////////////////////////////////////
void ser() interrupt 4
{
	idata uchar c;

	if(_testbit_(TI))			// 检测发送完成位
	{
		if(maxtrans)				// 大数据量传输
		{
			trans_ctr++;			// 发送指针下移
			if(trans_ctr<trans_size)
				SBUF=SPIbuf[trans_ctr];	// 发送数据
			else
			{
				trans_ctr=0;
				trans_size=0;
				Dir=0;				// 停止发送
			}
		}
		else						// 小数据量传输
		{
			trans_ctr++;			// 发送指针下移
			if(trans_ctr<trans_size)
				SBUF=trans_buf[trans_ctr];	// 发送数据
			else
			{
				trans_ctr=0;
				trans_size=0;
				Dir=0;				// 停止发送
			}
		}
	}

	if(_testbit_(RI))			// 检测接收完成位
	{
		c=SBUF;
		if(c!=0)
		{
			if(maxtrans)			// 大数据量传输
			{
				SPIbuf[recv_ctr]=c;
				recv_ctr++;
				if(recv_ctr>BUFSIZE)
					recv_ctr=0;
			}
			else					// 小数据量传输
			{
				recv_buf[recv_ctr]=c;
				recv_ctr++;
				if(recv_ctr>RCVBUFSIZE)
					recv_ctr=0;
			}
		}
	}
}

///////////////////////////////////////////////////////////////////////////////
// 发送信息
///////////////////////////////////////////////////////////////////////////////
void sendmessage(uchar message)
{
	idata uchar i;
	idata uchar temp;

	if(maxtrans)				// 大模式数据传输
	{
		if(message==NAK)		// 数据接收错误,向上位机返回NAK
		{
			SPIbuf[0]=SOH;
			SPIbuf[1]=haddr;	// 源地址
			SPIbuf[2]=laddr;
			SPIbuf[3]='0';		// 目标地址
			SPIbuf[4]='0';
			SPIbuf[5]='0';		// 信息号
			SPIbuf[6]=NAK;		// NAK
			SPIbuf[7]=EOT;		// 结束
	
			Dir=1;				// 485发送
			COMENABLE;			// 允许串口中断
			trans_ctr=0;
			trans_size=8;
			SBUF=SPIbuf[0];		// 发送
		}
	}
	else
	{
		trans_ctr=0;
		checksum=0;
		trans_buf[trans_ctr]=SOH;
		checksum+=trans_buf[trans_ctr];
		trans_ctr++;
		trans_buf[trans_ctr]=haddr;			// 源地址
		checksum+=trans_buf[trans_ctr];
		trans_ctr++;
		trans_buf[trans_ctr]=laddr;
		checksum+=trans_buf[trans_ctr];
		trans_ctr++;
		trans_buf[trans_ctr]='0';			// 目标地址
		checksum+=trans_buf[trans_ctr];
		trans_ctr++;
		trans_buf[trans_ctr]='0';
		checksum+=trans_buf[trans_ctr];
		trans_ctr++;
		trans_buf[trans_ctr]='0';			// 信息号
		checksum+=trans_buf[trans_ctr];
		trans_ctr++;

		if(message==ACK)
		{
			trans_buf[trans_ctr++]=ACK;
		}
		else if(message==NAK)
		{
			trans_buf[trans_ctr++]=NAK;
		}
		else
		{
			trans_buf[trans_ctr]=STX;
			checksum+=trans_buf[trans_ctr];
			trans_ctr++;

			for(i=0; i<MAX_REALREC_SIZE;i++)	// 发送实时记录
			{
				trans_buf[trans_ctr]=RTrecord[i];
				checksum+=trans_buf[trans_ctr];
				trans_ctr++;
			}

			trans_buf[trans_ctr]=ETX;			
			checksum+=trans_buf[trans_ctr];
			trans_ctr++;

			checksum=~checksum+1;			// 计算校验和

			temp=(checksum&0xF0)>>4;
			trans_buf[trans_ctr]=Hex_ascii(temp);
			trans_ctr++;

			temp=checksum&0x0F;
			trans_buf[trans_ctr]=Hex_ascii(temp);
			trans_ctr++;
		}

		trans_buf[trans_ctr++]=EOT;

		Dir=1;				// 485发送
		trans_size=trans_ctr;
		trans_ctr=0;
		SBUF=trans_buf[0];
	}	
}

///////////////////////////////////////////////////////////////////////////////
// 检查接收缓冲区是否有完整的数据包
// 如果有返回成功,如果数据包不完整可能数据有部分丢失或者没有完整的数据返回失败
// 检查SOH和EOT来判断
///////////////////////////////////////////////////////////////////////////////
bit checkmessage()
{
	bdata bit  SOHfound;
	bdata bit  EOTfound;
	idata uint sohptr, eotptr;
	idata uchar temp;
	idata uint i;

	SOHfound=FALSE;
	EOTfound=FALSE;

	sohptr=0;
	eotptr=0;

	if(recv_ctr==0)			// 接收缓冲区中没有任何信息
		return FALSE;

	for(i=0;i<recv_ctr;i++)
	{
		if(maxtrans)
			temp=SPIbuf[i];
		else
			temp=recv_buf[i];

		if(temp==SOH)
		{
			SOHfound=TRUE;	// 发现SOH
			sohptr=i;
		}
		if(temp==EOT)
		{
			EOTfound=TRUE;	// 发现 EOT
			eotptr=i;
		}
	}

	if((SOHfound&&EOTfound)&&(eotptr>sohptr))
		return TRUE;			// 接收到完整的数据包
	else if(!SOHfound&&EOTfound)
	{
//		sendmessage(NAK);	// 发送NAK,数据可能部分丢失
		recv_ctr=0;
		return FALSE;
	}
	else
		return FALSE;
}

///////////////////////////////////////////////////////////////////////////////
// 读取并分析接收缓冲区数据
///////////////////////////////////////////////////////////////////////////////
uchar readbuf()
{
	idata uchar curstate;		// 当前信息类别
	idata uchar nextstate;		// 下一个信息类别
	idata uchar temp;
	idata uint  i;
	idata uint  strindex;
	bdata bit   endofmessage;	// 数据包是否结束
	bdata bit   errordect;		// 是否有错误检测到
	bdata bit   wrongaddr;		// 地址是否错误

	curstate=STATE_SOH;			// 当前信息状态
	nextstate=STATE_SOH;		// 下一个信息状态

	i=0;			// 数据指针索引
	strindex=0;		// 命令体数据指针索引
	errordect=FALSE;
	wrongaddr=FALSE;
	endofmessage=FALSE;

	checksum=0;		// 校验和
	testchecksum=0;

	if(maxtrans)
		COMDISABLE;			// 大数据模式下禁止串口中断
 	while (TRUE)
 	{
		curstate=nextstate;		// 当前状态从SOH开始

		switch(curstate)
		{
		case STATE_SOH:
			if(maxtrans)
				temp=SPIbuf[i];
			else
				temp=recv_buf[i];

			if(temp!=SOH)
			{
				if(i==(recv_ctr-1))
					errordect=TRUE;		// 有错误检测到
				else
				{
					nextstate=STATE_SOH;	// 保持状态,直到找到SOH
					i++;
				}
			}
			else
			{
				checksum+=SOH;
				nextstate=STATE_SRC_ADDR;
				i++;
			}
		break;
		case STATE_SRC_ADDR:
			if(maxtrans)
				temp=SPIbuf[i];
			else
				temp=recv_buf[i];

			checksum+=temp;
			if(temp!='0')
				wrongaddr=TRUE;
			else
			{
				i++;
				if(maxtrans)
					temp=SPIbuf[i];
				else
					temp=recv_buf[i];
				checksum+=temp;
				if(temp!='0')
					wrongaddr=TRUE;
				i++;
			}
			nextstate=STATE_DST_ADDR;
			break;
		case STATE_DST_ADDR:
			if(maxtrans)
				temp=SPIbuf[i];
			else
				temp=recv_buf[i];
			checksum+=temp;
			if(temp!=haddr)
				wrongaddr=TRUE;
			else
			{
				i++;
				if(maxtrans)
					temp=SPIbuf[i];
				else
					temp=recv_buf[i];

				checksum+=temp;
				if(temp!=laddr)
					wrongaddr=TRUE;		// 地址不正确
				i++;
			 }
			 nextstate=STATE_MSG_NUM;
			 break;

⌨️ 快捷键说明

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