AS608與STC89C52指紋密碼鎖
原理圖與PCB圖
首先先附上原理圖,如下圖所示。爲了方便製版,於是畫了原理圖進行PCB打板。
PCB的三維圖如下圖所示。看起來還是很不錯的。由於指紋模塊AS608的供電電壓是3.3v,大家可以買AMS1117模塊進行降壓。我沒有試過AS608接5V。大家可以試一下,如果可以用那還省事一點。
AS608模塊的介紹
錄入圖像
首先肯定是要錄入指紋的,錄入指紋的指令與詳解如下所示,我就不一 一贅述了。我直接講解我寫這個代碼的思路叭。首先可以肯定的是串口初始化,串口初始化完成之後,我們可以將包頭、芯片地址之類的生成一個不可改變的數組,通過調用數組去發送,會讓代碼看起來更容易理解一點。
生成特徵
對比兩個指紋
我的程序裏並沒有用到,所以導致錄入指紋的時候會出現同一個手指錄了兩個不同指紋。我想應該是沒有比對的原因。
搜索指紋
搜索指紋,由於AS608有內部flash,所以可以存好多枚指紋,於是大家在掃描指紋開鎖的時候,可以採用搜索指紋的方式,看看是否內部存有指紋進行開鎖。
合成模板
將錄入的指紋合成特徵模板
大概關鍵的指令就這些。
24C02的代碼
另外在附錄一下24C02的代碼,大家可以借鑑學習一下。
/*************************************************
D羅電子設計qq:1679960378 qq:672939453
***************************************************/
#include <reg52.h>
#include <intrins.h>
#include "24C02.h"
//#include"mytype.h"
#include <24c02.h>
void nop()
{
_nop_();
_nop_();
}
/24C02讀寫驅動程序
void delay1(unsigned int m)
{
unsigned int n;
for(n=0;n<m;n++);
}
void x24c02_init() //24C02初始化
{
wp=0;
scl=1;
nop();
sda=1;
nop();
}
void start() //啓動I2C總線
{
sda=1;
nop();
scl=1;
nop();
sda=0;
nop();
scl=0;
nop();
}
void stop() //停止I2C總線
{
sda=0;
nop();
scl=1;
nop();
sda=1;
nop();
}
void writebyte(unsigned char j) //寫一個字節
{
unsigned char i,temp;
temp=j;
for (i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
nop();
sda=CY; //temp左移時,移出的值放入了CY中
nop();
scl=1; //待sda線上的數據穩定後,將scl拉高
nop();
}
scl=0;
nop();
sda=1;
nop();
}
unsigned char readbyte() //讀一個字節
{
unsigned char i,j,k=0;
scl=0; nop(); sda=1;
for (i=0;i<8;i++)
{
nop(); scl=1; nop();
if(sda==1)
j=1;
else
j=0;
k=(k<<1)|j;
scl=0;
}
nop();
return(k);
}
void clock() //I2C總線時鐘
{
unsigned char i=0;
scl=1;
nop();
while((sda==1)&&(i<255))
i++;
scl=0;
nop();
}
從24c02的地址address中讀取一個字節數據/
unsigned char read24c02(unsigned char address)
{
unsigned char i;
start();
writebyte(0xa0);
clock();
writebyte(address);
clock();
start();
writebyte(0xa1);
clock();
i=readbyte();
stop();
delay1(100);
return(i);
}
//向24c02的address地址中寫入一字節數據info/
void write24c02(unsigned char address,unsigned char info)
{
start();
writebyte(0xa0);
clock();
writebyte(address);
clock();
writebyte(info);
clock();
stop();
delay1(5000); //這個延時一定要足夠長,否則會出錯。因爲24c02在從sda上取得數據後,還需要一定時間的燒錄過程。
}
12864的代碼
/*************************************************
D羅電子設計
***************************************************/
#include <reg52.h>
#include <intrins.h>
#include"12864.h"
/**************************************************************
這裏採用串行方式控制,因爲不要接數據傳輸的腳,爲了省實物焊接過程。
**************************************************************/
unsigned char code AC_TABLE[]={
//座標編碼
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
};
/****************************************************************
發送一個字節
*****************************************************************/
void SendByte(unsigned char Dbyte)
{
unsigned char i;
for(i=0;i<8;i++)
{
SCK = 0;
Dbyte=Dbyte<<1;
SID = CY;
SCK = 1;
SCK = 0;
}
}
/**********************************************************
接收一個字節
***********************************************************/
unsigned char ReceiveByte(void)
{
unsigned char i,temp1,temp2;
temp1=temp2=0;
for(i=0;i<8;i++)
{
temp1=temp1<<1;
SCK = 0;
SCK = 1;
SCK = 0;
if(SID) temp1++;
}
for(i=0;i<8;i++)
{
temp2=temp2<<1;
SCK = 0;
SCK = 1;
SCK = 0;
if(SID) temp2++;
}
return ((0xf0&temp1)+(0x0f&temp2));
}
/****************************************************************
檢查忙狀態
******************************************************************/
void CheckBusy( void )
{
do SendByte(0xfc); //11111,RW(1),RS(0),0
while(0x80&ReceiveByte());
}
/******************************************************************
寫一個字節的指令
*******************************************************************/
void WriteCommand( unsigned char Cbyte )
{
CS = 1;
CheckBusy();
SendByte(0xf8);
SendByte(0xf0&Cbyte);
SendByte(0xf0&Cbyte<<4);
CS = 0;
}
/*************************************************************
寫一個字節的數據
**************************************************************/
void WriteData( unsigned char Dbyte )
{
CS = 1;
CheckBusy();
SendByte(0xfa); //11111,RW(0),RS(1),0
SendByte(0xf0&Dbyte);
SendByte(0xf0&Dbyte<<4);
CS = 0;
}
/******************************************************************
lcd初始化函數
*******************************************************************/
void LcmInit( void )
{
WriteCommand(0x30);
WriteCommand(0x03);
WriteCommand(0x0c);
WriteCommand(0x01);
WriteCommand(0x06);
}
/*******************************************************************************************************
設定光標函數
********************************************************************************************************/
void Location_xy_12864(unsigned char x,unsigned char y)
{
switch(x)
{
case 0:
x=0x80;break;
case 1:
x=0x90;break;
case 2:
x=0x88;break;
case 3:
x=0x98;break;
default:
x=0x80;
}
y=y&0x07;
WriteCommand(0x30);
WriteCommand(y+x);
WriteCommand(y+x);
}
/***********************************************************************************
清除文本
************************************************************************************/
void LcmClearTXT( void )
{
unsigned char i;
WriteCommand(0x30);
WriteCommand(0x80);
for(i=0;i<64;i++)
WriteData(0x20);
Location_xy_12864(0,0);
}
/***********************************************************************
顯示字符串
***********************************************************************/
void PutStr(unsigned char row,unsigned char col,unsigned char *puts)
{
WriteCommand(0x30);
WriteCommand(AC_TABLE[8*row+col]);
while(*puts != '\0')
{
if(col==8)
{
col=0;
row++;
}
if(row==4) row=0;
WriteCommand(AC_TABLE[8*row+col]);
WriteData(*puts);
puts++;
if(*puts != '\0')
{
WriteData(*puts);
puts++;
col++;
}
}
}
按鍵掃描
unsigned char Keycan(void)
{
unsigned char row,col,i;
P1=0xf0;
if((P1&0xf0)!=0xf0)
{
delay(50);
delay(50);
if((P1&0xf0)!=0xf0)
{
row=P1^0xf0; //確定行線
i=0;
P1=a[i]; //精確定位
while(i<4)
{
if((P1&0xf0)!=0xf0)
{
col=~(P1&0xff); //確定列線
break; //已定位後提前退出
}
else
{
i++;
P1=a[i];
}
}
}
else
{
return 0;
}
while((P1&0xf0)!=0xf0);
return (row|col); //行線與列線組合後返回
}
else
return 0; //無鍵按下時返回0
}
void KeyDeal(unsigned char Key)
{
//unsigned char n;
if(Key!=0)
{
switch(Key)
{
case 0x11: K=1; break;
case 0x21: K=2; break;
case 0x41: K=3; break;
case 0x81: break;
case 0x12: K=4; break;
case 0x22: K=5; break;
case 0x42: K=6; break;
case 0x82: break;
case 0x14: K=7; break;
case 0x24: K=8; break;
case 0x44: K=9; break;
case 0x84: break;
case 0x18: break;
case 0x28: K=0; break;
case 0x48: K=11; break;
case 0x88: K=34;break;
default: break;
}
}
}
仔細講解一下錄指紋
附上代碼。
//不可改變與可以改變的數組如下所示
unsigned char code a[]={
0xFE,0xFD,0xFB,0xF7}; //按鍵掃描數組
unsigned char code FPM10A_Pack_Head[6] = {
0xEF,0x01,0xFF,0xFF,0xFF,0xFF}; //協議包頭
unsigned char code FPM10A_Get_Img[6] = {
0x01,0x00,0x03,0x01,0x00,0x05}; //獲得指紋圖像
unsigned char code FPM10A_Img_To_Buffer1[7]={
0x01,0x00,0x04,0x02,0x01,0x00,0x08}; //將圖像放入到BUFFER1 PageId+0x07
unsigned char code FPM10A_Img_To_Buffer2[7]={
0x01,0x00,0x04,0x02,0x02,0x00,0x09}; //將圖像放入到BUFFER2 PageId+0x07
unsigned char code FPM10A_Reg_Model[6]={
0x01,0x00,0x03,0x05,0x00,0x09}; //將BUFFER1跟BUFFER2合成特徵模版
unsigned char code FPM10A_Search[11]={
0x01,0x00,0x08,0x04,0x01,0x00,0x00,0x03,0xE7,0x00,0xF8}; //搜索指紋搜索範圍0 - 999,使用BUFFER1中的特徵碼搜索 //起始頁+頁數+校驗和
unsigned char code FPM10A_Delete_All_Model[6]={
0x01,0x00,0x03,0x0d,0x00,0x11};//刪除指紋模塊裏所有的模版
volatile unsigned char FPM10A_Delete_Finger[10]={
0x01,0x00,0x07,0x0c,0x00,0x00,0x00,0x01,0x00,0x15};//刪除指紋模塊裏的模版
volatile unsigned char FPM10A_Save_Finger[9]={
0x01,0x00,0x06,0x06,0x02,0x00,0x0B,0x00,0x19};//將BUFFER1中的特徵碼存放到指定的位置
串口初始化代碼如下:
void UART_Init()
{
SCON= 0x50; //串口方式1 //REN=1; 允許接收
PCON=0x00; //SMOD=0
TMOD= 0x20; //定時器1定時方式2
TH1= 0xFD; //11.0592MHz 模塊默認波特率爲9600bps
TL1= 0xFD;
TR1= 1; //啓動定時器
EA=1;
}
/***********************************************************************************************
串口發送函數
D羅電子設計qq:1679960378 qq:672939453
***********************************************************************************************/
void Uart_Send_Byte(unsigned char c)//UART Send a byte
{
SBUF = c;
while(!TI);
TI = 0;
}
unsigned char Uart_Receive_Byte()//UART Receive a byteg
{
unsigned char dat;
while(!RI);
RI = 0;
dat = SBUF;
return (dat);
}
大家還是不要看後面的註釋哈,有的是最開始就註釋了的,但是後面改了忘了修改註釋。
在添加指紋代碼之前,現將各種包頭、與接收的數據寫成函數
void FPM10A_Cmd_Send_Pack_Head(void)
{
int i;
for(i=0;i<6;i++) //包頭
{
Uart_Send_Byte(FPM10A_Pack_Head[i]);
}
}
//接收反饋數據緩衝
void FPM10A_Receive_Data(unsigned char ucLength)
{
unsigned char i;
for (i=0;i<ucLength;i++)
FPM10A_RECEICE_BUFFER[i] = Uart_Receive_Byte();
}
//FINGERPRINT_獲得指紋圖像命令
void FPM10A_Cmd_Get_Img(void)
{
unsigned char i;
FPM10A_Cmd_Send_Pack_Head(); //發送通信協議包頭
for(i=0;i<6;i++) //發送命令
{
Uart_Send_Byte(FPM10A_Get_Img[i]);
}
}
//將圖像轉換成特徵碼存放在Buffer1中
void FINGERPRINT_Cmd_Img_To_Buffer1(void)
{
unsigned char i;
FPM10A_Cmd_Send_Pack_Head(); //發送通信協議包頭
for(i=0;i<7;i++) //發送命令 將圖像轉換成 特徵碼 存放在 CHAR_buffer1
{
Uart_Send_Byte(FPM10A_Img_To_Buffer1[i]);
}
}
//將圖像轉換成特徵碼存放在Buffer2中
void FINGERPRINT_Cmd_Img_To_Buffer2(void)
{
unsigned char i;
for(i=0;i<6;i++) //發送包頭
{
Uart_Send_Byte(FPM10A_Pack_Head[i]);
}
for(i=0;i<7;i++) //發送命令 將圖像轉換成 特徵碼 存放在 CHAR_buffer2
{
Uart_Send_Byte(FPM10A_Img_To_Buffer2[i]);
}
}
//合成特徵模板
void FPM10A_Cmd_Reg_Model(void)
{
unsigned char i;
FPM10A_Cmd_Send_Pack_Head(); //發送通信協議包頭
for(i=0;i<6;i++)
{
Uart_Send_Byte(FPM10A_Reg_Model[i]);
}
}
再就是添加指紋函數了,添加指紋函數有如下幾步
發送包頭,發送添加指紋的指令這個函數 FPM10A_Cmd_Get_Img(void);在前文添加指紋的指令中我們發現如果返回來接收到的數據是0則接收到了指紋,如果沒有則一直掃描指紋,直到接收到。在錄入了指紋之後應該先與指紋庫比對一下,如果指紋庫中有這個指紋則不再存入。如果指紋庫中沒有這個指紋則再次按下指紋,於是將指紋存下來,此時指紋ID加1,24C02中的區域中也要存下ID值,以便掉電存儲。
/***********************************************************************************************
添加指紋函數合集
D羅電子設計qq:1679960378 qq:672939453
***********************************************************************************************/
//保存指紋
void FPM10A_Cmd_Save_Finger( unsigned int storeID )
{
unsigned long temp = 0;
unsigned char i;
FPM10A_Save_Finger[5] =(storeID&0xFF00)>>8;
FPM10A_Save_Finger[6] = (storeID&0x00FF);
for(i=0;i<7;i++) //計算校驗和
{
temp = temp + FPM10A_Save_Finger[i];
}
FPM10A_Save_Finger[7]=(temp & 0x00FF00) >> 8; //存放校驗數據
FPM10A_Save_Finger[8]= temp & 0x0000FF;
FPM10A_Cmd_Send_Pack_Head(); //發送通信協議包頭
for(i=0;i<9;i++)
Uart_Send_Byte(FPM10A_Save_Finger[i]); //發送命令 將圖像轉換成 特徵碼 存放在 CHAR_buffer2
}
//添加指紋
void FPM10A_Add_Fingerprint()
{
uchar IDa1,IDa2,IDa3;
LcmClearTXT();
PutStr(1,2,"請按手指");
delayms(2000);
FPM10A_Cmd_Get_Img(); //獲得指紋圖像
FPM10A_Receive_Data(12);
while(FPM10A_RECEICE_BUFFER[9]!=0)
{
FPM10A_Cmd_Get_Img(); //獲得指紋圖像
FPM10A_Receive_Data(12);
}
if(FPM10A_RECEICE_BUFFER[9]==0)
{
FINGERPRINT_Cmd_Img_To_Buffer1();
FPM10A_Receive_Data(12);
FPM10A_Cmd_Search_Finger();
FPM10A_Receive_Data(16);
if(FPM10A_RECEICE_BUFFER[9] == 0) //搜索是否已經存儲
{
PageID = FPM10A_RECEICE_BUFFER[10]*256 + FPM10A_RECEICE_BUFFER[11];
IDa1=PageID/100;
IDa2=PageID/10%10;
IDa3=PageID%10;
LcmClearTXT();
PutStr(0,1,"該指紋已存儲");
PutStr(1,1,"編號爲:");
WriteCommand(0x8D);
WriteData(0x30+IDa1);
WriteData(0x30+IDa2);
WriteData(0x30+IDa3);
PutStr(3,0," 按任意鍵繼續");
while(Keycan()==0);
}
if(FPM10A_RECEICE_BUFFER[9] == 9)
{
LcmClearTXT();
PutStr(1,1,"請再次按指紋");
FPM10A_Cmd_Get_Img(); //獲得指紋圖像
FPM10A_Receive_Data(12);
if(FPM10A_RECEICE_BUFFER[9] == 0)
{
FINGERPRINT_Cmd_Img_To_Buffer2();
FPM10A_Receive_Data(12);
FPM10A_Cmd_Reg_Model();
FPM10A_Receive_Data(12);
IDa1=PageID/100;
IDa2=PageID/10%10;
IDa3=PageID%10;
LcmClearTXT();
PutStr(1,1,"指紋採集成功");
PutStr(2,1,"編號爲:");
WriteCommand(0x8D);
WriteData(0x30+IDa1);
WriteData(0x30+IDa2);
WriteData(0x30+IDa3);
delay(1000);
write24c02(116,PageID+1);
FPM10A_Cmd_Save_Finger(PageID++);
FPM10A_Receive_Data(12);
}
}
PutStr(3,0," 按任意鍵繼續");
while(Keycan()==0);
}
LcmClearTXT();
}
由於篇幅關係,只介紹錄入指紋的代碼,但是其餘代碼都大同小異,只要弄清楚指令就可以了。
另外將剩下的的代碼都附錄如下,以便大家學習借鑑。
/***********************************************************************************************
管理員與開鎖合集
D羅電子設計——鄧工
***********************************************************************************************/
void shuazhiwen()
{
LcmClearTXT();
PutStr(1,1,"請按手指開鎖");
FPM10A_Find_Fingerprint();
}
void gaimima() //修改用戶密碼
{
uchar i,j=0,mima1[6],mima2[6];
uchar k,temp;
LcmClearTXT();
PutStr(1,1,"請輸入新密碼");
for(i=0;i<6;i++)
{
mima1[i]=0;
}
Key=Keycan();
while(Key!=queren)
{
Key=Keycan();
KeyDeal(Key);
delay(30);
if(Key==0)
{
K=10;
}
if((K>=0)&&(K<=9))
{
mima1[j]=K;
if(j<6)
{
WriteCommand(0x89+j); //指定第三行顯示位置
//WriteData(0x0f);
WriteData(K+0x30);
}
++j;
if(j==7)
j=6;
} //顯示LCD12864並行顯示
if(K==34) //按了刪除鍵
{
if(j==0)
{
WriteCommand(0x89); //指定第三行顯示位置
WriteData(0x20);
}
else
{
--j;
WriteCommand(0x89+j); //指定第三行顯示位置
WriteData(0x20);
}
}
}
LcmClearTXT();
j=0;
PutStr(1,0,"請再次輸入新密碼");
for(i=0;i<6;i++)
{
mima2[i]=0;
}
Key=Keycan();
while(Key!=queren)
{
Key=Keycan();
KeyDeal(Key);
delay(30);
if(Key==0)
{
K=10;
}
if((K>=0)&&(K<=9))
{
mima2[j]=K;
if(j<6)
{
WriteCommand(0x89+j); //指定第三行顯示位置
//WriteData(0x0f);
WriteData(K+0x30);
}
++j;
if(j==7)
j=6;
} //顯示LCD12864並行顯示
if(K==34) //按了刪除鍵
{
if(j==0)
{
WriteCommand(0x89); //指定第三行顯示位置
WriteData(0x20);
}
else
{
--j;
WriteCommand(0x89+j); //指定第三行顯示位置
WriteData(0x20);
}
}
}
LcmClearTXT();
if((mima1[0]==mima2[0])&&(mima1[1]==mima2[1])&&(mima1[2]==mima2[2])&&(mima1[3]==mima2[3])&&(mima1[4]==mima2[4])&&(mima1[5]==mima2[5]))
{
for(i=0;i<6;i++)
mimaID[i]=mima1[i];
for(i=0;i<6;i++) //密碼限制在6位以內
{
UserPassword[i]=mima1[i]+0x30;
}
temp=(Member-1)*100+10;
delayms(5);
for(k=0;k<6;k++)
{
write24c02(temp,UserPassword[k]);
delayms(10);
temp++;
}
//
PutStr(0,1,"密碼修改成功");
PutStr(3,0," 按任意鍵繼續");
Member=0; //方便下次修改密碼
while(Keycan()==0);
}
else
{
PutStr(0,0," 密碼修改失敗 ");
PutStr(1,0,"兩次輸入的密碼不");
PutStr(2,0,"一致,請重新操作");
PutStr(3,0," 按任意鍵繼續");
while(Keycan()==0);
}
LcmClearTXT();
}
void zhu()
{
LcmClearTXT();
PutStr(1,2,"門已打開");
jidianqi=0;
delay(2500);
jidianqi=1;
PutStr(3,0," 按任意鍵繼續");
while(Keycan()==0);
}
void guanliyuan() //管理員
{
uchar i,j=0,x=1;uchar Right_flag;
LcmClearTXT();
PutStr(1,1,"請輸入密碼:");
for(i=0;i<6;i++)
{
mima[i]=0;
}
Key=Keycan();
while(Key!=queren)
{
Key=Keycan();
KeyDeal(Key);
delay(30);
if(Key==0)
{
K=10;
}
if((K>=0)&&(K<=9))
{
mima[j]=K;
if(j<6)
{
WriteCommand(0x89+j); //指定第三行顯示位置
WriteData(0x0f);
}
++j;
if(j==7)
{
j=6;
}
} //顯示LCD12864並行顯示
if(K==34) //按了刪除鍵
{
if(j==0)
{
WriteCommand(0x89); //指定第三行顯示位置
WriteData(0x20);
}
else
{
--j;
WriteCommand(0x89+j); //指定第三行顯示位置
WriteData(0x20);
}
}
}
LcmClearTXT();
for(i=0;i<6;i++)
{
UserPassword[i]=mima[i]+0x30;
}
if(j==6)
{
Right_flag=PassWord_Chack();
}
if (Right_flag==1)
{
Right_flag=0;
Key=Keycan();
while(Key!=tuichu)
{
PutStr(0,0,"按鍵1 : 增加指紋");
PutStr(1,0,"按鍵2 : 刪去指紋");
PutStr(2,0,"按鍵3 : 清空所有");
PutStr(3,0,"按鍵4 : 修改密碼");
Key=Keycan();
KeyDeal(Key);
switch(K)
{
case 1:
FPM10A_Add_Fingerprint(); K=8; //僅錄一次,如果不設置K=8(可以比4大就行),會一直錄指紋
break;
case 2:
FPM10A_Delete_Fingerprint();
break;
case 3:
FPM10A_Delete_All_Fingerprint();
break;
case 4:
gaimima();
break;
default:
break;
}
}
}
else
{
alarm=0;
PutStr(1,2,"密碼錯誤");
PutStr(2,0," 請重新操作!");
PutStr(3,0," 按任意鍵繼續");
delay(2500);
alarm=1;
while(Keycan()==0);
}
Key=0;
LcmClearTXT();
}
//功能介紹
void MEMU()
{
PutStr(0,2,"歡迎使用");
PutStr(1,1,"D羅電子設計");
PutStr(2,1,"qq1679960378");
PutStr(3,1,"qq:672939453");
Key=Keycan();
if(k2==1) //指紋刷機
{
LcmClearTXT();
shuazhiwen();
LcmClearTXT();
}
if(Key==0x81) //管理員操作
{
LcmClearTXT();
guanliyuan();
LcmClearTXT();
}
}
void main()
{
UART_Init(); //串口初始化
x24c02_init(); //24C02初始化
LcmInit(); //LCD12864初始化
LcmClearTXT(); //LCD12864清屏
// write24c02(110,0x30);
// write24c02(111,0x30);//24c02的第110到115地址單元作爲密碼存儲區
// write24c02(112,0x30);
// write24c02(113,0x30);
// write24c02(114,0x30);
// write24c02(115,0x30);
// write24c02(116,0);
PageID=read24c02(116);
while(1)
{
MEMU();
delay(100);
}
}
附上實物圖
圖中所示的3.2是5v降壓到3.3的顯示屏,大家降壓可以前文提到的AMS1117模塊。
串口通訊失敗的原因
1、串口初始化有問題,如果想知道初始化是否正確,用USB TO TTL串口下載器進行調試一下,如果不對,大家再多查一下串口的資料。
2、另外,最後最重要的是,AS608模塊是有波特率的,一開始你不可能一下就能把波特率設置對。你可以自己用單片機串口初始化設置波特率。運用指紋上位機調試指紋模塊波特率,與單片機一致就可以了。
指紋上位機去我的資源裏下載,免費哈。
指紋模塊波特率設置就是與下載器普通的連接就行了。RXD----TXD,TXD-----RXD。