请选择 进入手机版 | 继续访问电脑版
快捷导航
25 234

基于指纹识别的门禁系统

许阳旭 于 2018-12-19 19:49 发表在 [开源项目] [复制链接]

注册后可查看大图哦

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 许阳旭 于 2019-1-9 16:55 编辑

项目名称:基于指纹识别的门禁系统

项目成员:许阳旭、张怀中、於坚敏、洪斌、张国强
一、项目名称
基于指纹识别的门禁系统
二、项目概述
项目采用STM32单片机作为核心板,12864液晶显示屏作为屏幕显示。该项目分成两种模式:管理员模式和用户模式。管理员模式下,管理员可以添加可删除指纹,也可以修改开锁密码。用户模式下,用户可通过指纹和密码实现开锁。关于指纹开锁,首先指纹识别模块检测用户录入指纹,将指纹信息进行相关处理得到对应特征值信息。将此信息与数据库中已存储的指纹信息进行对比。若指纹验证通过,则通过触发继电器模块开启门锁;若输入指纹验证不正确则用户可通过密码开锁,输入正确密码验证后门锁才会打开,若三次密码输入错误,则等60s后重新输入。
三、项目模块
1. 指纹模块采集
将手指放在指纹采集器上进行指纹采集,可采集三次,并在上位机中观察指纹图像,选取清晰指纹图像。
2. 指纹数据处理
当指纹采集模块采集到清晰指纹图像时,开始对指纹进行特征提取,根据特征值及其相互之间的位置与拓扑关系在指纹库中匹配。为了提取这些特征,必须先把灰度的指纹图像处理为二值线形图,此过程即为指纹图像的预处理。通过利用手指指纹凹凸不平的纹形来进行成像,通常我们把凸出的纹形称为“嵴”,而凹下去的纹形成称为“峪”,而指纹采集的过程本质上是指纹成像的过程。其原理是根据嵴与峪的几何特性、物理特征和生物特性的不同,以得到不同的光学或者电流电阻反馈信号,根据反馈信号的量值利用不同算法的图像处理算法来绘成指纹图像,然后在此指纹图像基础上通过指纹识别算法软件来进行指纹特征的提取和指纹特征码的比对。
3. 数组存储
需将提取到的指纹特征值数据存储到数据库中,对应每个id序号存储。当用户进行验证操作时,可将二次识别并处理后的指纹数据与数据库中存入的数据进行对比,可对应该用户身份,从而控制门锁状态。
4.  显示屏显示
通过12864液晶显示屏,我们可以看到当前门禁锁的开启或关闭状态与用户验证结果显示。
5.  继电器模块
如果指纹验证成功或密码输入正确后,继电器的触点将会打开,连接门锁位置的开关也将同步开启,从而开启门禁。
6.数字按键模块
用户模式下,用户可选择指纹和按键开锁。当选择按键开锁时,用户有三次机会输入密码,若三次密码输入错误,则等待60s重新输入。若密码输入正确,则门开锁
四、项目功能
1、数据采集
使用AS608光学指纹模块,用来完成指纹的采集和指纹的识别。利用光的折射和反射原理,光从底部射向三棱镜,并经棱镜射出,射出的光线在手指表面指纹凹凸不平的线纹上折射的角度及反射回去的光线明暗就会不一样。CMOS或者CCD的光学器件就会收集到不同明暗程度的图片信息,就完成指纹的采集。
2、数据处理
1)  数据预处理
采集到指纹图像后,通过预处理算法,包括平滑、均衡化、增强、二值化、细化等对图像进行预处理,使得采集的指纹图像更加清晰,特征点便于提取。
2)     特征值提取
通过提取指纹的端点、叉点和奇异点等得到指纹的主要特征信息,保存到固定内存中。
3)     数据对比
根据提取的特征点信息,将模板指纹的特征点与待鉴定指纹的特征点进行匹配,通过指纹算法处理识别当前的指纹。
3、数据存储
采集指纹时提取指纹的特征值,并将指纹的特征值存储于数据库中,以作下次解锁时进行指纹比对。
4、数据显示
根据采集的信息,使用12864液晶显示屏,将所获得的数据信息显示在屏幕中,并同步更新验证时显示的信息。相关操作如下:
1.读状态:输入RS=0,RW=1,E=高脉冲。输出:D0—D7为状态字。
2.读数据:输入RS=1,RW=1,E=高脉冲。输出:D0—D7为数据。
3.写命令:输入RS=0,RW=0,E=高脉冲。输出:无。
4.写数据:输入RS=1,RW=0,E=高脉冲。输出:无
DDRAM(Display Data RAM)就是显示数据RAM,用来寄存待显示的字符代码并且先要驱动初始化液晶显示屏。并不是所有写入DDRAM的字符代码都能在屏幕上显示出来,只有写在上图所示范围内的字符才可以显示出来,写在范围外的字符不能显示出来。这样,我们在程序中可以利用“光标或显示移动指令”使字符慢慢移动到可见的显示范围内,看到字符的移动效果。
5、 开关控制
继电器是在内部线圈两端加上一定的电压,线圈中就会流过一定的电流,从而产生电磁效应。衔铁在电磁力吸引的作用下克服返回弹簧的拉力吸向铁芯,带动衔铁的动触点与静触点(动合输触电)吸合。当线圈断电后,电磁的吸力也随之消失,衔铁就会在弹簧的反作用力下返回到原来的位置,使动触点与原来的静触点(动断触点)吸合。这样通过吸合、释放,从而达到了开锁和关闭锁的功能。
   
