搜索
bottom↓
回复: 181

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

  [复制链接]

出0入0汤圆

发表于 2011-4-25 11:58:11 | 显示全部楼层 |阅读模式
潜水有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[ucTemp] = g_ucDataBuff[ucTemp] & 0x1f;
            }
            g_bitResevData = TRUE;//接收完成,处理数据
        }
        else
        {
            //把数据放入缓冲区
            ucTemp = s_ucBitCounter - 18;//减去同步头的18个跳变
            ucTemp /= 5;//得到当前接收到的数据属于第几个字节
            g_ucDataBuff[ucTemp] <<= 1;//从高位开始接收
            g_ucDataBuff[ucTemp] += bData;
            s_ucBitCounter++;//继续接收下一位
        }
    }
   
    s_bLastData = bData;//更新历史数据
    return;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

有一句段子是这样说的,身家过亿的只关心自己的身体,身家千万的,在担心传承,勉强糊口度日才天天看国际新闻,关心国家大事。

出0入0汤圆

 楼主| 发表于 2012-12-5 21:54:40 | 显示全部楼层
本帖最后由 gentlerain 于 2012-12-5 21:56 编辑
czg94215 发表于 2012-11-9 10:19
请教一下楼主, 收到的数据怎么解码 换算得到卡号呢?


各位抱歉了,这么久都没有回复大家的问题.
我这个程序是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’。




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2012-12-5 22:08:01 | 显示全部楼层
正面上传一份清晰的PDF文档,内容同上面的原理图.


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 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)。

出50入0汤圆

发表于 2011-4-25 12:04:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-25 12:36:04 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-4-25 12:56:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-25 14:01:55 | 显示全部楼层
mark!!!!

出0入0汤圆

发表于 2011-4-27 11:54:28 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-27 12:00:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-27 12:01:48 | 显示全部楼层
我也来mark

出0入0汤圆

发表于 2011-5-4 10:50:59 | 显示全部楼层
标记~ ~

出0入0汤圆

发表于 2011-5-4 11:54:29 | 显示全部楼层
RFID 定时器解码

出0入0汤圆

发表于 2011-5-12 14:37:11 | 显示全部楼层
很好!

出0入0汤圆

发表于 2011-5-12 14:59:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-12 15:20:00 | 显示全部楼层
偶早期做过一个用STC的产品
用M0做了个具备读写功能的产品

出0入0汤圆

发表于 2011-5-12 20:19:58 | 显示全部楼层
标记下。以后有用。

出0入0汤圆

发表于 2011-5-12 20:24:49 | 显示全部楼层
mark rfid

出0入0汤圆

发表于 2011-5-13 00:53:14 | 显示全部楼层
mark

出100入0汤圆

发表于 2011-5-13 01:07:57 | 显示全部楼层
Mark

出0入90汤圆

发表于 2011-5-13 01:12:54 | 显示全部楼层
呵呵,我也准备弄这个呢!!!思路基本清楚了,正好参考下!

出0入0汤圆

发表于 2011-5-13 07:38:56 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-5-18 16:06:59 | 显示全部楼层
回复【17楼】honami520
-----------------------------------------------------------------------

又见   哈哈

出0入0汤圆

发表于 2011-5-18 16:31:50 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-6-1 22:31:48 | 显示全部楼层
想找个写的程序!
按照datasheet写的序列写下去数据没改变。还是原来的数据。

出0入0汤圆

发表于 2011-6-1 22:49:31 | 显示全部楼层
mark

出0入0汤圆

发表于 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环境

出0入0汤圆

发表于 2011-6-3 08:19:14 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-6-3 09:13:46 | 显示全部楼层
感觉定时器2总是弄不好

出0入0汤圆

发表于 2011-6-3 09:23:48 | 显示全部楼层
感谢分享!

出0入0汤圆

发表于 2011-6-3 10:19:13 | 显示全部楼层
是不是我的定时器设置不对啊

出0入0汤圆

发表于 2011-6-6 21:59:30 | 显示全部楼层
没人用stm8l吗

出0入0汤圆

