读卡购票c语言程序,求ID/IC卡的原理与C语言读取程序?

第一次读取ID卡,费了不少周折 !本程序采用U2270B来读取卡号,所用单片机为新华龙的C8051F340,并采用串口1(P0.6和P0.7)的方式发送到PC机,通过串口调试助手观察所读到的数据,本程序不足之处就是所得到的校验位有些不正确,还请高手不吝赐教。

ID卡的工作原理:当读写器正常工作时,不断地向外辐射一组固定频率的电磁波,典型频率为125KHZ,当有卡靠近时,卡片内的一个LG串连谐振电路,其频率与读卡器的频率相同,这样在电磁波的激励下,LG谐振电路产生共振,从而使电容充电,在这个电容的另一端,接有一个单向导电的电子泵,将将电容内的电荷送到另一个电容内存储,当电容器充电达到2V时,电容就作为电源为卡片上的其他电路提供电压,将卡片的数据发射出去或接收读取。

/*****************************************************************************

新卡检测方法:检测上次接收数据的结束位与下次接收数据的起始位(半个周期的低电平

与一个周期的高电平),但是,此时INPORT输入脚电平已变为低电平信号。

之后再连续检测16个半周期电平翻转,到达第9个1的前半周期(高电平),

之后INPORT变为低电平,再通过定时器0来模拟同步时钟,对曼彻斯特码进行解码。

注意:卡号发送顺序:先发校验位,紧接着是最高位、次高位····连发5位数据。

如本卡的卡号是11100 00110 00000 00000 11100 10101 10100 00010 01011 01010 10010

最先接收到是第一个五位的校验位0,然后才是1110,依次类推。

下降沿为 1

上升沿为 0

整个程序的思想:每次采样完成,判断一次所采到的数据是否为1 ,若为1,继续采样,直到采完9个1,

若为0,丢掉数据,重新采样。从而实现是否有卡的判断。

***********************************************************************************/

#include 

#include 

#include 

//增加部分:由于改版,读卡输入和蜂鸣器输入的io口有所更改

//-----------------------------------------------------------------------------

// 16-bit SFR Definitions for 'F34x

sfr16 SBRL1 = 0xB4;

// Global CONSTANTS

#define SYSCLK 12000000 // SYSCLK frequency in Hz

#define BAUDRATE0 115200 // Baud rate of UART0 in bps

#define BAUDRATE1 115200 // Baud rate of UART1 in bps

#define BIT5 0x20

sbit SPK= P3^5;//蜂鸣器

sbit INPORT= P0^3;//解码输入

sbit wave = P1^7;

//用来区分脉冲宽度的参数

#define TIME00180

#define TIME05300

#define TIME10560

bit bitin=1; //上一次的状态位

bit Y_flag = 0; //厂商信息以0开头标志位

bit N_flag = 0; //厂商信息以1开头标志位

unsigned char CardNo[11]={0}; //用来暂存接收到的卡号信息8位卡号32位数据。

unsigned char stemp =0; //先接收到的二进制数据存在最高位,其次次高位

unsigned char bit_num=0,num=0; //用来记录读取的位数

unsigned int mk; //定义脉冲宽度变量

unsigned char CheckBit[11]={0}; //用来存储14位校验位

void delay_ms(unsigned int ms);

void Delay(void);

unsigned char readbit(); //读位函数,用来判断是否有卡进入读写器区域

unsigned char readdata();

bit CheckCard(); //是否有卡检测函数

void ReadCardNo(void); //读取卡号信息函数

void speaker(void); //蜂鸣器提示读卡成功函数

void init(void);

void PORT_Init(void);

void SYSCLK_Init(void);

void System_Uart(void);

void UART1_Init(void);

void SendData(unsigned char datas);

void SendCardNo();

main()

{

PORT_Init ();

SYSCLK_Init ();

UART1_Init ();

init();//初始化

ET0 = 1;

TCON &=~BIT5; //清楚定时器0中断标志位

printf("UART1 is OK \n");

for(;;)

{

unsigned data_i=0;

if(CheckCard())//检测是否有卡

{

ReadCardNo();

for(data_i=0;data_i<11;data_i++)

{

stemp =CardNo[data_i];

CardNo[data_i] = (stemp&0x0f); //存储四位卡号

stemp= _cror_(stemp,4);

CheckBit[data_i]=(stemp&0x01);

}

SendCardNo();

speaker();

//在这里可以做其它事.

}

}

}

void delay_ms(unsigned int ms)

{

unsigned char i;

while(ms--)

{

i=112;

while(i--);

}

}

unsigned char readbit()

