FM1208CPU卡是一款由上海復旦微電子股份有限公司(Fudan Microelectronics Group, FMG)研發的高端智能非接觸CPU卡芯片。以下是對該產品的詳細介紹:
一、技術特點
1.先進工藝:FM1208采用先進的超深亞微米EEPROM工藝技術制造,具有高性能和穩定性。
大容量存儲:該芯片擁有64K Byte EEPROM的存儲容量,可以支持多種應用,如公交結算、小額支付等金融行業應用,實現一卡多種功能。
2.高安全性:芯片內置硬件DES協處理器,支持Triple-DES加密,提供比普通卡片更高的安全性。同時,芯片和卡片操作系統(COS)的協同安全技術為CPU卡提供了雙重的安全保證,有效防止金融交易中的數據錯誤,保護消費者交易的私密性、安全性及個人利益。
3.廣泛兼容性:FM1208符合ISO14443 Type A標準和ISO/IEC 7816-5規范,可以兼容現有的非接觸邏輯加密卡,如市場上廣泛應用的S50等,方便在已有應用下的升級和擴展。
二、功能與應用
功能強大:FM1208不僅具有數據存儲功能,還具有命令處理、計算和數據加密等功能。其內置的卡片操作系統(COS)使得該芯片相當于一臺微型計算機,可以根據實際應用情況靈活改變系統,滿足客戶的不同需求。
應用領域廣泛:FM1208CPU卡廣泛應用于城市公交、一卡通、高速公路卡、小額消費卡、校園卡、金融支付電子錢包、身份認證等領域。其高安全性、大容量和廣泛兼容性使得該芯片在這些領域中具有顯著的優勢。
三、性能指標
通信協議:支持ISO 14443-A協議,工作頻率為13.56MHz。
數據傳輸速率:支持高達106Kbps的數據傳輸速率。
程序存儲器:32K x 8bit ROM。
數據存儲器:8K x 8bit EEPROM,滿足10萬次擦寫和10年數據保存指標。
內置RAM:256 x 8bit iRAM和384 x 8bit xRAM。
工作距離:不小于10CM。
識別時間:識別一張卡的時間約為3ms(包括復位應答和防沖突)。
EEPROM擦寫時間:約為2.4ms。
典型交易過程:小于350ms。
四、市場應用與反饋
FM1208CPU卡已在多個城市大面積推廣,如重慶的掌中行、合肥的一卡通等。特別是上海公共交通方面的試點,為非接觸CPU卡在長江三角洲乃至全國的公交領域的應用推廣起到了示范和推動作用。該產品的推出和應用,不僅提高了城市區域經濟合作水平,還實現了城際間的互聯互通,加強了城市間的聯系。
綜上所述,FM1208CPU卡憑借其先進的技術特點、廣泛的應用領域以及卓越的性能指標,在智能卡市場中占據了重要地位。
QT小程序UI界面:
QT小程序mainWindow.cpp代碼:
static bool checkinput(QString inputstr){ QString inputyes="0123456789abcdefABCDEF"; for(int i=0;isetupUi(this); QPalette pa; pa.setColor(QPalette::WindowText,QColor(255, 0, 0)); ui->label_7->setPalette(pa); ui->label_8->setPalette(pa); ui->label_9->setPalette(pa); ui->label_19->setPalette(pa); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pb_beep_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char status; if (mypcdbeep != NULL){ //是否成功連接上 pcdbeep()函數 status = mypcdbeep(30); if(status==0){ } else { disperrinf(status); } } else{ QMessageBox::critical(NULL, "提示", "函數‘pcdbeep’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_getdevnum_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char devicenumber[4]; //設備編號緩沖 unsigned char status; //函數返回狀態 if (mypcdgetdevicenumber != NULL){ //是否成功連接上 pcdgetdevicenumber()函數 status = mypcdgetdevicenumber(devicenumber); if(status==0){ mypcdbeep(30); QMessageBox::information(NULL, "提示", QString::asprintf("設備編號:%03d-%03d-%03d-%03d", devicenumber[0],devicenumber[1],devicenumber[2],devicenumber[3])); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘pcdgetdevicenumber’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_request_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char mypiccserial[4]; //卡序列號 unsigned char myparam[4]; //參數 unsigned char myver[1]; //版本 unsigned char mycode[1]; //廠商代碼(復旦為90) unsigned char status; //函數返回狀態 if (mycpurequest != NULL){ //是否成功連接上 cpurequest()函數 status = mycpurequest(mypiccserial,myparam,myver,mycode); if(status==0 || status==52){ mypcdbeep(30); QString uidstr=QString::asprintf("%02X%02X%02X%02X", mypiccserial[0],mypiccserial[1],mypiccserial[2],mypiccserial[3]); QString parstr=QString::asprintf("%02X%02X%02X%02X", myparam[0],myparam[1],myparam[2],myparam[3]); QString verstr=QString::asprintf("%02X", myver[0]); QString codestr=QString::asprintf("%02X", mycode[0]); ui->lineEdit_uid->setText(uidstr); QMessageBox::information(NULL, "提示", "卡號:"+uidstr+",參數:"+parstr+",版本號:"+verstr+",廠商代碼:"+codestr+" 的CPU卡已激活進入14443-4協議模式,可以繼續以下的功能操作!"); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘cpurequest’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_init_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char status; //函數返回狀態 unsigned char ctrlword; //是否先清空卡 unsigned char mylen[1]; //密鑰長度 unsigned char keybuf[20]; //密鑰 int keylen; int spacesize; //空間大小 if(ui->checkBox_clear->isChecked()){ ctrlword=1; }else{ctrlword=0;} QString writinf = ui->lineEdit_cardkey->text().trimmed(); keylen=checkhexdata(writinf,keybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制卡密碼!"); ui-?>lineEdit_cardkey->setFocus(); return; } mylen[0]=keylen; spacesize=ui->spinBox_maxsize->value(); if (mycpursinit != NULL){ //是否成功連接上 cpursinit()函數 status = mycpursinit(ctrlword,keybuf,mylen,spacesize); if(status==0 ){ mypcdbeep(30); QMessageBox::information(NULL, "提示", "CPU卡初始化成功!"); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘cpursinit’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_addeasyfile_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char status; //函數返回狀態 unsigned char fileno; //文件號 unsigned char readkeylen[1]; //只讀密鑰長度 unsigned char readkeybuf[20]; //只讀密鑰 unsigned char rwkeylen[1]; //讀寫密鑰長度 unsigned char rwkeybuf[20]; //讀寫密鑰 int keylen; int spacesize; //空間大小 QString keystr; fileno=ui->comboBox_addfile->currentIndex(); //新增加的文件號 keystr = ui->lineEdit_readkey->text().trimmed(); keylen=checkhexdata(keystr,readkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制文件只讀密碼!"); ui-?>lineEdit_readkey->setFocus(); return; } readkeylen[0]=keylen; keystr = ui->lineEdit_rwkey->text().trimmed(); keylen=checkhexdata(keystr,rwkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制文件讀寫密碼!"); ui-?>lineEdit_rwkey->setFocus(); return; } rwkeylen[0]=keylen; spacesize=ui->spinBox_2->value(); if (mycpursfileadd_s != NULL){ //是否成功連接上 cpursfileadd_s()函數 status = mycpursfileadd_s(fileno,readkeybuf,readkeylen,rwkeybuf,rwkeylen,spacesize); if(status==0 ){ mypcdbeep(30); QMessageBox::information(NULL, "提示", "CPU卡創建易寫文件成功,需要使用易寫函數寫入文件數據!"); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘cpursfileadd_s’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_addfile_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char status; //函數返回狀態 unsigned char fileno; //文件號 unsigned char readkeylen[1]; //只讀密鑰長度 unsigned char readkeybuf[20]; //只讀密鑰 unsigned char rwkeylen[1]; //讀寫密鑰長度 unsigned char rwkeybuf[20]; //讀寫密鑰 int keylen; int spacesize; //空間大小 QString keystr; fileno=ui->comboBox_addfile->currentIndex(); //新增加的文件號 keystr = ui->lineEdit_readkey->text().trimmed(); keylen=checkhexdata(keystr,readkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制文件只讀密碼!"); ui-?>lineEdit_readkey->setFocus(); return; } readkeylen[0]=keylen; keystr = ui->lineEdit_rwkey->text().trimmed(); keylen=checkhexdata(keystr,rwkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制文件讀寫密碼!"); ui-?>lineEdit_rwkey->setFocus(); return; } rwkeylen[0]=keylen; spacesize=ui->spinBox_2->value(); if (mycpursfileadd != NULL){ //是否成功連接上 cpursfileadd()函數 status = mycpursfileadd(fileno,readkeybuf,readkeylen,rwkeybuf,rwkeylen,spacesize); if(status==0 ){ mypcdbeep(30); QMessageBox::information(NULL, "提示", "CPU卡創建標準文件成功,需使用寫標準文件函數寫入數據!"); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘cpursfileadd’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_changkey_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char status; //函數返回狀態 unsigned char fileno; //文件號 unsigned char ctrlword; //控制字 unsigned char oldkeylen[1]; //舊密鑰長度 unsigned char oldkeybuf[20]; //舊密鑰 unsigned char newkeylen[1]; //新密鑰長度 unsigned char newkeybuf[20]; //新密鑰 int keylen; QString keystr; fileno=ui->comboBox_changekeyfile->currentIndex(); //要更改密鑰的文件號 if(ui->comboBox_changekey->currentIndex()==0){ ctrlword=NEWKEYR; //更改只讀密碼 }else{ctrlword=NEWKEYWR;} //更改讀寫密碼 if(ui->comboBox_authkey->currentIndex()==0){ ctrlword=ctrlword+OLDKEYR; //用只讀密碼來認證 }else{ctrlword=ctrlword+OLDKEYWR;} //用讀寫密碼來認證 keystr = ui->lineEdit_authkey->text().trimmed(); keylen=checkhexdata(keystr,oldkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制文件認證密碼!"); ui-?>lineEdit_authkey->setFocus(); return; } oldkeylen[0]=keylen; keystr = ui->lineEdit_newkey->text().trimmed(); keylen=checkhexdata(keystr,newkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制文件新密碼!"); ui-?>lineEdit_newkey->setFocus(); return; } newkeylen[0]=keylen; if (mycpursfilekeychg != NULL){ //是否成功連接上 cpursfilekeychg()函數 status = mycpursfilekeychg(fileno,ctrlword,oldkeybuf,oldkeylen,newkeybuf,newkeylen); if(status==0 ){ mypcdbeep(30); QMessageBox::information(NULL, "提示", "修改文件密碼成功"); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘cpursfilekeychg’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_read_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char status; //函數返回狀態 unsigned char fileno; //文件號 unsigned char ctrlword; //控制字 unsigned char oldkeylen[1]; //舊密鑰長度 unsigned char oldkeybuf[20]; //舊密鑰 int staradd; //讀寫起始地址 int datalen; //讀寫長度 unsigned char rwbuf[8000]; //讀寫數據緩沖 int keylen; QString keystr; fileno=ui->comboBox_rwfile->currentIndex(); //要讀寫的文件號 staradd=ui->spinBox_rwbegin->value(); //讀寫起始地址 datalen=ui->spinBox_rwlen->value(); //讀寫數據長度 if(datalen1 || datalen?>255){ QMessageBox::critical(NULL, "提示", "每次讀卡最多255字節,請輸入正確的讀卡長度!"); ui->spinBox_rwlen->setFocus(); return; } if(ui->comboBox_authrwkey->currentIndex()==0){ ctrlword=OLDKEYR; //用只讀密碼來認證 }else{ctrlword=OLDKEYWR;} //用讀寫密碼來認證 keystr = ui->lineEdit_authkey2->text().trimmed(); keylen=checkhexdata(keystr,oldkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制文件認證密碼!"); ui-?>lineEdit_authkey2->setFocus(); return; } oldkeylen[0]=keylen; if (mycpursfiledataread != NULL){ //是否成功連接上 cpursfiledataread()函數 status = mycpursfiledataread(fileno,ctrlword,oldkeybuf,oldkeylen,staradd,rwbuf,datalen); if(status==0 ){ mypcdbeep(30); QString datastr=""; for(int i=0;iplainTextEdit->setPlainText(datastr); QMessageBox::information(NULL, "提示", "讀取數據成功!"); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘cpursfiledataread’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_write_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char status; //函數返回狀態 unsigned char fileno; //文件號 unsigned char ctrlword; //控制字 unsigned char oldkeylen[1]; //舊密鑰長度 unsigned char oldkeybuf[20]; //舊密鑰 int staradd; //讀寫起始地址 int datalen; //讀寫長度 unsigned char rwbuf[8000]; //讀寫數據緩沖 int keylen; QString keystr; QString datastr; keystr = ui->lineEdit_authkey2->text().trimmed(); keylen=checkhexdata(keystr,oldkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制文件認證密碼!"); ui-?>lineEdit_authkey2->setFocus(); return; } oldkeylen[0]=keylen; datastr = ui->plainTextEdit->toPlainText().trimmed(); datalen=checkhexdata(datastr,rwbuf); if(datalen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制寫入數據!"); ui-?>plainTextEdit->setFocus(); return; } fileno=ui->comboBox_rwfile->currentIndex(); //要讀寫的文件號 staradd=ui->spinBox_rwbegin->value(); //讀寫起始地址 datalen=ui->spinBox_rwlen->value(); //讀寫數據長度 if(datalen1 || datalen?>247){ QMessageBox::critical(NULL, "提示", "每次寫卡最多247字節,請輸入正確的寫卡長度!"); ui->spinBox_rwlen->setFocus(); return; } if(ui->comboBox_authrwkey->currentIndex()==0){ ctrlword=OLDKEYR; //用只讀密碼來認證 }else{ctrlword=OLDKEYWR;} //用讀寫密碼來認證 if (mycpursfiledatawrite != NULL){ //是否成功連接上 cpursfiledatawrite()函數 status = mycpursfiledatawrite(fileno,ctrlword,oldkeybuf,oldkeylen,staradd,rwbuf,datalen); if(status==0 ){ mypcdbeep(30); QMessageBox::information(NULL, "提示", "寫入數據成功!"); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘cpursfiledatawrite’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_easy_write_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char status; //函數返回狀態 unsigned char fileno; //文件號 unsigned char ctrlword; //控制字 unsigned char oldkeylen[1]; //舊密鑰長度 unsigned char oldkeybuf[20]; //舊密鑰 int staradd; //讀寫起始地址 int datalen; //讀寫長度 unsigned char rwbuf[8000]; //讀寫數據緩沖 int keylen; QString keystr; QString datastr; keystr = ui->lineEdit_authkey2->text().trimmed(); keylen=checkhexdata(keystr,oldkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制文件認證密碼!"); ui-?>lineEdit_authkey2->setFocus(); return; } oldkeylen[0]=keylen; datastr = ui->plainTextEdit->toPlainText().trimmed(); datalen=checkhexdata(datastr,rwbuf); if(datalen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制寫入數據!"); ui-?>plainTextEdit->setFocus(); return; } fileno=ui->comboBox_rwfile->currentIndex(); //要讀寫的文件號 staradd=ui->spinBox_rwbegin->value(); //讀寫起始地址 datalen=ui->spinBox_rwlen->value(); //讀寫數據長度 if(ui->comboBox_authrwkey->currentIndex()==0){ ctrlword=OLDKEYR; //用只讀密碼來認證 }else{ctrlword=OLDKEYWR;} //用讀寫密碼來認證 if (mycpursfiledatawrite_s != NULL){ //是否成功連接上 cpursfiledatawrite_s()函數 status = mycpursfiledatawrite_s(fileno,ctrlword,oldkeybuf,oldkeylen,staradd,rwbuf,datalen); if(status==0 ){ mypcdbeep(30); QMessageBox::information(NULL, "提示", "寫入數據成功!"); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘cpursfiledatawrite_s’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_clear_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char status; if (mycpurscardclr != NULL){ //是否成功連接上 cpurscardclr()函數 status = mycpurscardclr(); if(status==0){ mypcdbeep(30); QMessageBox::information(NULL, "提示", "cpu卡強制清空卡成功"); }else{ if(status==64){ QMessageBox::information(NULL, "提示", "此卡為未經過我們cpursinit函數成功初始化的卡"); }else{ disperrinf(status); } } } else{ QMessageBox::critical(NULL, "提示", "函數‘cpurscardclr’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_changecardkey_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char status; //函數返回狀態 unsigned char oldkeylen[1]; //舊密鑰長度 unsigned char oldkeybuf[20]; //舊密鑰 unsigned char newkeylen[1]; //新密鑰長度 unsigned char newkeybuf[20]; //新密鑰 int keylen; QString keystr; keystr = ui->lineEdit_cardoldkey->text().trimmed(); keylen=checkhexdata(keystr,oldkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制卡舊密碼!"); ui-?>lineEdit_cardoldkey->setFocus(); return; } oldkeylen[0]=keylen; keystr = ui->lineEdit_cardnewkey->text().trimmed(); keylen=checkhexdata(keystr,newkeybuf); if(keylen0){ QMessageBox::critical(NULL, "提示", "請輸入正確的16進制卡新密碼!"); ui-?>lineEdit_cardnewkey->setFocus(); return; } newkeylen[0]=keylen; if (mycpurscardkeychg != NULL){ //是否成功連接上 cpurscardkeychg()函數 status = mycpurscardkeychg(oldkeybuf,oldkeylen,newkeybuf,newkeylen); if(status==0 ){ mypcdbeep(30); QMessageBox::information(NULL, "提示", "修改卡片密碼成功"); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘cpurscardkeychg’未正確載入,請查詢DLL文件版本是否正確!"); } } void MainWindow::on_pb_request1_clicked() { if(!checkdllos()){return;} //判斷運行目錄內動態庫文件是否存在 unsigned char mypiccserial[4]; //卡序列號 unsigned char atqasakbuf[3]; //參數 unsigned char status; //函數返回狀態 if (mypiccrequest1 != NULL){ //是否成功連接上 cpurequest()函數 status = mypiccrequest1(mypiccserial,atqasakbuf); if(status==0 || status==52){ mypcdbeep(30); QString uidstr=QString::asprintf("%02X%02X%02X%02X", mypiccserial[0],mypiccserial[1],mypiccserial[2],mypiccserial[3]); QString atqastr=QString::asprintf("%02X%02X", atqasakbuf[0],atqasakbuf[1]); QString sakstr=QString::asprintf("%02X", atqasakbuf[2]); ui->lineEdit_uid->setText(uidstr); QMessageBox::information(NULL, "提示", "卡號:"+uidstr+",ATQA:"+atqastr+",SAK:"+sakstr); } else { disperrinf(status); } }else{ QMessageBox::critical(NULL, "提示", "函數‘cpurequest’未正確載入,請查詢DLL文件版本是否正確!"); } }
-
IC卡
+關注
關注
2文章
168瀏覽量
34148 -
讀卡器
+關注
關注
2文章
417瀏覽量
39391 -
EEPROM
+關注
關注
9文章
1022瀏覽量
81676 -
小程序
+關注
關注
1文章
238瀏覽量
12161
發布評論請先 登錄
相關推薦
評論