发表于 2011-6-7 09:56:45 | 显示全部楼层
请问楼主,这段程序可以解什么样的标签卡,译码好像是BIPHASE码吧。。。

出0入0汤圆

发表于 2011-6-7 19:33:54 | 显示全部楼层
说的有道理,但我没实现,我用stm8L

出0入0汤圆

发表于 2011-6-7 20:44:00 | 显示全部楼层
mark rfid

出0入0汤圆

发表于 2011-6-14 00:46:54 | 显示全部楼层
mark一下。。最近准备做一个,

出0入0汤圆

发表于 2011-6-15 16:56:02 | 显示全部楼层
没实现,倒是用延时实现了,很稳定很强大

出0入0汤圆

发表于 2011-6-17 02:13:53 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-7-15 10:15:29 | 显示全部楼层

出0入0汤圆

发表于 2011-7-15 16:19:05 | 显示全部楼层
13.56MHz TypeA解码吧

出0入0汤圆

发表于 2011-7-16 10:13:44 | 显示全部楼层
remind

出0入0汤圆

发表于 2011-8-2 16:54:00 | 显示全部楼层
stm32据说很猛

出0入0汤圆

发表于 2011-9-22 10:20:47 | 显示全部楼层
了解下
!!

出0入0汤圆

发表于 2011-9-22 11:25:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-22 13:19:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-14 16:30:11 | 显示全部楼层
不知道哪款读卡器?

出0入0汤圆

发表于 2011-11-16 11:44:25 | 显示全部楼层
我做的门禁用延时做的,很稳定,已经量产了

出0入0汤圆

发表于 2011-11-16 11:50:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-3 13:36:59 | 显示全部楼层
mark!!!!

出20入0汤圆

发表于 2012-1-12 14:54:35 | 显示全部楼层
有没有哪位成功了?麻烦贴出来参考下

出0入0汤圆

发表于 2012-1-12 15:02:38 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-19 15:28:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-19 15:58:18 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-2 10:34:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-7 15:11:00 | 显示全部楼层
RFID卡读卡器解码程序

出0入0汤圆

发表于 2012-3-26 16:14:24 | 显示全部楼层
125k 的 RFID卡读卡器解码程序

出0入0汤圆

发表于 2012-3-26 16:19:20 | 显示全部楼层
注释做得很好哦

出0入0汤圆

发表于 2012-5-11 01:49:01 | 显示全部楼层
LZ好细致啊,每条code都有批注...

出0入0汤圆

发表于 2012-5-11 10:19:15 | 显示全部楼层
楼主好细致啊,每一行code都给了注释...

出0入0汤圆

发表于 2012-6-3 00:47:33 | 显示全部楼层
马克~

出0入0汤圆

发表于 2012-6-5 14:13:01 | 显示全部楼层
非常感谢,正好需要

出0入0汤圆

发表于 2012-6-6 13:20:45 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2012-6-9 15:26:50 | 显示全部楼层
马克帕克

出0入0汤圆

发表于 2012-6-20 16:28:13 | 显示全部楼层
mark!!!

出0入0汤圆

发表于 2012-6-24 22:32:08 | 显示全部楼层
支持!!!

出0入0汤圆

发表于 2012-7-2 11:18:08 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2012-7-19 08:46:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-7-27 09:59:47 | 显示全部楼层
学习了,支持。

出0入0汤圆

发表于 2012-8-26 11:58:20 | 显示全部楼层
EM ID卡的ID解码程序

出0入0汤圆

发表于 2012-9-6 20:51:24 | 显示全部楼层
RFID 记号,谢谢

出0入0汤圆

发表于 2012-9-7 21:57:02 | 显示全部楼层
rfid编码解码程序

出0入0汤圆

发表于 2012-9-8 01:23:09 来自手机 | 显示全部楼层
mark好东西

出0入0汤圆

发表于 2012-9-8 13:34:26 | 显示全部楼层
能说下定时器怎么设置吗?

出0入0汤圆

发表于 2012-9-8 15:46:36 | 显示全部楼层
经验证可用

出0入0汤圆

发表于 2012-9-17 17:31:23 | 显示全部楼层
你好,请问一下EM4095在收发状态时,没有进行读卡时(即ID卡没有靠近时)的电流也有100来mA吗?

