项目需求
- 矩阵键盘输入密码,正确开锁,错误提示,三次错误后蜂鸣器响三秒;
- 按下#号确认输入,按下*号修改密码;
- 密码保存在W25Q128里;
- OLED屏幕显示信息。
硬件清单
矩阵键盘 | OLED显示屏 | 继电器 | 蜂鸣器 | W25Q128存储器 |
开发板 | ST-Link | USB转TTL | 杜邦线 | ------ |
其中,OLED显示器利用的是I2C的通信协议,W25Q128用的是SPI的通信协议 ;
矩阵键盘这节课进行介绍。
硬件接线
简图:
模块:矩阵键盘(原理+驱动)
学了了独立按键之后,发现使用一个按键就要浪费一个IO口。那有没有一种节约GPIO的方法,比如要用16个按键,怎么样才能节省IO口?那我们就可以用矩阵键盘。16个按键,只需8个IO口。
矩阵键盘介绍
我们矩阵键盘的型号多种多样,有 1x4、3x3、3x4、4x4,甚至是 8x8 的;有薄膜的,有按键的。
矩阵键盘常见用途:
1. 电子密码锁
2. ATM 的键盘
3. POS机 的键盘
4. 家用电器的控制面板(微波炉、洗衣机等)
工作参数及引脚介绍
引脚介绍:
- 按键式的有的有引脚标识,R 是行,C 是列。有的没有引脚标识,可以找商家问下,或者自己看原理图。
- 薄膜式的都没有引脚标识。键盘正对自己,引脚是先行后列,从小到大。
矩阵键盘工作原理
这是矩阵键盘(4x4)内部电路示意图:
矩阵键盘识别常用——逐行逐列扫描法
- 使列线连接的I/O引脚输出低电平,四条行线所连接的I/O引脚输出高电平,当没有按键按下时,四条行线所连接的I/O引脚读取的将全部是高电平;当按键按下时,由于按键所在的行线与列线相通,行线将被下拉到低电阻。此时读取行线所连接的引脚,将不再是高电平。
- 逐列将列线依次置低电平,读取行线,如果某一条行线为低电平,则说明该行线与当前的行线为低电平的列线交叉点处的按键被按下,从判断按键按下。
中断来实现识别
- 把所有行引脚设成中断引脚,默认是上拉输入,下降沿触发,GPIO引脚输出高电平。
- 把所有列引脚连接的GPIO引脚设成输入,内部下拉。(GPIO引脚输入,默认是下拉)
-
当有中断触发的时候就可以知道哪一行有按键按下,再逐列看哪一列变成高电平,就是哪个按键被触发了。
小实验:串口输出矩阵键盘按下的按键
硬件清单:
STM32F103C8T6、矩阵键盘(3x4,薄膜)、USB转TTL、ST-Link
硬件接线:
文件代码:
- keyboard.c
#include "keyboard.h"
#include "delay.h"
uint8_t key_value;
void keyboard_init(void){
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE();
//调用GPIO的初始化函数
GPIO_InitTypeDef GPIO_Initstruct;
GPIO_Initstruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10;
GPIO_Initstruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_Initstruct.Pull = GPIO_PULLUP;
GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_Initstruct);
GPIO_Initstruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14;
GPIO_Initstruct.Mode = GPIO_MODE_INPUT;
GPIO_Initstruct.Pull = GPIO_PULLDOWN; //配置成下拉模式,当导通时,会变成高电平
GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_Initstruct);
HAL_NVIC_SetPriority(EXTI0_IRQn,2,2);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
HAL_NVIC_SetPriority(EXTI1_IRQn,2,2);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);
HAL_NVIC_SetPriority(EXTI2_IRQn,2,2);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);
HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,2);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
void EXTI0_IRQHandler(void){
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
void EXTI1_IRQHandler(void){
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
}
void EXTI2_IRQHandler(void){
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
}
void EXTI15_10_IRQHandler(void){
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
uint8_t row = 0,column = 0;
if(key_value != 0) return; //防止手速过快,只读取第一次按下时的按键值
//确定行
if(GPIO_Pin == GPIO_PIN_0)
row = 0x10;
else if(GPIO_Pin == GPIO_PIN_1)
row = 0x20;
else if(GPIO_Pin == GPIO_PIN_2)
row = 0x30;
else if(GPIO_Pin == GPIO_PIN_10)
row = 0x40;
//确定列
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11) == GPIO_PIN_SET){
delay_ms(10);
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11) == GPIO_PIN_SET);
column = 0x01;
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12) == GPIO_PIN_SET){
delay_ms(10);
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12) == GPIO_PIN_SET);
column = 0x02;
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == GPIO_PIN_SET){
delay_ms(10);
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == GPIO_PIN_SET);
column = 0x03;
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14) == GPIO_PIN_SET){
delay_ms(10);
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14) == GPIO_PIN_SET);
column = 0x04;
}
if(row != 0 && column != 0)
key_value = row | column; //按位与进行拼接
}
uint8_t keyboard_get_value(void){
uint8_t ch = 0;
if(key_value != 0)
{
if(key_value == 0x11) ch = '1';
else if(key_value == 0x12) ch = '2';
else if(key_value == 0x13) ch = '3';
else if(key_value == 0x14) ch = 'A';
else if(key_value == 0x21) ch = '4';
else if(key_value == 0x22) ch = '5';
else if(key_value == 0x23) ch = '6';
else if(key_value == 0x24) ch = 'B';
else if(key_value == 0x31) ch = '7';
else if(key_value == 0x32) ch = '8';
else if(key_value == 0x33) ch = '9';
else if(key_value == 0x34) ch = 'C';
else if(key_value == 0x41) ch = '*';
else if(key_value == 0x42) ch = '0';
else if(key_value == 0x43) ch = '#';
else if(key_value == 0x44) ch = 'D';
delay_ms(400);
key_value = 0x00;
}
return ch;
}
- keyboard.h
#ifndef __KEYBOARD_H__
#define __KEYBOARD_H__
#include "stm32f1xx.h"
void keyboard_init(void);
uint8_t keyboard_get_value(void);
#endif
- main.c文件代码
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "uart1.h"
#include "keyboard.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* LED初始化 */
uart1_init(115200);
printf("hello,world");
keyboard_init();
uint8_t key_value = 0;
while(1)
{
key_value = keyboard_get_value();
if(key_value != 0){
printf("按下了:%c \r\n",key_value);
key_value = 0;
}
}
}
注意:这个代码采用的是配置中断来实现,要回顾关于中断的配置流程。
项目框图
(要养成习惯,在做项目的时候一定要配置流程图)
项目代码
输出设备
OLED
oled.c文件代码:
#include "oled.h"
#include "delay.h"
#include "font.h"
void oled_gpio_init(void){
GPIO_InitTypeDef gpio_initstruct;
OLED_I2C_SCL_CLK();
OLED_I2C_SDA_CLK();
gpio_initstruct.Pin = OLED_I2C_SCL_PIN;
gpio_initstruct.Mode = GPIO_MODE_OUTPUT_OD;
gpio_initstruct.Pull = GPIO_PULLUP;
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(OLED_I2C_SCL_PORT,&gpio_initstruct);
gpio_initstruct.Pin = OLED_I2C_SDA_PIN;
HAL_GPIO_Init(OLED_I2C_SDA_PORT,&gpio_initstruct);
}
/**
* @breif 配置I2C协议的时序图:开始,读写,应答,结束。
* @note 在配置读写时序的时候,要注意。。。。。
*
*/
void oled_i2c_start(void){
OLED_SCL_SET();
OLED_SDA_SET();
OLED_SDA_RESET();
OLED_SCL_RESET();
}
void oled_i2c_stop(void){
OLED_SCL_RESET();
OLED_SDA_RESET();
OLED_SCL_SET();
OLED_SDA_SET();
}
void oled_i2c_ack(void){
OLED_SCL_SET();
OLED_SCL_RESET();
}
void oled_i2c_write_byte(uint8_t data){
uint8_t i,temp;
temp = data;
for(i = 0;i < 8 ;i++){
if((temp & 0x80) == 0x80)
OLED_SDA_SET();
else
OLED_SDA_RESET();
temp = temp << 1;
OLED_SCL_SET();
OLED_SCL_RESET();
}
}
/**
* @breif 利用I2C的时序图,配置OLED相关的写命令和写指令的函数
* @note
*
*/
void oled_write_cmd(uint8_t cmd){
oled_i2c_start();
oled_i2c_write_byte(0x78);
oled_i2c_ack();
oled_i2c_write_byte(0x00);
oled_i2c_ack();
oled_i2c_write_byte(cmd);
oled_i2c_ack();
oled_i2c_stop();
}
void oled_write_date(uint8_t data){
oled_i2c_start();
oled_i2c_write_byte(0x78);
oled_i2c_ack();
oled_i2c_write_byte(0x40);
oled_i2c_ack();
oled_i2c_write_byte(data);
oled_i2c_ack();
oled_i2c_stop();
}
/**
* @breif 初始化OLED显示屏的函数
* @note 包括初始化GPIO引脚和初始化OLED的1相关命令
*
*/
void oled_init(void){
oled_gpio_init();
//初始化后要发送一系列的命令要进行发送。
delay_ms(100);
oled_write_cmd(0xAE); //设置显示开启/关闭,0xAE关闭,0xAF开启
oled_write_cmd(0xD5); //设置显示时钟分频比/振荡器频率
oled_write_cmd(0x80); //0x00~0xFF
oled_write_cmd(0xA8); //设置多路复用率
oled_write_cmd(0x3F); //0x0E~0x3F
oled_write_cmd(0xD3); //设置显示偏移
oled_write_cmd(0x00); //0x00~0x7F
oled_write_cmd(0x40); //设置显示开始行,0x40~0x7F
oled_write_cmd(0xA1); //设置左右方向,0xA1正常,0xA0左右反置
oled_write_cmd(0xC8); //设置上下方向,0xC8正常,0xC0上下反置
oled_write_cmd(0xDA); //设置COM引脚硬件配置
oled_write_cmd(0x12);
oled_write_cmd(0x81); //设置对比度
oled_write_cmd(0xCF); //0x00~0xFF
oled_write_cmd(0xD9); //设置预充电周期
oled_write_cmd(0xF1);
oled_write_cmd(0xDB); //设置VCOMH取消选择级别
oled_write_cmd(0x30);
oled_write_cmd(0xA4); //设置整个显示打开/关闭
oled_write_cmd(0xA6); //设置正常/反色显示,0xA6正常,0xA7反色
oled_write_cmd(0x8D); //设置充电泵
oled_write_cmd(0x14);
oled_write_cmd(0xAF); //开启显示
oled_fill(0x00);
}
/**
* @breif 设置oled显示屏显示的坐标
* @note
*/
void oled_set_cursor(uint8_t x,uint8_t y){
oled_write_cmd(0xB0 + x);
oled_write_cmd((y & 0x0F) | 0x00); //取x的低位
oled_write_cmd(((y & 0xF0) >> 4) | 0x10); //取高位
}
/**
* @breif 设置oled显示屏清屏函数
* @note
*/
void oled_fill(uint8_t data){
uint8_t i,j;
for (i = 0;i < 8 ;i++){
oled_set_cursor(i,0);
for(j = 0;j < 128;j++)
oled_write_date(data);
}
}
/**
* @breif 封装oled显示屏显示字符、字符串、汉字、图像的函数
* @note
*/
void oled_show_char(uint8_t x ,uint8_t y,uint8_t number ,uint8_t size){ //size代表的是高度
number = number - ' ';
uint8_t i,j,page; //page:表示输入的字符总共需要的PAGE
page = size / 8;
if(size % 8 != 0)
page ++;
for (i = 0;i < page; i++)
{
oled_set_cursor(x+i,y);
for (j = size / 2 * i;j < size / 2 * (i + 1); j++){ //size/2:高度的一半是宽度
if(size == 16)
oled_write_date(ascii_8X16[number][j]);
}
}
}
//显示字符串
void oled_show_string(uint8_t x,uint8_t y,char *p ,uint8_t size){
while(*p != '\0'){
oled_show_char(x,y,*p,size); //*p:取出数组中的首元素
y += size / 2;
p++; //p++:代表的是数组指针递增,指向下一个元素地址。
}
}
//void oled_show_chinese(uint8_t x,uint8_t y, uint8_t N ,uint8_t size){
// uint8_t i,j;
// for (i = 0 ; i < size / 8 ;i++){
// oled_set_cursor(x+i,y);
// for(j = size * i;j < size * (i + 1);j++){
// if(size == 16)
// oled_write_date(chinese_16X16[N][j]);
if(size == 24)
oled_write_date(chinese_24X24[N][j]);
// }
// }
//}
//显示汉字的函数
void oled_show_chinese(uint8_t x,uint8_t y, uint8_t N ,uint8_t message_type){
uint8_t i,j;
for (i = 0 ; i < 2 ;i++){
oled_set_cursor(x+i,y);
for(j = 16 * i;j < 16 * (i + 1);j++){
switch (message_type){
case SHOW_INPUT_PWD:
oled_write_date(chinese_enter_password[N][j]);
break;
case SHOW_PWD_RIGHT:
oled_write_date(chinese_password_right[N][j]);
break;
case SHOW_PWD_ERROR:
oled_write_date(chinese_password_error[N][j]);
break;
case SHOW_INPUT_OLD_PWD:
oled_write_date(chinese_enter_oldPassword[N][j]);
break;
case SHOW_INPUT_NEW_PWD:
oled_write_date(chinese_enter_newPassword[N][j]);
break;
case SHOW_PWD_CHANGE:
oled_write_date(modify_passWord_complete[N][j]);
break;
case SHOW_SET_PWD:
oled_write_date(set_passWord[N][j]);
break;
default:
break;
}
}
}
}
//请输入密码
void oled_show_input(void){
oled_fill(0x00);
oled_show_chinese(1,10,0,SHOW_INPUT_PWD);
oled_show_chinese(1,30,1,SHOW_INPUT_PWD);
oled_show_chinese(1,50,2,SHOW_INPUT_PWD);
oled_show_chinese(1,70,3,SHOW_INPUT_PWD);
oled_show_chinese(1,90,4,SHOW_INPUT_PWD);
oled_show_char(1,110,':',16);
}
//密码正确
void oled_pwd_right(void){
oled_fill(0x00);
oled_show_chinese(1,10,0,SHOW_PWD_RIGHT);
oled_show_chinese(1,30,1,SHOW_PWD_RIGHT);
oled_show_chinese(1,50,2,SHOW_PWD_RIGHT);
oled_show_chinese(1,70,3,SHOW_PWD_RIGHT);
oled_show_char(1,90,':',16);
}
//密码错误
void oled_pwd_error(void){
oled_fill(0x00);
oled_show_chinese(1,10,0,SHOW_PWD_ERROR);
oled_show_chinese(1,30,1,SHOW_PWD_ERROR);
oled_show_chinese(1,50,2,SHOW_PWD_ERROR);
oled_show_chinese(1,70,3,SHOW_PWD_ERROR);
oled_show_char(1,110,':',16);
}
//请输入旧密码
void oled_input_old_pwd(void){
oled_fill(0x00);
oled_show_chinese(1,10,0,SHOW_INPUT_OLD_PWD);
oled_show_chinese(1,26,1,SHOW_INPUT_OLD_PWD);
oled_show_chinese(1,42,2,SHOW_INPUT_OLD_PWD);
oled_show_chinese(1,58,3,SHOW_INPUT_OLD_PWD);
oled_show_chinese(1,74,4,SHOW_INPUT_OLD_PWD);
oled_show_chinese(1,90,5,SHOW_INPUT_OLD_PWD);
oled_show_char(1,106,':',16);
}
//请输入新密码
void oled_input_new_pwd(void){
oled_fill(0x00);
oled_show_chinese(1,10,0,SHOW_INPUT_NEW_PWD);
oled_show_chinese(1,26,1,SHOW_INPUT_NEW_PWD);
oled_show_chinese(1,42,2,SHOW_INPUT_NEW_PWD);
oled_show_chinese(1,58,3,SHOW_INPUT_NEW_PWD);
oled_show_chinese(1,74,4,SHOW_INPUT_NEW_PWD);
oled_show_chinese(1,90,4,SHOW_INPUT_NEW_PWD);
oled_show_char(1,106,':',16);
}
//密码修改完成
void oled_modif_pwd_complete(void){
oled_fill(0x00);
oled_show_chinese(1,10,0,SHOW_PWD_CHANGE);
oled_show_chinese(1,26,1,SHOW_PWD_CHANGE);
oled_show_chinese(1,42,2,SHOW_PWD_CHANGE);
oled_show_chinese(1,58,3,SHOW_PWD_CHANGE);
oled_show_chinese(1,74,4,SHOW_PWD_CHANGE);
oled_show_chinese(1,90,5,SHOW_PWD_CHANGE);
oled_show_char(1,106,':',16);
}
//请设置密码
void oled_set_pwd(void){
oled_fill(0x00);
oled_show_chinese(1,10,0,SHOW_SET_PWD);
oled_show_chinese(1,30,1,SHOW_SET_PWD);
oled_show_chinese(1,50,2,SHOW_SET_PWD);
oled_show_chinese(1,70,3,SHOW_SET_PWD);
oled_show_chinese(1,90,4,SHOW_SET_PWD);
oled_show_char(1,110,':',16);
}
//显示图像
void oled_show_image(uint8_t x,uint8_t y, uint8_t width ,uint8_t highth ,uint8_t * bpm){
uint8_t i,j;
for(i = 0; i < highth ;i++)
{
oled_set_cursor(x+i,j);
for(j = 0;j < width;j++)
oled_write_date(bpm[ width * i + j ]);
}
}
oled.h文件代码:
#ifndef __OLED_H__
#define __OLED_H__
#include "stm32f1xx.h"
enum message{
SHOW_INPUT_PWD = 0,
SHOW_PWD_RIGHT,
SHOW_PWD_ERROR,
SHOW_INPUT_OLD_PWD,
SHOW_INPUT_NEW_PWD,
SHOW_PWD_CHANGE,
SHOW_SET_PWD
};
#define OLED_I2C_SCL_CLK() __HAL_RCC_GPIOB_CLK_ENABLE()
#define OLED_I2C_SCL_PORT GPIOB
#define OLED_I2C_SCL_PIN GPIO_PIN_8
#define OLED_I2C_SDA_CLK() __HAL_RCC_GPIOB_CLK_ENABLE()
#define OLED_I2C_SDA_PORT GPIOB
#define OLED_I2C_SDA_PIN GPIO_PIN_9
#define OLED_SCL_RESET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SCL_PIN,GPIO_PIN_RESET)
#define OLED_SCL_SET() HAL_GPIO_WritePin(OLED_I2C_SCL_PORT,OLED_I2C_SCL_PIN,GPIO_PIN_SET)
#define OLED_SDA_RESET() HAL_GPIO_WritePin(OLED_I2C_SDA_PORT,OLED_I2C_SDA_PIN,GPIO_PIN_RESET)
#define OLED_SDA_SET() HAL_GPIO_WritePin(OLED_I2C_SDA_PORT,OLED_I2C_SDA_PIN,GPIO_PIN_SET)
void oled_init(void);
void oled_set_cursor(uint8_t x,uint8_t y);
void oled_fill(uint8_t data);
void oled_write_date(uint8_t data);
void oled_show_char(uint8_t x ,uint8_t y,uint8_t number ,uint8_t size);
void oled_show_string(uint8_t x,uint8_t y,char *p ,uint8_t size);
void oled_show_chinese(uint8_t x, uint8_t y, uint8_t N, uint8_t size);
void oled_show_image(uint8_t x,uint8_t y, uint8_t width ,uint8_t highth,uint8_t * bpm);
void oled_show_input(void);
void oled_pwd_right(void);
void oled_pwd_error(void);
void oled_input_old_pwd(void);
void oled_input_new_pwd(void);
void oled_modif_pwd_complete(void);
void oled_set_pwd(void);
#endif
font.h文件代码
#ifndef __FONT_H__
#define __FONT_H__
//请输入密码;
const unsigned char chinese_enter_password[][32] = {
0x40,0x42,0xCC,0x00,0x00,0x44,0x54,0x54,0x54,0x7F,0x54,0x54,0x54,0x44,0x40,0x00,
0x00,0x00,0x7F,0x20,0x10,0x00,0xFF,0x15,0x15,0x15,0x55,0x95,0x7F,0x00,0x00,0x00,/*"请",0*/
0x88,0x68,0x1F,0xC8,0x08,0x10,0xC8,0x54,0x52,0xD1,0x12,0x94,0x08,0xD0,0x10,0x00,
0x09,0x19,0x09,0xFF,0x05,0x00,0xFF,0x12,0x92,0xFF,0x00,0x5F,0x80,0x7F,0x00,0x00,/*"输",1*/
0x00,0x00,0x00,0x00,0x00,0x01,0xE2,0x1C,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x03,0x0C,0x30,0x40,0x80,0x80,0x00,/*"入",2*/
0x10,0x8C,0x44,0x04,0xE4,0x04,0x95,0xA6,0x44,0x24,0x14,0x84,0x44,0x94,0x0C,0x00,
0x02,0x02,0x7A,0x41,0x41,0x43,0x42,0x7E,0x42,0x42,0x42,0x43,0xF8,0x00,0x00,0x00,/*"密",3*/
0x04,0x84,0xE4,0x5C,0x44,0xC4,0x00,0x02,0xF2,0x82,0x82,0x82,0xFE,0x80,0x80,0x00,
0x02,0x01,0x7F,0x10,0x10,0x3F,0x00,0x08,0x08,0x08,0x08,0x48,0x88,0x40,0x3F,0x00,/*"码",4*/
};
//密码正确;
const unsigned char chinese_password_right[][32] = {
0x10,0x8C,0x44,0x04,0xE4,0x04,0x95,0xA6,0x44,0x24,0x14,0x84,0x44,0x94,0x0C,0x00,
0x02,0x02,0x7A,0x41,0x41,0x43,0x42,0x7E,0x42,0x42,0x42,0x43,0xF8,0x00,0x00,0x00,/*"密",0*/
0x04,0x84,0xE4,0x5C,0x44,0xC4,0x00,0x02,0xF2,0x82,0x82,0x82,0xFE,0x80,0x80,0x00,
0x02,0x01,0x7F,0x10,0x10,0x3F,0x00,0x08,0x08,0x08,0x08,0x48,0x88,0x40,0x3F,0x00,/*"码",1*/
0x00,0x02,0x02,0xC2,0x02,0x02,0x02,0xFE,0x82,0x82,0x82,0x82,0x82,0x02,0x00,0x00,
0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,/*"正",2*/
0x04,0x84,0xE4,0x5C,0x44,0xC4,0x20,0x10,0xE8,0x27,0x24,0xE4,0x34,0x2C,0xE0,0x00,
0x02,0x01,0x7F,0x10,0x10,0x3F,0x80,0x60,0x1F,0x09,0x09,0x3F,0x49,0x89,0x7F,0x00,/*"确",3*/
};
//密码错误;
const unsigned char chinese_password_error[][32] = {
0x10,0x8C,0x44,0x04,0xE4,0x04,0x95,0xA6,0x44,0x24,0x14,0x84,0x44,0x94,0x0C,0x00,
0x02,0x02,0x7A,0x41,0x41,0x43,0x42,0x7E,0x42,0x42,0x42,0x43,0xF8,0x00,0x00,0x00,/*"密",0*/
0x04,0x84,0xE4,0x5C,0x44,0xC4,0x00,0x02,0xF2,0x82,0x82,0x82,0xFE,0x80,0x80,0x00,
0x02,0x01,0x7F,0x10,0x10,0x3F,0x00,0x08,0x08,0x08,0x08,0x48,0x88,0x40,0x3F,0x00,/*"码",1*/
0x40,0x30,0xEF,0x24,0x64,0x48,0x48,0x7F,0x48,0x48,0x48,0x7F,0x48,0x48,0x40,0x00,
0x01,0x01,0x7F,0x21,0x11,0x00,0xFF,0x49,0x49,0x49,0x49,0x49,0xFF,0x00,0x00,0x00,/*"错",2*/
0x40,0x42,0xCC,0x00,0x00,0x80,0x9E,0x92,0x92,0x92,0x92,0x92,0x9E,0x80,0x00,0x00,
0x00,0x00,0x7F,0x20,0x94,0x84,0x44,0x24,0x14,0x0F,0x14,0x24,0x44,0x84,0x84,0x00,/*"误",3*/
};
//请输入旧密码;
const unsigned char chinese_enter_oldPassword[][32] = {
0x40,0x42,0xCC,0x00,0x00,0x44,0x54,0x54,0x54,0x7F,0x54,0x54,0x54,0x44,0x40,0x00,
0x00,0x00,0x7F,0x20,0x10,0x00,0xFF,0x15,0x15,0x15,0x55,0x95,0x7F,0x00,0x00,0x00,/*"请",0*/
0x88,0x68,0x1F,0xC8,0x08,0x10,0xC8,0x54,0x52,0xD1,0x12,0x94,0x08,0xD0,0x10,0x00,
0x09,0x19,0x09,0xFF,0x05,0x00,0xFF,0x12,0x92,0xFF,0x00,0x5F,0x80,0x7F,0x00,0x00,/*"输",1*/
0x00,0x00,0x00,0x00,0x00,0x01,0xE2,0x1C,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x03,0x0C,0x30,0x40,0x80,0x80,0x00,/*"入",2*/
0x00,0x00,0xFF,0x00,0x00,0x00,0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0xFE,0x00,0x00,
0x00,0x00,0xFF,0x00,0x00,0x00,0x7F,0x20,0x20,0x20,0x20,0x20,0x20,0x7F,0x00,0x00,/*"旧",3*/
0x10,0x8C,0x44,0x04,0xE4,0x04,0x95,0xA6,0x44,0x24,0x14,0x84,0x44,0x94,0x0C,0x00,
0x02,0x02,0x7A,0x41,0x41,0x43,0x42,0x7E,0x42,0x42,0x42,0x43,0xF8,0x00,0x00,0x00,/*"密",4*/
0x04,0x84,0xE4,0x5C,0x44,0xC4,0x00,0x02,0xF2,0x82,0x82,0x82,0xFE,0x80,0x80,0x00,
0x02,0x01,0x7F,0x10,0x10,0x3F,0x00,0x08,0x08,0x08,0x08,0x48,0x88,0x40,0x3F,0x00,/*"码",5*/
};
//请输入新密码
const unsigned char chinese_enter_newPassword[][32] = {
0x40,0x42,0xCC,0x00,0x00,0x44,0x54,0x54,0x54,0x7F,0x54,0x54,0x54,0x44,0x40,0x00,
0x00,0x00,0x7F,0x20,0x10,0x00,0xFF,0x15,0x15,0x15,0x55,0x95,0x7F,0x00,0x00,0x00,/*"请",0*/
0x88,0x68,0x1F,0xC8,0x08,0x10,0xC8,0x54,0x52,0xD1,0x12,0x94,0x08,0xD0,0x10,0x00,
0x09,0x19,0x09,0xFF,0x05,0x00,0xFF,0x12,0x92,0xFF,0x00,0x5F,0x80,0x7F,0x00,0x00,/*"输",1*/
0x00,0x00,0x00,0x00,0x00,0x01,0xE2,0x1C,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x03,0x0C,0x30,0x40,0x80,0x80,0x00,/*"入",2*/
0x40,0x44,0x54,0x65,0xC6,0x64,0x54,0x44,0x00,0xFC,0x44,0x44,0xC4,0x42,0x40,0x00,
0x20,0x12,0x4A,0x82,0x7F,0x02,0x0A,0x92,0x60,0x1F,0x00,0x00,0xFF,0x00,0x00,0x00,/*"新",3*/
0x10,0x8C,0x44,0x04,0xE4,0x04,0x95,0xA6,0x44,0x24,0x14,0x84,0x44,0x94,0x0C,0x00,
0x02,0x02,0x7A,0x41,0x41,0x43,0x42,0x7E,0x42,0x42,0x42,0x43,0xF8,0x00,0x00,0x00,/*"密",4*/
0x04,0x84,0xE4,0x5C,0x44,0xC4,0x00,0x02,0xF2,0x82,0x82,0x82,0xFE,0x80,0x80,0x00,
0x02,0x01,0x7F,0x10,0x10,0x3F,0x00,0x08,0x08,0x08,0x08,0x48,0x88,0x40,0x3F,0x00,/*"码",5*/
};
//密码修改成功
const unsigned char modify_passWord_complete[][32] = {
0x10,0x8C,0x44,0x04,0xE4,0x04,0x95,0xA6,0x44,0x24,0x14,0x84,0x44,0x94,0x0C,0x00,
0x02,0x02,0x7A,0x41,0x41,0x43,0x42,0x7E,0x42,0x42,0x42,0x43,0xF8,0x00,0x00,0x00,/*"密",0*/
0x04,0x84,0xE4,0x5C,0x44,0xC4,0x00,0x02,0xF2,0x82,0x82,0x82,0xFE,0x80,0x80,0x00,
0x02,0x01,0x7F,0x10,0x10,0x3F,0x00,0x08,0x08,0x08,0x08,0x48,0x88,0x40,0x3F,0x00,/*"码",1*/
0x40,0x20,0xF8,0x07,0xF0,0xA0,0x90,0x4C,0x57,0x24,0xA4,0x54,0x4C,0x80,0x80,0x00,
0x00,0x00,0xFF,0x00,0x1F,0x80,0x92,0x52,0x49,0x29,0x24,0x12,0x08,0x00,0x00,0x00,/*"修",2*/
0x04,0x84,0x84,0x84,0x84,0xFC,0x40,0x30,0xCC,0x0B,0x08,0x08,0xF8,0x08,0x08,0x00,
0x00,0x7F,0x20,0x10,0x10,0x08,0x80,0x40,0x21,0x16,0x08,0x16,0x21,0x40,0x80,0x00,/*"改",3*/
0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0xFF,0x08,0x09,0x0A,0xC8,0x08,0x00,
0x80,0x60,0x1F,0x00,0x10,0x20,0x1F,0x80,0x40,0x21,0x16,0x18,0x26,0x41,0xF8,0x00,/*"成",4*/
0x08,0x08,0x08,0xF8,0x08,0x08,0x08,0x10,0x10,0xFF,0x10,0x10,0x10,0xF0,0x00,0x00,
0x10,0x30,0x10,0x1F,0x08,0x88,0x48,0x30,0x0E,0x01,0x40,0x80,0x40,0x3F,0x00,0x00,/*"功",5*/
};
//请设定密码
const unsigned char set_passWord[][32] = {
0x40,0x42,0xCC,0x00,0x00,0x44,0x54,0x54,0x54,0x7F,0x54,0x54,0x54,0x44,0x40,0x00,
0x00,0x00,0x7F,0x20,0x10,0x00,0xFF,0x15,0x15,0x15,0x55,0x95,0x7F,0x00,0x00,0x00,/*"请",0*/
0x40,0x40,0x42,0xCC,0x00,0x40,0xA0,0x9E,0x82,0x82,0x82,0x9E,0xA0,0x20,0x20,0x00,
0x00,0x00,0x00,0x3F,0x90,0x88,0x40,0x43,0x2C,0x10,0x28,0x46,0x41,0x80,0x80,0x00,/*"设",1*/
0x10,0x0C,0x44,0x44,0x44,0x44,0x45,0xC6,0x44,0x44,0x44,0x44,0x44,0x14,0x0C,0x00,
0x80,0x40,0x20,0x1E,0x20,0x40,0x40,0x7F,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00,/*"定",2*/
0x10,0x8C,0x44,0x04,0xE4,0x04,0x95,0xA6,0x44,0x24,0x14,0x84,0x44,0x94,0x0C,0x00,
0x02,0x02,0x7A,0x41,0x41,0x43,0x42,0x7E,0x42,0x42,0x42,0x43,0xF8,0x00,0x00,0x00,/*"密",3*/
0x04,0x84,0xE4,0x5C,0x44,0xC4,0x00,0x02,0xF2,0x82,0x82,0x82,0xFE,0x80,0x80,0x00,
0x02,0x01,0x7F,0x10,0x10,0x3F,0x00,0x08,0x08,0x08,0x08,0x48,0x88,0x40,0x3F,0x00,/*"码",4*/
};
BEEP (蜂鸣器)
beep.c文件代码
#include "stm32f1xx.h"
#include "beep.h"
//初始化GPIO口
void beep_init(void){
//打开时钟
__HAL_RCC_GPIOC_CLK_ENABLE();
//打开GPIO口
GPIO_InitTypeDef GPIO_Initstruct;
GPIO_Initstruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Initstruct.Pin = GPIO_PIN_13;
GPIO_Initstruct.Pull = GPIO_NOPULL;
GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC,&GPIO_Initstruct);
//关闭蜂鸣器
beep_off();
}
//打开蜂鸣器函数
void beep_on(void){
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
}
//关闭蜂鸣器
void beep_off(void){
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
}
//反转蜂鸣器
void beep_toggle(void){
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}
SWITCH(开关)
switch.h文件代码
#include "alarm.h"
#include "stm32f1xx.h" // 外设的驱动函数
//初始化GPIO口
void alarm_init(void){
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE();
//调用GPIO的初始化函数
GPIO_InitTypeDef GPIO_Initstruct;
GPIO_Initstruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Initstruct.Pin = GPIO_PIN_7;
GPIO_Initstruct.Pull = GPIO_PULLUP;
GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_Initstruct);
//关闭继电器
alarm_off();
}
//接通继电器的函数
void alarm_on(void){
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET);
}
//断开继电器的函数
void alarm_off(void){
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);
}
//获取继电器的状态
uint8_t alarm_status_get(void){
return (uint8_t)HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7);
}
W25Q128(FLASH存储器)
w25q128.c文件代码
#include "w25q128.h"
SPI_HandleTypeDef spi_handle = {0};
void w25q128_spi_init(void){
spi_handle.Instance = SPI1;
spi_handle.Init.Mode = SPI_MODE_MASTER; //配置成主模式还是从模式
spi_handle.Init.Direction = SPI_DIRECTION_2LINES; //配置全双工还是半双工
spi_handle.Init.DataSize = SPI_DATASIZE_8BIT; //数据的长度:8bit
spi_handle.Init.CLKPolarity = SPI_POLARITY_LOW; //CPOL = 0
spi_handle.Init.CLKPhase = SPI_PHASE_1EDGE; //CPHA = 奇数边沿检测
spi_handle.Init.NSS = SPI_NSS_SOFT; //软件控制SS引脚配置
spi_handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; //波特率分频 :256
spi_handle.Init.FirstBit = SPI_FIRSTBIT_MSB; //高位先行还是低位先行:高位先行
//下面这三个先不需要考虑
spi_handle.Init.TIMode = SPI_TIMODE_DISABLE;
spi_handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
spi_handle.Init.CRCPolynomial = 7;
HAL_SPI_Init(&spi_handle);
}
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi){
if(hspi->Instance == SPI1){
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_SPI1_CLK_ENABLE();
GPIO_InitTypeDef gpio_initstruct;
//NSS引脚
gpio_initstruct.Pin = GPIO_PIN_4;
gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;
gpio_initstruct.Pull = GPIO_PULLUP;
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&gpio_initstruct);
//SCL引脚和输出引脚
gpio_initstruct.Pin = GPIO_PIN_5 |GPIO_PIN_7;
gpio_initstruct.Mode = GPIO_MODE_AF_PP;
HAL_GPIO_Init(GPIOA,&gpio_initstruct);
//输入引脚
gpio_initstruct.Pin = GPIO_PIN_6;
gpio_initstruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOA,&gpio_initstruct);
}
}
uint8_t w25q128_spi_swap_byte(uint8_t data){
uint8_t recv_data = 0;
HAL_SPI_TransmitReceive(&spi_handle,&data, &recv_data,1,1000); ///size:尺寸代表是多少个字节
return recv_data;
}
//初始化w25q128模块
void w25q128_init(void){
w25q128_spi_init();
}
//测试:读ID
uint16_t w25q128_read_id(void){
uint16_t device_id = 0;
W25Q128_CS(0);
w25q128_spi_swap_byte(FLASH_ManufactDeviceID);
w25q128_spi_swap_byte(0x00);
w25q128_spi_swap_byte(0x00);
w25q128_spi_swap_byte(0x00);
device_id = w25q128_spi_swap_byte(FLASH_DummyBtye) << 8; /* 将数据放在高8位 */
device_id |= w25q128_spi_swap_byte(FLASH_DummyBtye); /* 利用 |= 将数据放在低8位,并保留高8位的数据 */
W25Q128_CS(1);
return device_id;
}
//写使能
void w25q128_write_enable(void)
{
W25Q128_CS(0);
w25q128_spi_swap_byte(FLASH_WriteEable);
W25Q128_CS(1);
}
//读SR1寄存器
uint8_t w25q128_read_sr1(void){
uint8_t recv_data = 0;
W25Q128_CS(0);
w25q128_spi_swap_byte(FLASH_ReadStatusReg1);
recv_data = w25q128_spi_swap_byte(FLASH_DummyBtye);
W25Q128_CS(1);
return recv_data;
}
//发送地址的函数
void w25q128_send_address(uint32_t address){ //地址是3个字节,先发送高位,在发送中位,最后发送低位
w25q128_spi_swap_byte(address >> 16);//高位
w25q128_spi_swap_byte(address >> 8); //中位:由于函数是一个8位的,因此,移动后数据后,高位自动去掉。
w25q128_spi_swap_byte(address);
}
//忙等待的函数
void w25q128_wait_busy(void){
while ((w25q128_read_sr1() & 0x01) == 0x01); //判断最后一位是不是1
}
//读数据
void w25q128_read_data(uint32_t address,uint8_t *data,uint32_t size){
uint32_t i = 0;
W25Q128_CS(0);
w25q128_spi_swap_byte(FLASH_ReadDate);
w25q128_send_address(address);
for(i = 0;i< size; i++)
data[i] = w25q128_spi_swap_byte(FLASH_DummyBtye);
W25Q128_CS(1);
}
//页写:写的是256个字节,
void w25q128_write_page(uint32_t address,uint8_t *data,uint16_t size){ //代表的是字节数量
uint16_t i = 0;
w25q128_write_enable();
W25Q128_CS(0);
w25q128_spi_swap_byte(FLASH_PageProgram);
w25q128_send_address(address);
for(i = 0;i < size; i++)
w25q128_spi_swap_byte(data[i]);
W25Q128_CS(1);
//忙等待,写入数据是需要花费时间的;看状态寄存器的最后一位是0还是1
w25q128_wait_busy();
}
//扇区擦除
void w25q128_erase_sector(uint32_t address){
w25q128_write_enable();
w25q128_wait_busy();
W25Q128_CS(0);
w25q128_spi_swap_byte(FLASH_SectorErase);
w25q128_send_address(address);
W25Q128_CS(1);
w25q128_wait_busy();
}
//如何指定变量的数据类型是多少
w25q128.h文件代码
#ifndef __W25Q128_H__
#define __W25Q128_H__
#include "stm32f1xx.h"
#define W25Q128_CS(x) do{x ? \
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET): \
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);\
}while(0)
/* 指令表 */
#define FLASH_ManufactDeviceID 0x90
#define FLASH_WriteEable 0x06
#define FLASH_ReadStatusReg1 0x05
#define FLASH_ReadDate 0x03
#define FLASH_PageProgram 0x02
#define FLASH_SectorErase 0x20
#define FLASH_DummyBtye 0xFF
void w25q128_init(void);
uint16_t w25q128_read_id(void);
void w25q128_read_data(uint32_t address,uint8_t *data,uint32_t size);
void w25q128_write_page(uint32_t address,uint8_t *data,uint16_t size);
void w25q128_erase_sector(uint32_t address);
#endif
输入设备
KEYBOARD(矩阵键盘)
keyboard.c文件代码:
#include "keyboard.h"
#include "delay.h"
static uint8_t key_value;
void keyboard_init(void){
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE();
//调用GPIO的初始化函数
GPIO_InitTypeDef GPIO_Initstruct;
GPIO_Initstruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10;
GPIO_Initstruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_Initstruct.Pull = GPIO_PULLUP;
GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_Initstruct);
GPIO_Initstruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14;
GPIO_Initstruct.Mode = GPIO_MODE_INPUT;
GPIO_Initstruct.Pull = GPIO_PULLDOWN; //配置成下拉模式,当导通时,会变成高电平
GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_Initstruct);
HAL_NVIC_SetPriority(EXTI0_IRQn,2,2);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
HAL_NVIC_SetPriority(EXTI1_IRQn,2,2);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);
HAL_NVIC_SetPriority(EXTI2_IRQn,2,2);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);
HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,2);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
void EXTI0_IRQHandler(void){
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
void EXTI1_IRQHandler(void){
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
}
void EXTI2_IRQHandler(void){
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
}
void EXTI15_10_IRQHandler(void){
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
uint8_t row = 0,column = 0;
if(key_value != 0) return; //防止手速过快,只读取第一次按下时的按键值
//确定行
if(GPIO_Pin == GPIO_PIN_0)
row = 0x10;
else if(GPIO_Pin == GPIO_PIN_1)
row = 0x20;
else if(GPIO_Pin == GPIO_PIN_2)
row = 0x30;
else if(GPIO_Pin == GPIO_PIN_10)
row = 0x40;
//确定列
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11) == GPIO_PIN_SET){
delay_ms(10);
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11) == GPIO_PIN_SET);
column = 0x01;
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12) == GPIO_PIN_SET){
delay_ms(10);
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12) == GPIO_PIN_SET);
column = 0x02;
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == GPIO_PIN_SET){
delay_ms(10);
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == GPIO_PIN_SET);
column = 0x03;
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14) == GPIO_PIN_SET){
delay_ms(10);
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14) == GPIO_PIN_SET);
column = 0x04;
}
if(row != 0 && column != 0)
key_value = row | column; //按位与进行拼接
}
uint8_t keyboard_get_value(void){
uint8_t ch = 0;
if(key_value != 0)
{
if(key_value == 0x11) ch = '1';
else if(key_value == 0x12) ch = '2';
else if(key_value == 0x13) ch = '3';
else if(key_value == 0x14) ch = 'A';
else if(key_value == 0x21) ch = '4';
else if(key_value == 0x22) ch = '5';
else if(key_value == 0x23) ch = '6';
else if(key_value == 0x24) ch = 'B';
else if(key_value == 0x31) ch = '7';
else if(key_value == 0x32) ch = '8';
else if(key_value == 0x33) ch = '9';
else if(key_value == 0x34) ch = 'C';
else if(key_value == 0x41) ch = '*';
else if(key_value == 0x42) ch = '0';
else if(key_value == 0x43) ch = '#';
else if(key_value == 0x44) ch = 'D';
delay_ms(400);
key_value = 0x00;
}
return ch;
}
PASSWORD(配置密码)
password.c文件代码:
#include "password.h"
#include "w25q128.h"
#include "oled.h"
#include "keyboard.h"
#include "string.h"
#include "stdio.h"
#include "alarm.h"
#include "beep.h"
#include "delay.h"
#define PASSWORD_SIZE 10
uint8_t pwd_input[PASSWORD_SIZE] = {0};
uint8_t pwd_read[PASSWORD_SIZE] = {0};
uint8_t i = 0,key_value = 0,try_times = 0;
/********** 1 *********/
//初始化函数
void password_init(void){
w25q128_init();
}
//读取密码:读取的是w25Q128_read_data();
//保存密码
void password_save(void){
w25q128_erase_sector(0x000000);
w25q128_write_page(0x000000,pwd_input,PASSWORD_SIZE);
oled_modif_pwd_complete();
}
//清空输入缓存
void password_input_clear(void){
memset(pwd_input, 0 ,PASSWORD_SIZE);
i = 0;
}
//获取键盘输入:将按键输入(数字、字母)存到一个字符串数组当中,而“#”,“*”则进行返回。
uint8_t password_get_input(void){
password_input_clear(); /*清除 字符数组 中的值 */
while(1){
key_value = keyboard_get_value();
if(key_value == '#'){
printf("按下了 %c 键 \r\n", key_value);
return POUND_KEY;
}
else if(key_value == '*'){
printf("按下了 %c 键 \r\n", key_value);
return STAR_KEY;
}
else if(key_value != 0){
printf("按下了 %c 键 \r\n", key_value);
oled_show_char(3,i * 10,key_value,16); //字符的尺寸。
pwd_input[i++] = key_value;
}
}
}
/********** 2 *********/
//密码比对:长度和元素。返回值:TURE和FLASE
uint8_t password_compare(void){
uint8_t i = 0;
w25q128_read_data(0x000000,pwd_read,PASSWORD_SIZE);
//先检查两个字符串的长度
if(strlen((char *)pwd_input) != strlen((char *)pwd_read))
return FALSE;
for (i = 0;i < strlen((char *)pwd_read); i++){
if(pwd_input[i] != pwd_read[i])
return FALSE;
}
return TRUE;
}
//密码输入正确的操作
void password_input_right_action(void){
oled_pwd_right();
alarm_on();
beep_on();
delay_ms(500);
beep_off();
delay_s(1);
alarm_off();
try_times = 0;
}
//密码输入错误的操作
void password_input_error_action(void){
oled_pwd_error();
try_times ++;
if(try_times >= 3){
beep_on();
delay_ms(1000);
beep_off();
try_times = 0;
}
delay_s(1);
}
//旧密码输入正确的操作
void password_old_right_action(void){
oled_input_new_pwd();
password_get_input();
password_save();
beep_on();
delay_ms(300);
beep_off();
delay_ms(700);
}
//旧密码输入错误的操作
void password_old_error_action(void){
oled_pwd_error();
delay_ms(1000);
}
//检查密码是否存在
void password_check(void){
w25q128_read_data(0x000000,pwd_read,PASSWORD_SIZE);
printf("读出密码:%s\r\n",pwd_read);
if(pwd_read[0] == '\0' || pwd_read[0] == 0xFF){
oled_set_pwd();
password_get_input();
password_save();
}
}
password.h文件代码
#ifndef __PASSWORD_H__
#define __PASSWPRD_H__
#include "stm32f1xx.h"
#define FALSE 0
#define TRUE 1
#define POUND_KEY '#'
#define STAR_KEY '*'
void password_init(void);
void password_check(void);
void password_save(void);
uint8_t password_get_input(void);
uint8_t password_compare(void);
void password_input_right_action(void);
void password_input_error_action(void);
void password_old_right_action(void);
void password_old_error_action(void);
#endif
主函数
main.c文件代码:
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "uart1.h"
#include "oled.h"
#include "beep.h"
#include "alarm.h"
#include "w25q128.h"
#include "keyboard.h"
#include "password.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
uart1_init(115200);
printf("hello,world!!!\r\n");
beep_init();
alarm_init();
oled_init();
keyboard_init();
password_init();
// w25q128_init();
password_check();
uint8_t key_last = 0;
while(1)
{
oled_show_input();
key_last = password_get_input();
if(key_last == POUND_KEY){
if(password_compare() == TRUE)
password_input_right_action();
else
password_input_error_action();
}
else if(key_last == STAR_KEY){
oled_input_old_pwd();
password_get_input();
if(password_compare() == TRUE)
password_old_right_action();
else
password_old_error_action();
}
}
}