五、价格预算
  
型号
  
名称
价格
AS608
光学指纹模块
80
SPA-05V
继电器
75
12864液晶显示屏
液晶显示屏
30元
STM32
百为主控板
实验室提供
数字按键
1个
6
电插锁
1
实验室提供
六、项目分工
指纹识别:许阳旭、张怀中
12864显示屏:洪斌
继电器控制:张国强
文档编写:於坚敏
七、项目周期
预估时间:2018.12.21-2019.01.10












Connecting & Messaging from Any.

共 25 个关于本帖的回复 最后回复于 2019-1-9 20:51

许阳旭 新手上路 发表于 2019-1-9 20:51:12 | 显示全部楼层
今天是对项目的最后完善,以及编写最后产物文档。在这次的项目里,我懂得了独立思考与自主学习的重要性。不再是照抄老师的代码或是稍加修改,而是真正的从零开始。拿到一个新的模块,不是急着敲代码,而是查找资料,弄懂原理,只有原理懂了,才能让模块成为你想要的东西。就像当时弄红外传感,不同的厂家、不同型号的产品,所用的红外协议是不同的,所以红外的接收、发送程序就要根据实际进行写,弄懂了原理,就不是那么难了。真正通过自己的努力,完成一件事,感觉真的很好,很有成就,而且收获也是很大的,印象深刻。
Connecting & Messaging from Any.
举报 使用道具
洪斌 新手上路 发表于 2019-1-8 20:28:56 | 显示全部楼层
项目进入尾声,整合代码,理清原理,还有键盘按键不灵的问题尽快解决
实验室上的门锁也用来进行了验证,还有关于文档和PPT的整理正在进行



Connecting & Messaging from Any.
举报 使用道具
许阳旭 新手上路 发表于 2019-1-8 19:46:27 | 显示全部楼层
今天主要任务是通过stm32开发板来控制继电器,从而实现电插锁的闭与合。一开始遇到的难点是没有弄清楚继电器的工作原理,后来通过问学长和淘宝卖家才知道它的原理。其主要工作原理为通过信号线使它输入高电平,即能完成常开端与常闭断之间的跳转。并把继电器附在了门锁上,成功的实现了门锁的开与关。至此,项目的雏形已经完成。除此,今天遇到了一个问题,就是按键乱序问题,后期将完善代码,解决今天遇到的问题
Connecting & Messaging from Any.
举报 使用道具
於坚敏 新手上路 发表于 2019-1-5 20:36:42 | 显示全部楼层
今天学习了12864显示屏模块的相关资料,以下是串口接口管脚信号的资料:
管脚号        名称        LEVEL           功能
1                VSS          OV              电池地
2                VDD       +5V              电源正极3.3V
3                VO          --                 对比度和亮度的调整            
4                CS           H/L              模组片选端,高电平有效            
5                SID          H/L              串行数据输入端                  
6                CLK         H/L              串行同步时钟:上升沿读取SID数据
15              PSB         L                   将PSB固定接低电平            
17              RESET      H/L              复位端,低电平有效                        
Connecting & Messaging from Any.
举报 使用道具
冰泪年华 新手上路 发表于 2019-1-5 20:32:25 | 显示全部楼层
本帖最后由 冰泪年华 于 2019-1-5 20:34 编辑

