赞
踩
【本文发布于https://blog.csdn.net/Stack_/article/details/116952678,未经许可不得转载,转载须注明出处】
这个图是别人画的,不是太懂原理。
MCU产生125K 方波,经过74HC04和4.7欧电阻后到达铜质线圈,ID卡靠近线圈,LM358会输出“曼彻斯特编码”的数据。MCU采集后校验通过得到卡号。
曼彻斯特编码的ID卡每次输出64bit数据,其载波编码为曼彻斯特码。
曼彻斯特码调制方式下,EM4100卡片每传送一位数据的时间是64个振荡周期。
125KHZ载波时,卡片传送一bit数据理论频率为125KHz / 64 = 1.953125KHz。
得一个周期为1 000 000us / 1.953125KHz = 512us。
曼彻斯特码一个完整的数据跳变为一个周期(512us),
存在空跳则半个跳变为半个周期(256us)。
假设MCU的PC5产生125K方波,PD2作检波。PD2配置为外部中断输入,且中断触发方式为上升沿&下降沿。
低电平 | 此bit为1 |
---|---|
高电平 | 此bit为0 |
上次bit = 1 | 此次bit为1 |
---|---|
上次bit = 0 | 此次bit为0 |
或者 | |
PD2 = 0 | 此次bit为1 |
PD2 = 1 | 此次bit为0 |
以STM8S103为例,主频16MHz
/**
* @brief 定时器
* @note
* @param None
* @retval None
* @author PWH @ CSDN Tyrion.Mon
* @date 2020
*/
void Tim1_Init(void)
{
Tim1_DeInit();
TIM1_TimeBaseInit(1, TIM1_COUNTERMODE_UP, 9999, 0); //2分频,计数模式-向上,溢出值,重载值
TIM1_ARRPreloadConfig(ENABLE);//使能数值自动重装载功能
TIM1_Cmd(ENABLE);
}
根据此配置得
计数器频率 | 16MHz / 2 = 8MHz |
---|---|
计数周期 | 1000000us / 8MHz = 0.125us |
一个周期(512us)计数值为 | 512us / 0.125 = 4096 |
半个周期(256us)计数值为 | 256us / 0.125 = 2048 |
因为一次传输64bit,所以一次接收128bit数据,其中肯定包含完整的一组数据。
用一个数组存储采集的数据
uint8_t ManchesterCodeBits[16] = {0}; //125KhzID卡 曼彻斯特码(Manchester code) 一次输出64位数据信息 ,采集两组 64bit*2 = 128bit 128/8=16Bytes
/**
* @brief 外部中断配置
* @note
* @param None
* @retval None
* @author PWH @ CSDN Tyrion.Mon
* @date 2020
*/
void Exti_init(void)
{
GPIO_Init(GPIOD,GPIO_PIN_2,GPIO_MODE_IN_PU_IT);
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOD, EXTI_SENSITIVITY_RISE_FALL);
}
uint8_t CodeBitsRecComplete = 0; //为0接收,为1校验 /** * @brief PD中断服务函数 * @note * @param None * @retval None * @author PWH @ CSDN Tyrion.Mon * @date 2020 */ INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6) { static uint8_t BitsCnt = 0; //接收到的bit计数,接收完128bit后暂停接收,进入校验步骤 uint8_t Value = 0; uint16_t temp = 0; static uint8_t flag = 0; if (!CodeBitsRecComplete) { temp |= TIM1->CNTRH; temp <<= 8; temp |= TIM1->CNTRL; //temp为计数器当前值 if (temp > 3000 && temp < 5000) // 1个周期计数值约4096 { TIM1->CR1 &= 0xFE; //关定时器 TIM1->CNTRH = 0; //清零计数器 TIM1->CNTRL = 0; TIM1->CR1 |= 0x01; //开定时器 if (flag) //上一个跳变为空跳 { Value = ((ManchesterCodeBits[(BitsCnt - 1) / 8] >> (7 - (BitsCnt - 1) % 8)) & 0x01) ? 1 : 0; //上一bit为1则为1,否则为0 } else Value = (GPIOD->IDR) & 0x04 ? 0 : 1; flag = 0; ManchesterCodeBits[BitsCnt / 8] |= (Value << (7 - BitsCnt % 8)); BitsCnt++; if (BitsCnt > 127) { CodeBitsRecComplete = 1; BitsCnt = 0; } } else if (temp > 1000 && temp < 3000) // 1/2个周期计数值约2048 { flag = 1; //检测到一个空跳 } } }
引导码 | 1 1111 1111 (9bit) |
---|---|
D00 - D13 | 版本号之类的(8bit) |
D20 - D93 | 卡号(32bit) |
Px | 行校验 (10bit) |
PCx | 列校验 (4bit) |
S0 | 停止位 (1bit) |
bit 0 - bit 8 | 引导位 1 1111 1111 (9bit) |
---|---|
bit 9 - bit 13 | D00 D01 D02 D03 P0 |
bit 14 - bit 18 | D10 D11 D12 D13 P1 |
… | … |
bit 54 - bit 58 | D90 D91 D92 D93 P9 |
bit 59 - bit 62 | PC0 PC1 PC2 PC3 |
bit 63 | S0 |
uint8_t GetBitValue(uint8_t bitsCnt) { return (ManchesterCodeBits[bitsCnt / 8] >> (7 - bitsCnt % 8)) & 0x01; } /** * @brief 数据校验 * @note 此函数在主循环中执行,或放在过滤函数(例如连续多次读到的数据均无错误才认为读到卡)中执行 * @param pBuff 存储卡号的数组 * @retval None * @author PWH @ CSDN Tyrion.Mon * @date 2020 */ uint8_t GetCardNO(uint8_t * pBuff) { uint8_t bitsCnt = 0; uint8_t i = 0; uint8_t j = 0; uint16_t Value = 0; uint8_t status = CARDFALSE; if (!CodeBitsRecComplete) return CARDREADING; //有卡时,1秒满13次 //无卡,1秒4 - 6次 status = CARDFALSE; /* 找 0 1 1111 1111 (1停止位+9引导位) 如果bit63-bit72仍不是,则没必要继续找 */ while (bitsCnt <= 63) { Value = 0; for (j = 0; j <= 9; j++) { Value <<= 1; Value |= GetBitValue(bitsCnt + j); } if ( Value == 0x01ff ) //找到 0 1 1111 1111 { bitsCnt += 10; //跳过停止位和引导位 break; } else //没 找到 0 1 1111 1111 { bitsCnt++; } } /* 找到了 0 1 1111 1111 */ if (bitsCnt != 64) { /* 数据行0校验 */ if ( (GetBitValue(bitsCnt) + GetBitValue(bitsCnt + 1) + GetBitValue(bitsCnt + 2) + GetBitValue(bitsCnt + 3)) % 2 == GetBitValue(bitsCnt + 4) ) { /* 数据行1校验 */ if ( (GetBitValue(bitsCnt + 5) + GetBitValue(bitsCnt + 6) + GetBitValue(bitsCnt + 7) + GetBitValue(bitsCnt + 8)) % 2 == GetBitValue(bitsCnt + 9) ) { /* 数据行2校验 */ if ( (GetBitValue(bitsCnt + 10) + GetBitValue(bitsCnt + 11) + GetBitValue(bitsCnt + 12) + GetBitValue(bitsCnt + 13)) % 2 == GetBitValue(bitsCnt + 14) ) { /* 数据行3校验 */ if ( (GetBitValue(bitsCnt + 15) + GetBitValue(bitsCnt + 16) + GetBitValue(bitsCnt + 17) + GetBitValue(bitsCnt + 18)) % 2 == GetBitValue(bitsCnt + 19) ) { /* 数据行4校验 */ if ( (GetBitValue(bitsCnt + 20) + GetBitValue(bitsCnt + 21) + GetBitValue(bitsCnt + 22) + GetBitValue(bitsCnt + 23)) % 2 == GetBitValue(bitsCnt + 24) ) { /* 数据行5校验 */ if ( (GetBitValue(bitsCnt + 25) + GetBitValue(bitsCnt + 26) + GetBitValue(bitsCnt + 27) + GetBitValue(bitsCnt + 28)) % 2 == GetBitValue(bitsCnt + 29) ) { /* 数据行6校验 */ if ( (GetBitValue(bitsCnt + 30) + GetBitValue(bitsCnt + 31) + GetBitValue(bitsCnt + 32) + GetBitValue(bitsCnt + 33)) % 2 == GetBitValue(bitsCnt + 34) ) { /* 数据行7校验 */ if ( (GetBitValue(bitsCnt + 35) + GetBitValue(bitsCnt + 36) + GetBitValue(bitsCnt + 37) + GetBitValue(bitsCnt + 38)) % 2 == GetBitValue(bitsCnt + 39) ) { /* 数据行8校验 */ if ( (GetBitValue(bitsCnt + 40) + GetBitValue(bitsCnt + 41) + GetBitValue(bitsCnt + 42) + GetBitValue(bitsCnt + 43)) % 2 == GetBitValue(bitsCnt + 44) ) { /* 数据行9校验 */ if ( (GetBitValue(bitsCnt + 45) + GetBitValue(bitsCnt + 46) + GetBitValue(bitsCnt + 47) + GetBitValue(bitsCnt + 48)) % 2 == GetBitValue(bitsCnt + 49) ) { /* 数据列0校验 */ if ( (GetBitValue(bitsCnt) + GetBitValue(bitsCnt + 5) + GetBitValue(bitsCnt + 10) + GetBitValue(bitsCnt + 15) + GetBitValue(bitsCnt + 20) + GetBitValue(bitsCnt + 25) + GetBitValue(bitsCnt + 30) + GetBitValue(bitsCnt + 35) + GetBitValue(bitsCnt + 40) + GetBitValue(bitsCnt + 45)) % 2 == GetBitValue(bitsCnt + 50) ) { /* 数据列1校验 */ if ( (GetBitValue(bitsCnt + 1) + GetBitValue(bitsCnt + 6) + GetBitValue(bitsCnt + 11) + GetBitValue(bitsCnt + 16) + GetBitValue(bitsCnt + 21) + GetBitValue(bitsCnt + 26) + GetBitValue(bitsCnt + 31) + GetBitValue(bitsCnt + 36) + GetBitValue(bitsCnt + 41) + GetBitValue(bitsCnt + 46)) % 2 == GetBitValue(bitsCnt + 51) ) { /* 数据列2校验 */ if ( (GetBitValue(bitsCnt + 2) + GetBitValue(bitsCnt + 7) + GetBitValue(bitsCnt + 12) + GetBitValue(bitsCnt + 17) + GetBitValue(bitsCnt + 22) + GetBitValue(bitsCnt + 27) + GetBitValue(bitsCnt + 32) + GetBitValue(bitsCnt + 37) + GetBitValue(bitsCnt + 42) + GetBitValue(bitsCnt + 47)) % 2 == GetBitValue(bitsCnt + 52) ) { /* 数据列3校验 */ if ( (GetBitValue(bitsCnt + 3) + GetBitValue(bitsCnt + 8) + GetBitValue(bitsCnt + 13) + GetBitValue(bitsCnt + 18) + GetBitValue(bitsCnt + 23) + GetBitValue(bitsCnt + 28) + GetBitValue(bitsCnt + 33) + GetBitValue(bitsCnt + 38) + GetBitValue(bitsCnt + 43) + GetBitValue(bitsCnt + 48)) % 2 == GetBitValue(bitsCnt + 53) ) { /* 停止位 */ if (GetBitValue(bitsCnt + 54) == 0) { status = CARDTRUE; /* 4字节卡号 */ pBuff[0] = GetBitValue(bitsCnt + 10) << 7 | GetBitValue(bitsCnt + 11) << 6 | GetBitValue(bitsCnt + 12) << 5 | GetBitValue(bitsCnt + 13) << 4 | GetBitValue(bitsCnt + 15) << 3 | GetBitValue(bitsCnt + 16) << 2 | GetBitValue(bitsCnt + 17) << 1 | GetBitValue(bitsCnt + 18); pBuff[1] = GetBitValue(bitsCnt + 20) << 7 | GetBitValue(bitsCnt + 21) << 6 | GetBitValue(bitsCnt + 22) << 5 | GetBitValue(bitsCnt + 23) << 4 | GetBitValue(bitsCnt + 25) << 3 | GetBitValue(bitsCnt + 26) << 2 | GetBitValue(bitsCnt + 27) << 1 | GetBitValue(bitsCnt + 28); pBuff[2] = GetBitValue(bitsCnt + 30) << 7 | GetBitValue(bitsCnt + 31) << 6 | GetBitValue(bitsCnt + 32) << 5 | GetBitValue(bitsCnt + 33) << 4 | GetBitValue(bitsCnt + 35) << 3 | GetBitValue(bitsCnt + 36) << 2 | GetBitValue(bitsCnt + 37) << 1 | GetBitValue(bitsCnt + 38); pBuff[3] = GetBitValue(bitsCnt + 40) << 7 | GetBitValue(bitsCnt + 41) << 6 | GetBitValue(bitsCnt + 42) << 5 | GetBitValue(bitsCnt + 43) << 4 | GetBitValue(bitsCnt + 45) << 3 | GetBitValue(bitsCnt + 46) << 2 | GetBitValue(bitsCnt + 47) << 1 | GetBitValue(bitsCnt + 48); } } } } } } } } } } } } } } } } for (i = 0; i < 16; i++) { ManchesterCodeBits[i] = 0; } CodeBitsRecComplete = 0; return status; }
在理解校验原理的基础上用循环结构对校验进行简写
if (bitsCnt != 64) { status = CARDTRUE; /* 对10组行数据进行校验 */ for (i = bitsCnt; i <= (bitsCnt + 45); i += 5) { Value = 0; for (j = 0; j <= 3; j++) { Value += GetBitValue(i + j); //每行4bit数据累加 } if ( Value % 2 != GetBitValue(i + 4) ) { status = CARDFALSE; break; } } if (status == CARDTRUE) { /* 对4组列数据进行校验 */ for (i = bitsCnt; i <= (bitsCnt + 3); i++) { Value = 0; for (j = 0; j <= 45; j += 5) { Value += GetBitValue(i + j); //每列10bit数据累加 } if ( Value % 2 != GetBitValue(i + 50) ) { status = CARDFALSE; break; } } } if (status == CARDTRUE) { /* 停止位 */ if (GetBitValue(bitsCnt + 54) == 0) { status = CARDTRUE; /* 4字节卡号 */ for (i = 0; i < 4; i++) { pBuff[i] = 0; for (j = 0; j <= 8; j++) { if (j != 4) { pBuff[i] <<= 1; pBuff[i] |= GetBitValue(bitsCnt + (i + 1) * 10 + j); } } } } else status = CARDFALSE; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。