处女贴,看到这个版块的出现,迫不及待地把自己刚做好的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: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’。
正面上传一份清晰的PDF文档,内容同上面的原理图.
下面再详细说说卡号的表示方法。
由于各个厂家的读卡器译码格式不尽相同,在读卡输出时,读出的二进制或十六进制(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)。 mark mark! mark mark!!!! mark mark 我也来mark 标记~ ~ RFID 定时器解码 很好! mark 偶早期做过一个用STC的产品
用M0做了个具备读写功能的产品 标记下。以后有用。 mark rfid mark Mark 呵呵,我也准备弄这个呢!!!思路基本清楚了,正好参考下! mark! 回复【17楼】honami520
-----------------------------------------------------------------------
又见 哈哈 MARK 想找个写的程序!
按照datasheet写的序列写下去数据没改变。还是原来的数据。 mark 回复【楼主位】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环境 MARK 感觉定时器2总是弄不好 感谢分享! 是不是我的定时器设置不对啊 没人用stm8l吗 请问楼主,这段程序可以解什么样的标签卡,译码好像是BIPHASE码吧。。。 说的有道理,但我没实现,我用stm8L mark rfid mark一下。。最近准备做一个, 没实现,倒是用延时实现了,很稳定很强大 MARK 好 13.56MHz TypeA解码吧 remind stm32据说很猛 了解下
!! mark mark 不知道哪款读卡器? 我做的门禁用延时做的,很稳定,已经量产了 mark mark!!!! 有没有哪位成功了?麻烦贴出来参考下 mark mark mark mark RFID卡读卡器解码程序 125k 的 RFID卡读卡器解码程序 注释做得很好哦 LZ好细致啊,每条code都有批注... 楼主好细致啊,每一行code都给了注释... 马克~{:smile:} 非常感谢,正好需要 谢谢分享 马克帕克 mark!!! 支持!!! 谢谢分享 mark{:biggrin:} 学习了,支持。 EM ID卡的ID解码程序 RFID 记号,谢谢 rfid编码解码程序 mark好东西
能说下定时器怎么设置吗? 经验证可用 你好,请问一下EM4095在收发状态时,没有进行读卡时(即ID卡没有靠近时)的电流也有100来mA吗? 86793 发表于 2012-9-17 17:31 static/image/common/back.gif
你好,请问一下EM4095在收发状态时,没有进行读卡时(即ID卡没有靠近时)的电流也有100来mA吗? ...
这个我还真的不太清楚,没用过这个。 gentlerain 发表于 2012-9-17 23:12 static/image/common/back.gif
这个我还真的不太清楚,没用过这个。
有哪位朋友知道的,回答一下。自己来顶一下。 每次读的数据都不一样.楼主这程序有谁用成功过 抽时间试一下!谢绝! 有时候慢慢学习,谢谢分享 mark看看 请教一下楼主, 收到的数据怎么解码 换算得到卡号呢? 硬件我还没有弄,不过可以先研究代码{:smile:} LZ 程序的注释很详细,支持LZ! {:smile:}{:lol:} mark
下面上传我根据一块读卡头重画的读卡原理图,可用于读取125K的非接触式ID卡.
下图中,PWM输入125KHz的方波,345uH的电感就是感应线圈,可以自己用漆包线绕制.当有卡进入读卡区域时,在LM358的7脚即可接收到数据.
gentlerain 发表于 2012-12-5 22:08 static/image/common/back.gif
正面上传一份清晰的PDF文档,内容同上面的原理图.
谢谢楼主的详细解答.谢谢 想学习下..... 学习!
mark! mark MARK!
后续学习 收藏,以后能用上! 呵呵,我也准备弄这个呢!!!思路基本清楚了,正好参考下! mark!!!!!!!! 你好,能不能把定时器2设置贴出?还有可以用定时器1吗? 本帖最后由 gentlerain 于 2013-5-28 12:16 编辑
380523337 发表于 2013-5-28 10:36 static/image/common/back.gif
你好,能不能把定时器2设置贴出?还有可以用定时器1吗?
用任意的定时器都可以,只要定时器的Counter每个值等于4us即可.
不需要开任何中断.前提是不会溢出,因为此程序没有溢出处理.
而且还能与其它定时器共用.
至于定时器的设置,就不用我教你了吧 这个好,最近在做 {:shocked:} gentlerain 发表于 2013-5-28 12:15 static/image/common/back.gif
用任意的定时器都可以,只要定时器的Counter每个值等于4us即可.
不需要开任何中断.前提是不会溢出,因为此 ...
谢谢!{:lol:} {:lol:} {:lol:}
页:
[1]
2