gentlerain 发表于 2011-4-25 11:58:11

处女贴,看到这个版块的出现,迫不及待地把自己刚做好的RFID卡读卡解码程序同大家分享,带

潜水有N天后,今天终于与大家分享一下我的东东。
看到这个版块的出现,相当鸡动,因为这几天刚好在搞RFID卡读卡解码的程序。
在坛里找了些资料,也看了此人家的程序。部分是用延时方式,用定时方式的好像说成功率不高。
由于延时方式占用CPU资源太高,所以我还是想自己写一个用定时器+外部中断引脚方式的程序,
当然,各位可以根据自己硬件的用定时器输入捕获方式,原理一样。
我用的是STM8三合1的板子做的,用PC3口作读卡头数据输入(中断方式),
用定时器2时间计数器,把解码得到的数据通过串口发送出去。
下面贴出我写的中断服务程序,可以直接使用。
环境是STVD V4.1.6,
编译器是COSMIC STM8 C Compiler 16K ,Version: 4.3.1
调用的库有:GPIO,TIM2

相关宏定义:

//RF数据引脚
#define DATA_PORT   GPIOC
#define DATA_PIN    GPIO_PIN_3

//定义每一位的宽度,t/4us
#define BIT_TIME      128//一位数据时间
#define HAFE_TIME       64//半位数据时间
#define ERROR_BAND      10//允许是时间误差
#define BIT_HAFE_TIME   192//1.5位数据时间

//端口C外部中断,捕捉RFID卡数据输出的所有电平跳变
@far @interrupt void IntSrvPortC(void)
{
    unsigned char ucTemp;
    unsigned char ucCurrBitTime;
    _Bool bData;
   
    static _Bool s_bLastData;
   
    //先读取定时器计数器,即与上次中断的时间间隔,这是当前位的位宽
    //定时器每个值为4us,单独开启一个定时器计数
    if(TIM2->CNTRH == 0)
    {
      ucCurrBitTime = TIM2->CNTRL;
    }
    else//如果定时时间超过255,则以255计算
    {
      ucCurrBitTime = 255;
    }
    TIM2_SetCounter(0);//复位计数器,从0开始重新计时
   
    //接收到数据,接收超时计数器清零
    g_ucNoDataCnt = 0;
   
    //开始接收
    if(s_ucBitCounter < 18)//同步头,一共9个1,所以有18个跳变
    {
      if(s_ucBitCounter == 0)
      {
            //先找上升沿,数据0
            if(RESET != GPIO_ReadInputPin(DATA_PORT,DATA_PIN))
            {
                //找到上升沿,进入下一步
                s_ucBitCounter = 1;
            }
      }
      else if(s_ucBitCounter == 1)
      {
            //再找下降沿,如果上次的上升沿与本下降沿时间间隔为1个数据周期,则为连续的"01"
            //高电平时间持续1个数据周期,必定是"01"
            if(RESET == GPIO_ReadInputPin(DATA_PORT,DATA_PIN)//本次为下降沿
            && ucCurrBitTime > BIT_TIME - ERROR_BAND)//一个周期以上的高电平
            {
                //找到"01",进入下一步
                s_ucBitCounter = 2;
            }
            else//不是"01",重新找"01"
            {
                s_ucBitCounter = 0;
            }
      }
      else
      {
            //已经找到"01"了,接下来要再找到连续的8个1
            //若两个电平跳变间隔1个数据周期,则必定出现0,重新找"01"
            if(ucCurrBitTime > BIT_TIME - ERROR_BAND)
            {
                if(RESET == GPIO_ReadInputPin(DATA_PORT,DATA_PIN))//下降沿
                {
                  //本次下降沿,重新找上升沿
                  s_ucBitCounter = 0;
                }
                else//本次上升沿,接着找下降沿
                {
                  s_ucBitCounter = 1;
                }
            }
            else
            {
                s_ucBitCounter++;
                bData = 1;//为下面接收到数据作准备
            }
      }
    }
    else//获取同步头成功
    {
      //根据本次电平跳变情况,与上次跳变间隔,及上次数据位,
      //可判断出本次跳变是空跳还是有效数据
      //本次是下降沿
      if(RESET == GPIO_ReadInputPin(DATA_PORT,DATA_PIN))
      {
            //与上次跳变间隔1个数据周期,说明高电平持续了1个数据周期,必然是1
            if(ucCurrBitTime > BIT_TIME - ERROR_BAND)
            {
                bData = 1;
            }
            //与上次跳变间隔半个周期,若上次数据为1,本次数据也为1
            //即连续的两个1
            else if(s_bLastData == 1)
            {
                bData = 1;
            }
            //间隔不足1个数据周期,且上次数据为0,则本次是空跳
            else
            {
                return;
            }
      }
      //本次上升沿
      else
      {
            //与上次跳变间隔1个数据周期,说明低电平持续了1个数据周期,必然是0
            if(ucCurrBitTime > BIT_TIME - ERROR_BAND)
            {
                bData = 0;
            }
            //与上次跳变间隔半个周期,若上次数据为0,本次数据也为0
            //即连续的两个0
            else if(s_bLastData == 0)
            {
                bData = 0;
            }
            //间隔不跳1个数据周期,且上次数据为1,则本次是空跳
            else
            {
                return;
            }
      }
      
      if(s_ucBitCounter >= 73)//同步头18个跳变,加上55个数据位
      {
            //接收到完成数据,重新开始接收数据
            s_ucBitCounter = 0;
            //把数据移出缓冲区,且清空缓冲区
            for(ucTemp=0;ucTemp<11;ucTemp++)
            {
                g_ucData = g_ucDataBuff & 0x1f;
            }
            g_bitResevData = TRUE;//接收完成,处理数据
      }
      else
      {
            //把数据放入缓冲区
            ucTemp = s_ucBitCounter - 18;//减去同步头的18个跳变
            ucTemp /= 5;//得到当前接收到的数据属于第几个字节
            g_ucDataBuff <<= 1;//从高位开始接收
            g_ucDataBuff += bData;
            s_ucBitCounter++;//继续接收下一位
      }
    }
   
    s_bLastData = bData;//更新历史数据
    return;
}

