📄 zlg500b.c
字号:
#include "main.h"
#define __SRC
#include "zlg500B.h"
#undef __SRC
void Serial_int(void) interrupt 4 using 1 //串口中断来干什么呢
{
uchar stx,index,BCC_sum=0,rcv_len=5;
ES0=0; //串行中断允许位,
RI0=0; //串口接收中断标志清零
stx=SBUF0; //收到的数据转到stx
/*通信协议中500B向主机发出响应信号*/
delay_50us(1); //延时:协议中没有这一延时
CON_485=1; //TXD发送时为高 即是主机有数据发出了
REN0=0; //暂时的禁止接收
SBUF0=ACK; //主机发送应答信号 主机己经准备好了接收从ZLG500B发出来的数据帧
while(TI0==0);
TI0=0;
CON_485=0; //因为串口己经发送完毕,将RS485控制信号拉低
REN0=1; //允许接收
for(index=0;index<rcv_len;index++)
{
START_T2(RCAP2_10ms); //定时器2的10MS的溢出率是自动重装方式
while(RI0==0&&TF2==0); //没有接收到什么AND定时器2没有溢出
if(RI0==1) //如果产生了接收中断
{ RI0=0;
ser_buffer[index]=SBUF0; //发送数据
if(index==LENGTH) //发到最后一个数据了
rcv_len+=ser_buffer[index]; //最后一个数据与rcv_len
if(index<rcv_len-2) //当前序列号小于3
BCC_sum^=ser_buffer[index]; //异或
/* BCC校验码计算数据块中所有的INFO字节然后将结果传送到数据块的最后一个字节
如下式所示
INFO[n] = BCC = ~ INFO[0] ⊕ INFO[1] ⊕ ... ⊕ INFO[n-1] (⊕ ... XOR ~…NOT)*/
}
else break;
} //完成的数据的下行,命令模式
STOP_T2(); //停用TIMER2
ES0=1; //串行口中断允许位
if(stx!=STX) return; //如果主机收到的是错的数据
if(index==rcv_len)
{
if(BCC_sum!=~ser_buffer[rcv_len-2]) return; //BCC码又不对
if(ser_buffer[rcv_len-1]!=ETX) return; //结束标志数据又不对
}
else return;
newdata=1; //成功 当中断接收到新数据时该位置位
}
uchar senddata()
{
uchar send_cnt=3; //主机最多发3次STX信号
uchar send_len;
uchar temp;
ES0=0; //串行中断允许
do
{ CON_485=1;
REN0=0;
SBUF0=STX; //主机向从机发送开始
while(TI0==0);
TI0=0;
CON_485=0; //发送完成就可以拉低
REN0=1;
START_T2(RCAP2_10ms); //自动重装方式
while(RI0==0&&TF2==0); //没有接收到什么 AND 定时器2没有溢出 //这里是查询,一定要有事发生才行
//很可能是串口收到数据(500B的应答信号)
STOP_T2();
if(RI0==1) //如果收到500B的响应
{ RI0=0;
temp=SBUF0;
delay_50us(1);
if(temp==ACK) break; //收到500B的ACK信号
}
}while(--send_cnt);
if(send_cnt==0) return COMM_ERR; //退出整个发送数据
send_len=ser_buffer[LENGTH]+5; //有5个附属字节
ser_buffer[send_len-2]=0;
ser_buffer[send_len-1]=ETX; //最后发送一个终止符ETX结束本次发送
REN0=0;
CON_485=1; //表示又要发送数据了
for(send_cnt=0;send_cnt<send_len;send_cnt++)
{
SBUF0=ser_buffer[send_cnt];
if(send_cnt<(send_len-2)) //非BCC和ETX字节
ser_buffer[send_len-2]^=ser_buffer[send_cnt]; //求BCC
if(send_cnt==send_len-3)
ser_buffer[send_len-2]=~ser_buffer[send_len-2]; //最后求到BCC
while(TI0==0);
TI0=0;
}
CON_485=0; //发送完成收工
REN0=1;
ES0=1; //开中断
return COMM_OK;
}
uchar ser_comm(void) //主机等待500B发回状态和响应数据.若在300MS内未检测到响应,则退出本次传输
{
uchar ser_wdg=120;
if(senddata()!=COMM_OK) return COMM_ERR; //数据发送失败
START_T2(RCAP2_2ms); //定时器溢出2MS
while(newdata==0&&ser_wdg!=0)
{
if(TF2)
{
START_T2(RCAP2_2ms);
ser_wdg--;
}
}
if(newdata)
{
newdata=0;
return COMM_OK;
}
else
return COMM_ERR; //在300MS未栓测到响应
}
#if mifs_request_en
uchar mifs_request(uchar _Mode,uchar idata *_TagType) //发出询问命令,栓查在在效范围内是否有卡存在
{
ser_buffer[SEQNR]=0; //数据交换包的序号
ser_buffer[COMMAND]=0x41; //命令对应的数值
ser_buffer[LENGTH]=0x01; //数据长度
ser_buffer[DATA]=_Mode; //只有一个数据
if(ser_comm()!=COMM_OK) //主机等待500B发回状态和响应数据.若在300MS内未检测到响应,则退出本次传输
return COMM_ERR;
if(ser_buffer[STATUS]==MI_OK) //500B---主机:响应模式的状态字符
{
_TagType[0]=ser_buffer[DATA];
_TagType[1]=ser_buffer[DATA+1];
}
return ser_buffer[STATUS]; //返回状态值
}
#endif
#if mifs_anticoll_en
uchar mifs_anticoll(uchar _Bcnt,uchar idata *_SNR) //开始防冲突操作,返回卡的序列号
{
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x42; //
ser_buffer[LENGTH]=0x01;
ser_buffer[DATA]=_Bcnt;
if(ser_comm()!=COMM_OK)
return COMM_ERR; //己经将数据发出
if(ser_buffer[STATUS]==MI_OK)
{
memcpy(_SNR,&ser_buffer[DATA],4); //复制字符得到卡序列号
}
return ser_buffer[STATUS];
}
#endif
#if mifs_anticoll2_en
uchar mifs_anticoll2(uchar _Encoll,uchar _Bcnt,uchar idata *_SNR) //可禁止或允许多张卡进入
{
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x71;
ser_buffer[LENGTH]=0x02;
ser_buffer[DATA]=_Encoll;
ser_buffer[DATA+1]=_Bcnt;
if(ser_comm()!=COMM_OK)
return COMM_ERR;
if(ser_buffer[STATUS]==MI_OK)
{
memcpy(_SNR,&ser_buffer[DATA],4); //复制字符得到卡序列号
}
return ser_buffer[STATUS];
}
#endif
#if mifs_select_en
uchar mifs_select(uchar idata *_SNR,uchar idata *_Size) //选择卡,返回卡的存贮容量
{
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x43;
ser_buffer[LENGTH]=0x04;
memcpy(&ser_buffer[DATA],_SNR,4); //数据字节为卡的序列号
if(ser_comm()!=COMM_OK)
return COMM_ERR;
if(ser_buffer[STATUS]==MI_OK)
{
*_Size=ser_buffer[DATA]; //返回卡的容量
}
return ser_buffer[STATUS];
}
#endif
#if mifs_authentication_en
uchar mifs_authentication(uchar _Mode,uchar _SecNr) //开始进行验证操作
{
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x44;
ser_buffer[LENGTH]=0x02;
ser_buffer[DATA]=_Mode;
ser_buffer[DATA+1]=_SecNr; //所访问卡的扇区号 必须小于16
if(ser_comm()!=COMM_OK)
return COMM_ERR;
return ser_buffer[STATUS];
}
#endif
#if mifs_authentication2_en
uchar mifs_authentication2(uchar _Mode,uchar _SecNr,uchar _KeyNr) //可选择密匙区验证
{ //_KeyNr 用于证实的密钥区号
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x72;
ser_buffer[LENGTH]=0x03;
ser_buffer[DATA]=_Mode;
if(_SecNr<=32)
ser_buffer[DATA+1]=_SecNr;
else
ser_buffer[DATA+1]=32+((_SecNr-32)<<2); //为了支持S70卡
ser_buffer[DATA+2]=_KeyNr;
if(ser_comm()!=COMM_OK)
return COMM_ERR;
return ser_buffer[STATUS];
}
#endif
#if mifs_authKey_en //ISO 9798-2在RWM和RFID之间使用3轮确认
uchar mifs_authKey(uchar _Mode,uchar _SecNr,uchar *_Key) //直接密码验证
{ //_Key用于证实的密码首址
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x73;
ser_buffer[LENGTH]=0x08;
ser_buffer[DATA]=_Mode;
if(_SecNr<=32)
ser_buffer[DATA+1]=_SecNr;
else
ser_buffer[DATA+1]=32+((_SecNr-32)<<2); //为了支持S70卡
memcpy(&ser_buffer[DATA+2],_Key,6); //将密码向500B上面发
if(ser_comm()!=COMM_OK)
return COMM_ERR;
return ser_buffer[STATUS];
}
#endif
#if mifs_halt_en
uchar mifs_halt(void) //将卡置于挂起状态
{
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x45;
ser_buffer[LENGTH]=0x00;
if(ser_comm()!=COMM_OK)
return COMM_ERR;
return ser_buffer[STATUS];
}
#endif
#if mifs_read_en
uchar mifs_read(uchar _Adr,uchar idata *_Data) //从卡中相应地址中读出一个16字节的数据块
{
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x46;
ser_buffer[LENGTH]=0x01;
ser_buffer[DATA]=_Adr;
if(ser_comm()!=COMM_OK)
return COMM_ERR;
if(ser_buffer[STATUS]==MI_OK) //如果读成功
{
memcpy(_Data,&ser_buffer[DATA],16); //将数据复制出来
}
return ser_buffer[STATUS];
}
#endif
#if mifs_write_en
uchar mifs_write(uchar _Adr,uchar idata *_Data) //向指定地址写入16字节的数据
{
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x47;
ser_buffer[LENGTH]=17;
ser_buffer[DATA]=_Adr;
memcpy(&ser_buffer[DATA+1],_Data,16); //将要发送的数据复制到数据帧中
if(ser_comm()!=COMM_OK)
return COMM_ERR;
return ser_buffer[STATUS];
}
#endif
#if mifs_increment_en
uchar mifs_increment(uchar _Adr,long idata *_Value) //增加访问单元块的字节中的数值,并将结果保存在卡的内部寄存器
{ uchar *temp=(uchar *)_Value; //temp为首地址
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x48;
ser_buffer[LENGTH]=5;
ser_buffer[DATA]=_Adr;
ser_buffer[DATA+1]=*(temp+3);
ser_buffer[DATA+2]=*(temp+2);
ser_buffer[DATA+3]=*(temp+1);
ser_buffer[DATA+4]=*temp;
if(ser_comm()!=COMM_OK)
return COMM_ERR;
return ser_buffer[STATUS];
}
#endif
#if mifs_decrement_en
uchar mifs_decrement(uchar _Adr,long idata *_Value)
{
uchar *temp=(uchar *)_Value;
ser_buffer[SEQNR]=0;
ser_buffer[COMMAND]=0x49;
ser_buffer[LENGTH]=5;
ser_buffer[DATA]=_Adr;
ser_buffer[DATA+1]=*(temp+3);
ser_buffer[DATA+2]=*(temp+2);
ser_buffer[DATA+3]=*(temp+1);
ser_buffer[DATA+4]=*temp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -