我这里介绍的是常用的125KHz的ID卡。ID卡内固化了64位数据,由5个区组成:9个引导位、10个行偶校验位“PO~P9′’、4个列偶校验位“PC0~PC3”、40个数据位“D00~D93”和1个停止位S0。9个引导位是出厂时就已掩膜在芯片内的,其值为“111111111”,当它输出数据时,首先输出9个引导位,然后是10组由4个数据位和1个行偶校验位组成的数据串,其次是4个列偶校验位,最后是停止位“0”。“D00~D13”是一个8位的晶体版本号或ID识别码。“D20~D93”是8组32位的芯片信息,即卡号。注意校验位都是偶校验,网上有些资料写的是奇校验,很明显是错的,如果是奇校验的话,在一个字节是FF的情况下,很容易就出现9个1,这样引导位就不是唯一的了,也就无法判断64位数据的起始位了。
数据结构如下图:
我读的一个ID卡数据是111111111 10001 00101 00000 00011 00000 01010 00000 11011 00110 01100 01100,对应的ID卡号是01050d36。
ID卡数据采用曼彻斯特编码,1对应着电平下跳,0对应着电平上跳。每一位数据的时间宽度都是一样的(1T)。由于电路参数的差别,时间宽度要实际测量。解码芯片采用U2270B,单片机采用89S52。U2270B的输出脚把解码得到的曼彻斯特码输出到89S52的INT脚。在89S52的外部中断程序中完成解码。
在没有ID卡在读卡器射频范围内时,U2270B的输出脚会有杂波输出,ID卡进入读卡器射频范围内后,会循环发送64位数据,直到ID卡离开读卡器的有效工作区域。
根据ID卡的数据结构,64位数据的最后一位停止位是0。最开始的9位引导位是1,可以把0111111111做为引导码。也就是说在ID卡进入读卡器工作范围后,丢掉ID卡发送的第一个64位码,检测最后1位0,然后检测ID卡发送的第2个64位码的9个引导码111111111,引导码检测成功后,解码剩余的55位码。得到ID卡的数据。然后丢掉ID卡发送的第3个64位码,检测第3个64位码的最后1位0,再检测ID卡发送的第4个64位码。这样连续3次检测到同一个码,就认为解码到了正确的ID卡号。
之所以要丢掉ID卡发送的第一个64位数据,是因为U2270B在没有ID卡刷卡时,也会输出波形到89S52的INT脚,这样将无法判断ID卡数据的头码。从第2个码开始解码能确保检测的头码正确。丢掉第3个码的原因是在检测第2个码时,最后一位停止位也被解码,那么就不能采用0111111111来检测第3个码了,只能检测第3个码的最后1位0,再解码第4个码。
下面详细介绍解码原理,程序中要用到的变量定义如下:
Bit_over:为0,表示1位数据处理完,为1,表示当前处于数据位的跳变处。
Head_start:检测到头码0时,把head_start置1,然后连续检测到8次下降沿时间间隔大于0.75T,小于1.25T,并且head_start为1,置位头码标志head_flag。Head_start的作用就是保证是连续检测到0111111111。
Head_flag:头码标志,检测到0111111111后置1。
Prev_bit:保存当前数据位的值,下一位数据的值要根据当前位的值来判断。
Pulse_width:16位数据,保存INT脚两次下降沿之间的时间间隔。
Bit_cnt:检测完头码后,每次检测5位数据,也就是一行。
Row:行数,不包括头码,总共11行,用来判断64位数据是否接收完。
Buff[11]:缓冲区,用来保存接收的11行数据。每个数据只有低5位有效。
Id_data[11]:保存缓冲区的11个数据,进行校验,得到ID卡号。
头码检测
外部中断设置成下降沿中断,在外部中断函数中,用T1来计算两次下降沿的时间间隔。从上图可以看到,64位为0,1位为1,64到1两次下降沿之间的间隔大于0.75T,小于1.25T,认为检测到数据0-1的变化。这时置标志位head_start为1,然后连续检测到8次下降沿间隔时间大于0.75T,小于1.25T,且head_start为1,认为检测到了0111111111,这时置头码标志head_flag,因为这时下降沿在数据1的电平跳变处,数据1还没接收完,把bit_over置1,prev_bit置1。
数据位检测
分析曼彻斯特码,有以下5种情况,其它情况下是错误码。
Bit_over = 1时,也就是进入下降沿中断时,上一位的数据没处理完
1、
(两次下降沿时间间隔1T)
Bit_over=1时,x=1T,bit_cnt+1,当前位为1,bit_over仍为1。
2、
(两次下降沿时间间隔1.5T)
Bit_over=1时,x=1.5T,bit_cnt+1,当前位为0,bit_over变为0。
3、
(两次下降沿时间间隔2T)
Bit_over =1时,x=2T,bit_cnt+2,一次接收2位数据,第1位数据与上一位值相反,第2位数据与上一位值相同,bit_over仍为1。
Bit_over=0时,有2种情况
4、
(两次下降沿时间间隔1T)
Bit_over = 0时,x = 1T,bit_cnt+1,当前位与上一位值相同,bit_over仍为0。
5、
(两次下降沿时间间隔1.5T)
Bit_over=0时,x=1.5T,bit_cnt+2,一次接收2位数据,第1位值与上一位值相同,第2位值与上一位值相反,bit_over变为1。
解ID卡码我想了好几天,也和网上的解码方法对比了下,觉得采用这种解码方法程序量很少,也不会占用很多硬件资源,是一种很简便的方法。如果大家有更好的方法,可以一起讨论。
文章评论(0条评论)
登录后参与讨论