?? em4100.c
字號(hào):
/* 檢測方法
1).確定起始位,首先要正確找到數(shù)據(jù)1 按規(guī)則下跳為1 上跳為0. 可檢測高電平并等其變低
但這會(huì)把0錯(cuò)檢為1因?yàn)?也存在高電平。但是如果檢測到一個(gè)周期的高電平(數(shù)據(jù)01)則可
確定找到了數(shù)據(jù)1,找到1后就可以同步了,因?yàn)镋M4100卡最后一位數(shù)據(jù)就是0正好可以利用
作為判斷的特征。
2).對于數(shù)據(jù)的確定,由于有了同步則可在同步后延時(shí)384us即3/4個(gè)碼原周期在判斷接受段電平如何
如為高則置數(shù)據(jù)為1,并一直等到低電平的出現(xiàn),相反則等高電平的出現(xiàn),并在此之間插入超時(shí)
判斷。這樣,一個(gè)完整的數(shù)據(jù)判斷就完成了,并確保數(shù)據(jù)的準(zhǔn)確性,另外這種方法的抗干擾性
會(huì)非常好,而如果采用定時(shí)同步的話則會(huì)因信號(hào)的畸變而引起數(shù)據(jù)出錯(cuò),整體會(huì)導(dǎo)致讀卡幾率降低
但是此程序也有其缺點(diǎn),因?yàn)椴捎眉冄訒r(shí)判斷的手段,因此其占用單片機(jī)的運(yùn)行時(shí)間比較大。
3).同步后開始接受同步數(shù)據(jù)即9個(gè)1,這一部分用一個(gè)循環(huán)做,如果出錯(cuò)則放棄接收
4).同步數(shù)據(jù)接收完后,則開始接受數(shù)據(jù),數(shù)據(jù)分11行5列接收以利于校驗(yàn)位的判斷
如有出錯(cuò)則放棄數(shù)據(jù)
5).如一切正常則返回卡號(hào),如因嘗試讀卡次數(shù)到了則返回0以表示沒有卡
*/
#include"EM4100.h"
//精確的384us延時(shí),此延時(shí)可以不嚴(yán)格,但要大于256us小于512us
void Delay384us()
{
uchar i=DELAY_VAL;
while(i--);
}
//讀取卡號(hào),
ulong Read_Card()
{
uchar i=0; //起始為的計(jì)數(shù)值
uchar error; //時(shí)間溢出的計(jì)數(shù)值
uchar error_flag; //時(shí)間溢出標(biāo)志
uchar row,col; //行列寄存器
uchar row_parity; //行校驗(yàn)寄存器
uchar col_parity[5]; //列校驗(yàn)寄存器
uchar _data; //數(shù)據(jù)寄存器
ulong temp; //卡號(hào)寄存器
ulong timeout=0; //搜索次數(shù)寄存器
while(1)
{
if(timeout==10)return 0;//嘗試10次搜索,如沒有責(zé)返回0
else timeout++;
error=0;
// Manchester_IN=0;
while(Manchester_IN==0)//等高電平
{
if(error==TIME_OF)break;//超時(shí)退出
else error++;
}
if(error==150)continue;//結(jié)束本次主循環(huán)
else error=0;
Delay384us();
if(Manchester_IN)//尋找真正的1起始位,利用01的波形確定1起始位,即最后一位加第一位
{
for(i=0;i<8;i++)//判斷是否是真的起始位
{
error=0; //限定等待時(shí)間
while(Manchester_IN)
{
if(error==TIME_OF)
{
error_flag=1;//時(shí)間溢出
break; //退出
}
else error++;
}
Delay384us(); //延時(shí)至下一碼原
if(Manchester_IN&&error_flag==0); //判斷下一位是否為1 和是否沒有時(shí)間溢出
else break; //不是1退出,溢出退出
}
if(error_flag)//因時(shí)間溢出造成的本次主循環(huán)退出
{
error_flag=0;
continue; //退出本次循環(huán)
}
else;
if(i==8) //起始位接受完并且正確后開始接受數(shù)據(jù)
{
error_flag=0;
error=0; //限定等待時(shí)間
while(Manchester_IN)
{
if(error==TIME_OF)
{
error_flag=0;
break; //時(shí)間溢出造成的出錯(cuò)
}
else error++;
}
if(error_flag)
{
error_flag=0;
continue; //因等待待第一個(gè)正式數(shù)據(jù)錯(cuò)誤引起的本次主循環(huán)退出
}
else;
//所有列校驗(yàn)清零
col_parity[0]=col_parity[1]=col_parity[2]=col_parity[3]=col_parity[4]=0;
for(row=0;row<11;row++) //共11行數(shù)據(jù)
{
for(col=0,row_parity=0/*行校驗(yàn)清零*/;col<5;col++)//共5列數(shù)據(jù)
{
Delay384us(); //延時(shí)至下一碼原
if(Manchester_IN)_data=1; //數(shù)據(jù)為1
else _data=0; //數(shù)據(jù)為0
if(col<4&&row<10) //數(shù)據(jù)區(qū)的接受,后四個(gè)字節(jié)
{
temp<<=1; //左移一位
temp+=(ulong)_data; //數(shù)據(jù)相加
}
else;
row_parity+=_data; //行校驗(yàn)加入數(shù)據(jù)
col_parity[col]+=_data; //相應(yīng)列校驗(yàn)加入數(shù)據(jù) 雖最后一列沒有校驗(yàn)但為了方便也加上
error=0; //限定等待時(shí)間清零
while(Manchester_IN==(bit)_data)
{
if(error==TIME_OF) //由于時(shí)間溢出造成的數(shù)據(jù)出錯(cuò)
{
error_flag=1;
break; //退出本while循環(huán)
}
else error++;
}
if(error_flag)break; //出錯(cuò)退出內(nèi)層for循環(huán)
else;
}
if(row<10)//最后一行沒有校驗(yàn)所以要加限制
{
if((row_parity&0x01)||error_flag) //出錯(cuò)退出外for循環(huán)
{
temp=0;
error_flag=1;
break; //退出
}
else;
}
else;
}
//對最后接收的列校驗(yàn)進(jìn)行判斷,及對來自上面數(shù)據(jù)錯(cuò)誤error_flag處理以結(jié)束本次主循環(huán)
if(error_flag||((col_parity[0]&0x01)&&(col_parity[1]&0x01)&&(col_parity[2]&0x01)&&(col_parity[3]&0x01)))
{ //最后一列沒有校驗(yàn)
error_flag=0;
temp=0;
continue; //退出本次循環(huán)
}
else return temp;//將正確的數(shù)據(jù)返回
}
continue;
}
continue;
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -