粤嵌stm32f407zet6开发板:一个简单的智能门锁小项目测试

一、用draw.io画的主要流程图如下:(主要是这个软件它开源且免费,但是个人刚用起来不太习惯;在编程过程中发现此流程图还需要优化,但是也暂时懒得改了😄)

还能优化的地方:

1、帧率不高,刷新慢;

2、密码错误设置只是响几下,oled无错误提示;输错密码无法对当前密码位清零并重新输入;

3、oled显示屏利用效率不高,数字、字母贪方便都用了show_chinese函数,占用了空间;

4、进入管理员密码设置后并没有显示当前密码;

5、掉电后重新设置的密码丢失;

6、静音状态指示灯存在逻辑问题。

效果:

①上电初始化后进入主界面

②密码界面

1、密码正确

2、密码错误

3、按下s4返回主界面

③管理员界面

1、验证失败

2、验证成功进入

3、密码锁密码设置、验证

4、管理员密码设置、验证

④静音设置(这里我给的资源包有逻辑bug的,进入验证界面,验证完成后指示灯led1直接熄灭,其实可以用状态值就可以解决了,下面代码的work.c里的if(buzzer_state==1){LED1(on);}是已经修复了一点点)

1、主界面按下s4,进入静音后led1灯亮起,表示按下按键无声音

2、静音状态下,在主界面下再次按下s4,led1闪烁几次后恢复有声音

二、相关模块主要代码

1、main.c

#include "work.h"
int main(void)
{
	system_init();
	while(1)
	{
		work();
	}
}

2、work.c的oled显示函数部分

/*显示主界面*/
void Show_MainInterface(void)
{
	unsigned char x,y;
	for(y=10;y<17;y++)
	{
		x=(y-10)*16;
		OLED_ShowCHinese(x,0,y);
	}

	for(y=17;y<25;y++)
	{
		x=(y-17)*16;
		OLED_ShowCHinese(x,2,y);
	}
	OLED_ShowCHinese(0,4,25);
	
	for(y=26;y<34;y++)
	{
		x=(y-26)*16;
		OLED_ShowCHinese(x,6,y);
	}
}

/*显示请求输入密码*/
void Show_PasswordInterface(void)
{
	unsigned char x,y;
	for(y=35;y<40;y++)
	{
		x=(y-34)*16;
		OLED_ShowCHinese(x+16,0,y);
	}
}

/*显示验证成功*/
void Show_Success(void)
{
	unsigned char x,y;
	for(y=40;y<45;y++)
	{
		x=(y-40)*16;
		OLED_ShowCHinese(x+32,3,y);
	}
}

/*显示密码界面说明*/
void Show_PassKeyList(unsigned char h,unsigned char l)
{
	unsigned char x,y;
	switch(h)
	{
		case 0:
				for(y=45;y<53;y++)
				{
					x=(y-45)*16;
					OLED_ShowCHinese(x,l,y);
				}
		break;
		case 1:
				for(y=53;y<59;y++)
				{
					x=(y-53)*16;
					OLED_ShowCHinese(x,l,y);
				}
	
		break;
		case 2:
				for(y=59;y<65;y++)
				{
					x=(y-59)*16;
					OLED_ShowCHinese(x,l,y);
				}
		break;
		case 3:
				for(y=65;y<72;y++)
				{
					x=(y-65)*16;
					OLED_ShowCHinese(x,l,y);
				}
		break;
		case 4:
				for(y=72;y<80;y++)
				{
					x=(y-72)*16;
					OLED_ShowCHinese(x,l,y);
				}
				for(y=80;y<88;y++)
				{
					x=(y-80)*16;
					OLED_ShowCHinese(x,l+2,y);
				}
				OLED_ShowCHinese(0,l+4,y);
		break;
	}	
}

