第一次读取ID卡,费了不少周折!本程序采用U2270B来读取卡号,所用单片机为新华龙的C8051F340,并采用串口1(P0.6和P0.7)的方式发送到PC机,通过串口调试助手观察所读到的数据,本程序不足之处就是所得到的校验位有些不正确,还请高手不吝赐教。
ID卡的工作原理:当读写器正常工作时,不断地向外辐射一组固定频率的电磁波,典型频率为125KHZ,当有卡靠近时,卡片内的一个LG串连谐振电路,其频率与读卡器的频率相同,这样在电磁波的激励下,LG谐振电路产生共振,从而使电容充电,在这个电容的另一端,接有一个单向导电的电子泵,将将电容内的电荷送到另一个电容内存储,当电容器充电达到2V时,电容就作为电源为卡片上的其他电路提供电压,将卡片的数据发射出去或接收读取。
/*****************************************************************************
新卡检测方法:检测上次接收数据的结束位与下次接收数据的起始位(半个周期的低电平
与一个周期的高电平),但是,此时INPORT输入脚电平已变为低电平信号。
之后再连续检测16个半周期电平翻转,到达第9个1的前半周期(高电平),
之后INPORT变为低电平,再通过定时器0来模拟同步时钟,对曼彻斯特码进行解码。
注意:卡号发送顺序:先发校验位,紧接着是最高位、次高位····连发5位数据。
如本卡的卡号是1110000110000000000011100101011010000010010110101010010
最先接收到是第一个五位的校验位0,然后才是1110,依次类推。
下降沿为1
上升沿为0
整个程序的思想:每次采样完成,判断一次所采到的数据是否为1,若为1,继续采样,直到采完9个1,
若为0,丢掉数据,重新采样。从而实现是否有卡的判断。
***********************************************************************************/
#include
#include
#include
//增加部分:由于改版,读卡输入和蜂鸣器输入的io口有所更改
//-----------------------------------------------------------------------------
//16-bitSFRDefinitionsfor'F34x
sfr16SBRL1=0xB4;
//GlobalCONSTANTS
#defineSYSCLK12000000//SYSCLKfrequencyinHz
#defineBAUDRATE0115200//BaudrateofUART0inbps
#defineBAUDRATE1115200//BaudrateofUART1inbps
#defineBIT50x20
sbitSPK=P3^5;//蜂鸣器
sbitINPORT=P0^3;//解码输入
sbitwave=P1^7;
//用来区分脉冲宽度的参数
#defineTIME00180
#defineTIME05300
#defineTIME10560
bitbitin=1;//上一次的状态位
bitY_flag=0;//厂商信息以0开头标志位
bitN_flag=0;//厂商信息以1开头标志位
unsignedcharCardNo[11]={0};//用来暂存接收到的卡号信息8位卡号32位数据。
unsignedcharstemp=0;//先接收到的二进制数据存在最高位,其次次高位
unsignedcharbit_num=0,num=0;//用来记录读取的位数
unsignedintmk;//定义脉冲宽度变量
unsignedcharCheckBit[11]={0};//用来存储14位校验位
voiddelay_ms(unsignedintms);
voidDelay(void);
unsignedcharreadbit();//读位函数,用来判断是否有卡进入读写器区域
unsignedcharreaddata();
bitCheckCard();//是否有卡检测函数
voidReadCardNo(void);//读取卡号信息函数
voidspeaker(void);//蜂鸣器提示读卡成功函数
voidinit(void);
voidPORT_Init(void);
voidSYSCLK_Init(void);
voidSystem_Uart(void);
voidUART1_Init(void);
voidSendData(unsignedchardatas);
voidSendCardNo();
main()
{
PORT_Init();
SYSCLK_Init();
UART1_Init();
init();//初始化
ET0=1;
TCON&=~BIT5;//清楚定时器0中断标志位
printf("UART1isOK\n");
for(;;)
{
unsigneddata_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();
//在这里可以做其它事.
}
}
}
voiddelay_ms(unsignedintms)
{
unsignedchari;
while(ms--)
{
i=112;
while(i--);
}
}
unsignedcharreadbit()
{
mk=TIME10*12;//定义脉冲宽度变量
TL0=TH0=0;//初始化计时器
TR0=1;//开始计时
while(--mk)//超时机制,防止死等
{
if(bitin!=INPORT)//有跳变
break;
}
TR0=0;//停止计时
if(mk==0)//超时退出
return0;
bitin=INPORT;//保存状态,数据读完后电平翻转,bitin翻转
mk=TH0*256+TL0;//计算这样跳变的脉宽
if((mk>TIME05)&&(mk<=TIME10))//一个周期LGZ:300
return1;
if((mk>=TIME00)&&(mk<=TIME05))//半个周期LGZ:180
return2;
return0;//出错
}
bitCheckCard()
{
unsignedchari;
bitin=INPORT;//保存位状态
if(readbit()==1)//新卡检测方法
{
if(INPORT==0)
{
for(i=0;i<16;i++)
{
if(readbit()!=2)
return0;
}
return1;
}
}
//至此以实现ID的检测功能,下面将进行ID卡的卡号读取和分析;
return0;
}
voidReadCardNo(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;
}
voidspeaker()
{
SPK=0;
delay_ms(3000);
SPK=1;
delay_ms(7000);
}
voidinit(void)
{
SPK=0;
wave=0;
TMOD=0x01;
INPORT=1;
delay_ms(3000);
SPK=1;
}
/*****************************************
功能:端口初始化;
入口参数:无
*****************************************/
voidPORT_Init(void)
{
PCA0MD&=~0x40;//关看门狗;
P0SKIP=0x0F;
XBR0=0x01;//UART0
XBR1=0x40;
XBR2=0x01;//UART1
}
/*****************************************
功能:时钟初始化;
入口参数:无
*****************************************/
voidSYSCLK_Init(void)
{
OSCICN|=0x83;//不分频,得到12M内部振荡器频率;
RSTSRC=0x04;//检测到时钟丢失条件时触发复位;
}
voidUART1_Init(void)
{
SMOD1=0x0C;//settodisableparity,8-databit,
//disableextrabit,
//stopbit1bitwide
SCON1=0x10;//SCON1:8-bitvariablebitrate
//levelofSTOPbitisignored
//RXenabled
//ninthbitsarezeros
//clearRI0andTI0bits
if(SYSCLK/BAUDRATE1/2/0xFFFF
SBRL1=-(SYSCLK/BAUDRATE1/2);
SBCON1|=0x03;//setprescalerto1
}elseif(SYSCLK/BAUDRATE1/2/0xFFFF
SBRL1=-(SYSCLK/BAUDRATE1/2/4);
SBCON1&=~0x03;
SBCON1|=0x01;//setprescalerto4
}elseif(SYSCLK/BAUDRATE1/2/0xFFFF
SBRL1=-(SYSCLK/BAUDRATE1/2/12);
SBCON1&=~0x03;//setprescalerto12
}else{
SBRL1=-(SYSCLK/BAUDRATE1/2/48);
SBCON1&=~0x03;
SBCON1|=0x02;//setprescalerto4
}
SCON1|=0x02;//indicatereadyforTX
SBCON1|=0x40;//enablebaudrategenerator
}
//putchar,printf(''~'')调用此函数
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
charputchar(charc)
{
if(c=='\n')
{//checkfornewlinecharacter
while(!(SCON1&0x02));//waituntilUART1isreadytotransmit
SCON1&=~0x02;//clearTI1interruptflag
SBUF1=0x0d;//outputcarriagereturn
}
while(!(SCON1&0x02));//waituntilUART1isreadytotransmit
SCON1&=~0x02;//clearTI1interruptflag
return(SBUF1=c);//outputusingUART1
}
voidSendData(unsignedchardatas)
{
while(!(SCON1&0x02));//waituntilUART1isreadytotransmit
SCON1&=~0x02;//clearTI1interruptflag
SBUF1=(0x30+datas);//outputcarriagereturn
}
voidSendCardNo()
{
unsignedchari=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);
}
}
voidTimer0_ISR(void)interrupt1
{
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;
}