第一次读取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;
}