gentlerain 发表于 2012-12-5 21:54:40

本帖最后由 gentlerain 于 2012-12-5 21:56 编辑

czg94215 发表于 2012-11-9 10:19 static/image/common/back.gif
请教一下楼主, 收到的数据怎么解码 换算得到卡号呢?

各位抱歉了,这么久都没有回复大家的问题.
我这个程序是125K非接触ID卡的解码程序,其中卡体中主要有台湾4001卡和瑞士H4001卡,EM4100。它们都采用125kHz的典型工作频率,有64位激光可编程ROM,调制方式为曼彻斯特码(Manchester)调制,位数据传送周期为512μs,其64位数据结构如下图所示。

连续9位“1”作为头数据,是读取数据时的同步标识;D00~D93位是用户定义数据位;P0~P9是行奇校验位,PC0~PC3是列奇校验位,最后位“0”是结束标志。非接触ID卡的这种数据结构非常有利于判断读出数据的正确性。
至于读到的数据如何转换成卡号,是这样的.
以上图为说明,除了9个同步头和其它的校验,你将收到5个字节的数据.即该芯片的十位 16 进制唯一序列号代码是 84C2A6E195。该卡的序列号代码在卡面印制卡号时,又以这串序列号代码为依据,采用掐头留尾、分段相加、高低倒置等多种转换方式,将其转换为人们易于理解的十进制代码。例如:将上述16进制序列号的低6位印刷为8位10进制代码,即取‘A6E195’转换为‘10936665’;又如:将上述 16 进制序列号取其低 6 位,并将其分为前两位+后4位的微根格式:‘A6’+‘E195’再分别转换为两段 5 位的 10 进制数,段间以小数点或豆号隔开,即印刷卡号为:‘00166,57749’。




gentlerain 发表于 2012-12-5 22:08:01

正面上传一份清晰的PDF文档,内容同上面的原理图.


gentlerain 发表于 2013-4-17 15:41:49