关于指纹录入模块,有很多细节需要考虑。比如说,如何检测指纹模块上是否放上手指,以及两次输入的指纹是否一样,若两次输入的指纹不同,则应重新录入指纹。如果两次录入的指纹相同,则生成指纹模板,然后存入指纹库中。关于指纹的存储,我们是用数组存储指纹,其核心代码如下:
void Add_FR(u16 ID)
{
        u8 i,ensure ,processnum=0;
        while(1)
        {
                switch (processnum)
                {
                        case 0:
                                i++;
                           LCD12864lcdcls();
                           Lcd_ShowSring(1,0,"请按指纹");
                                ensure=PS_GetImage();
                                if(ensure==0x00)
                                {
                                        ensure=PS_GenChar(CharBuffer1);//生成特征
                                        if(ensure==0x00)
                                        {
                                                 LCD12864lcdcls();
                                                 Lcd_ShowSring(1,0,"指纹正常");
                                                i=0;
                                                processnum=1;//跳到第二步                                                
                                        }else
                                        ShowErrMessage(ensure);                        
                                       
                                }else ShowErrMessage(ensure);                                                
                                break;
                        
                        case 1:
                                i++;
                         LCD12864lcdcls();
                                 Lcd_ShowSring(1,0,"请按再按一次指纹");
                                ensure=PS_GetImage();
                                if(ensure==0x00)
                                {
                                        ensure=PS_GenChar(CharBuffer2);//生成特征
                                        if(ensure==0x00)
                                        {
                                                 LCD12864lcdcls();
                                                 Lcd_ShowSring(1,0,"指纹正常");
                                                i=0;
                                                processnum=2;//跳到第三步
                                        }else ShowErrMessage(ensure);        
                                }else ShowErrMessage(ensure);               
                                break;

                        case 2:
                                ensure=PS_Match();
                                if(ensure==0x00)
                                {
                                         LCD12864lcdcls();
                                         Lcd_ShowSring(1,0,"两次指纹一样");
                                        processnum=3;//跳到第四步
                                }
                                else
                                {
                                         LCD12864lcdcls();
                                         Lcd_ShowSring(1,0,"失败重新录入指纹");
                                        ShowErrMessage(ensure);
                                        i=0;
                                        processnum=0;//跳回第一步               
                                }
                                delay_ms(1200);
                                break;

                        case 3:
                         LCD12864lcdcls();
                                         Lcd_ShowSring(1,0,"生成指纹模板中");
                                ensure=PS_RegModel();
                                if(ensure==0x00)
                                {
                                         LCD12864lcdcls();
                                         Lcd_ShowSring(1,0,"生成指纹模板完成");
                                        processnum=4;//跳到第五步
                                }else {processnum=0;ShowErrMessage(ensure);}
                                delay_ms(1200);
                                break;
                        case 4:        
                         LCD12864lcdcls();
                           Lcd_ShowSring(1,0,"正在存入, 请稍后");                  
                                ensure=PS_StoreChar(CharBuffer2,ID);//储存模板     
                                if(ensure==0x00)
                                {                        
                                        LCD12864lcdcls();
                                        Lcd_ShowSring(1,0,"录入指纹完成");
                                        PS_ValidTempleteNum(&ValidN);//读库指纹个数
                                        delay_ms(1500);
                                        return ;
                                }else
       {
              processnum=0;
        ShowErrMessage(ensure);
                         }                                       
                                break;                                
                }
                delay_ms(400);
                if(i==5)//超过5次没有按手指则退出
                {
           LCD12864lcdcls();
                Lcd_ShowSring(1,0,"没有按下指纹正在退出");
                        break;        
                }                                
        }
}
Connecting & Messaging from Any.
举报 使用道具
洪斌 新手上路 发表于 2019-1-5 20:13:57 | 显示全部楼层
关于指纹不通过改用按键密码解锁,咱用了个矩阵键盘,并且添加指纹,删除指纹,只能进入管理员模式才能使用。下面写了一半部分关于矩阵键盘初始化和管理员模式的代码,大家瞅瞅
void KEY_Init(void)
{
    RCC->APB2ENR |= 1 << 2;
    RCC->APB2ENR |= 1 << 6;
    GPIOA->CRL &= 0XFFFFFFF0;   
    GPIOA->CRL |= 0X00000008;

    GPIOE->CRL &= 0XFFF000FF;   
    GPIOE->CRL |= 0X00088800;
    GPIOE->ODR |= 7 << 2;           
}
void Board_Init(void) {
//Êä³ö¶Ë¿ÚÅä3
    RCC->APB2ENR |= 1 << 4; //ʹÄÜPORTCʱÖÓ
    GPIOC->CRL &= 0X00000000;
    GPIOC->CRL |= 0x88883333;
    GPIOC->ODR |= 0X0F << 0;
}
u8 Board() {      //¾ØÕó¼üÅÌ
    uint8_t LIE, HANG, k, i = 0;
    unsigned char cord_h, cord_l; //ÐÐÁÐÖµÖмä±äÁ¿
    u32 data = 0;
    unsigned long count = 0;
    GPIO_Write(GPIOC, 0xF0);
    if((GPIO_ReadInputData(GPIOC) & 0xF0) != 0xF0)
    {
        delay_ms(48);
        if((GPIO_ReadInputData(GPIOC) & 0xF0) != 0xF0)
        {
            LIE = GPIO_ReadInputData(GPIOC);
            HANG = LIE;
            LIE = ~LIE;
            LIE = LIE & 0XF0;
            for(i = 0; i < 4 && ((HANG & 0xF0) != 0xF0); i++)
            {
                GPIO_Write(GPIOC, (HANG & 0xF0) | (0x01 << i));
                HANG = GPIO_ReadInputData(GPIOC);
            }
            HANG &= 0x0F;
            GPIO_Write(GPIOC, 0xF0);
            while((GPIO_ReadInputData(GPIOC) & 0xF0) != 0xF0) {
                count++;
            }
            if(count >= 4500000)
            {
                switch((LIE | HANG)) {
                case 0x81:
                   printf ("µ±Ç°¼üֵΪ0X:%X", (LIE | HANG)) ;
                    return 0X90 ;
                    break;
                case 0x41:
                   printf ("µ±Ç°¼üֵΪ0X:%X", (LIE | HANG)) ;
                    return 0X91 ;
                    break;
                case 0x21:
                   printf ("µ±Ç°¼üֵΪ0X:%X", (LIE | HANG)) ;
                    return 0X92 ;
                    break;
                case 0x11:
                   printf ("µ±Ç°¼üֵΪ0X:%X", (LIE | HANG)) ;
                    return 0X93 ;
                    break;
                case 0x18:
                   printf ("µ±Ç°¼üֵΪ0X:%X", (LIE | HANG)) ;
                    return 0X94 ;
                    break;
                case 0x12:
                   printf (" °´¼üΪ = :%X", (LIE | HANG)) ;
                    return 0X95 ;
                    break;
                default:
                   printf (" °´¼üΪ = :%X", (LIE | HANG) + 1) ;
                    return (LIE | HANG) + 1;
                }
            }
            else     return LIE | HANG;
        }
    }
}
。。。。。。。。。。。
/¹ÜÀíÔ±ÃÜÂë
u8 AdministratorPassword() {
    u8 num = 0;
    u8 j;
    u8 i = 0;
    clear_screen();
    display_GB2312_string(0, 20 + 8 * i, "ÇëÊäÈë¹ÜÀíÔ±ÃÜÂë");
    LCD12864lcdcls();
    Lcd_ShowSring(1, 0, "ÇëÊäÈë¹ÜÀíÔ±ÃÜÂë");
    while(1)
    {
        num = GetBoardValu1();
        if((num < 10))
        {
            passwordtemp[i] = num + 48;
            display_GB2312_string(4, 20 + 8 * i, "*");
            Lcd_ShowSring(3, i, "*");
           printf("*");
            i++;               
        }
        else if(num == 13)
        {
            clear_screen();
            display_GB2312_string(0, 20 + 8 * i, "ÖØÐÂÊäÈë:");
            LCD12864lcdcls();
            Lcd_ShowSring(1, 0, "ÇëÖØÐÂÊäÈë:");
            for(j = 0; j < 9; j++)   
                passwordtemp[j] = 0;
            i = 0;
            display_GB2312_string(2, 20 + 8 * i, "        ");
                     Lcd_ShowSring(3, 0, "        ");
        }
        else if(num == 14)
        {
           printf ("×Ö·û´®:%s\r\n", IntToStr(FLASHI_get_tada(SectorHeadAddr(password_addr))));
            if((passwordtemp[0] == Administrator[0]) &&
                    (passwordtemp[1] == Administrator[1]) &&
                    (passwordtemp[2] == Administrator[2]) &&
                    (passwordtemp[3] == Administrator[3]) &&
                    (passwordtemp[4] == Administrator[4]) &&
                    (passwordtemp[5] == Administrator[5]) &&
                    (passwordtemp[6] == Administrator[6]) &&
                    (passwordtemp[7] == Administrator[7])
              )
            {
                clear_screen();
                display_GB2312_string(2, 0, "½øÈë¹ÜÀíԱģʽ");
                LCD12864lcdcls();
                Lcd_ShowSring(1, 0, "½øÈë¹ÜÀíԱģʽ");
                for(j = 0; j < 9; j++)   
                    passwordtemp[j] = 0;
                i = 0;
                ModeSelection_Flag = 1;
                AdministratorMODE();
                return 1;
            } else {
                clear_screen();
                display_GB2312_string(2, 0, "ÊäÈë´íÎó,ÇëÖØÐÂÊäÈë!");
                LCD12864lcdcls();
                Lcd_ShowSring(1, 0, "¹ÜÀíÔ±ÃÜÂë´íÎó!");
                for(j = 0; j < 9; j++)   
                passwordtemp[j] = 0;
                i = 0;
            }
        }
    }
}
。。。。。。。。


