根據(jù)賓夕法尼亞州立大學(xué)的研究人員的說法,人類更容易信任機(jī)器而不是人,這很可能從我們?nèi)绱溯p易地向機(jī)器透露我們的 ATM 密碼就可以看出。今天,在人工智能、機(jī)器學(xué)習(xí)、聊天機(jī)器人、智能揚聲器、機(jī)器人等正在積極發(fā)展的世界中,人類和機(jī)器人之間的這種協(xié)同作用只會增加。今天,從過橋收費員到收銀員,我們周圍的一切都被機(jī)器取代,以使工作更輕松、更高效。為了跟上這個階段,在這個項目中,我們將使用 AVR 微控制器構(gòu)建一個生物識別考勤系統(tǒng)取代人工考勤程序。該系統(tǒng)將更加可靠和高效,因為它可以節(jié)省時間并避免躲閃。
在這個項目中,我們使用了指紋模塊和AVR(atmega32)進(jìn)行考勤。通過使用指紋傳感器,系統(tǒng)將為用戶變得更加安全。以下部分解釋了 使用 AVR 制作基于指紋的生物識別考勤系統(tǒng)的技術(shù)細(xì)節(jié)。
所需組件
Atmega32 -1
指紋模塊 (r305) -1
按鈕或薄膜按鈕 - 4
發(fā)光二極管 -2
1K電阻-2
2.2K電阻-1
電源 12v 適配器
連接線
蜂鳴器-1
16x2 液晶屏 -1
PCB或面包板
RTC 模塊(ds1307 或 ds3231)-1
LM7805 -1
1000uf、10uf電容-1
Burgstips 男性 女性
直流插孔(可選)
BC547晶體管-1
在這個 指紋考勤系統(tǒng)電路中,我們使用指紋傳感器模塊 通過在系統(tǒng)中輸入他們的指紋來驗證個人或員工的身份。在這里,我們使用 4 個按鈕來注冊、刪除、增加和減少指紋數(shù)據(jù)。密鑰 1 用于將新人員注冊到系統(tǒng)中。因此,當(dāng)用戶想要注冊一個新手指時,他/她需要按 1 鍵,然后 LCD 要求他/她將手指放在指紋傳感器上兩次,然后詢問員工 ID。同理,key 2具有雙重功能,比如用戶注冊新手指時,需要選擇指紋ID通過使用另外兩個鍵,即 3 和 4。現(xiàn)在用戶需要按鍵 1(這次該鍵的行為類似于 OK)以繼續(xù)選擇 ID。鍵 2 也用于復(fù)位或刪除微控制器 EEPROM 中的數(shù)據(jù)。
指紋傳感器模塊捕獲指紋圖像,然后將其轉(zhuǎn)換為等效模板,并根據(jù)微控制器選擇的 ID 將它們保存到內(nèi)存中。所有過程都由微控制器控制,就像拍攝指紋圖像一樣;將其轉(zhuǎn)換為模板并存儲為 ID 等。
電路原理圖
基于指紋的考勤系統(tǒng)項目的完整電路圖如下所示。它具有 Atmega32 微控制器,用于控制項目的所有過程。按鈕或薄膜按鈕用于登記、刪除、選擇考勤 ID,蜂鳴器用于指示,16x2 LCD用于指導(dǎo)用戶如何使用機(jī)器。
如電路圖所示,按鈕或薄膜按鈕直接連接到微控制器的引腳 PA2(ENROL 鍵 1)、PA3(DEL 鍵 2)、PA0(UP 鍵 3)、PA1(DOWN 鍵 4)相對于地或 PA4。并且一個 LED 通過一個 1k 電阻連接在微控制器的引腳 PC2 上,相對于地。指紋模塊的 Rx 和 Tx 直接連接在微控制器的串行引腳 PD1 和 PD3 上。5v電源用于為整個電路供電,使用LM7805穩(wěn)壓器,由12v直流適配器供電。蜂鳴器也連接在引腳 PC3 上。16x2 LCD 配置為 4 位模式 ,其 RS、RW、EN、D4、D5、D6 和 D7 直接連接到微控制器的引腳 PB0、PB1、PB2、PB4、PB5、PB6、PB7。實時時鐘模塊連接在 I2Cpin PC0 SCL 和 PC1 SDA。PD7 用作軟 UART Tx 引腳,用于獲取當(dāng)前時間。
指紋考勤系統(tǒng)的工作原理
每當(dāng)用戶將手指放在指紋模塊上時,指紋模塊就會捕獲手指圖像,并在系統(tǒng)中搜索是否有任何 ID 與該指紋相關(guān)聯(lián)。如果檢測到指紋ID,則LCD 將顯示已注冊的考勤,同時蜂鳴器將鳴響一次。
除了指紋模塊,我們還使用 RTC 模塊來處理時間和日期數(shù)據(jù)。時間和日期在系統(tǒng)中連續(xù)運行,因此當(dāng)真正的用戶將手指放在指紋傳感器上時,微控制器可以獲取時間和日期,然后將它們保存在分配的內(nèi)存插槽中的 EEPROM 中。
用戶可以長按4號鍵下載考勤數(shù)據(jù)。接通電源,等待一段時間后,LCD會顯示“Downloading 。..。”。并且用戶可以通過串行監(jiān)視器看到考勤數(shù)據(jù),在此代碼軟件中,UART 在引腳 PD7-pin20 處被編程為 Tx,以將數(shù)據(jù)發(fā)送到終端。用戶還需要一個 TTL 到 USB 轉(zhuǎn)換器才能通過串行終端查看考勤數(shù)據(jù)。
如果用戶想刪除所有數(shù)據(jù),那么他/她必須按住鍵 2,然后連接電源并等待一段時間。一段時間后,LCD 將顯示“請稍候。..”,然后顯示“記錄已成功刪除”。最后給出的演示視頻中沒有顯示這兩個步驟。
代碼說明
最后給出了這個生物識別考勤系統(tǒng)的完整代碼和視頻。這個項目的代碼對于初學(xué)者來說有點冗長和復(fù)雜。因此,我們嘗試采用描述性變量來提高可讀性和理解性。首先,我們已經(jīng)包含了一些必要的頭文件,然后為不同的目的編寫了宏。
?
#define F_CPU 8000000ul #include#include #include /***宏*/ #define USART_BAUDRATE 9600 #define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) #define uchar 無符號字符 #define uint 無符號整數(shù) #define LCDPORTDIR DDRB #define LCDPORT PORTB #定義rs 0 #define rw 1 #define en 2 #define RSLow (LCDPORT&=~(1< ?
在此之后,我們?yōu)橹讣y命令和響應(yīng)聲明了一些變量和數(shù)組。我們還添加了一些用于獲取和設(shè)置 RTC 數(shù)據(jù)的功能。
?
無效 RTC_stp() { TWCR=(1<?
然后我們有一些用于 LCD 的函數(shù),它們負(fù)責(zé)驅(qū)動 LCD。LCD 驅(qū)動函數(shù)是為 4 位模式驅(qū)動編寫的。其次,我們還有一些 UART 驅(qū)動函數(shù),負(fù)責(zé)初始化 UART 并在指紋傳感器和微控制器之間交換數(shù)據(jù)。
?
void serialbegin() { UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); UBRRH = (BAUD_PRESCALE >> 8); UBRRL = BAUD_PRESCALE; UCSRB=(1<0) 標(biāo)志=1; //serial1Write(ch); } void serialwrite(char ch) { while ((UCSRA & (1 << UDRE)) == 0); UDR = 通道; } void serialprint(char *str) { while(*str) { serialwrite(*str++); } } ?
現(xiàn)在我們有了更多的 UART 功能,但它們是軟件 UART。用于通過串行終端將保存的數(shù)據(jù)傳輸?shù)接嬎銠C(jī)。這些函數(shù)是基于延遲的,不使用任何類型的中斷。對于 UART,只有 tx 信號可以工作,我們將軟 UART 的波特率硬編碼為 9600。
?
void SerialSoftWrite(char ch) { PORTD&=~(1<<7); _delay_us(104); for(int i=0;i<8;i++) { if(ch & 1) PORTD|=(1<<7); 否則 PORTD&=~(1<<7); _delay_us(104); 通道>>=1; } 端口|=(1<<7); _delay_us(104); } void SerialSoftPrint(char *str) { while(*str) { SerialSoftWrite(*str); 字符串++; } }?
其次,我們有負(fù)責(zé)在 LCD 中顯示 RTC 時間的函數(shù)。下面給出的函數(shù)用于將考勤數(shù)據(jù)寫入 EEPROM 和從 EEPROM 讀取考勤數(shù)據(jù)。
?
int eeprom_write(unsigned int add,unsigned char data) { while(EECR&(1<?
下面的函數(shù)負(fù)責(zé)讀取指紋圖像并將其轉(zhuǎn)換為模板并與已存儲的圖像匹配并在 LCD 上顯示結(jié)果。
?
void matchFinger() { // lcdwrite(1,CMD); // lcdprint("放置手指"); // lcdwrite(192,CMD); // _delay_ms(2000); if(!sendcmd2fp((char *)&f_detect[0],sizeof(f_detect))) { if(!sendcmd2fp((char *)&f_imz2ch1[0],sizeof(f_imz2ch1))) { if(!sendcmd2fp((char * )&f_search[0],sizeof(f_search))) { LEDHigh; 蜂鳴器(200); uint id=數(shù)據(jù)[0]; 身份證<<=8; id+=數(shù)據(jù)[1]; uint分?jǐn)?shù)=數(shù)據(jù)[2]; 分?jǐn)?shù)<<=8; 分?jǐn)?shù)+=數(shù)據(jù)[3]; (void)sprintf((char *)buf1,"Id: %d",(int)id); 液晶寫入(1,CMD); lcdprint((char *)buf1); 保存數(shù)據(jù)(id); _delay_ms(1000); 液晶寫入(1,CMD); lcdprint("出席情況"); 液晶寫入(192,CMD); lcdprint("已注冊"); _delay_ms(2000); LED低; }?
其次,我們有一個用于注冊新手指并在 LCD 上顯示結(jié)果或狀態(tài)的功能。然后下面的函數(shù)用于通過使用 id 號從模塊中刪除存儲的指紋并顯示相同的狀態(tài)。
?
無效刪除指() { 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))) { 液晶寫入(1,CMD); sprintf((char *)buf1,"手指 ID %d",id); lcdprint((char *)buf1); 液晶寫入(192,CMD); lcdprint("刪除成功"); } 別的 { 液晶寫入(1,CMD); lcdprint("錯誤"); } _delay_ms(2000); }?
下面的函數(shù)負(fù)責(zé)通過軟UART引腳PD7和TTL到USB轉(zhuǎn)換器將考勤數(shù)據(jù)發(fā)送到串行終端。
?
/*使用軟串行引腳 PD7 在串行監(jiān)視器上顯示出勤數(shù)據(jù)的函數(shù)*/ void ShowAttendance() { char buf[128]; 液晶寫入(1,CMD); lcdprint("正在下載...."); SerialSoftPrintln("考勤記錄"); SerialSoftPrintln(" "); SerialSoftPrintln("S.No ID1 ID2 ID3 ID4 ID5"); //serialprintln("考勤記錄"); //serialprintln(""); //serialprintln("S.No ID1 ID2 ID3 ID4 ID5"); for(int cIndex=1;cIndex<=8;cIndex++) { sprintf((char *)buf,"%d " "%d:%d: "%d:%d:%d %d/%d/20%d " "%d:%d:%d %d/%d/20%d " "%d:%d:%d %d/ %d/20%d ", cIndex, eeprom_read((cIndex*6)),eeprom_read((cIndex*6)+1),eeprom_read((cIndex*6)+2),eeprom_read((cIndex*6)+3 ),eeprom_read((cIndex*6)+4),eeprom_read((cIndex*6)+5), eeprom_read((cIndex*6)+48),eeprom_read((cIndex*6)+1+48),eeprom_read( (cIndex*6)+2+48),eeprom_read((cIndex*6)+3+48),eeprom_read((cIndex*6)+4+48),eeprom_read((cIndex*6)+5+48), eeprom_read((cIndex*6)+96),eeprom_read((cIndex*6)+1+96),eeprom_read((cIndex*6)+2+96),eeprom_read((cIndex*6)+3+96), eeprom_read((cIndex*6)+4+96),eeprom_read((cIndex*6)+5+96), eeprom_read((cIndex*6)+144),eeprom_read((cIndex*6)+1+144),eeprom_read((cIndex*6)+2+144),eeprom_read((cIndex*6)+3+144), eeprom_read((cIndex*6)+4+144),eeprom_read((cIndex*6)+5+144), eeprom_read((cIndex*6)+192),eeprom_read((cIndex*6)+1+192), eeprom_read((cIndex*6)+2+192),eeprom_read((cIndex*6)+3+192),eeprom_read((cIndex*6)+4+192),eeprom_read((cIndex*6)+5+192 )); SerialSoftPrintln(buf); //serialprintln(buf); } lcdwrite(192,CMD); lcdprint("完成"); _delay_ms(2000); }?
以下函數(shù)用于從微控制器的 EEPROM 中刪除所有考勤數(shù)據(jù)。
?
無效 DeleteRecord() { lcdwrite(1,CMD); lcdprint("請稍等..."); for(int i=0;i<255;i++) eeprom_write(i,10); _delay_ms(2000); 液晶寫入(1,CMD); lcdprint("記錄已刪除"); 液晶寫入(192,CMD); lcdprint("成功"); _delay_ms(2000); }?
在 main 函數(shù)中,我們將初始化所有使用的模塊和 gpio 引腳。最后在this中執(zhí)行全控事件,如下圖
?
while(1) { RTC(); // if(match == LOW) // { matchFinger(); // } if(enrol == LOW) { 蜂鳴器(200); 登記手指(); _delay_ms(2000); // lcdinst(); } 否則如果(刪除==低) { 蜂鳴器(200); 獲取標(biāo)識(); 刪除手指(); _delay_ms(1000); } } 返回 0; }?
/*
?* 出勤系統(tǒng).c
?*
?* 創(chuàng)建時間:2019 年 1 月 8 日晚上 10:10:44
?* 作者:埃文
?*/?
#define F_CPU 8000000ul
#include
#include
#include
/***宏*/
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
#define uchar 無符號字符
#define uint 無符號整數(shù)
#define LCDPORTDIR DDRB
#define LCDPORT PORTB
#定義rs 0
#define rw 1
#define en 2
#define RSLow (LCDPORT&=~(1<
#define RSHigh (LCDPORT|=(1<
#define RWLow (LCDPORT&=~(1<
#define ENLow (LCDPORT&=~(1<
#define ENHigh (LCDPORT|=(1<
#define KeyPORTdir DDRA
#define 密鑰 PINA
#define KeyPORT PORTA
#定義確定 3
#定義向上 0
#define 向下 1
#define 刪除 3
#define MATCH 1
#define 注冊 2
#define 注冊 (key & (1<
#define match (key & (1<
#define delete (key & (1<
#define up (key & (1<
#define down (key & (1<
#define ok (key & (1<
#define LEDdir DDRC
#define LEDPort 端口
#定義 LED 3
#define BUZ 2
#define LEDHigh (LEDPort += (1<
#define LEDLow (LEDPort &= ~(1<
#define BUZHigh (LEDPort += (1<
#define BUZLow (LEDPort &= ~(1<
#define 高 1
#define 低 0
#define 通過 0
#定義錯誤 1
#define check(id) id=up
#define maxId 5
#define dataLenth 6
#define eepStartAdd 10
/*多變的*/
uchar buf[20];
uchar buf1[20];
volatile uint ind;
易失性單位標(biāo)志;
uint msCount=0;
易失性單位計數(shù)=0;
uchar 數(shù)據(jù)[10];
單位 ID=1;
整數(shù) s,a,b,c;
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};
//const char f_readNotepad[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x4,0x19,0x0,0x0,0x1E};
//char f_writeNotepad[]={0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x24};
int timeStamp[7],day;
枚舉
{
?CMD=0,
?數(shù)據(jù),?
};
無效蜂鳴器(uint);
無效 lcdwrite(char ch,char r)
{
? ? ?LCDPORT=ch & 0xF0;
RW 低;
? ? ?如果(r == 1)
RS高;
別的?
RS低;
? ? ?EN高;
? ? ?_delay_ms(5);
低;
_delay_ms(10);
? ? ?LCDPORT=ch<<4 & 0xF0;
RW 低;
如果(r == 1)
RS高;
別的
RS低;
EN高;
_delay_ms(5);
低;
_delay_ms(10);?
}
無效液晶打印(字符 *str)
{
? ? 而(*str)
? ? {
? ? ? ? lcdwrite(*str++,DATA);
? ? ? ? //__delay_ms(20);
? ? }
}
無效液晶開始()
{
? ? uchar lcdcmd[5]={0x02,0x28,0x0E,0x06,0x01};
? ? uint i=0;
? ? for(i=0;i<5;i++)
? ? lcdwrite(lcdcmd[i], CMD);
}
無效序列開始()
{
? UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
? UBRRH = (BAUD_PRESCALE >> 8);
? UBRRL = BAUD_PRESCALE;
? UCSRB=(1<
? sei();
}
ISR(USART_RXC_vect)
{
字符 ch=UDR;
buf[ind++]=ch;
如果(指數(shù)> 0)
標(biāo)志=1;
//serial1Write(ch);
}
無效串行寫入(字符 ch)
{
而 ((UCSRA & (1 << UDRE)) == 0);
UDR = 通道;
}
無效序列打印(字符 *str)
{
? ? 而(*str)
? ? {
? ? ? ? 串行寫入(*str++);
? ? }
}
無效串行打印(字符 *str)
{
序列打印(str);
串行寫入(0x0d);
串行寫入(0x0a);
}
無效的串行沖洗()
{
? ? for(int i=0;i
? ? {
? ? ? ? buf[i]=0;
? ? }
}
無效的 SerialSoftWrite(char ch)
{
端口&=~(1<<7);
_delay_us(104);
for(int i=0;i<8;i++)
{
如果(通道和 1)
端口|=(1<<7);
別的
端口&=~(1<<7);
_delay_us(104);
通道>>=1;
}
端口|=(1<<7);
_delay_us(104);
}
無效 SerialSoftPrint(char *str)
{
而(*str)
{
SerialSoftWrite(*str);
字符串++;
}
}
void SerialSoftPrintln(char *str)
{
SerialSoftPrint(str);
串行軟件寫入(0x0D);
串行軟件寫入(0x0A);
}
int bcdtochar(字符數(shù))
{
返回 ((num/16 * 10) + (num % 16));
}
無效 RTC_start()
{
TWCR=(1<
而((TWCR&0x80)==0x00);
}
無效 RTC_stp()
{?
TWCR=(1<
}
無效 RTC_read()
{?
TWCR=(1<
而((TWCR&0x80)==0x00);
TWDR=0xD0;//RTC寫入(從地址)
TWCR=(1<
而(!(TWCR&(1<
TWDR=0x00;//RTC寫入(字地址)
TWCR=(1<
而(!(TWCR&(1<
TWCR=(1<
而 ((TWCR&0x80)==0x00);
TWDR=0xD1;// RTC 命令讀取
TWCR=(1<
而(!(TWCR&(1<
}
無效 sec_init(無符號字符 d)
{??
TWDR=d; //第二次初始化
TWCR=(1<
而(!(TWCR&(1<
}
void min_init(unsigned char d)
{??
TWDR=d; //分鐘初始化
TWCR=(1<
而(!(TWCR&(1<
}
無效 hr_init(無符號字符 d)
{?
TWDR=d; //小時初始化
TWCR=(1<
而(!(TWCR&(1<
}
void day_init(unsigned char d)
{?
TWDR=d; //天數(shù)初始化
TWCR=(1<
而(!(TWCR&(1<
}
無效日期初始化(無符號字符 d)
{?
TWDR=d; //日期初始化
TWCR=(1<
而(!(TWCR&(1<
}
無效month_init(無符號字符d)
{?
TWDR=d; //月份初始化
TWCR=(1<
而(!(TWCR&(1<
}
無效 yr_init(無符號字符 d)
{?
TWDR=d; //年份初始化
TWCR=(1<
而(!(TWCR&(1<
}
int sec_rw()
{
TWCR|=(1<
而((TWCR & 0x80)==0x00);
返回 bcdtochar(TWDR)??;
}
int min_rw()
{?
TWCR|=(1<
TWCR|=(1<
而((TWCR & 0x80)==0x00);
返回 bcdtochar(TWDR)??;
}
int hr_rw()
{?
TWCR|=(1<
而((TWCR & 0x80)==0x00);
返回 bcdtochar(TWDR)??;
}
int day_rd()
{?
TWCR|=(1<
而((TWCR&0x80)==0x00);
返回 bcdtochar(TWDR)??;
}
int date_rw()
{?
TWCR|=(1<
而((TWCR & 0x80)==0x00);
返回 bcdtochar(TWDR)??;
}
int month_rw()
{?
TWCR|=(1<
而((TWCR & 0x80)==0x00);
返回 bcdtochar(TWDR)??;
}
int yr_rw()
{?
TWCR|=(1<
TWCR&=(~(1<
而((TWCR & 0x80)==0x00);
返回 bcdtochar(TWDR)??;
}
無效設(shè)備()
{
TWDR=0xD0;//RTC寫入(從地址)
TWCR=(1<
而(!(TWCR&(1<
TWDR=0x00;// 字地址寫入
TWCR=(1<
而(!(TWCR&(1<
}
無效 RTCTimeSet()
{
RTC_start();
設(shè)備();
sec_init(0);
min_init(0x47);
hr_init(0x22);
day_init(0x03);
date_init(0x23);
month_init(0x08);
yr_init(0x19);
RTC_stp();
}
無效顯示()
{
字符 [20];
sprintf(tem,"%d",timeStamp[0]);
液晶寫入(0x80,CMD);
lcdprint("時間:");
液晶打印(TEM);
lcdwrite(':',數(shù)據(jù));
sprintf(tem,"%d",timeStamp[1]);
液晶打印(TEM);
lcdwrite(':',數(shù)據(jù));
sprintf(tem,"%d",timeStamp[2]);
液晶打印(TEM);
液晶打印(“”);
液晶寫入(0xc0,CMD);
lcdprint("日期:");
sprintf(tem,"%d",timeStamp[3]);
液晶打印(TEM);
lcdwrite('/',數(shù)據(jù));
sprintf(tem,"%d",timeStamp[4]);
液晶打印(TEM);
lcdwrite('/',數(shù)據(jù));
sprintf(tem,"%d",timeStamp[5]);
液晶打印(“20”);
如果(時間戳[5]<10)
液晶寫入('0',數(shù)據(jù));
液晶打印(TEM);
液晶打印(“”);
}
無效 RTC()
{
RTC_read();
時間戳[2]=sec_rw();
時間戳[1]=min_rw();
時間戳[0]=hr_rw();
day=day_rd();
時間戳[3]=date_rw();
時間戳[4]=month_rw();
時間戳[5]=yr_rw();
RTC_stp();
節(jié)目();
}
int eeprom_write(unsigned int add,unsigned char data)
{
而(EECR&(1<
EEAR=添加;
EEDR=數(shù)據(jù);
EECR|=(1<
EECR|=(1<
返回0;
}
char eeprom_read(unsigned int add)
{
而(EECR & (1<
EEAR=添加;
EECR|=(1<
返回 EEDR;
}
無效保存數(shù)據(jù)(int id)
{
uint cIndex=eeprom_read(id);
如果(cIndex == 0)
c索引=1;
uint cAddress= (cIndex*6) + (id-1)*48;
for(int i=0;i<6;i++)
eeprom_write(cAddress+i,timeStamp[i]);
eeprom_write(id,cIndex+1);
}
int sendcmd2fp(char *pack, int len)
{
? 詮釋水=錯誤;
? 串行沖洗();
? 指數(shù)=0;
? _delay_ms(100);
? for(int i=0;i
? {
? ? 串行寫入(*(pack+i));
? }
? _delay_ms(1000);
? 如果(標(biāo)志 == 1)
? {
? ? 如果(buf[0] == 0xEF && buf[1] == 0x01)
? ? {
? ? ? ? if(buf[6] == 0x07) // 確認(rèn)
? ? ? ? {
? ? ? ? 如果(buf [9] == 0)
? ? ? ? {
? ? ? ? ? ? uint data_len=buf[7];
? ? ? ? ? ? 數(shù)據(jù)長度<<=8;
? ? ? ? ? ? data_len|=buf[8];
? ? ? ? ? ? for(int i=0;i
? ? ? ? ? ? ? ? 數(shù)據(jù)[i]=0;
? ? ? ? ? ? //data=(char *)calloc(data_len, sizeof(data));
? ? ? ? ? ? for(int i=0;i
? ? ? ? ? ? {
? ? ? ? ? ? ? ? 數(shù)據(jù)[i]=buf[10+i];
? ? ? ? ? ? }
? ? ? ? ? ? 水庫=通過;
? ? ? ? }
? ? ? ? 別的
? ? ? ? {
? ? ? ? ?資源=錯誤;
? ? ? ? }
? ? ? ? }
? ? }
? ? 指數(shù)=0;
? ? 標(biāo)志=0;
? ? 返回資源;
}
返回資源;
}
uint getId()
{
? ? uint id=0;
? ? 液晶寫入(1,CMD);
? ? 而(1)
? ? {
? ? ? ? //檢查(id);
如果(向上 == 低)
{
身份證++;
蜂鳴器(200);
}
否則如果(下降 == 低)
{
ID - ;
如果(id==0)
身份證=0;
蜂鳴器(200);
}
? ? ? ? 否則如果(確定 == 低)
{
蜂鳴器(200);
? ? ? ? ? ? 返回標(biāo)識;
}
液晶寫入(0x80,CMD);
(void)sprintf((char *)buf1,"輸入 ID:%d",id);
lcdprint((char *)buf1);
_delay_ms(200);
? ? }
}
無效的 matchFinger()
{
? ? // lcdwrite(1,CMD);
? ? // lcdprint("放置手指");?
? ? // lcdwrite(192,CMD);
? ? // _delay_ms(2000);
? ? ?if(!sendcmd2fp((char *)&f_detect[0],sizeof(f_detect)))
? ? ?{
? ? ? ? ?if(!sendcmd2fp((char *)&f_imz2ch1[0],sizeof(f_imz2ch1)))
? ? ? ? ?{
? ? ? ? ? ? if(!sendcmd2fp((char *)&f_search[0],sizeof(f_search)))
? ? ? ? ? ? {
LED高;
蜂鳴器(200);
? ? ? ? ? ? ? ? uint id=數(shù)據(jù)[0];
? ? ? ? ? ? ? ? ? ? ?身份證<<=8;
? ? ? ? ? ? ? ? ? ? ?id+=數(shù)據(jù)[1];
? ? ? ? ? ? ? ? uint分?jǐn)?shù)=數(shù)據(jù)[2];
? ? ? ? ? ? ? ? ? ? ? ? 分?jǐn)?shù)<<=8;
? ? ? ? ? ? ? ? ? ? ? ? 分?jǐn)?shù)+=數(shù)據(jù)[3];
? ? ? ? ? ? ? ? (void)sprintf((char *)buf1,"Id: %d",(int)id);
? ? ? ? ? ? ? ? 液晶寫入(1,CMD);
? ? ? ? ? ? ? ? lcdprint((char *)buf1);
保存數(shù)據(jù)(id);
_delay_ms(1000);
液晶寫入(1,CMD);
lcdprint("出席情況");
液晶寫入(192,CMD);
lcdprint("已注冊");
_delay_ms(2000);
LED低;
? ? ? ? ? ? }
? ? ? ? ? ? 別的
? ? ? ? ? ? {
LED高;
? ? ? ? ? ? ? ? 液晶寫入(1,CMD);
? ? ? ? ? ? ? ? lcdprint("未找到");
蜂鳴器(5000);
LED低;
? ? ? ? ? ? }
? ? ? ? ?}
別的
{
LED高;
液晶寫入(1,CMD);
lcdprint("未找到");
蜂鳴器(2000);
LED低;
}
? ? ?}
? ? ?別的
? ? ?{
? ? ? ? ?//lcdprint("沒有手指");?
? ? ?}
? ? ? //_delay_ms(200);
}
無效注冊手指()
{
? ? ?液晶寫入(1,CMD);
? ? ?lcdprint("登記手指");
? ? ?_delay_ms(2000);
? ? ?液晶寫入(1,CMD);
? ? ?lcdprint("放置手指");?
? ? ?液晶寫入(192,CMD);
? ? ?_delay_ms(1000);
for(int i=0;i<3;i++)
{
? ? ?if(!sendcmd2fp((char *)&f_detect[0],sizeof(f_detect)))
? ? ?{
? ? ? ? ?//lcdprint("檢測到手指");
? ? ? ? ?//__delay_ms(1000);
? ? ? ? if(!sendcmd2fp((char *)&f_imz2ch1[0],sizeof(f_imz2ch1)))
? ? ? ? {
液晶寫入(192,CMD);
? ? ? ? ? ? lcdprint("檢測到手指");
? ? ? ? ? ? _delay_ms(1000);
? ? ? ? ? // lcdwrite(1,CMD);
? ? ? ? ? // lcdprint("模板 1");
? ? ? ? ? // __delay_ms(1000);
? ? ? ? ? ? 液晶寫入(1,CMD);
? ? ? ? ? ? lcdprint("放置手指");
? ? ? ? ? ? 液晶寫入(192,CMD);
? ? ? ? ? ? lcdprint("再次");?
? ? ? ? ? ? _delay_ms(2000);
? ? ? ? ? ? if(!sendcmd2fp((char *)&f_detect[0],sizeof(f_detect)))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(!sendcmd2fp((char *)&f_imz2ch2[0],sizeof(f_imz2ch2)))
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? 液晶寫入(1,CMD);
? ? ? ? ? ? ? ? ? ? lcdprint("檢測到手指");
? ? ? ? ? ? ? ? ? ? _delay_ms(1000);
? ? ? ? ? ? ? ? ? ? if(!sendcmd2fp((char *)&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((char *)&f_storeModel[0],sizeof(f_storeModel)))
? ? ? ? ? ? ? ? ? ? ? ?{
? ? 蜂鳴器(200);
? ? ? ? ? ? ? ? ? ? ? ? ? ? 液晶寫入(1,CMD);
? ? ? ? ? ? ? ? ? ? ? ? ? ? lcdprint("指紋存儲");
? ? ? ? ? ? ? ? ? ? ? ? ? ? (void)sprintf((char *)buf1,"Id:%d",(int)id);
? ? ? ? ? ? ? ? ? ? ? ? ? ? 液晶寫入(192,CMD);
? ? ? ? ? ? ? ? ? ? ? ? ? ? lcdprint((char *)buf1);
? ? ? ? ? ? ? ? ? ? ? ? ? ? _delay_ms(1000);
? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ?別的
? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ? 液晶寫入(1,CMD);
? ? ? ? ? ? ? ? ? ? ? ? ? ? lcdprint("手指未存儲");
蜂鳴器(3000);
? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? 別的
? ? ? ? ? ? ? ? ? ? ? ? lcdprint("錯誤");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? 別的
? ? ? ? ? ? ? ? ? ?lcdprint("錯誤");??
}? ?
別的??
我=2;??
? ? ? ? }?
休息;
? ? ?}
? ? ?如果(我==2)
? ? ?{
液晶寫入(0xc0,CMD);
? ? ? ? ?lcdprint("沒有手指");?
? ? ?}
}
? ? ?_delay_ms(2000);
}
無效刪除指()
{
? ? 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)))
? {
? ? ?液晶寫入(1,CMD);
? ? ?sprintf((char *)buf1,"手指 ID %d",id);
? ? ?lcdprint((char *)buf1);
? ? ?液晶寫入(192,CMD);
? ? ?lcdprint("刪除成功");
? }
? ?別的
? ?{
? ? ? ?液晶寫入(1,CMD);
? ? ? ?lcdprint("錯誤");
? ?}
? ?_delay_ms(2000);
}
無效 lcdinst()
{
? ? 液晶寫入(0x80,CMD);
? ? lcdprint("1-注冊手指");
? ? 液晶寫入(0xc0,CMD);
? ? lcdprint("2-刪除手指");
? ? _delay_ms(10);
}
無效蜂鳴器(uint t)
{
BUZ高;
for(int i=0;i
_delay_ms(1);
BUZ低;
}
/*函數(shù)使用softserial pin PD7在串行監(jiān)視器上顯示出勤數(shù)據(jù)*/
無效顯示出勤()
{
字符緩沖區(qū)[128];
液晶寫入(1,CMD);
lcdprint("正在下載....");
SerialSoftPrintln("考勤記錄");
SerialSoftPrintln(" ");
SerialSoftPrintln("S.No ID1 ID2 ID3 ID4 ID5");
//serialprintln("考勤記錄");
//serialprintln("");
//serialprintln("S.No ID1 ID2 ID3 ID4 ID5");
for(int cIndex=1;cIndex<=8;cIndex++)
{
sprintf((char *)buf,"%d"
"%d:%d:%d %d/%d/20%d"??
"%d:%d:%d %d/%d/20%d"??
"%d:%d:%d %d/%d/20%d"??
"%d:%d:%d %d/%d/20%d"??
"%d:%d:%d %d/%d/20%d",
指數(shù),
eeprom_read((cIndex*6)),eeprom_read((cIndex*6)+1),eeprom_read((cIndex*6)+2),eeprom_read((cIndex*6)+3),
eeprom_read((cIndex*6)+4),eeprom_read((cIndex*6)+5),
eeprom_read((cIndex*6)+48),eeprom_read((cIndex*6)+1+48),eeprom_read((cIndex*6)+2+48),
eeprom_read((cIndex*6)+3+48),eeprom_read((cIndex*6)+4+48),eeprom_read((cIndex*6)+5+48),
eeprom_read((cIndex*6)+96),eeprom_read((cIndex*6)+1+96),eeprom_read((cIndex*6)+2+96),
eeprom_read((cIndex*6)+3+96),eeprom_read((cIndex*6)+4+96),eeprom_read((cIndex*6)+5+96),
eeprom_read((cIndex*6)+144),eeprom_read((cIndex*6)+1+144),eeprom_read((cIndex*6)+2+144),
eeprom_read((cIndex*6)+3+144),eeprom_read((cIndex*6)+4+144),eeprom_read((cIndex*6)+5+144),
eeprom_read((cIndex*6)+192),eeprom_read((cIndex*6)+1+192),eeprom_read((cIndex*6)+2+192),
eeprom_read((cIndex*6)+3+192),eeprom_read((cIndex*6)+4+192),eeprom_read((cIndex*6)+5+192));
SerialSoftPrintln(buf);
//serialprintln(buf);
}
液晶寫入(192,CMD);
lcdprint("完成");
_delay_ms(2000);
}
無效刪除記錄()
{
液晶寫入(1,CMD);
lcdprint("請稍等...");
for(int i=0;i<255;i++)
eeprom_write(i,10);
_delay_ms(2000);
液晶寫入(1,CMD);
lcdprint("記錄已刪除");
液晶寫入(192,CMD);
lcdprint("成功");
_delay_ms(2000);?
}?
主函數(shù)()
{? ? ? ? ? ? ?
? LEDdir=0xFF;
? LED端口=0x03;
? KeyPORTdir=0xF0;
? 密鑰端口=0x0F;??
? LCDPORTDIR=0xFF;
? DDRD+=1<<7;
? 端口+=1<<7;
? 序列開始();
? SerialSoftPrint("電路文摘");
? //serialprint("薩達(dá)姆汗");
? 蜂鳴器(2000);
? 液晶開始();
? lcdprint("考勤系統(tǒng)");
? 液晶寫入(192,CMD);
? lcdprint("使用 AVR 和 FP");
? _delay_ms(2000);
? 如果(下降 == 低)
? ShowAttendance();
? 否則如果(刪除 == 低)
刪除記錄();? ??
? 指數(shù)=0;? ??
? while(sendcmd2fp((char *)&passPack[0],sizeof(passPack)))
? {
? ? ?液晶寫入(1,CMD);
? ? ?lcdprint("找不到 FP");
? ? ?_delay_ms(2000);
? ? ?指數(shù)=0;
? }
? 液晶寫入(1,CMD);
? lcdprint("找到 FP");
? _delay_ms(1000);
? lcdinst();
? _delay_ms(2000);
? 液晶寫入(1,CMD);
? //RTCTimeSet();
? 而(1)
? {?
? ? 實時時鐘();
? // 如果(匹配 == 低)
? ?// {?
匹配手指();
? ?// }
? ? 如果(注冊 == 低)
? ? {
蜂鳴器(200);
? ? ? ? 登記手指();?
? ? ? ? _delay_ms(2000);
? ? ? ?// lcdinst();
? ? }
? ? 否則如果(刪除 == 低)
? ? {
蜂鳴器(200);
? ? ? ? 獲取標(biāo)識();
? ? ? ? 刪除手指();
? ? ? ? _delay_ms(1000);
? ? }
? }?
? 返回0;
}
評論
查看更多