stm32F407主控芯片
RFID模块
矩阵按键模块
AS608指纹模块
SG90舵机模块文章来源:https://www.toymoban.com/news/detail-540053.html
OLED显示屏模块文章来源地址https://www.toymoban.com/news/detail-540053.html
一、系统设计框架图
![基于stm32的门禁系统设计,嵌入式硬件,stm32,Powered by 金山文档](https://imgs.yssmx.com/Uploads/2023/07/540053-1.png)
二、模块设计
RFID
寻卡
//功能描述寻卡读取卡类型号
//输入参数reqMode--寻卡方式
// TagType--返回卡片类型
// 0x4400 = Mifare_UltraLight
// 0x0400 = Mifare_One(S50)
// 0x0200 = Mifare_One(S70)
// 0x0800 = Mifare_Pro(X)
// 0x4403 = Mifare_DESFire
//返 回 值成功返回MI_OK
u8 MFRC522_Request(u8 reqMode, u8 *TagType)
{
u8 status;
u16 backBits; //接收到的数据位数
//
Write_MFRC522(BitFramingReg, 0x07); //TxLastBists = BitFramingReg[2..0]
TagType[0] = reqMode;
status = MFRC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits);
//
if ((status != MI_OK) || (backBits != 0x10))
{
status = MI_ERR;
}
//
return status;
}
读取卡序列号
//功能描述防冲突检测读取选中卡片的卡序列号
//输入参数serNum--返回4字节卡序列号,第5字节为校验字节
//返 回 值成功返回MI_OK
u8 MFRC522_Anticoll(u8 *serNum)
{
u8 status;
u8 i;
u8 serNumCheck=0;
u16 unLen;
//
ClearBitMask(Status2Reg, 0x08); //TempSensclear
ClearBitMask(CollReg,0x80); //ValuesAfterColl
Write_MFRC522(BitFramingReg, 0x00); //TxLastBists = BitFramingReg[2..0]
serNum[0] = PICC_ANTICOLL1;
serNum[1] = 0x20;
status = MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen);
//
if (status == MI_OK)
{
//校验卡序列号
for(i=0;i<4;i++)
serNumCheck^=serNum[i];
//
if(serNumCheck!=serNum[i])
status=MI_ERR;
}
SetBitMask(CollReg,0x80); //ValuesAfterColl=1
//
return status;
}
匹配卡号
u8 check_ID(u8 *a, u8 *b)
{
int i;
for(i=0;i<4;i++)
{
if( a[i] == b[i])
continue;
else
return 1;
}
return 0;
}
保存卡
//保存卡号
void save_id(u8 *card_numberbuf)
{
char Wbuf[32];
int i;
printf("count:%d\n",count);
w25q128_sector_erase(0x001000+0x001000*count);//擦除第count+1个扇区
delay_ms(500);
w25q128_read_data(0x001000+0x001000*count,Wbuf,20);//读取
for(i=0;i<10;i++)
printf("[%#x] ",Wbuf[i]);
printf("\r\n");
//sprintf(Wbuf,"%x%x%x%x\0",);
w25q128_write_data(0x001000+0x001000*count,(char *)card_numberbuf,4);
w25q128_read_data(0x001000+0x001000*count,Wbuf,20);
for(i=0;i<10;i++)
printf("[%#x] ",Wbuf[i]);
printf("\r\n");
memset(Wbuf,0,sizeof(Wbuf));
count++;
}
删除卡
//删除卡号
void del_id(u8 *card_numberbuf)
{
int i,j;
u8 flag;
char NextID[32];
for(i=0;i<count;i++)
{
w25q128_read_data(0x001000+0x001000*i,NextID,4);
printf("card_id[%d]",i);
printf("now_card_id:");
flag = check_ID((u8 *)NextID,card_numberbuf);
printf("比较第%d张卡\n",i+1);
if(flag == 0) //遍历成功找到
{
printf("卡号存在!");
printf("为第%d张卡\n",i+1);
break;
}
}
for(j = i;j<count;j++)
{
w25q128_sector_erase(0x001000+0x001000*j);
w25q128_read_data(0x001000+0x001000*(j+1),NextID,4);
w25q128_write_data(0x001000+0x001000*j,NextID,4);
memset(NextID,0,sizeof(NextID));
}
count--;
}
矩阵按键
按行按列读取,获取按键值
char get_keyboard()
{
int x,y;
//设置PA0~PA3为输出,PB0~PB3为输入
GPIO_SET_MODE(GPIO_Mode_OUT,1);
//读取电平
x = get_num(GPIO_Mode_OUT);
//设置PB0~PB3为输出模式,清零
GPIO_SET_MODE(GPIO_Mode_OUT,0);
//设置PB0~PB3为输出模式,PA0~PA3为输入模式
GPIO_SET_MODE(GPIO_Mode_IN,1);
//读取电平
y = get_num(GPIO_Mode_IN);
//清零
GPIO_SET_MODE(GPIO_Mode_IN,0);
//printf("x=%d\n",x);
//printf("x=%d\n",x);
return arr[x][y];
}
指纹
检测是否有手指按下图像
//录入图像 PS_GetImage
//功能:探测手指,探测到后录入指纹图像存于ImageBuffer。
//模块返回确认字
u8 PS_GetImage(void)
{
u16 temp;
u8 ensure;
u8 *data;
SendHead();
SendAddr();
SendFlag(0x01);//命令包标识
SendLength(0x03);
Sendcmd(0x01);
temp = 0x01+0x03+0x01;
SendCheck(temp);
data=JudgeStr(2000);
if(data)
ensure=data[9];
else
ensure=0xff;
return ensure;
}
刷指纹
void press_FR(void)
{
SearchResult seach;
u8 ensure;
ensure=PS_GetImage();
delay_ms(3000);
if(ensure==0x00)//获取图像成功
{
printf("获取图像成功!");
PFout(10) = 0;
ensure=PS_GenChar(CharBuffer1);
if(ensure==0x00) //生成特征成功
{
printf("生成特征成功!");
PFout(10) = 1;
ensure=PS_HighSpeedSearch(CharBuffer1,0,AS608Para.PS_max,&seach);
if(ensure==0x00)//搜索成功
{
printf("搜索成功!");
printf("刷指纹成功,此人ID:%d 匹配得分:%d\r\n",seach.pageID,seach.mathscore);
opendoor();
}
else
{
printf("指纹不存在,匹配失败!");
ShowErrMessage(ensure);
}
}
else
{
printf("指纹识别失败\r\n");
ShowErrMessage(ensure);
}
//PFout(10) = 1;
delay_ms(2000);
}
AS608_flag = 0;
}
录入指纹
void Add_FR(void)
{
u8 i,ensure ,processnum=0;
u16 ID;
while(AS608_flag == 1)
{
switch (processnum)
{
case 0:
i++;
printf("请按下指纹...\r\n");
OLED_Clear();
OLED_ShowCHinese(0,2,48);//请
OLED_ShowCHinese(18,2,49);//按
OLED_ShowCHinese(36,2,50);//下
OLED_ShowCHinese(54,2,40);//指
OLED_ShowCHinese(72,2,41);//纹
delay_xms(2000);
ensure=PS_GetImage();
if(ensure==0x00)
{
PFout(9) = 0;
ensure=PS_GenChar(CharBuffer1);//生成特征
PFout(9) = 1;
if(ensure==0x00)
{
printf("指纹正常\r\n");
i=0;
processnum=1;//跳到第二步
}else ShowErrMessage(ensure);
}else ShowErrMessage(ensure);
break;
case 1:
i++;
printf("请再按一次指纹...\r\n");
OLED_Clear();
OLED_ShowCHinese(0,2,48);//请
OLED_ShowCHinese(18,2,51);//再
OLED_ShowCHinese(36,2,49);//按
OLED_ShowCHinese(54,2,50);//下
OLED_ShowCHinese(72,2,40);//指
OLED_ShowCHinese(90,2,41);//纹
ensure=PS_GetImage();
if(ensure==0x00)
{
PFout(9) = 0;
ensure=PS_GenChar(CharBuffer2);//生成特征
PFout(9) = 1;
if(ensure==0x00)
{
printf("指纹正常\r\n");
i=0;
processnum=2;//跳到第三步
}else ShowErrMessage(ensure);
}else ShowErrMessage(ensure);
break;
case 2:
printf("对比两次指纹...\r\n");
ensure=PS_Match();
if(ensure==0x00)
{
printf("对比成功,两次指纹一样\r\n");
processnum=3;//跳到第四步
}
else
{
printf("对比失败,请重新录入指纹\r\n");
ShowErrMessage(ensure);
i=0;
processnum=0;//跳回第一步
}
delay_ms(1200);
break;
case 3:
printf("生成指纹模板...\r\n");
ensure=PS_RegModel();
if(ensure==0x00)
{
printf("生成指纹模板成功\r\n");
processnum=4;//跳到第五步
}else {processnum=0;ShowErrMessage(ensure);}
delay_ms(1200);
break;
case 4:
ID = ID_input();//输入存储用的ID号
ensure=PS_StoreChar(CharBuffer2,ID);//储存模板
if(ensure==0x00)
{
printf("录入指纹成功\r\n");
//录入失败
OLED_ShowCHinese(0,2,40);//指
OLED_ShowCHinese(18,2,41);//纹
OLED_ShowCHinese(36,2,53);//录
OLED_ShowCHinese(54,2,54);//入
OLED_ShowCHinese(72,2,26);//成
OLED_ShowCHinese(90,2,27);//功
AS608_flag = 0;
PS_ValidTempleteNum(&ValidN);//读库指纹个数
printf("剩余指纹容量为%d\r\n",AS608Para.PS_max-ValidN);
return ;
}else {processnum=0;ShowErrMessage(ensure);}
break;
}
delay_xms(2000);
if(i==5)//超过5次没有按手指则退出
{
printf("--------超过5次没有按手指则退出--------\r\n");
//录入失败
OLED_ShowCHinese(0,2,40);//指
OLED_ShowCHinese(18,2,41);//纹
OLED_ShowCHinese(36,2,53);//录
OLED_ShowCHinese(54,2,54);//入
OLED_ShowCHinese(72,2,28);//失
OLED_ShowCHinese(90,2,29);//败
AS608_flag = 0;
break;
}
}
}
删除指纹
void Del_FR(void)
{
u8 ensure;
u16 num;
printf("删除指纹,请输入指纹ID\r\n");
OLED_Clear();
OLED_ShowCHinese(0,2,55);//输
OLED_ShowCHinese(18,2,56);//入
OLED_ShowCHinese(36,2,40);//指
OLED_ShowCHinese(54,2,41);//纹
OLED_ShowCHinese(72,2,57);//编
OLED_ShowCHinese(90,2,58);//号
delay_ms(50);
num = ID_input();//输入删除用的ID号
if(num==0xFFFF)
goto MENU ; //返回主页面
else if(num==0xFF00)
ensure=PS_Empty();//清空指纹库
else
ensure=PS_DeletChar(num,1);//删除单个指纹
if(ensure==0)
{
printf("删除指纹成功\r\n");
OLED_Clear();
OLED_ShowCHinese(0,2,40);//指
OLED_ShowCHinese(18,2,41);//纹
OLED_ShowCHinese(36,2,32);//删
OLED_ShowCHinese(54,2,33);//除
OLED_ShowCHinese(72,2,26);//成
OLED_ShowCHinese(90,2,27);//功
}
else
ShowErrMessage(ensure);
delay_ms(750);
PS_ValidTempleteNum(&ValidN);//读库指纹个数
printf("剩余指纹个数:%d\r\n",AS608Para.PS_max-ValidN);
AS608_flag = 0;
MENU:
printf("返回主程序\r\n");
}
三、主函数设计
int main()
{
char buf[8];
count = 0;
char keyboard_buf[5] = {0};
u8 ensure;
//中断优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//滴答定时器采用8分频
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
//初始化LED灯
led_init();
//初始化按键
key_nvic_init();
//初始化USART1
usart1_init(9600);
//USART1_init(9600);
//初始化USART2--蓝牙模块
//usart2_init(9600);
tim4_init(); //定时器 舵机
tim6_init();//
MFRC522_Initializtion(); //初始化MFRC522
AT24C02_init();//flash缓存
SPI1_init();
//初始化OLED
OLED_Init();
//
// char ch = count +'0';
// w25q128_sector_erase(0x000000);
// w25q128_write_data(0x000000,&ch,1);
w25q128_read_data(0x000000,buf,1);
printf("buf:%s\n",buf);
count = buf[0] -'0';
printf("count:%d\n",count);
show_page();
//system config
//USART1_init(115200); //初始化串口,并设置波特率为115200
usart2_init(57600); //初始化串口2,用于与指纹模块通讯
//hardware config
//PS_StaGPIO_Init(); //初始化FR读状态引脚---PA6高电平表示有指纹按下
printf("与AS608模块握手....\r\n");
while(PS_HandShake(&AS608Addr))//与AS608模块握手
{
delay_ms(400);
printf("未检测到模块\r\n");
delay_ms(800);
printf("尝试连接模块...\r\n");
}
printf("通讯成功!!!\r\n");
printf("波特率:%d 地址:%x\r\n",57600,0XFFFFFFFF);
ensure=PS_ValidTempleteNum(&ValidN);//读库指纹个数
if(ensure!=0x00)
{
ShowErrMessage(ensure);
while(1);
}
ensure=PS_ReadSysPara(&AS608Para); //读参数
if(ensure==0x00)
{
printf("库容量:%d 对比等级: %d\r\n",AS608Para.PS_max-ValidN,AS608Para.PS_level);
}
else
{
ShowErrMessage(ensure);
while(1);
}
while(1)
{
MFRC522Test();//测试代码
//密码操作
if(keyboard_flag == 1) //按下key4 标志位改变 开始获取按键值
{
int i = 0;
while(1)
{
delay_xms(1000);//太快 导致按键连续检测 最后不成功 这里加上延时就行了
char a=get_keyboard();
printf("a:%c",a);
if(a != NULL)
{
keyboard_buf[i] = a;
i++;
printf("i:%d",i);
if(i == 6)
break;//获取五位密码之后结束按键获取
}
}
if(strncmp(password,keyboard_buf,5) == 0)
{
//密码正确 开门 显示提示信息
OLED_Clear();
OLED_ShowCHinese(0,4,34);//密
OLED_ShowCHinese(18,4,35);//码
OLED_ShowCHinese(36,4,36);//正
OLED_ShowCHinese(54,4,37);//确
printf("密码正确!");
delay_xms(2000);
opendoor();
show_page();
}
else
{
OLED_Clear();
OLED_ShowCHinese(0,4,34);//密
OLED_ShowCHinese(18,4,35);//码
OLED_ShowCHinese(36,4,38);//错
OLED_ShowCHinese(54,4,39);//误
printf("密码错误!");
delay_xms(2000);
show_page();
}
}
keyboard_flag = 0;//密码解锁结束 标志位置为0
uint32_t sec=0;
//指纹检测 //按下key3
while(AS608_flag == 1)
{
u8 press_flag = NULL;
delay_ms(500);delay_ms(500);
printf("sec:%d\r\n",sec++);
press_flag = PS_GetImage();
delay_ms(2000);
printf("press_flag:%d\n",press_flag);
if(press_flag == 0) //检测PS_Sta状态,如果有手指按下
{
press_FR();//刷指纹
//AS608_flag = 0;
}
if(usart1_flag == 1)//串口1接收到消息
{
printf("usart1_buf recv:%s\r\n",usart1_buf_rx);
if( usart1_buf_rx[0] == '1' )
{
printf("准备删除指纹\r\n");
Del_FR();
//AS608_flag = 0;
}
else if( usart1_buf_rx[0] == '2' )
{
printf("准备录入指纹\r\n");
Add_FR();
//AS608_flag = 0;
}
memset((void*)usart1_buf_rx,0,32);//清空缓冲区
usart1_flag=0;//标志位置0
usart1_cnt=0;//数组下标置0
}
show_page();
}
delay_xms(1000);
}
}
到了这里,关于基于STM32的智能门禁系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!