Connecting & Messaging from Any.
举报 使用道具
许阳旭 新手上路 发表于 2019-1-5 19:59:58 | 显示全部楼层
今天整合了一下指纹模块和12864显示屏,使显示屏能显示指纹是否输入,以及验证成功。关于12864显示屏,它是128x64点阵型液晶显示屏,分为两种工作模式:文本工作模式和绘图工作模式。我们用的是它的第一个工作模式,整屏平均分成32个显示区(每个显示区是16X16点阵),每个显示区可显示一个中文,每个显示区可显示两个英文ASCII字符。对于它的操作可概括为四步:一、读忙状态(同时读出指针地址内容),初始化之后每次对12864的读写均要进行忙检测,二、写命令:所有的命令可以查看指令表。写地址也是写指令,三、写数据:操作对象有DDRAM、CGRAM、GDRAM,四、读数据:操作对象也是DDRAM、CGRAM、GDRAM。
Connecting & Messaging from Any.
举报 使用道具
许阳旭 新手上路 发表于 2019-1-3 20:38:24 | 显示全部楼层
今天了解关于继电器的内容。先简单的通过stm32控制继电器点亮发光二极管,通过发光二极管来模拟锁的开关。我觉得控制继电器的关键点在于当输入量的变化达到规定要求时,在电气输出电路中使被控量发生预定的  阶跃变化的一种电器。它具有控制系统(又称输入回路)和被控制系统(又称输出回路)之间的互动关系。通常应用于自动化    的控制电路中,它实际上是用小电流去控制大电流运作的一种“自动开关”。
相关配置代码:
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD|RCC_APB2Periph_AFIO, ENABLE );
/* Configure USART1 Tx (PA.09) as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_13; // 选中管脚9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 最高输出速率50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure); // 选择A端口
/* Configure USART1 Rx (PA.10) as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9; //选中管脚10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure); //选择A端口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //选中管脚10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
Connecting & Messaging from Any.
举报 使用道具
洪斌 新手上路 发表于 2019-1-2 21:12:26 | 显示全部楼层
TFT LCD触摸显示屏遇到些问题,这两天本人身体也欠佳,所以改用12846的屏幕,具体不说明了
看看咱这两天写的关于指纹的处理:
//录指纹
void Add_FR(void)
{
    u8 i,ensure ,processnum=0;
    u16 ID;
    while(1)
    {
        switch (processnum)
        {
            case 0:
                i++;
                LCD_Fill(0,100,lcddev.width,160,WHITE);
                Show_Str_Mid(0,100,"Çë°´Ö¸ÎÆ",16,240);
                ensure=PS_GetImage();
                if(ensure==0x00)
                {
                    BEEP=1;
                    ensure=PS_GenChar(CharBuffer1);//Éú³ÉÌØÕ÷
                    BEEP=0;
                    if(ensure==0x00)
                    {
                        LCD_Fill(0,120,lcddev.width,160,WHITE);
                        Show_Str_Mid(0,120,"Ö¸ÎÆÕý³£",16,240);
                        i=0;
                        processnum=1;//Ìøµ½µÚ¶þ²½                        
                    }else ShowErrMessage(ensure);               
                }else ShowErrMessage(ensure);                        
                break;
            
            case 1:
                i++;
                LCD_Fill(0,100,lcddev.width,160,WHITE);
                Show_Str_Mid(0,100,"Çë°´ÔÙ°´Ò»´ÎÖ¸ÎÆ",16,240);
                ensure=PS_GetImage();
                if(ensure==0x00)
                {
                    BEEP=1;
                    ensure=PS_GenChar(CharBuffer2);//Éú³ÉÌØÕ÷
                    BEEP=0;
                    if(ensure==0x00)
                    {
                        LCD_Fill(0,120,lcddev.width,160,WHITE);
                        Show_Str_Mid(0,120,"Ö¸ÎÆÕý³£",16,240);
                        i=0;
                        processnum=2;//Ìøµ½µÚÈý²½
                    }else ShowErrMessage(ensure);   
                }else ShowErrMessage(ensure);        
                break;

            case 2:
                LCD_Fill(0,100,lcddev.width,160,WHITE);
                Show_Str_Mid(0,100,"¶Ô±ÈÁ½´ÎÖ¸ÎÆ",16,240);
                ensure=PS_Match();
                if(ensure==0x00)
                {
                    LCD_Fill(0,120,lcddev.width,160,WHITE);
                    Show_Str_Mid(0,120,"¶Ô±È³É¹¦,Á½´ÎÖ¸ÎÆÒ»Ñù",16,240);
                    processnum=3;//Ìøµ½µÚËIJ½
                }
                else
                {
                    LCD_Fill(0,100,lcddev.width,160,WHITE);
                    Show_Str_Mid(0,100,"¶Ô±Èʧ°Ü£¬ÇëÖØмÈëÖ¸ÎÆ",16,240);
                    ShowErrMessage(ensure);
                    i=0;
                    processnum=0;//Ìø»ØµÚÒ»²½        
                }
                delay_ms(1200);
                break;

            case 3:
                LCD_Fill(0,100,lcddev.width,160,WHITE);
                Show_Str_Mid(0,100,"Éú³ÉÖ¸ÎÆÄ£°å",16,240);
                ensure=PS_RegModel();
                if(ensure==0x00)
                {
                    LCD_Fill(0,120,lcddev.width,160,WHITE);
                    Show_Str_Mid(0,120,"Éú³ÉÖ¸ÎÆÄ£°å³É¹¦",16,240);
                    processnum=4;//Ìøµ½µÚÎå²½
                }else {processnum=0;ShowErrMessage(ensure);}
                delay_ms(1200);
                break;
               
            case 4:   
                LCD_Fill(0,100,lcddev.width,160,WHITE);
                Show_Str_Mid(0,100,"ÇëÊäÈë´¢´æID,°´Enter±£´æ",16,240);
                Show_Str_Mid(0,120,"0=< ID <=299",16,240);
                do
                    ID=GET_NUM();
                while(!(ID<AS608Para.PS_max));//ÊäÈëID±ØÐëСÓÚÖ¸ÎÆÈÝÁ¿µÄ×î´óÖµ
                ensure=PS_StoreChar(CharBuffer2,ID);//´¢´æÄ£°å
                if(ensure==0x00)
                {            
                    LCD_Fill(0,100,lcddev.width,160,WHITE);                    
                    Show_Str_Mid(0,120,"¼ÈëÖ¸ÎƳɹ¦",16,240);
                    PS_ValidTempleteNum(&ValidN);//¶Á¿âÖ¸ÎƸöÊý
                    LCD_ShowNum(56,80,AS608Para.PS_max-ValidN,3,16);
                    delay_ms(1500);
                    LCD_Fill(0,100,240,160,WHITE);
                    return ;
                }else {processnum=0;ShowErrMessage(ensure);}                    
                break;               
        }
        delay_ms(400);
        if(i==5)//³¬¹ý5´ÎûÓа´ÊÖÖ¸ÔòÍ˳ö
        {
            LCD_Fill(0,100,lcddev.width,160,WHITE);
            break;   
        }               
    }
}
部分有乱码,就不



Connecting & Messaging from Any.
举报 使用道具
许阳旭 新手上路 发表于 2019-1-2 21:06:28 | 显示全部楼层
今天研究了一下tft-lcd显示屏的驱动问题,尝试了几次,都没有达到想要的结果。由于时间问题,我们组决定暂时先购买一个12864液晶显示屏,根据官方提供的相关代码,先完成小组的项目。后期若有时间,会继续研究tft-lcd的驱动问题。关于12864液晶显示屏,我从网上找了一些资料,下面是关于显示屏的管脚问题


管脚号        管脚名称        LEVER        管脚功能描述
1        VSS        0        电源地
2        VDD        +5.0V        电源电压
3        V0        -        液晶显示器驱动电压
4        D/I(RS)        H/L        D/I=“H”,表示DB7∽DB0为显示数据
D/I=“L”,表示DB7∽DB0为显示指令数据
5        R/W        H/L        R/W=“H”,E=“H”数据被读到DB7∽DB0
R/W=“L”,E=“H→L”数据被写到IR或DR
6        E        H/L        R/W=“L”,E信号下降沿锁存DB7∽DB0
R/W=“H”,E=“H”DDRAM数据读到DB7∽DB0
7        DB0        H/L        数据线
8        DB1        H/L        数据线
9        DB2        H/L        数据线
10        DB3        H/L        数据线
11        DB4        H/L        数据线
12        DB5        H/L        数据线
13        DB6        H/L        数据线
14        DB7        H/L        数据线
15        CS1        H/L        H:选择芯片(右半屏)信号
16        CS2        H/L        H:选择芯片(左半屏)信号
17        RET        H/L        复位信号,低电平复位
18        VOUT        -10V        LCD驱动负电压
19        LED+        -        LED背光板电源
20        LED-        -        LED背光板电源
Connecting & Messaging from Any.
举报 使用道具
冰泪年华 新手上路 发表于 2019-1-1 20:03:31 | 显示全部楼层
关于指纹识别的部分已经弄得差不多了,现在我们组面临着新的问题,那就是LCD的显示问题,该显示什么内容和怎么控制屏幕,还有要实现增添指纹和删除指纹功能我们还在研究中。
Connecting & Messaging from Any.
举报 使用道具
於坚敏 新手上路 发表于 2018-12-29 09:29:03 | 显示全部楼层
昨天学习了有关AS608指纹模块的工作模式,知道了AS608 指纹模块 SOC 挂接必要的外围电路(传感器、晶振、电源等)后即可构成完整的指纹识别模块,模块始终处于从属地位(Slave mode),主机(Host)需要通过不同的指令让模块完成各种功能。主机的指令、模块的应答以及数据交换都是按照规定格式的数据包来进行的。主机必须按照下述格式封装要发送的指令或数据,也必须按下述格式解析收到的数据包。
指令包/数据包格式
指令/数据包共分为三类:
包标识=01 命令包
包标识=02 数据包,且有后续包
包标识=08 最后一个数据包,即结束包
所有的数据包都要加包头:0xEF01
Connecting & Messaging from Any.
举报 使用道具
冰泪年华 新手上路 发表于 2018-12-29 09:11:44 | 显示全部楼层
昨晚忘了更新,今天补上。昨天学习了录指纹,刷指纹和删除指纹。其中比较重要的是录指纹。下面是录指纹的步骤:
首先按指纹生成指纹特征。如果指纹不正常,则重新录一次指纹,若正常,则比对指纹,产生一个指纹模板,生成指纹模板成功。接着输入ID并保存,显示添加指纹成功。       
Connecting & Messaging from Any.
举报 使用道具
洪斌 新手上路 发表于 2018-12-29 09:11:30 | 显示全部楼层
今天继续更新LCD的编程,FSMC配置以及初始化LCD
void LCD_Init(void)
{                                        
        GPIO_InitTypeDef GPIO_InitStructure;
        FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
  FSMC_NORSRAMTimingInitTypeDef  readWriteTiming;
        FSMC_NORSRAMTimingInitTypeDef  writeTiming;
       
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOG,ENABLE);


        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_14|GPIO_Pin_15;       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOD, &GPIO_InitStructure);
            
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOE, &GPIO_InitStructure);                                                                                                                  

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_12;       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOG, &GPIO_InitStructure);

        readWriteTiming.FSMC_AddressSetupTime = 0x01;
  readWriteTiming.FSMC_AddressHoldTime = 0x00;       
  readWriteTiming.FSMC_DataSetupTime = 0x0f;               
  readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
  readWriteTiming.FSMC_CLKDivision = 0x00;
  readWriteTiming.FSMC_DataLatency = 0x00;
  readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A;         
   
        writeTiming.FSMC_AddressSetupTime = 0x00;       
  writeTiming.FSMC_AddressHoldTime = 0x00;       
  writeTiming.FSMC_DataSetupTime = 0x03;               
  writeTiming.FSMC_BusTurnAroundDuration = 0x00;
  writeTiming.FSMC_CLKDivision = 0x00;
  writeTiming.FSMC_DataLatency = 0x00;
  writeTiming.FSMC_AccessMode = FSMC_AccessMode_A;       


  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;
  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
  FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM;  
  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
        FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;   
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;  
  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;       
  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;   
  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;
  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;
  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &writeTiming;

  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
Connecting & Messaging from Any.
举报 使用道具
张国强3937 新手上路 发表于 2018-12-29 09:09:41 | 显示全部楼层
注意,stm32是3.3V的,如果继电器模块与stm32使用相同的电源,可能会难以驱动。


始终闭合。需要加个三极管。
Connecting & Messaging from Any.
举报 使用道具
许阳旭 新手上路 发表于 2018-12-29 08:55:19 | 显示全部楼层
关于指纹的存储,一开始准备存储在数组里,但对于数组的是没有断电保护的,所以打算存指纹库里。将提取到的特征值存放到特征文件缓冲区charbuffer1和charbuffer2中。模块在FLASH中开辟了一段存储区域作为指纹模板存放区,即指纹库。指纹库中的数据是断电保护的。
指纹模板按照序号存放,若指纹库容量为N,则指纹模板在指纹库中的序号定义为:0、1、2……N-2、N-1。用户只能根据序号访问指纹库内容,相应的存储和搜索功能对应的都是针对指纹序号的操作
u8 PS_GenChar(u8 BufferID)
{
        u16 temp;
  u8  ensure;
        u8  *data;
        SendHead();
        SendAddr();
        SendFlag(0x01);//命令包标识
        SendLength(0x04);
        Sendcmd(0x02);
        MYUSART_SendData(BufferID);
        temp = 0x01+0x04+0x02+BufferID;
        SendCheck(temp);
        data=JudgeStr(2000);
        if(data)
                ensure=data[9];
        else
                ensure=0xff;
        return ensure;

指纹的预处理

从指纹图像局部特征开始,结合指纹的全局特征来判断指纹图像的质量。通过检测图像的有效面积和清晰度,来确定图像是否合格。具体方法是:首先,通过计算图像方向信息,确定前景块和背景块;然后,通过比较前景块和背景块的比例来判断是否是偏手指;再次,通过图像块的对比度的大小来判断是干手指或湿手指。在指纹图像质量评估合格后,需要对图像进行灰度变换,即对指纹图像均衡化,使得图像灰度均衡,以及对图像进行归一化。在这些完成之后,还需要对图像按照一定的算法和要求进行分割
Connecting & Messaging from Any.
举报 使用道具
张国强3937 新手上路 发表于 2018-12-27 21:20:10 | 显示全部楼层
 控制继电器这个应该不是太复杂吧,首先得看你的硬件电路怎么接的,一般都是一个三极管做开关,通过高低电平控制三极管的导通与关闭实现继电器的开关与闭合,这里假如用的PB3输出低电平控制继电器闭合则代码如下
  GPIO_InitTypeDef GPIO_InitStruct;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  GPIO_StructInit(&GPIO_InitStruct);
  GPIO_InitStruct.GPIO_Mode        =        GPIO_Mode_Out_PP;
  GPIO_InitStruct.GPIO_Pin        =        GPIO_Pin_3;
  GPIO_InitStruct.GPIO_Speed        =        GPIO_Speed_2MHz;
  GPIO_Init(GPIOB,&GPIO_InitStruct);
  /*输出高电平*/
  GPIO_SetBits(GPIOB,GPIO_Pin_3);
  /*控制输出低电平*/
  GPIO_ResetBits(GPIOB,GPIO_Pin_3);
  其他GPIO_InitTypeDef GPIO_InitStruct;
