基于stm32c8t6的as608指纹模块

演示视频:https://www.bilibili.com/video/BV1tC411n7x8/

代码汇总

主函数

查询网上的添加指纹的代码,进入不了状态机,后按照江科大的状态机写法,修改的代码。目前只能添加一个指纹。
main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "OLED.h"
#include "Timer.h"
#include "Serial.h"
#include "as608.h"
#include "usart2.h"
#include "sys.h"
#include "Servo.h"
#include "Key.h"
SysPara AS608Para;//指纹模块AS608参数
u16 ValidN;//模块内有效指纹个数
void press_FR(void);//刷指纹
void Add_FR(void);
void Del_FR(void);
int main(void)
{
	uint8_t KeyNum;
	myLED_Init();
	Servo_Init();
//	Servo_SetAngle(180);
	Servo_SetAngle(0);
	OLED_Init();
	PS_StaGPIO_Init();//初始化PA6读状态引脚
	Serial_Init();
	usart2_init();
	Key_Init();
	while(1)
	{	
		//Servo_SetAngle(60);
//		Del_FR();
		LED_OFF();
		OLED_ShowString(1,1,"NUM:");
		KeyNum = Key_GetNum();
		OLED_ShowNum(1,5,KeyNum,2);
		Delay_ms(100);
//		OLED_Clear();
		if(KeyNum)
		{
			if(KeyNum==1)
			{
				Add_FR();
			}
//			else
//			{
//				OLED_ShowString(2,1,"hhh");
//				Delay_ms(500);
//			}
		}
		
		if(KeyNum==2)
			{
				Del_FR();
			}
Del_FR();
		if(PS_Sta)
		{
			press_FR();
		}
	} 	
}



//刷指纹
void press_FR(void)
{
	SearchResult seach;
	u8 ensure;
	OLED_Clear();
	OLED_ShowString(1,1,"Press Finger");
	ensure=PS_GetImage();
	if(ensure==0x00)//获取图像成功 
	{	
		ensure=PS_GenChar(CharBuffer1);
		if(ensure==0x00) //生成特征成功
		{		
			ensure=PS_HighSpeedSearch(CharBuffer1,0,300,&seach);
			if(ensure==0x00)//搜索成功
			{				
				OLED_Clear();
				OLED_ShowString(1,1,"Find Finger");
				LED_ON();
				Servo_SetAngle(60);
			}
			else 
			{
				OLED_Clear();
				OLED_ShowString(1,1,"Unknow Finger");//未搜索到指纹
			}		
	  }
		else
			OLED_ShowString(1,1,"creat fail");//生成失败
	 Delay_ms(600);	
  }
	OLED_Clear();
}



void Add_FR(void)
{
	uint8_t ID,i,ensure,processnum = 0;
	while(1)
	{
		if(processnum == 0)
		{
			i++;
			OLED_Clear();
			OLED_ShowString(1,1,"Put Finger");
			ensure = PS_GetImage();
			if(ensure == 0x00)
			{
				ensure = PS_GenChar(CharBuffer1);
				if(ensure == 0x00)
				{
					OLED_Clear();
					OLED_ShowString(1,1,"Finger OK");
					i=0;
					processnum=1;//跳到第二步
				}
				else
				{
					OLED_ShowString(2,1,"err");
				}
			}
			else
			{
				OLED_ShowString(2,1,"err");
			}
		}
		else if(processnum == 1)
		{
			i++;
			OLED_Clear();
			OLED_ShowString(1,1,"Finger Again");//请在按一次
			ensure=PS_GetImage();
			if(ensure==0x00)
			{
				ensure = PS_GenChar(CharBuffer2);
				if(ensure == 0x00)
				{
					OLED_Clear();
					OLED_ShowString(1,1,"Finger OK");
					i=0;
					processnum=2;//跳到第三步
				}
				else
				{
					OLED_ShowString(2,1,"err");
				}
			}
			else
			{
				OLED_ShowString(2,1,"err");
			}
			
		}
		else if(processnum == 2)
		{
			OLED_Clear();
			OLED_ShowString(1,1,"Fing Comper");//对比两次指纹
			ensure=PS_Match();
			if(ensure == 0x00)
			{
				OLED_Clear();
				OLED_ShowString(1,1,"Match-Ok");//对比成功,两次指纹一样
				processnum=3;//跳到第四步
			}
			else
			{
				OLED_Clear();
				OLED_ShowString(1,1,"Match No");//对比失败
				OLED_ShowString(2,1,"Back 1");//重新录入指纹
				i=0;
				processnum=0;//跳回第一步
			}
			Delay_ms(600);
		}
		else if (processnum == 3)
		{
			OLED_Clear();
			OLED_ShowString(1,1,"Creat Mode");//生成指纹模板
			ensure=PS_RegModel();
			if(ensure==0x00) 
			{
				OLED_Clear();
				OLED_ShowString(1,1,"Creat Success");//生成指纹模板成功
				processnum=4;//跳到第五步
			}
			else
			{
				processnum = 0;
				OLED_ShowString(2,1,"err");
			}
			Delay_ms(600);
		}
		else if(processnum == 4)
		{
			OLED_Clear();
			ID = 0x01;
			ensure=PS_StoreChar(CharBuffer2,ID);//储存模板
			if(ensure == 0x00)
			{
				OLED_Clear();
				OLED_ShowString(1,1,"Add ok");//录入指纹成功
				Delay_ms(600);
				break;
			}
			else 
			{
				processnum=0;
				OLED_ShowString(1,1,"Add no");
				Delay_ms(600);
				break;
			}
		}
	}
}