下面再详细说说卡号的表示方法。
由于各个厂家的读卡器译码格式不尽相同,在读卡输出时,读出的二进制或十六进制(Hex)结果应该是唯一的,但是又可以通过以下几种主要换算办法,输出不同结果的十进制卡号(Dec),因此,请您一定在购买卡片或卡片喷号时,注意卡号格式的一致性:

1、格式0:10位十六进制的ASCII字符串,即10 Hex格式。
如:某样卡读出十六进制卡号为:“01026f6c3a”。

2、格式1:将格式0中的后8位,转换为10位十进制卡号,即8H---10D。
即将“ 026f6c3a”转换为:“0040856634”。

此格式喷码喷码较为常见。

3、格式2:将格式0中的后6位,转换为8位十进制卡号,即6H---8D。
即将“ 6f6c3a”转换为:“07302202”。

4、格式3:将格式0中的倒数第5、第6位,转换为3位十进制卡号,再将后4位,转换为5位十进制卡号,中间用“,”分开,即“2H + 4H”。
即将2H“ 6f”转换为:“111”,4H “6c3a”转为“27706”。 最终将2段号连在一起输出为“111,27706”。

此格式为标准的韦根26(V26)格式,只使用最后6位编码,也有许多卡采用此格式喷码。

5、格式4:将格式0中后8位的前4位,转换为5位十进制卡号,再将后4位,转换为5位十进制卡号,中间用“,”分开,即“4Hex + 4Hec”。
照此推算结果为:00623,27706 (4H+4H)。

yuzr 发表于 2011-4-25 12:04:52

mark

gaoyukun 发表于 2011-4-25 12:36:04

mark!

unic 发表于 2011-4-25 12:56:19

mark

jack_yu 发表于 2011-4-25 14:01:55

mark!!!!

shuiyp 发表于 2011-4-27 11:54:28

mark

zhangjinxing 发表于 2011-4-27 12:00:46

mark

gotearcom 发表于 2011-4-27 12:01:48

我也来mark

sdql213 发表于 2011-5-4 10:50:59

标记~ ~

zyw19987 发表于 2011-5-4 11:54:29

RFID 定时器解码

xiaowei0588 发表于 2011-5-12 14:37:11

很好!

Totry 发表于 2011-5-12 14:59:50

mark

liubo1234 发表于 2011-5-12 15:20:00

偶早期做过一个用STC的产品
用M0做了个具备读写功能的产品

Gloriousle 发表于 2011-5-12 20:19:58

标记下。以后有用。

dzmcs 发表于 2011-5-12 20:24:49

mark rfid

Lufy 发表于 2011-5-13 00:53:14

mark

dong889 发表于 2011-5-13 01:07:57

Mark

honami520 发表于 2011-5-13 01:12:54

呵呵,我也准备弄这个呢!!!思路基本清楚了,正好参考下!

plc_avr 发表于 2011-5-13 07:38:56

mark!

jssz_hf 发表于 2011-5-18 16:06:59

回复【17楼】honami520
-----------------------------------------------------------------------

又见   哈哈

oaixuw 发表于 2011-5-18 16:31:50

MARK

yanrz 发表于 2011-6-1 22:31:48

想找个写的程序!
按照datasheet写的序列写下去数据没改变。还是原来的数据。

pjdu 发表于 2011-6-1 22:49:31

mark

baiheshu 发表于 2011-6-3 07:11:26

回复【楼主位】gentlerain
-----------------------------------------------------------------------

我试了一下,怎么不行啊


/* Initialize I/O in Input Mode with Interrupt */
GPIO_Init(GPIOB, GPIO_Pin_0, GPIO_Mode_In_PU_IT );
/* Initialize the Interrupt sensitivity */
EXTI_SetPinSensitivity(EXTI_Pin_0, EXTI_Trigger_Rising_Falling );


进入中断后,定时器2的值不对
这是定时器2的设置
TIM2_DeInit();
/* Enable TIM2 clock */
CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE);
TIM2_TimeBaseInit(TIM2_Prescaler_64, TIM2_CounterMode_Up, 255);//定时单位4us
TIM2_ARRPreloadConfig(ENABLE);
TIM2_ITConfig (TIM2_IT_Update,ENABLE);
TIM2_Cmd(ENABLE);