//开启相应管脚时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);
//配置相应需要控制的管脚
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14|GPIO_Pin_15;
//设置管脚最大处理速率
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MH;
//设置管脚模式
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
//初始化管脚
GPIO_Init(GPIOG , &GPIO_InitStruct);
然后,通过
//置高
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);以及
//置低
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
进行控制;配置要根据你的硬件电路进行配置
Connecting & Messaging from Any.
举报 使用道具
许阳旭 新手上路 发表于 2018-12-27 20:45:14 | 显示全部楼层
对于指纹算法的思路:
(1)使用指纹采集设备采集指纹图像。(2)对指纹图像中的大量噪声点进行预处理,从而提升后面处理的效率。在预处理之后,得到了一个关于指纹图像的轮廓线,为下一步特征提取做准备。(3)进行指纹图像的特征提取,提取出其特征信息点。(4)对指纹图像进行特征匹配,把提取的特征点与数据库中预存的特征点进行比对,通过比对来判断身份。

今天了解了一下采集指纹图像的算法:用串口接收图像采集器采集到的指纹,然后将接收到的收据存在ImageBuffer中
static void MYUSART_SendData(u8 data)
{
        while((USART2->SR&0X40)==0);
        USART2->DR = data;
}

static u8 *JudgeStr(u16 waittime)
{
        char *data;
        u8 str[8];
        str[0]=0xef;str[1]=0x01;str[2]=AS608Addr>>24;
        str[3]=AS608Addr>>16;str[4]=AS608Addr>>8;
        str[5]=AS608Addr;str[6]=0x07;str[7]='\0';
        USART2_RX_STA=0;
        while(--waittime)
        {
                delay_ms(1);
                if(USART2_RX_STA&0X8000)//接收到一次数据
                {
                        USART2_RX_STA=0;
                        data=strstr((const char*)USART2_RX_BUF,(const char*)str);
                        if(data)
                                return (u8*)data;       
                }
        }
        return 0;
}
Connecting & Messaging from Any.
举报 使用道具
冰泪年华 新手上路 发表于 2018-12-27 20:37:13 | 显示全部楼层
总结了一下需要我们接下来实现的指纹模块的一些功能流程:
1,删指纹——与模块握手通过之后,屏幕将虚拟一个键盘,按‘删指纹’进入删除界面。在此界面可以按照提示输出一个数值按删除键删除单个指纹,如果是误操作也可以按‘返回’主界面。
2,录指纹——按‘录指纹’进入此项。录指纹流程:按第一次手指-->按第二次手指-->自动生成模板-->输入存储ID-->存储指纹成功。
3,刷指纹--与模块握手成功之后,主函数中判断指纹模块的感应引脚模块感应到手指输出高电平,程序判断后进入刷指纹流程。读指纹图像-->搜索匹配指纹库-->成功或没有搜到指纹。