{

mk=TIME10*12;//定义脉冲宽度变量

TL0=TH0=0;//初始化计时器

TR0=1;//开始计时

while(--mk)//超时机制,防止死等

{

if(bitin!=INPORT)//有跳变

break;

}

TR0=0;//停止计时

if(mk==0)//超时退出

return 0;

bitin=INPORT;//保存状态,数据读完后电平翻转,bitin翻转

mk=TH0*256+TL0;//计算这样跳变的脉宽

if((mk>TIME05)&&(mk<=TIME10))//一个周期 LGZ:300

return 1;

if((mk>=TIME00)&&(mk<=TIME05))//半个周期 LGZ:180

return 2;

return 0;//出错

}

bit CheckCard()

{

unsigned char i;

bitin=INPORT; //保存位状态

if(readbit()==1) //新卡检测方法

{

if(INPORT == 0)

{

for(i=0;i<16;i++)

{

if(readbit() != 2)

return 0;

}

return 1;

}

}

//至此以实现ID的检测功能,下面将进行ID卡的卡号读取和分析;

return 0;

}

void ReadCardNo(void)

{

TH0=(65536-340)/256;

TL0=(65536-340)%256;

// TCON &=~BIT5;

// ET0 = 1;

EA = 1;

TR0 = 1; //启动定时器0,开始模拟同步时钟。

while(bit_num<55);

bit_num = 0;

}

void speaker()

{

SPK=0;

delay_ms(3000);

SPK=1;

delay_ms(7000);

}

void init(void)

{

SPK=0;

wave = 0;

TMOD = 0x01;

INPORT=1;

delay_ms(3000);

SPK=1;

}

/*****************************************

功能 :端口初始化;

入口参数:无

*****************************************/

void PORT_Init (void)

{

PCA0MD &= ~0x40; //关看门狗;

P0SKIP = 0x0F;

XBR0 = 0x01; //UART0

XBR1 = 0x40;

XBR2 = 0x01; //UART1

}

/*****************************************

功能 :时钟初始化;

入口参数:无

*****************************************/

void SYSCLK_Init (void)

{

OSCICN |= 0x83; //不分频,得到12M内部振荡器频率;

RSTSRC = 0x04; //检测到时钟丢失条件时触发复位;

}

void UART1_Init (void)

{

SMOD1 = 0x0C; // set to disable parity, 8-data bit,

// disable extra bit,

// stop bit 1 bit wide

SCON1 = 0x10; // SCON1: 8-bit variable bit rate

// level of STOP bit is ignored

// RX enabled

// ninth bits are zeros

// clear RI0 and TI0 bits

if (SYSCLK/BAUDRATE1/2/0xFFFF 

SBRL1 = -(SYSCLK/BAUDRATE1/2);

SBCON1 |= 0x03; // set prescaler to 1

} else if (SYSCLK/BAUDRATE1/2/0xFFFF 

SBRL1 = -(SYSCLK/BAUDRATE1/2/4);

SBCON1 &= ~0x03;

SBCON1 |= 0x01; // set prescaler to 4

} else if (SYSCLK/BAUDRATE1/2/0xFFFF 

SBRL1 = -(SYSCLK/BAUDRATE1/2/12);

SBCON1 &= ~0x03; // set prescaler to 12

} else {

SBRL1 = -(SYSCLK/BAUDRATE1/2/48);

SBCON1 &= ~0x03;

SBCON1 |= 0x02; // set prescaler to 4

}

SCON1 |= 0x02; // indicate ready for TX

SBCON1 |= 0x40; // enable baud rate generator

}

// putchar,printf(''~'')调用此函数

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

char putchar (char c)

{

if (c == '\n')

{ // check for newline character

while (!(SCON1 & 0x02)); // wait until UART1 is ready to transmit

SCON1 &= ~0x02; // clear TI1 interrupt flag

SBUF1 = 0x0d; // output carriage return

}

while (!(SCON1 & 0x02)); // wait until UART1 is ready to transmit

SCON1 &= ~0x02; // clear TI1 interrupt flag

return (SBUF1 = c); // output  using UART 1

}

void SendData(unsigned char datas)

{

while (!(SCON1 & 0x02)); // wait until UART1 is ready to transmit

SCON1 &= ~0x02; // clear TI1 interrupt flag

SBUF1 = (0x30+datas); // output carriage return

}

void SendCardNo()

{

unsigned char i=0;

for(i=0;i<11;i++)

{

SendData(CardNo[i]%16/8);

SendData(CardNo[i]%8/4);

SendData(CardNo[i]%4/2);

SendData(CardNo[i]%2);

SendData(CheckBit[i]%2);

}

}

void Timer0_ISR(void) interrupt 1

{

TR0= 0;

CY = 0;

num = bit_num/5;

CardNo[num] <<= 1;

wave = ~wave;

if(INPORT == 1)

CardNo[num] |= 0x01;

bit_num ++;

TH0 =(65536-454)/256;

TL0 =(65536-454)%256;

TR0 = 1;

if(bit_num == 55)

EA = 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值