/*管理员设置显示*/
void Show_User(unsigned char c)
{
	unsigned char x,y;
	switch(c)
	{
		case 0:
			for(y=89;y<97;y++)
				{
					x=(y-89)*16;
					OLED_ShowCHinese(x,0,y);
				}
		break;
		case 1:
			for(y=97;y<105;y++)
				{
					x=(y-97)*16;
					OLED_ShowCHinese(x,0,y);
				}OLED_ShowCHinese(x+16,2,105);OLED_ShowCHinese(x+32,2,106);
		break;
		case 2:
			for(y=107;y<115;y++)
				{
					x=(y-107)*16;
					OLED_ShowCHinese(x,4,y);
				}OLED_ShowCHinese(x+16,6,115);OLED_ShowCHinese(x+32,6,116);
		break;
		case 3:
			for(y=117;y<125;y++)
				{
					x=(y-117)*16;
					OLED_ShowCHinese(x,6,y);
				}
		break;
	}
}

/*显示设置成功*/
void Show_SetY()
{
	unsigned char x,y;
	for(y=125;y<130;y++)
	{
		x=(y-125)*16;
		OLED_ShowCHinese(x+32,3,y);
	}
}

3、work.c的主体部分

#include "work.h"
void system_init(void)
{
	SysTick_Init(168);
	OLED_Init();						// oled模块引脚初始化
	OLED_Clear(); 					// oled模块清屏(清全屏)
	led_init();
	key_init();
	buzzer_Init();
}

unsigned char key;
unsigned char main_param,face_param,pointer;
unsigned char password[]={1,2,3,4},input[4],user[]={1,1,1,1};
/*密码输入显示*/
void Show_Input(unsigned char location)
{
	OLED_ShowCHinese(location*16+32,3,input[location]);
}

/*管理员密码验证*/
void user_verify()
{
	unsigned char x,y,state;
	pointer=0;
	while(state==0)
	{
		Show_Input(pointer);
		while(key==0)
		{x=check_key();if(x!=0){key=x;}}

		if(key==1)
		{input[pointer]++;if(input[pointer]==10){input[pointer]=0;}key=0;}//密码加
		if(key==2)
		{input[pointer]--;if(input[pointer]==255){input[pointer]=9;}key=0;}//密码减
		if(key==3)
		{
			key=0;
			pointer++;
		}
		if(key==4)
		{OLED_Clear();face_param=0;main_param=0;pointer=0;key=0;state=1;}
		
		/*密码验证部分*/
		if(pointer==4)//输入密码4个完成以后识别
		{
			pointer=0;y=0;
			for(x=0;x<4;x++)//识别
			{
				if(input[x]==user[x])
				{y++;}//识别完成暂存值清零
			}
			for(x=0;x<4;x++)
			{input[x]=0;}//识别完成暂存值清零
			
			if(y!=4){state=0;OLED_Clear();Show_PasswordInterface();red_warn();buzzer_wrong();}//密码验证失败,重新显示输入请求
			if(state==0){if(y==4){OLED_Clear();Show_Success();buzzer_right();run_horse();state=1;}}//密码验证成功			
		}
	}
}


/*密码设置*/
void set_code(unsigned char *mima)
{
	unsigned char x,state;
	pointer=0;
	Show_PasswordInterface();//显示输入请求
	while(state==0)
	{
		Show_Input(pointer);
		while(key==0)
		{x=check_key();if(x!=0){key=x;}}

		if(key==1)
		{input[pointer]++;if(input[pointer]==10){input[pointer]=0;}key=0;}//密码加
		if(key==2)
		{input[pointer]--;if(input[pointer]==255){input[pointer]=9;}key=0;}//密码减
		if(key==3)
		{
			key=0;
			pointer++;
		}
		if(key==4)
		{OLED_Clear();face_param=0;main_param=0;pointer=0;key=0;state=1;}
		
		/*密码输入部分*/
		if(pointer==4)//输入密码4个
		{
			pointer=0;
			for(x=0;x<4;x++)//录入
			{mima[x]=input[x];}
			for(x=0;x<4;x++)
			{input[x]=0;}//识别完成暂存值清零
			
			if(x==4){OLED_Clear();Show_SetY();run_horse();buzzer_right();state=1;}//密码设置成功			
		}
	}
}