Connecting & Messaging from Any.
举报 使用道具
洪斌 新手上路 发表于 2018-12-27 20:19:58 | 显示全部楼层
昨天今天把FSMC研究了一番,因为要用到液晶显示屏,所以对FSMC进行了配置

void LCD_FSMCConfig(void)
{
    FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
    FSMC_NORSRAMTimingInitTypeDef  p;
   

    p.FSMC_AddressSetupTime = 0;
    p.FSMC_AddressHoldTime = 0;
    p.FSMC_DataSetupTime = 2;
    p.FSMC_BusTurnAroundDuration = 0;
    p.FSMC_CLKDivision = 0;
    p.FSMC_DataLatency = 0;
    p.FSMC_AccessMode = FSMC_AccessMode_A;
   

    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;
    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
    FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
    FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
    FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
    //FSMC_NORSRAMInitStructure.FSMC_AsyncWait = FSMC_AsyncWait_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
   
    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  
   
    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);
}


Connecting & Messaging from Any.
举报 使用道具
lxye 新手上路 发表于 2018-12-27 09:30:22 | 显示全部楼层

让你们回帖的意义是让你们知道自己每天做了哪些工作,而不是直接把现成的原理放上来
Connecting & Messaging from Any.
举报 使用道具
lxye 新手上路 发表于 2018-12-27 09:21:02 | 显示全部楼层
Mr.six 发表于 2018-12-26 19:52
关于LCD液晶显示屏显示功能使得指纹解锁抽象实现在液晶显示屏上,具体可以见附件 ...