出0入0汤圆

 楼主| 发表于 2012-9-17 23:12:12 | 显示全部楼层
86793 发表于 2012-9-17 17:31
你好,请问一下EM4095在收发状态时,没有进行读卡时(即ID卡没有靠近时)的电流也有100来mA吗? ...

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

出0入0汤圆

发表于 2012-9-18 09:10:39 | 显示全部楼层
gentlerain 发表于 2012-9-17 23:12
这个我还真的不太清楚,没用过这个。

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

出0入0汤圆

发表于 2012-9-21 13:10:17 | 显示全部楼层
每次读的数据都不一样.楼主这程序有谁用成功过

出0入0汤圆

发表于 2012-9-28 09:01:07 | 显示全部楼层
抽时间试一下!谢绝!

出0入13汤圆

发表于 2012-9-29 10:26:52 | 显示全部楼层
有时候慢慢学习,谢谢分享

出0入0汤圆

发表于 2012-10-11 14:18:51 | 显示全部楼层
mark看看

出0入0汤圆

发表于 2012-11-9 10:19:59 | 显示全部楼层
请教一下楼主, 收到的数据怎么解码 换算得到卡号呢?

出0入10汤圆

发表于 2012-11-21 14:03:15 | 显示全部楼层
硬件我还没有弄,不过可以先研究代码

出0入10汤圆

发表于 2012-11-21 14:05:16 | 显示全部楼层
LZ 程序的注释很详细,支持LZ!

出0入0汤圆

发表于 2012-11-26 18:10:27 | 显示全部楼层

出0入0汤圆

发表于 2012-12-5 19:36:40 | 显示全部楼层
mark


出0入0汤圆

 楼主| 发表于 2012-12-5 22:04:25 | 显示全部楼层
下面上传我根据一块读卡头重画的读卡原理图,可用于读取125K的非接触式ID卡.
下图中,PWM输入125KHz的方波,345uH的电感就是感应线圈,可以自己用漆包线绕制.当有卡进入读卡区域时,在LM358的7脚即可接收到数据.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-12-22 09:56:03 | 显示全部楼层
gentlerain 发表于 2012-12-5 22:08
正面上传一份清晰的PDF文档,内容同上面的原理图.

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

出0入0汤圆

发表于 2013-1-30 12:54:56 | 显示全部楼层
想学习下.....

出0入0汤圆

发表于 2013-2-14 22:36:56 | 显示全部楼层
学习!
mark!

出0入0汤圆

发表于 2013-3-11 21:58:46 | 显示全部楼层
        mark

出0入0汤圆

发表于 2013-4-10 13:52:10 | 显示全部楼层
MARK!
后续学习

出0入0汤圆

发表于 2013-5-4 21:09:11 | 显示全部楼层
收藏,以后能用上!

出0入0汤圆

发表于 2013-5-12 10:17:19 | 显示全部楼层
呵呵,我也准备弄这个呢!!!思路基本清楚了,正好参考下!

出0入0汤圆

发表于 2013-5-23 11:08:51 | 显示全部楼层
mark!!!!!!!!

出0入0汤圆

发表于 2013-5-28 10:36:38 | 显示全部楼层
你好,能不能把定时器2设置贴出?还有可以用定时器1吗?

出0入0汤圆

 楼主| 发表于 2013-5-28 12:15:12 | 显示全部楼层
本帖最后由 gentlerain 于 2013-5-28 12:16 编辑
380523337 发表于 2013-5-28 10:36
你好,能不能把定时器2设置贴出?还有可以用定时器1吗?


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

出0入0汤圆

发表于 2013-5-28 18:07:38 | 显示全部楼层
这个好,最近在做

出0入0汤圆

发表于 2013-5-31 21:43:38 | 显示全部楼层

出0入0汤圆

发表于 2013-6-1 08:34:30 | 显示全部楼层
gentlerain 发表于 2013-5-28 12:15
用任意的定时器都可以,只要定时器的Counter每个值等于4us即可.
不需要开任何中断.前提是不会溢出,因为此 ...

谢谢!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-12-12 00:59

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表