幾年前我們在科幻電影中看到的指紋傳感器,現在變得非常普遍,用于驗證一個人出于各種目的的身份。目前,我們在日常生活中隨處可見基于指紋的系統,例如辦公室考勤,銀行員工驗證,自動取款機中的現金提取或存款,政府辦公室的身份驗證等。我們已經將其與Arduino和Raspberry Pi接口,今天我們將指紋傳感器與PIC微控制器連接。
必需組件
PIC16f877A 微控制器
指紋模塊
按鈕或鍵盤
16x2 液晶顯示器
10k鍋
18.432000 MHz 晶體振蕩器
面包板或印刷電路板(從JLCPCB訂購)
跳線
指示燈(可選)
電阻 150 歐姆 -1 k 歐姆(可選)
5v 電源
電路圖及說明
在這個PIC微控制器指紋傳感器接口項目中,我們使用了4個按鈕:這些按鈕用于多功能。密鑰 1用于在系統中存儲或刪除指紋時匹配指紋和遞增指紋 ID。密鑰 2用于注冊新指紋以及在系統中存儲或刪除指紋時遞減指紋 ID。鍵 3 用于從系統中刪除存儲的手指,鍵 4 用于確定。LED用于指示檢測到或匹配指紋。在這里,我們使用了適用于UART的指紋模塊。因此,在這里,我們將此指紋模塊與PIC微控制器連接,其默認波特率為57600。
因此,首先,我們需要進行所有必需的連接,如下面的電路圖所示。連接很簡單,我們剛剛將指紋模塊連接到PIC微控制器的UART。16x2 LCD 用于顯示所有消息。10k電位器也與LCD一起使用,以控制其對比度。16x2 LCD 數據引腳是連接的 PORTA 引腳。LCD 的 d4、d5、d6 和 d7 引腳分別與 PIC 微控制器的引腳 RA0、RA1、RA2 和 RA3 連接。四個按鈕(或鍵盤)連接到 PORTD 的引腳 RD0、RD1、RD2 和 RD,LED 也連接到端口 PORTC 的引腳 RC3。在這里,我們使用了一個18.432000 MHz的外部晶體振蕩器來為微控制器提供時鐘。
帶PIC微控制器的指紋傳感器的操作
該項目的操作很簡單,只需在PIC編程器或刻錄機(PIckit2或Pickit3或其他)的幫助下,將從源代碼生成的十六進制文件上傳到PIC微控制器中,然后您將通過LCD看到一些介紹消息,然后要求用戶輸入操作選項。要匹配指紋,用戶需要按鍵1,然后LCD將要求將手指放在指紋傳感器上。現在,通過將手指放在指紋模塊上,我們可以檢查我們的指紋是否已存儲。如果您的指紋已存儲,則LCD將顯示帶有類似指紋的“ID:2”存儲ID的消息,否則將顯示“未找到”。
現在要注冊指紋,用戶需要按注冊按鈕或鍵 2 并按照 LCD 屏幕上的說明消息進行操作。
如果用戶想要刪除任何指紋,則用戶需要按刪除按鈕或鍵3。之后,LCD將詢問要刪除的指紋的ID。現在,通過使用遞增按鈕或鍵1(匹配按鈕或鍵1)和遞減按鈕或鍵2(注冊按鈕或鍵2)進行遞增和遞減,用戶可以選擇保存的指紋的ID,然后按確定按鈕刪除該指紋。
指紋接口 注意:這個項目的程序對于初學者來說有點復雜。但其簡單的接口代碼是利用讀取r305指紋模塊數據表制作的。該指紋模塊的所有功能說明都在數據表中給出。
在這里,我們使用幀格式與指紋模塊通信。每當我們向指紋模塊發送命令或數據請求幀時,它都會以相同的幀格式響應我們,其中包含與應用命令相關的數據或信息。所有數據和命令幀格式已在用戶手冊或R305指紋模塊的數據表中給出。
編程說明
在編程中,我們使用了以下幀格式。
我們通過設置配置位并定義LCD,按鈕和LED的宏和引腳來開始程序,您可以在該項目結束時給出的完整代碼中簽入。
然后我們聲明并初始化了一些變量和數組,并制作了一個框架,我們需要在這個項目中使用它來連接指紋模塊和PIC微控制器。
uchar buf[20];
uchar buf1[20];
volatile uint index=0;
volatile int flag=0;
uint msCount=0;
volatile uint count=0;
uchar data[10];
uint id=1;
enum
{
CMD,
DATA,
SBIT_CREN=4,
SBIT_TXEN,
SBIT_SPEN,
};
const char passPack[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x7, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1B};
const char f_detect[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x3, 0x1, 0x0, 0x5};
const char f_imz2ch1[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x4, 0x2, 0x1, 0x0, 0x8};
const char f_imz2ch2[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x4, 0x2, 0x2, 0x0, 0x9};
const char f_createModel[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x3,0x5,0x0,0x9};
char f_storeModel[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x6,0x6,0x1,0x0,0x1,0x0,0xE};
const char f_search[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x8, 0x1B, 0x1, 0x0, 0x0, 0x0, 0xA3, 0x0, 0xC8};
char f_delete[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x7,0xC,0x0,0x0,0x0,0x1,0x0,0x15};
之后,我們制作了LCD功能來驅動LCD。
void lcdwrite(uchar ch,uchar rw)
{
LCDPORT= ch>>4 & 0x0F;
RS=rw;
EN=1;
__delay_ms(5);
EN=0;
LCDPORT= ch & 0x0F;
EN=1;
__delay_ms(5);
EN=0;
}
lcdprint(char *str)
{
while(*str)
{
lcdwrite(*str++,DATA);
//__delay_ms(20);
}
}
lcdbegin()
{
uchar lcdcmd[5]={0x02,0x28,0x0E,0x06,0x01};
uint i=0;
for(i=0;i<5;i++)
lcdwrite(lcdcmd[i], CMD);
}
給定函數用于初始化UART
void serialbegin(uint baudrate)
{
SPBRG = (18432000UL/(long)(64UL*baudrate))-1; // baud rate @18.432000Mhz Clock
TXSTAbits.SYNC = 0; //Setting Asynchronous Mode, ie UART
RCSTAbits.SPEN = 1; //Enables Serial Port
TRISC7 = 1; //As Prescribed in Datasheet
TRISC6 = 0; //As Prescribed in Datasheet
RCSTAbits.CREN = 1; //Enables Continuous Reception
TXSTAbits.TXEN = 1; //Enables Transmission
GIE = 1; // ENABLE interrupts
INTCONbits.PEIE = 1; // ENable peripheral interrupts.
PIE1bits.RCIE = 1; // ENABLE USART receive interrupt
PIE1bits.TXIE = 0; // disable USART TX interrupt
PIR1bits.RCIF = 0;
}
給定函數用于將命令傳輸到指紋模塊并從指紋模塊接收數據。
void serialwrite(char ch)
{
while(TXIF==0); // Wait till the transmitter register becomes empty
TXIF=0; // Clear transmitter flag
TXREG=ch; // load the char to be transmitted into transmit reg
}
serialprint(char *str)
{
while(*str)
{
serialwrite(*str++);
}
}
void interrupt SerialRxPinInterrupt(void)
{
if((PIR1bits.RCIF == 1) && (PIE1bits.RCIE == 1))
{
uchar ch=RCREG;
buf[index++]=ch;
if(index>0)
flag=1;
RCIF = 0; // clear rx flag
}
}
void serialFlush()
{
for(int i=0;i
{
buf[i]=0;
}
}
之后,我們需要創建一個函數來準備要傳輸到指紋的數據并解碼來自指紋模塊的數據。
int sendcmd2fp(char *pack, int len)
{
uint res=ERROR;
serialFlush();
index=0;
__delay_ms(100);
for(int i=0;i
{
serialwrite(*(pack+i));
}
__delay_ms(1000);
if(flag == 1)
{
if(buf[0] == 0xEF && buf[1] == 0x01)
{
if(buf[6] == 0x07) // ack
{
if(buf[9] == 0)
{
uint data_len= buf[7];
data_len<<=8;
data_len|=buf[8];
for(int i=0;i
data[i]=0;
for(int i=0;i
{
data[i]=buf[10+i];
}
res=PASS;
}
else
{
res=ERROR;
}
}
}
現在,代碼中有四個函數可用于四個不同的任務:
輸入指紋ID的函數 –單位getId()
匹配手指的函數 –void matchFinger()
注冊新手指的函數 – 無效注冊手指()
刪除手指的函數 –void deleteFinger()
最后給出了包含所有四個函數的完整代碼。
現在在主功能中,我們初始化GPIO,LCD,UART并檢查指紋模塊是否與微控制器連接。然后它通過LCD顯示一些介紹消息。最后,在while循環中,我們讀取所有鍵或按鈕來操作項目。
int main()
{
void (*FP)();
ADCON1=0b00000110;
LEDdir= 0;
SWPORTdir=0xF0;
SWPORT=0x0F;
serialbegin(57600);
LCDPORTDIR=0x00;
TRISE=0;
lcdbegin();
lcdprint("Fingerprint");
lcdwrite(192,CMD);
lcdprint("Interfacing");
__delay_ms(2000);
lcdwrite(1,CMD);
lcdprint("Using PIC16F877A");
lcdwrite(192,CMD);
lcdprint("Circuit Digest");
__delay_ms(2000);
index=0;
while(sendcmd2fp(&passPack[0],sizeof(passPack)))
{
lcdwrite(1,CMD);
lcdprint("FP Not Found");
__delay_ms(2000);
index=0;
}
lcdwrite(1,CMD);
lcdprint("FP Found");
__delay_ms(1000);
lcdinst();
while(1)
{
FP=match
FP();
}
return 0;
}
#define _XTAL_FREQ 18432000
#include
#include
#include
#include
// BEGIN CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//END CONFIG
#define uchar unsigned char
#define uint unsigned int
#define LCDPORTDIR TRISA
#define LCDPORT PORTA
#define RS RE1
#define EN RE0
#define SWPORTdir TRISD
#define SWPORT PORTD
#define enrol RD4
#define match RD5
#define delet RD7
#define ok RD6
#define up RD5
#define down RD4
#define LEDdir TRISC3
#define LED RC3
#define HIGH 1
#define LOW 0
#define PASS 0
#define ERROR 1
#define checkKey(id) id=up
uchar buf[20];
uchar buf1[20];
volatile uint index=0;
volatile int flag=0;
uint msCount=0;
uint g_timerflag=1;
volatile uint count=0;
uchar data[10];
uint id=1;
enum
{
CMD,
DATA,
SBIT_CREN=4,
SBIT_TXEN,
SBIT_SPEN,
};
const char passPack[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x7, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1B};
const char f_detect[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x3, 0x1, 0x0, 0x5};
const char f_imz2ch1[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x4, 0x2, 0x1, 0x0, 0x8};
const char f_imz2ch2[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x4, 0x2, 0x2, 0x0, 0x9};
const char f_createModel[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x3,0x5,0x0,0x9};
char f_storeModel[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x6,0x6,0x1,0x0,0x1,0x0,0xE};
const char f_search[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x8, 0x1B, 0x1, 0x0, 0x0, 0x0, 0xA3, 0x0, 0xC8};
char f_delete[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x7,0xC,0x0,0x0,0x0,0x1,0x0,0x15};
void lcdwrite(uchar ch,uchar rw)
{
LCDPORT= ch>>4 & 0x0F;
RS=rw;
EN=1;
__delay_ms(5);
EN=0;
LCDPORT= ch & 0x0F;
EN=1;
__delay_ms(5);
EN=0;
}
lcdprint(char *str)
{
while(*str)
{
lcdwrite(*str++,DATA);
//__delay_ms(20);
}
}
lcdbegin()
{
uchar lcdcmd[5]={0x02,0x28,0x0E,0x06,0x01};
uint i=0;
for(i=0;i<5;i++)?
lcdwrite(lcdcmd[i], CMD);
}
void lcdinst()
{
lcdwrite(0x80, CMD);
lcdprint("1-Match 2-Enroll");
lcdwrite(0xc0, CMD);
lcdprint("3-delete Finger");
__delay_ms(10);
}
void serialbegin(uint baudrate)
{
SPBRG = (18432000UL/(long)(64UL*baudrate))-1; // baud rate @18.432000Mhz Clock
TXSTAbits.SYNC = 0; //Setting Asynchronous Mode, ie UART
RCSTAbits.SPEN = 1; //Enables Serial Port
TRISC7 = 1; //As Prescribed in Datasheet
TRISC6 = 0; //As Prescribed in Datasheet
RCSTAbits.CREN = 1; //Enables Continuous Reception
TXSTAbits.TXEN = 1; //Enables Transmission
GIE = 1; // ENABLE interrupts
INTCONbits.PEIE = 1; // ENable peripheral interrupts.
PIE1bits.RCIE = 1; // ENABLE USART receive interrupt
PIE1bits.TXIE = 0; // disable USART TX interrupt
PIR1bits.RCIF = 0;
}
void serialwrite(char ch)
{
while(TXIF==0); // Wait till the transmitter register becomes empty
TXIF=0; // Clear transmitter flag
TXREG=ch; // load the char to be transmitted into transmit reg
}
serialprint(char *str)
{
while(*str)
{
serialwrite(*str++);
}
}
void interrupt SerialRxPinInterrupt(void)
{
if((PIR1bits.RCIF == 1) && (PIE1bits.RCIE == 1))
{
uchar ch=RCREG;
buf[index++]=ch;
if(index>0)
flag=1;
RCIF = 0; // clear rx flag
}
}
void serialFlush()
{
for(int i=0;i
{
buf[i]=0;
}
}
int sendcmd2fp(char *pack, int len)
{
uint res=ERROR;
serialFlush();
index=0;
__delay_ms(100);
for(int i=0;i
{
serialwrite(*(pack+i));
}
__delay_ms(1000);
if(flag == 1)
{
if(buf[0] == 0xEF && buf[1] == 0x01)
{
if(buf[6] == 0x07) // ack
{
if(buf[9] == 0)
{
uint data_len= buf[7];
data_len<<=8;?
data_len|=buf[8];
for(int i=0;i
data[i]=0;
for(int i=0;i
{
data[i]=buf[10+i];
}
res=PASS;
}
else
{
res=ERROR;
}
}
}
index=0;
flag=0;
return res;
}
}
uint getId()
{
uint id=0;
lcdwrite(1, CMD);
while(1)
{
lcdwrite(0x80, CMD);
checkKey(id);
sprintf(buf1,"Enter Id:%d ",id);
lcdprint(buf1);
__delay_ms(200);
if(ok == LOW)
return id;
}
}
void matchFinger()
{
lcdwrite(1,CMD);
lcdprint("Place Finger");
lcdwrite(192,CMD);
__delay_ms(2000);
if(!sendcmd2fp(&f_detect[0],sizeof(f_detect)))
{
if(!sendcmd2fp(&f_imz2ch1[0],sizeof(f_imz2ch1)))
{
if(!sendcmd2fp(&f_search[0],sizeof(f_search)))
{
lcdwrite(1,CMD);
lcdprint("Finger Found");
uint id= data[0];
id<<=8;?
id+=data[1];
uint score=data[2];
score<<=8;?
score+=data[3];
sprintf(buf1,"Id:%d Score:%d",id,score);
lcdwrite(192,CMD);
lcdprint(buf1);
LED=1;
__delay_ms(1000);
LED=0;
}
else
{
lcdwrite(1,CMD);
lcdprint("Not Found");
}
}
}
else
{
lcdprint("No Finger");
}
__delay_ms(2000);
}
void enrolFinger()
{
lcdwrite(1,CMD);
lcdprint("Enroll Finger");
__delay_ms(2000);
lcdwrite(1,CMD);
lcdprint("Place Finger");
lcdwrite(192,CMD);
__delay_ms(1000);
if(!sendcmd2fp(&f_detect[0],sizeof(f_detect)))
{
if(!sendcmd2fp(&f_imz2ch1[0],sizeof(f_imz2ch1)))
{
lcdprint("Finger Detected");
__delay_ms(1000);
lcdwrite(1,CMD);
lcdprint("Place Finger");
lcdwrite(192,CMD);
lcdprint(" Again ");
__delay_ms(2000);
if(!sendcmd2fp(&f_detect[0],sizeof(f_detect)))
{
if(!sendcmd2fp(&f_imz2ch2[0],sizeof(f_imz2ch2)))
{
lcdwrite(1,CMD);
lcdprint("Finger Detected");
__delay_ms(1000);
if(!sendcmd2fp(&f_createModel[0],sizeof(f_createModel)))
{
id=getId();
f_storeModel[11]= (id>>8) & 0xff;
f_storeModel[12]= id & 0xff;
f_storeModel[14]= 14+id;
if(!sendcmd2fp(&f_storeModel[0],sizeof(f_storeModel)))
{
lcdwrite(1,CMD);
lcdprint("Finger Stored");
sprintf(buf1,"Id:%d",id);
lcdwrite(192,CMD);
lcdprint(buf1);
__delay_ms(1000);
}
else
{
lcdwrite(1,CMD);
lcdprint("Finger Not Stored");
}
}
else
lcdprint("Error");
}
else
lcdprint("Error");
}
else
lcdprint("No Finger");
}
}
else
{
lcdprint("No Finger");
}
__delay_ms(2000);
}
void deleteFinger()
{
id=getId();
f_delete[10]=id>>8 & 0xff;
f_delete[11]=id & 0xff;
f_delete[14]=(21+id)>>8 & 0xff;
f_delete[15]=(21+id) & 0xff;
if(!sendcmd2fp(&f_delete[0],sizeof(f_delete)))
{
lcdwrite(1,CMD);
sprintf(buf1,"Finger ID %d ",id);
lcdprint(buf1);
lcdwrite(192, CMD);
lcdprint("Deleted Success");
}
else
{
lcdwrite(1,CMD);
lcdprint("Error");
}
__delay_ms(2000);
}
int main()
{
void (*FP)();
ADCON1=0b00000110;
LEDdir= 0;
SWPORTdir=0xF0;
SWPORT=0x0F;
serialbegin(57600);
LCDPORTDIR=0x00;
TRISE=0;
lcdbegin();
lcdprint("Fingerprint");
lcdwrite(192,CMD);
lcdprint("Interfacing");
__delay_ms(2000);
lcdwrite(1,CMD);
lcdprint("Using PIC16F877A");
lcdwrite(192,CMD);
lcdprint("Circuit Digest");
__delay_ms(2000);
index=0;
while(sendcmd2fp(&passPack[0],sizeof(passPack)))
{
lcdwrite(1,CMD);
lcdprint("FP Not Found");
__delay_ms(2000);
index=0;
}
lcdwrite(1,CMD);
lcdprint("FP Found");
__delay_ms(1000);
lcdinst();
while(1)
{
FP=match
FP();
}
-
指紋傳感器
+關注
關注
6文章
195瀏覽量
63458 -
Arduino
+關注
關注
187文章
6464瀏覽量
186657
發布評論請先 登錄
相關推薦
評論