不是说自己写API嘛  你这是直接把别人的东西拿过来了把
Connecting & Messaging from Any.
举报 使用道具
张国强3937 新手上路 发表于 2018-12-26 20:33:16 | 显示全部楼层
继电器控制逻辑

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

点评

lxye 让你们回帖的意义是让你们知道自己每天做了哪些工作,而不是直接把现成的原理放上来  详情 回复 发表于 2018-12-27 09:30
Connecting & Messaging from Any.
举报 使用道具
冰泪年华 新手上路 发表于 2018-12-26 20:25:05 | 显示全部楼层
昨天一直在改需求文档,终于弄好了。今天看了一下我们项目指纹模块的需求,每个指纹ID都需要数据库来存储它,以作下次解锁时进行指纹比对,这是一个难点。
Connecting & Messaging from Any.
举报 使用道具
Mr.six 新手上路 发表于 2018-12-26 19:52:17 | 显示全部楼层
关于LCD液晶显示屏显示功能使得指纹解锁抽象实现在液晶显示屏上,具体可以见附件

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

点评

lxye 不是说自己写API嘛 你这是直接把别人的东西拿过来了把  详情 回复 发表于 2018-12-27 09:21
Connecting & Messaging from Any.
举报 使用道具
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

推荐板块

精彩推荐

热门排行

明星用户

手机版|小黑屋|AnyMSG ( ©AnyMSG 2009 - 2017 · ICP备16009991号 )

GMT+8, 2019-2-20 03:31