/*工作函数*/
void work(void)
{
	unsigned char x,y;
	/*主界面*/
	if(main_param==0)//让主界面只刷新一次即可,不然一直刷新需要时间影响按键识别
	{
		Show_MainInterface();
		while(main_param==0)
		{
			switch(check_key())
			{
				case 1:face_param=1;main_param=1;OLED_Clear();break;
				case 2:face_param=2;main_param=1;OLED_Clear();break;
				case 3:face_param=3;main_param=1;OLED_Clear();break;
				
				/*第四部分:静音*/
				case 4:
							buzzer_state++;
                            if(buzzer_state==1){LED1(on);}
							if(buzzer_state==2){buzzer_state=0;led_tips();}
																											break;
			}
		}
	}
	
	/*第一部分:密码界面*/
	if(face_param==1 && main_param==1)
	{
		Show_PasswordInterface();//显示输入请求
		while(face_param==1 && main_param==1)
		{
			Show_Input(pointer);
			while(key==0)
			{x=check_key();if(x!=0){key=x;}}
			
			
			if(key==1)
			{input[pointer]++;if(input[pointer]==10){input[pointer]=0;}key=0;}//密码加
			if(key==2)
			{input[pointer]--;if(input[pointer]==255){input[pointer]=9;}key=0;}//密码减
			if(key==3)
			{
				key=0;
				pointer++;
			}
			
			if(key==4)
			{
			OLED_Clear();face_param=0;main_param=0;pointer=0;key=0;
			for(x=0;x<4;x++)
			{input[x]=0;}
			}
			
			
			/*密码验证部分*/
			if(pointer==4)//输入密码4个完成以后识别
			{
				pointer=0;y=0;
				for(x=0;x<4;x++)//识别
				{
					if(input[x]==password[x])
					{y++;}//识别完成暂存值清零
					input[x]=0;	
				}
				
				if(y!=4){red_warn();buzzer_wrong();}//密码验证失败
				if(y==4){OLED_Clear();Show_Success();run_horse();buzzer_right();}//密码验证成功
				OLED_Clear();Show_PasswordInterface();//重新显示输入请求
			}
		}
	}
	
	/*第二部分:密码界面说明*/
	if(face_param==2 && main_param==1)
	{
		for(x=0;x<4;x++)
		{Show_PassKeyList(x,2*x);}
		while(face_param==2 && main_param==1)
		{
			while(key==0)
			{x=check_key();if(x!=0){key=x;}}
			
            if(key==1){key=0;}
			if(key==2)
			{
				OLED_Clear();
				for(x=0;x<4;x++)
				{Show_PassKeyList(x,2*x);}
				key=0;
			}
			
			if(key==3)
			{OLED_Clear();Show_PassKeyList(4,0);key=0;}
			if(key==4)
			{OLED_Clear();face_param=0;main_param=0;key=0;}
		}
	}
	
	

	
	/*第三部分:管理员设置*/
	if(face_param==3 && main_param==1)
	{
		Show_User(0);user_verify();
		while(face_param==3 && main_param==1)
		{
			x=0;
			OLED_Clear();
			Show_User(1);Show_User(2);
			while(face_param==3 && main_param==1 && x==0)//设置x是为了密码设置完成后重新会到管理员设置界面
			{
				while(key==0)
				{x=check_key();if(x!=0){key=x;}}

				if(key==1)
				{key=0;OLED_Clear();set_code(user);x=1;}//管理员密码
				if(key==2)
				{key=0;OLED_Clear();set_code(password);x=1;}//密码锁密码
				if(key==3)
				{key=0;}
				
				if(key==4)
				{OLED_Clear();face_param=0;main_param=0;pointer=0;key=0;}
			}
		}
	}
	
}

4、key.c和key.h