烦楼主帮忙

IAR环境

wpnx 发表于 2011-6-3 08:19:14

MARK

baiheshu 发表于 2011-6-3 09:13:46

感觉定时器2总是弄不好

guohua0710 发表于 2011-6-3 09:23:48

感谢分享!

baiheshu 发表于 2011-6-3 10:19:13

是不是我的定时器设置不对啊

baiheshu 发表于 2011-6-6 21:59:30

没人用stm8l吗

gordon85 发表于 2011-6-7 09:56:45

请问楼主,这段程序可以解什么样的标签卡,译码好像是BIPHASE码吧。。。

baiheshu 发表于 2011-6-7 19:33:54

说的有道理,但我没实现,我用stm8L

dzmcs 发表于 2011-6-7 20:44:00

mark rfid

forhappy 发表于 2011-6-14 00:46:54

mark一下。。最近准备做一个,

baiheshu 发表于 2011-6-15 16:56:02

没实现,倒是用延时实现了,很稳定很强大

jetimchen 发表于 2011-6-17 02:13:53

MARK

311711 发表于 2011-7-15 10:15:29

liubo1234 发表于 2011-7-15 16:19:05

13.56MHz TypeA解码吧

updown 发表于 2011-7-16 10:13:44

remind

fengzs918 发表于 2011-8-2 16:54:00

stm32据说很猛

xindeqing 发表于 2011-9-22 10:20:47

了解下
!!

ljh42728620 发表于 2011-9-22 11:25:29

mark

lostmj 发表于 2011-9-22 13:19:10

mark

Small_sand 发表于 2011-10-14 16:30:11

不知道哪款读卡器?

hkap 发表于 2011-11-16 11:44:25

我做的门禁用延时做的,很稳定,已经量产了

psocfans 发表于 2011-11-16 11:50:19

mark

huaifeng 发表于 2012-1-3 13:36:59

mark!!!!

amazing030 发表于 2012-1-12 14:54:35

有没有哪位成功了?麻烦贴出来参考下

chenqi 发表于 2012-1-12 15:02:38

mark

hwarm 发表于 2012-1-19 15:28:57

mark

tangwei039 发表于 2012-1-19 15:58:18

mark

rainingfore 发表于 2012-2-2 10:34:50

mark

xiangzhi28 发表于 2012-2-7 15:11:00

RFID卡读卡器解码程序

wolegequ 发表于 2012-3-26 16:14:24

125k 的 RFID卡读卡器解码程序

xrwf_2009 发表于 2012-3-26 16:19:20

注释做得很好哦

smilelb 发表于 2012-5-11 01:49:01

LZ好细致啊,每条code都有批注...

smilelb 发表于 2012-5-11 10:19:15

楼主好细致啊,每一行code都给了注释...

sacq12 发表于 2012-6-3 00:47:33

马克~{:smile:}

Iory1984 发表于 2012-6-5 14:13:01

非常感谢,正好需要

lookdown 发表于 2012-6-6 13:20:45

谢谢分享

cos 发表于 2012-6-9 15:26:50

马克帕克

sankycui 发表于 2012-6-20 16:28:13

mark!!!

林13623098033 发表于 2012-6-24 22:32:08

支持!!!

chtxzy 发表于 2012-7-2 11:18:08

谢谢分享

gmail@gmail.com 发表于 2012-7-19 08:46:21

mark{:biggrin:}

爱上DIY的汤姆猫 发表于 2012-7-27 09:59:47

学习了,支持。

xzsxiao213 发表于 2012-8-26 11:58:20

EM ID卡的ID解码程序

czg94215 发表于 2012-9-6 20:51:24

RFID 记号,谢谢

dahaicaoyuan 发表于 2012-9-7 21:57:02

rfid编码解码程序

fx5700 发表于 2012-9-8 01:23:09

mark好东西

fx5700 发表于 2012-9-8 13:34:26

能说下定时器怎么设置吗?

fx5700 发表于 2012-9-8 15:46:36

经验证可用

86793 发表于 2012-9-17 17:31:23

