根据宾夕法尼亚州立大学的研究人员的说法,人类更容易信任机器而不是人,这很可能从我们如此轻易地向机器透露我们的 ATM 密码就可以看出。今天,在人工智能、机器学习、聊天机器人、智能扬声器、机器人等正在积极发展的世界中,人类和机器人之间的这种协同作用只会增加。今天,从过桥收费员到收银员,我们周围的一切都被机器取代,以使工作更轻松、更高效。为了跟上这个阶段,在这个项目中,我们将使用 AVR 微控制器构建一个生物识别考勤系统取代人工考勤程序。该系统将更加可靠和高效,因为它可以节省时间并避免躲闪。
在这个项目中,我们使用了指纹模块和AVR(atmega32)进行考勤。通过使用指纹传感器,系统将为用户变得更加安全。以下部分解释了 使用 AVR 制作基于指纹的生物识别考勤系统的技术细节。
所需组件
Atmega32 -1
指纹模块 (r305) -1
按钮或薄膜按钮 - 4
发光二极管 -2
1K电阻-2
2.2K电阻-1
电源 12v 适配器
连接线
蜂鸣器-1
16x2 液晶屏 -1
PCB或面包板
RTC 模块(ds1307 或 ds3231)-1
LM7805 -1
1000uf、10uf电容-1
Burgstips 男性 女性
直流插孔(可选)
BC547晶体管-1
在这个 指纹考勤系统电路中,我们使用指纹传感器模块 通过在系统中输入他们的指纹来验证个人或员工的身份。在这里,我们使用 4 个按钮来注册、删除、增加和减少指纹数据。密钥 1 用于将新人员注册到系统中。因此,当用户想要注册一个新手指时,他/她需要按 1 键,然后 LCD 要求他/她将手指放在指纹传感器上两次,然后询问员工 ID。同理,key 2具有双重功能,比如用户注册新手指时,需要选择指纹ID通过使用另外两个键,即 3 和 4。现在用户需要按键 1(这次该键的行为类似于 OK)以继续选择 ID。键 2 也用于复位或删除微控制器 EEPROM 中的数据。
指纹传感器模块捕获指纹图像,然后将其转换为等效模板,并根据微控制器选择的 ID 将它们保存到内存中。所有过程都由微控制器控制,就像拍摄指纹图像一样;将其转换为模板并存储为 ID 等。
电路原理图
基于指纹的考勤系统项目的完整电路图如下所示。它具有 Atmega32 微控制器,用于控制项目的所有过程。按钮或薄膜按钮用于登记、删除、选择考勤 ID,蜂鸣器用于指示,16x2 LCD用于指导用户如何使用机器。
如电路图所示,按钮或薄膜按钮直接连接到微控制器的引脚 PA2(ENROL 键 1)、PA3(DEL 键 2)、PA0(UP 键 3)、PA1(DOWN 键 4)相对于地或 PA4。并且一个 LED 通过一个 1k 电阻连接在微控制器的引脚 PC2 上,相对于地。指纹模块的 Rx 和 Tx 直接连接在微控制器的串行引脚 PD1 和 PD3 上。5v电源用于为整个电路供电,使用LM7805稳压器,由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 引脚,用于获取当前时间。
指纹考勤系统的工作原理
每当用户将手指放在指纹模块上时,指纹模块就会捕获手指图像,并在系统中搜索是否有任何 ID 与该指纹相关联。如果检测到指纹ID,则LCD 将显示已注册的考勤,同时蜂鸣器将鸣响一次。
除了指纹模块,我们还使用 RTC 模块来处理时间和日期数据。时间和日期在系统中连续运行,因此当真正的用户将手指放在指纹传感器上时,微控制器可以获取时间和日期,然后将它们保存在分配的内存插槽中的 EEPROM 中。
用户可以长按4号键下载考勤数据。接通电源,等待一段时间后,LCD会显示“Downloading 。..。”。并且用户可以通过串行监视器看到考勤数据,在此代码软件中,UART 在引脚 PD7-pin20 处被编程为 Tx,以将数据发送到终端。用户还需要一个 TTL 到 USB 转换器才能通过串行终端查看考勤数据。
如果用户想删除所有数据,那么他/她必须按住键 2,然后连接电源并等待一段时间。一段时间后,LCD 将显示“请稍候。..”,然后显示“记录已成功删除”。最后给出的演示视频中没有显示这两个步骤。
代码说明
最后给出了这个生物识别考勤系统的完整代码和视频。这个项目的代码对于初学者来说有点冗长和复杂。因此,我们尝试采用描述性变量来提高可读性和理解性。首先,我们已经包含了一些必要的头文件,然后为不同的目的编写了宏。
#define F_CPU 8000000ul #include#include #include /***宏*/ #define USART_BAUDRATE 9600 #define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) #define uchar 无符号字符 #define uint 无符号整数 #define LCDPORTDIR DDRB #define LCDPORT PORTB #定义rs 0 #define rw 1 #define en 2 #define RSLow (LCDPORT&=~(1<
在此之后,我们为指纹命令和响应声明了一些变量和数组。我们还添加了一些用于获取和设置 RTC 数据的功能。
无效 RTC_stp() { TWCR=(1<
然后我们有一些用于 LCD 的函数,它们负责驱动 LCD。LCD 驱动函数是为 4 位模式驱动编写的。其次,我们还有一些 UART 驱动函数,负责初始化 UART 并在指纹传感器和微控制器之间交换数据。
void serialbegin() { UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); UBRRH = (BAUD_PRESCALE >> 8); UBRRL = BAUD_PRESCALE; UCSRB=(1<0) 标志=1; //serial1Write(ch); } void serialwrite(char ch) { while ((UCSRA & (1 << UDRE)) == 0); UDR = 通道; } void serialprint(char *str) { while(*str) { serialwrite(*str++); } }
现在我们有了更多的 UART 功能,但它们是软件 UART。用于通过串行终端将保存的数据传输到计算机。这些函数是基于延迟的,不使用任何类型的中断。对于 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); 字符串++; } }
其次,我们有负责在 LCD 中显示 RTC 时间的函数。下面给出的函数用于将考勤数据写入 EEPROM 和从 EEPROM 读取考勤数据。
int eeprom_write(unsigned int add,unsigned char data) { while(EECR&(1<
下面的函数负责读取指纹图像并将其转换为模板并与已存储的图像匹配并在 LCD 上显示结果。
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=数据[0]; 身份证<<=8; id+=数据[1]; uint分数=数据[2]; 分数<<=8; 分数+=数据[3]; (void)sprintf((char *)buf1,"Id: %d",(int)id); 液晶写入(1,CMD); lcdprint((char *)buf1); 保存数据(id); _delay_ms(1000); 液晶写入(1,CMD); lcdprint("出席情况"); 液晶写入(192,CMD); lcdprint("已注册"); _delay_ms(2000); LED低; }
其次,我们有一个用于注册新手指并在 LCD 上显示结果或状态的功能。然后下面的函数用于通过使用 id 号从模块中删除存储的指纹并显示相同的状态。
无效删除指() { 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); }
下面的函数负责通过软UART引脚PD7和TTL到USB转换器将考勤数据发送到串行终端。
/*使用软串行引脚 PD7 在串行监视器上显示出勤数据的函数*/ 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); }
以下函数用于从微控制器的 EEPROM 中删除所有考勤数据。
无效 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 函数中,我们将初始化所有使用的模块和 gpio 引脚。最后在this中执行全控事件,如下图
while(1) { RTC(); // if(match == LOW) // { matchFinger(); // } if(enrol == LOW) { 蜂鸣器(200); 登记手指(); _delay_ms(2000); // lcdinst(); } 否则如果(删除==低) { 蜂鸣器(200); 获取标识(); 删除手指(); _delay_ms(1000); } } 返回 0; }
/*
* 出勤系统.c
*
* 创建时间: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 无符号整数
#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;
易失性单位标志;
uint msCount=0;
易失性单位计数=0;
uchar 数据[10];
单位 ID=1;
整数 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,
数据,
};
无效蜂鸣器(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;
如果(指数> 0)
标志=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(字符数)
{
返回 ((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; //天数初始化
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);
}
无效设备()
{
TWDR=0xD0;//RTC写入(从地址)
TWCR=(1<
而(!(TWCR&(1<
TWDR=0x00;// 字地址写入
TWCR=(1<
而(!(TWCR&(1<
}
无效 RTCTimeSet()
{
RTC_start();
设备();
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(':',数据);
sprintf(tem,"%d",timeStamp[1]);
液晶打印(TEM);
lcdwrite(':',数据);
sprintf(tem,"%d",timeStamp[2]);
液晶打印(TEM);
液晶打印(“”);
液晶写入(0xc0,CMD);
lcdprint("日期:");
sprintf(tem,"%d",timeStamp[3]);
液晶打印(TEM);
lcdwrite('/',数据);
sprintf(tem,"%d",timeStamp[4]);
液晶打印(TEM);
lcdwrite('/',数据);
sprintf(tem,"%d",timeStamp[5]);
液晶打印(“20”);
如果(时间戳[5]<10)
液晶写入('0',数据);
液晶打印(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();
节目();
}
int eeprom_write(unsigned int add,unsigned char data)
{
而(EECR&(1<
EEAR=添加;
EEDR=数据;
EECR|=(1<
EECR|=(1<
返回0;
}
char eeprom_read(unsigned int add)
{
而(EECR & (1<
EEAR=添加;
EECR|=(1<
返回 EEDR;
}
无效保存数据(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)
{
诠释水=错误;
串行冲洗();
指数=0;
_delay_ms(100);
for(int i=0;i
{
串行写入(*(pack+i));
}
_delay_ms(1000);
如果(标志 == 1)
{
如果(buf[0] == 0xEF && buf[1] == 0x01)
{
if(buf[6] == 0x07) // 确认
{
如果(buf [9] == 0)
{
uint data_len=buf[7];
数据长度<<=8;
data_len|=buf[8];
for(int i=0;i
数据[i]=0;
//data=(char *)calloc(data_len, sizeof(data));
for(int i=0;i
{
数据[i]=buf[10+i];
}
水库=通过;
}
别的
{
资源=错误;
}
}
}
指数=0;
标志=0;
返回资源;
}
返回资源;
}
uint getId()
{
uint id=0;
液晶写入(1,CMD);
而(1)
{
//检查(id);
如果(向上 == 低)
{
身份证++;
蜂鸣器(200);
}
否则如果(下降 == 低)
{
ID - ;
如果(id==0)
身份证=0;
蜂鸣器(200);
}
否则如果(确定 == 低)
{
蜂鸣器(200);
返回标识;
}
液晶写入(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=数据[0];
身份证<<=8;
id+=数据[1];
uint分数=数据[2];
分数<<=8;
分数+=数据[3];
(void)sprintf((char *)buf1,"Id: %d",(int)id);
液晶写入(1,CMD);
lcdprint((char *)buf1);
保存数据(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低;
}
/*函数使用softserial pin PD7在串行监视器上显示出勤数据*/
无效显示出勤()
{
字符缓冲区[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",
指数,
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);
}
主函数()
{
LEDdir=0xFF;
LED端口=0x03;
KeyPORTdir=0xF0;
密钥端口=0x0F;
LCDPORTDIR=0xFF;
DDRD+=1<<7;
端口+=1<<7;
序列开始();
SerialSoftPrint("电路文摘");
//serialprint("萨达姆汗");
蜂鸣器(2000);
液晶开始();
lcdprint("考勤系统");
液晶写入(192,CMD);
lcdprint("使用 AVR 和 FP");
_delay_ms(2000);
如果(下降 == 低)
ShowAttendance();
否则如果(删除 == 低)
删除记录();
指数=0;
while(sendcmd2fp((char *)&passPack[0],sizeof(passPack)))
{
液晶写入(1,CMD);
lcdprint("找不到 FP");
_delay_ms(2000);
指数=0;
}
液晶写入(1,CMD);
lcdprint("找到 FP");
_delay_ms(1000);
lcdinst();
_delay_ms(2000);
液晶写入(1,CMD);
//RTCTimeSet();
而(1)
{
实时时钟();
// 如果(匹配 == 低)
// {
匹配手指();
// }
如果(注册 == 低)
{
蜂鸣器(200);
登记手指();
_delay_ms(2000);
// lcdinst();
}
否则如果(删除 == 低)
{
蜂鸣器(200);
获取标识();
删除手指();
_delay_ms(1000);
}
}
返回0;
}
评论
查看更多