#include "key.h"
#include "stm32f4xx.h"                  // Device header
#include "oled.h"
#include "delay.h"
#include "buzzer.h"

void key_init(void)
{
	// GPIO信息配置结构体
	GPIO_InitTypeDef  GPIO_InitStructure;

	// 1、GPIO硬件使能
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

	// 2、GPIO信息配置
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;							// 引脚:第1根引脚
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;						// 模式:输入模式						              
	GPIO_Init(GPIOA, &GPIO_InitStructure);				            	// 通过此函数,将配置的信息写入到相应的寄存器中                
                                         
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;	// 引脚:第1根引脚            
	GPIO_Init(GPIOE, &GPIO_InitStructure);				            	// 通过此函数,将配置的信息写入到相应的寄存器中    	                
}

unsigned char check_key(void)
{
	if(key0==0)
	{delay_ms(20);buzzer_di();while(key0==0);return 1;}
	              
	if(key1==0)   
	{delay_ms(20);buzzer_di();while(key1==0);return 2;}
	              
	if(key2==0)   
	{delay_ms(20);buzzer_di();while(key2==0);return 3;}
	              
	if(key3==0)   
	{delay_ms(20);buzzer_di();while(key3==0);return 4;}
	
	return 0;
}

unsigned char keynum;
void show_keynum(void)
{
	unsigned char s;
	s=check_key();
	if(s!=0)
	{keynum=s;}
	OLED_ShowCHinese(0,0,keynum);
}
#ifndef __key_h__
#define __key_h__

extern void key_init(void);
#define key0 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)
#define key1 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2)
#define key2 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)
#define key3 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)

unsigned char check_key(void);
void show_keynum(void);

#endif

5、led.c和led.h

#include "led.h"
#include "stm32f4xx.h"                  // Device header
void led_init()
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);


	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOF, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
	GPIO_Init(GPIOE, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOF,GPIO_Pin_9);
	GPIO_SetBits(GPIOF,GPIO_Pin_10);
	GPIO_SetBits(GPIOE,GPIO_Pin_13);
	GPIO_SetBits(GPIOE,GPIO_Pin_14);
}

void run_horse(void)
{
	LED1(on);
	delay_ms(30);	
	LED2(on);
	delay_ms(30);
	LED3(on);
	delay_ms(30);
	LED4(on);
	delay_ms(30);
	
	LED4(off);
	delay_ms(30);
	LED3(off);
	delay_ms(30);
	LED2(off);
	delay_ms(30);
	LED1(off);
}

void red_warn(void)
{
	unsigned char x;
	for(x=0;x<3;x++)
	{
		LED1(on);LED2(on);LED3(on);LED4(on);
		delay_ms(20);
		LED1(off);LED2(off);LED3(off);LED4(off);
		delay_ms(20);
	}
}

void led_tips(void)
{
	unsigned char x;
	for(x=0;x<2;x++)
	{
		LED1(on);
		delay_ms(50);
		LED1(off);
		delay_ms(50);
	}
	LED1(on);
	delay_ms(50);
	LED1(off);
}
#ifndef __led_h__
#define __led_h__

#include "delay.h"
void led_init(void);
#define on 1
#define off 0
#define LED1(X) X?GPIO_ResetBits(GPIOF, GPIO_Pin_9):GPIO_SetBits(GPIOF, GPIO_Pin_9)	// X为真执行第一个语句,否则执行第二个语句
#define LED2(X) X?GPIO_ResetBits(GPIOF, GPIO_Pin_10):GPIO_SetBits(GPIOF, GPIO_Pin_10)	
#define LED3(X) X?GPIO_ResetBits(GPIOE, GPIO_Pin_13):GPIO_SetBits(GPIOE, GPIO_Pin_13)	
#define LED4(X) X?GPIO_ResetBits(GPIOE, GPIO_Pin_14):GPIO_SetBits(GPIOE, GPIO_Pin_14)	

void run_horse(void);
void red_warn(void);
void led_tips(void);
#endif

