


main.c
cs
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "beep.h"
#include "keyboard.h"
#include "lock.h"
#include "oled.h"
#include "w25q128.h"
#include "password.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
uart1_init(115200);
beep_init();
keyboard_init();
oled_init();
// w25q128_init();
lock_init();
password_init();
printf("hello world!\r\n");
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_wrong_action();
}
else if(key_last == STAR_KEY)
{
oled_show_old();
password_get_input();
if(password_compare() == TRUE)
password_old_right_action();
else
password_old_wrong_action();
}
}
}
keyboard.c文件
cs
#include "keyboard.h"
#include "delay.h"
static uint8_t key_value =0; //用static 可以使得key_value变量只能在此中使用
void keyboard_init(void)
{
//①定义初始化结构体
GPIO_InitTypeDef gpio_initstruct;
//②初始化GPIO函数
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); //注意看硬件原理图中LED灯的引脚在哪一个组
//调用GPIO初始化函数
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_initstruct.Mode = GPIO_MODE_INPUT; //列设置为输入引脚
gpio_initstruct.Pull =GPIO_PULLDOWN; //正常状态下 下拉
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
//设置中断
HAL_NVIC_SetPriority(EXTI0_IRQn,3,0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
HAL_NVIC_SetPriority(EXTI1_IRQn,3,0);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);
HAL_NVIC_SetPriority(EXTI2_IRQn,3,0);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);
HAL_NVIC_SetPriority(EXTI15_10_IRQn,3,0);
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))
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))
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))
column =0x03;
}
//合并行列
if (row !=0 && column !=0)
key_value = row | column ; //这条语令是0x10 | 0X02 =0X12
}
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 ==0x21)
ch='4';
else if(key_value ==0x22)
ch='5';
else if(key_value ==0x23)
ch='6';
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 ==0x41)
ch='*';
else if(key_value ==0x42)
ch='0';
else if(key_value ==0x43)
ch='#';
delay_ms(400);
key_value=0x00;
}
return ch;
}
password.c文件
cs
#include "password.h"
#include "oled.h"
#include "w25q128.h"
#include "keyboard.h"
#include "string.h"
#include "stdio.h"
#include "lock.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;
uint8_t key_value =0;
uint8_t try_times=0;
//初始化函数
void password_init(void)
{
w25q128_init();
}
//清空输入缓存
void password_input_clear(void)
{
memset(pwd_input ,0,PASSWORD_SIZE);
i= 0;
}
//保存密码 即修改密码
void password_save(void)
{
w25q128_erase_sector(0x000000); //扇页擦除
w25q128_write_page(0x000000,pwd_input,PASSWORD_SIZE);
oled_show_changed();
}
//获取键盘的输入
uint8_t password_get_input(void)
{
password_input_clear();
while(1)
{
key_value =keyboard_get_value();
if(key_value == POUND_KEY)
{
printf("按下了#号键,input:%s\r\n",pwd_input);
return POUND_KEY; //输入#号就退出循环了
}
else if(key_value == STAR_KEY)
{
printf("按下了*号键\r\n");
return STAR_KEY; 输入*号就退出循环了
}
else if(key_value != 0)
{
printf("按下了: %c\r\n",key_value);
oled_show_char(20+ i*10,4,key_value,16);
pwd_input[i++] =key_value;
}
}
}
//密码比对
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_show_right();
lock_on();
beep_on();
delay_ms(300);
beep_off();
delay_ms(1000);
lock_off();
try_times =0;
}
//密码输入错误的操作
void password_input_wrong_action(void)
{
oled_show_wrong();
try_times++;
if(try_times >= 3)
{
beep_on();
delay_ms(1000);
beep_off();
try_times =0;
}
delay_ms(1000);
}
//旧密码输入正确的操作
void password_old_right_action(void)
{
oled_show_new();
password_get_input();
password_save();
beep_on();
delay_ms(300);
beep_off();
delay_ms(500);
}
//旧密码输入错误的操作
void password_old_wrong_action(void)
{
oled_show_wrong();
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_show_set();
password_get_input();
password_save();
}
}
oled.c文件
cs
#include "oled.h"
#include "font.h"
#include "delay.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; //LED1、LED2对应的引脚
gpio_initstruct.Pull = GPIO_PULLUP; //上拉
gpio_initstruct.Mode =GPIO_MODE_OUTPUT_PP; //开漏输出
gpio_initstruct.Speed =GPIO_SPEED_FREQ_HIGH; //高速
HAL_GPIO_Init(OLED_I2C_SCL_PORT,&gpio_initstruct);
gpio_initstruct.Pin = OLED_I2C_SDA_PIN; //LED1、LED2对应的引脚
HAL_GPIO_Init(OLED_I2C_SDA_PORT,&gpio_initstruct);
}
void oled_i2c_start(void)
{
OLED_SCL_SET();
OLED_SDA_SET();
OLED_SDA_RESET();
OLED_SCL_RESET();
}
void oled_i2c_stop(void)
{
OLED_SCL_SET();
OLED_SDA_RESET();
OLED_SDA_SET();
}
void oled_i2c_ack(void)
{
OLED_SCL_SET();
OLED_SCL_RESET();
}
void oled_i2c_write_byte(uint8_t data) //发送一个字节8位并保存数据 保存数据是偏移后的第一位如果是1则置SDA为高电平 反之则置低电平
{
uint8_t i,tmp;
tmp= data;
for(i=0;i<8;i++)
{
if((tmp & 0x80) == 0x80) //"与" AND的运算1&0=0 0&0=0 1&1=1 这是为了看最高位是否为1
OLED_SDA_SET();
else
OLED_SDA_RESET();
tmp=tmp << 1;
OLED_SCL_SET();
OLED_SCL_RESET();
}
}
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_data(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();
}
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); //及时清空避免出现雪花现象
}
void oled_set_cursor(uint8_t x, uint8_t y) //设置写的位置在哪里 y为page x为列
{
oled_write_cmd(0xB0 + y); //设置page
/*设置哪一列*/
oled_write_cmd(( x & 0x0F) | 0x00);
oled_write_cmd((x & 0xF0) >> 4 | 0x10 );
}
void oled_fill(uint8_t data) //注意oled_set_cursor(0, i); 的位置是因为这里的寻址模式采用的是页地址的寻址模式
{
uint8_t i, j;
for(i = 0; i < 8; i++)
{
oled_set_cursor(0, i);
for(j = 0; j < 128; j++)
{
oled_write_data(data);
}
}
}
void oled_show_char(uint8_t x,uint8_t y ,uint8_t num,uint8_t size) //y为哪一行 x为哪一列,num为ascii值,size为高度 设置了三个高度 12 16 24
{
uint8_t i,j,page;
num=num-' ';
page =size / 8;
if(size % 8 != 0)
page++;
for(j= 0;j<page;j++)
{
oled_set_cursor(x,y + j);
for( i = size / 2 * j; i < size / 2 * ( j + 1 ) ; i++)
{
if(size == 12)
oled_write_data(ascii_6X12[num][i]);
else if(size == 16)
oled_write_data(ascii_8X16[num][i]);
else if(size == 24)
oled_write_data(ascii_12X24[num][i]);
}
}
}
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);
x +=size/2;
p++;
}
}
//void oled_show_chinese(uint8_t x, uint8_t y, uint8_t N, uint8_t size) //N为汉字的位数
//{
// uint16_t i, j;
// for(j = 0; j < size/8; j++)
// {
// oled_set_cursor(x, y + j);
// for(i = size *j; i < size * (j + 1); i++)
// {
// if(size == 16)
// oled_write_data(chinese_16x16[N][i]);
// else if(size == 24)
// oled_write_data(chinese_24x24[N][i]);
// }
// }
//}
void oled_show_chinese(uint8_t x, uint8_t y, uint8_t N, uint8_t message_type) //N为汉字的位数
{
uint16_t i, j;
for(j = 0; j < 2; j++)
{
oled_set_cursor(x, y + j);
for(i = 16 *j; i < 16 * (j + 1); i++)
{
switch(message_type)
{
case SHOW_INPUT_PWD:
oled_write_data(chinese_enter_password[N][i]);
break;
case SHOW_PWD_RIGHT:
oled_write_data(chinese_password_right[N][i]);
break;
case SHOW_PWD_WRONG:
oled_write_data(chinese_password_wrong[N][i]);
break;
case SHOW_INPUT_OLD_PWD:
oled_write_data( chinese_enter_old_password[N][i]);
break;
case SHOW_INPUT_NEW_PWD:
oled_write_data(chinese_enter_new_password[N][i]);
break;
case SHOWPWD_CHANGED:
oled_write_data(chinese_password_changed[N][i]);
break;
case SHOW_SET_PWD:
oled_write_data(chinese_set_password[N][i]);
break;
default:
break;
}
}
}
}
//请输入密码
void oled_show_input(void)
{
oled_fill(0x00);
oled_show_chinese(10,1,0,SHOW_INPUT_PWD);
oled_show_chinese(30,1,1,SHOW_INPUT_PWD);
oled_show_chinese(50,1,2,SHOW_INPUT_PWD);
oled_show_chinese(70,1,3,SHOW_INPUT_PWD);
oled_show_chinese(90,1,4,SHOW_INPUT_PWD);
oled_show_char(110,1,':',16);
}
//密码正确
void oled_show_right(void)
{
oled_fill(0x00);
oled_show_chinese(10,1,0,SHOW_PWD_RIGHT);
oled_show_chinese(30,1,1,SHOW_PWD_RIGHT);
oled_show_chinese(50,1,2,SHOW_PWD_RIGHT);
oled_show_chinese(70,1,3,SHOW_PWD_RIGHT);
oled_show_char(90,1,'!',16);
}
//密码错误
void oled_show_wrong(void)
{
oled_fill(0x00);
oled_show_chinese(10,1,0,SHOW_PWD_WRONG);
oled_show_chinese(30,1,1,SHOW_PWD_WRONG);
oled_show_chinese(50,1,2,SHOW_PWD_WRONG);
oled_show_chinese(70,1,3,SHOW_PWD_WRONG);
oled_show_char(90,1,'!',16);
}
//请输入旧密码
void oled_show_old(void)
{
oled_fill(0x00);
oled_show_chinese(0,1,0,SHOW_INPUT_OLD_PWD);
oled_show_chinese(20,1,1,SHOW_INPUT_OLD_PWD);
oled_show_chinese(40,1,2,SHOW_INPUT_OLD_PWD);
oled_show_chinese(60,1,3,SHOW_INPUT_OLD_PWD);
oled_show_chinese(80,1,4,SHOW_INPUT_OLD_PWD);
oled_show_chinese(100,1,5,SHOW_INPUT_OLD_PWD);
oled_show_char(120,1,':',16);
}
//请输入新密码
void oled_show_new(void)
{
oled_fill(0x00);
oled_show_chinese(0,1,0,SHOW_INPUT_NEW_PWD);
oled_show_chinese(20,1,1,SHOW_INPUT_NEW_PWD);
oled_show_chinese(40,1,2,SHOW_INPUT_NEW_PWD);
oled_show_chinese(60,1,3,SHOW_INPUT_NEW_PWD);
oled_show_chinese(80,1,4,SHOW_INPUT_NEW_PWD);
oled_show_chinese(100,1,5,SHOW_INPUT_NEW_PWD);
oled_show_char(120,1,':',16);
}
//密码修改成功
void oled_show_changed(void)
{
oled_fill(0x00);
oled_show_chinese(0,1,0,SHOWPWD_CHANGED);
oled_show_chinese(20,1,1,SHOWPWD_CHANGED);
oled_show_chinese(40,1,2,SHOWPWD_CHANGED);
oled_show_chinese(60,1,3,SHOWPWD_CHANGED);
oled_show_chinese(80,1,4,SHOWPWD_CHANGED);
oled_show_chinese(100,1,5,SHOWPWD_CHANGED);
oled_show_char(120,1,'!',16);
}
//请设定密码
void oled_show_set(void)
{
oled_fill(0x00);
oled_show_chinese(10,1,0,SHOW_SET_PWD);
oled_show_chinese(30,1,1,SHOW_SET_PWD);
oled_show_chinese(50,1,2,SHOW_SET_PWD);
oled_show_chinese(70,1,3,SHOW_SET_PWD);
oled_show_chinese(90,1,4,SHOW_SET_PWD);
oled_show_char(110,1,':',16);
}
void oled_show_image(uint8_t x,uint8_t y,uint8_t width,uint8_t height,uint8_t *bmp) //其中参数bmp为指针
{
uint8_t i,j;
for(j=0;j<height;j++)
{
oled_set_cursor(x,y+j);
for(i=0;i<width;i++)
oled_write_data(bmp[width * j +i]);
}
}