📄 uart_new.c
字号:
///////////////////////////////////////////////////////////////////////////////
// 门禁终端与上位服务器通信
// 门禁终端与上位服务器通信采用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 + -