6、buzzer.c

#include "buzzer.h"
#include "stm32f4xx.h"                  // Device header
#include "delay.h"
void buzzer_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_8;						//引脚:Px?第9根引脚,对应LED0
	GPIO_InitStructure.GPIO_Mode	= GPIO_Mode_OUT;				//引脚模式:输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;				//输出模式:推挽
	GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;			//输出速度:高速
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL;			//上下拉:不拉
	GPIO_Init(GPIOF, &GPIO_InitStructure);								//通过此函数,将配置信息写入相应的PF引脚寄存器中【proteus仿真:F改D】
}

void buzzer_voice(unsigned int voice)
{
	buzzer(1);delay_ms(voice);buzzer(0);
}


unsigned char buzzer_state;

/*蜂鸣器响一下*/
void buzzer_di(void)
{
	if(buzzer_state==0)
	{
		buzzer_voice(15);
	}
}

/*蜂鸣器响一小段时间*/
void buzzer_right(void)
{
	if(buzzer_state==0)
	{
		buzzer_voice(120);
	}
}

/*蜂鸣器快速响几下*/
void buzzer_wrong(void)
{
	unsigned char i;
	if(buzzer_state==0)
	{
		for(i=0;i<5;i++)
		{buzzer_voice(15);delay_ms(15);}
	}
}

三、途中的问题

测试以下代码(密码输入界面)时显示不正常,不按多几下压根没反应,要按n多下才正确显示:

猜测:按键函数里有延时的东西,并且按键识别跟用老师给的oled显示函数在同一级别下,影响按键识别判断。

当时的按键代码:

可以看到是按键函数里的蜂鸣器里有延时函数。删了蜂鸣器测试之后发现还是老问题,基本可以忽略蜂鸣器延时对按键识别影响。给这显示函数上个状态值才好一点点(但是不灵敏,只识别++或者其它其中一个【其它全部屏蔽】这样才非常灵敏),开始我感觉是显示函数里面的问题。

但是后面测试发现是测试函数中多个if(check_key)按键识别判断的问题,换成以下:

主要是改了判别方式,直接是用了暂存值,保留识别的值,再对识别的值进行处理。if里面的判断还是尽量快一点的好。看来不是oled显示的问题,是我c语言不好的问题(悲)。这里就可以了,挺灵敏了,不会要按几下才有反应。

  • 31
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
STM32F407ZET6单片机开发板是基于STM32F407芯片的一款开发板,Altium Designer是一种专业的PCB设计软件,可用于设计硬件原理图和PCB图。 在设计硬件原理图时,需要根据STM32F407ZET6的引脚布局和功能,将各个组件按照电路连接图的要求进行连接。首先,根据开发板的功能需求,确定所需的外部器件,如电源模块、晶振、电容器、电阻等。然后,按照芯片的引脚定义,将这些器件与芯片进行连接,例如将晶振连接到芯片的晶振输入引脚上。 在Altium Designer中,可以利用组件库中已有的元件进行快速搭建原理图。选择对应的器件,将其拖拽到原理图中,并根据芯片的引脚定义进行连接。可以通过连线、引脚和连接器等工具来完成电路的连接。 在设计PCB图时,需要将原理图转换成实际的电路板布局。可以通过Altium Designer中的布局编辑器进行布局和布线,将原理图中的元件放置到合适的位置上,并根据电路连接需求进行布线。同时,还需要考虑电源线、地线和信号线的布置,以及元件的尺寸和间距等要求。 完成PCB布局后,还需要进行电路板的优化和检查。通过规则检查功能,检查电路板中可能存在的问题,如规则冲突、元件间距不足等。根据需要,还可以增加丝印、焊盘、贴片等特性,以便后续的焊接和组装工作。 总之,使用Altium Designer软件可以方便地进行STM32F407ZET6单片机开发板的硬件原理图和PCB图设计,通过合理的布局和布线,保证电路的可靠性和稳定性,帮助开发板的制作和使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值