//删除指纹
void Del_FR(void)
{
	u8  ensure;
	u16 num;
	OLED_Clear();
	OLED_ShowString(1,1," del finger");//删除指纹
	OLED_ShowString(2,1," input id");//请输入指纹ID按Enter发送
	
	Delay_ms(50);
	ensure=PS_Empty();//清空指纹库
	if(ensure==0)
	{
		OLED_Clear();
		OLED_ShowString(1,1,"del sucess");//删除指纹成功
	}
    else
	{
		OLED_Clear();
		OLED_ShowHexNum(1,1,ensure,4);	
	}
	Delay_ms(500);
	PS_ValidTempleteNum(&ValidN);//读库指纹个数
	OLED_ShowNum(1,1,AS608Para.PS_max-ValidN,4);

}


as608.c与as608.h的代码网上很多,本文就不放了

usart2代码

usart2.c

#include "stm32f10x.h"
#include "usart2.h"
#include "stdarg.h"	 	 
#include "stdio.h"	 	 
#include "string.h"	 
#include "Timer.h"
 #include "Delay.h" 	


//串口接收缓存区 	
uint8_t USART2_RX_BUF[USART2_MAX_RECV_LEN]; 				//接收缓冲,最大USART2_MAX_RECV_LEN个字节.
uint8_t USART2_TX_BUF[USART2_MAX_SEND_LEN]; 			  //发送缓冲,最大USART2_MAX_SEND_LEN字节

//通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据.
//如果2个字符接收间隔超过10ms,则认为不是1次连续数据.也就是超过10ms没有接收到
//任何数据,则表示此次接收完毕.
//接收到的数据状态
//[15]:0,没有接收到数据;1,接收到了一批数据.
//[14:0]:接收到的数据长度
vu16 USART2_RX_STA=0;   	


void USART2_IRQHandler(void)
{
	u8 res;	      
	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//接收到数据
	{	 
		res =USART_ReceiveData(USART2);		 
		if((USART2_RX_STA&(1<<15))==0)//接收完的一批数据,还没有被处理,则不再接收其他数据
		{ 
			if(USART2_RX_STA<USART2_MAX_RECV_LEN)	//还可以接收数据
			{
				TIM_SetCounter(TIM3,0);//计数器清空          				//计数器清空
				if(USART2_RX_STA==0) 				//使能定时器2的中断 
				{
					TIM_Cmd(TIM3,ENABLE);//使能定时器2
				}
				USART2_RX_BUF[USART2_RX_STA++]=res;	//记录接收到的值	 
			}else 
			{
				USART2_RX_STA|=1<<15;				//强制标记接收完成
			} 
		}
	}  				 											 
}   


//初始化IO 串口2
//pclk1:PCLK1时钟频率(Mhz)
//bound:波特率	  
void usart2_init(void)
{  
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	// GPIOA时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //串口2时钟使能

 	USART_DeInit(USART2);  //复位串口2
		 //USART2_TX   PA2
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA2
   
    //USART2_RX	  PA3
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
  GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PA3
	
	USART_InitTypeDef USART_InitStructure;

	USART_InitStructure.USART_BaudRate = 9600;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  
	USART_Init(USART2, &USART_InitStructure); //初始化串口2
  

	USART_Cmd(USART2, ENABLE);                    //使能串口 
	
	//使能接收中断
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断   
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	//设置中断优先级
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	
	
	Timer_Init();		//10ms中断
	USART2_RX_STA=0;		//清零
	TIM_Cmd(TIM3,DISABLE);			//关闭定时器2

}

//串口2,printf 函数
//确保一次发送数据不超过USART2_MAX_SEND_LEN字节
void u2_printf(char* fmt,...)  
{  
	u16 i,j; 
	va_list ap; 
	va_start(ap,fmt);
	vsprintf((char*)USART2_TX_BUF,fmt,ap);
	va_end(ap);
	i=strlen((const char*)USART2_TX_BUF);		//此次发送数据的长度
	for(j=0;j<i;j++)							//循环发送数据
	{
	  while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕   
		USART_SendData(USART2,USART2_TX_BUF[j]); 
	} 
}

usart2.h

#ifndef __USART2_H
#define __USART2_H

#include "sys.h"  


#define USART2_MAX_RECV_LEN		400					//最大接收缓存字节数
#define USART2_MAX_SEND_LEN		400					//最大发送缓存字节数
#define USART2_RX_EN 			1					//0,不接收;1,接收.

extern u8  USART2_RX_BUF[USART2_MAX_RECV_LEN]; 		//接收缓冲,最大USART2_MAX_RECV_LEN字节
extern u8  USART2_TX_BUF[USART2_MAX_SEND_LEN]; 		//发送缓冲,最大USART2_MAX_SEND_LEN字节
extern vu16 USART2_RX_STA;   						//接收数据状态

void usart2_init(void);//串口2初始化 
void u2_printf(char* fmt,...);
#endif

定时器代码

Timer.c

#include "stm32f10x.h"                  // Device header
extern uint16_t USART2_RX_STA;

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	TIM_InternalClockConfig(TIM3);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM3, TIM_FLAG_Update);
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM3, ENABLE);
}


void TIM3_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
	{
		USART2_RX_STA|=1<<15;	//标记接收完成
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
		TIM_Cmd(TIM3, DISABLE);  //关闭TIM7
	}
}


Timer.h

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);

#endif

本文其他代码则使用的是江科大的代码

遇见的问题汇总

一 as608与单片机连接失败(即握手失败)

as608的波特率不是9600,可通过下面这个链接修改as608的波特率
http://t.csdnimg.cn/batia

二定时器选用问题

1.as608和舵机都需要使用定时器,不能重复,且要根据自己使用的单片机型号,选择舵机的引脚,对应的引脚定时器可以控制pwm输出信号。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值