你好,请问一下EM4095在收发状态时,没有进行读卡时(即ID卡没有靠近时)的电流也有100来mA吗?

gentlerain 发表于 2012-9-17 23:12:12

86793 发表于 2012-9-17 17:31 static/image/common/back.gif
你好,请问一下EM4095在收发状态时,没有进行读卡时(即ID卡没有靠近时)的电流也有100来mA吗? ...

这个我还真的不太清楚,没用过这个。

86793 发表于 2012-9-18 09:10:39

gentlerain 发表于 2012-9-17 23:12 static/image/common/back.gif
这个我还真的不太清楚,没用过这个。

有哪位朋友知道的,回答一下。自己来顶一下。

czg94215 发表于 2012-9-21 13:10:17

每次读的数据都不一样.楼主这程序有谁用成功过

ddcchh 发表于 2012-9-28 09:01:07

抽时间试一下!谢绝!

weiwei4 发表于 2012-9-29 10:26:52

有时候慢慢学习,谢谢分享

onebobo126com 发表于 2012-10-11 14:18:51

mark看看

czg94215 发表于 2012-11-9 10:19:59

请教一下楼主, 收到的数据怎么解码 换算得到卡号呢?

linbin250 发表于 2012-11-21 14:03:15

硬件我还没有弄,不过可以先研究代码{:smile:}

linbin250 发表于 2012-11-21 14:05:16

LZ 程序的注释很详细,支持LZ!

lncwangfeilnc 发表于 2012-11-26 18:10:27

{:smile:}{:lol:}

chengying 发表于 2012-12-5 19:36:40

mark


gentlerain 发表于 2012-12-5 22:04:25

下面上传我根据一块读卡头重画的读卡原理图,可用于读取125K的非接触式ID卡.
下图中,PWM输入125KHz的方波,345uH的电感就是感应线圈,可以自己用漆包线绕制.当有卡进入读卡区域时,在LM358的7脚即可接收到数据.

czg94215 发表于 2012-12-22 09:56:03

gentlerain 发表于 2012-12-5 22:08 static/image/common/back.gif
正面上传一份清晰的PDF文档,内容同上面的原理图.

谢谢楼主的详细解答.谢谢

TNTHUAHUA 发表于 2013-1-30 12:54:56

想学习下.....

gjdzgcs2012 发表于 2013-2-14 22:36:56

学习!
mark!

JamesFanQin 发表于 2013-3-11 21:58:46

      mark

dbwu8280 发表于 2013-4-10 13:52:10

MARK!
后续学习

tuowai 发表于 2013-5-4 21:09:11

收藏,以后能用上!

myyule1 发表于 2013-5-12 10:17:19

呵呵,我也准备弄这个呢!!!思路基本清楚了,正好参考下!

hachineys2012 发表于 2013-5-23 11:08:51

mark!!!!!!!!

380523337 发表于 2013-5-28 10:36:38

你好,能不能把定时器2设置贴出?还有可以用定时器1吗?

gentlerain 发表于 2013-5-28 12:15:12

本帖最后由 gentlerain 于 2013-5-28 12:16 编辑

380523337 发表于 2013-5-28 10:36 static/image/common/back.gif
你好,能不能把定时器2设置贴出?还有可以用定时器1吗?

用任意的定时器都可以,只要定时器的Counter每个值等于4us即可.
不需要开任何中断.前提是不会溢出,因为此程序没有溢出处理.
而且还能与其它定时器共用.
至于定时器的设置,就不用我教你了吧

jaskle 发表于 2013-5-28 18:07:38

这个好,最近在做

whats 发表于 2013-5-31 21:43:38

{:shocked:}

380523337 发表于 2013-6-1 08:34:30

gentlerain 发表于 2013-5-28 12:15 static/image/common/back.gif
用任意的定时器都可以,只要定时器的Counter每个值等于4us即可.
不需要开任何中断.前提是不会溢出,因为此 ...

谢谢!{:lol:} {:lol:} {:lol:}
页: [1] 2
查看完整版本: 处女贴,看到这个版块的出现,迫不及待地把自己刚做好的RFID卡读卡解码程序同大家分享,带