目录
此次用的板子是普中的精灵板一,如图:
编辑
项目功能:实现设置密码,登陆密码,后期还可以通过E2PROM实现掉电不丢失数据。通过Oled的显示去判断我们是否设置或者登陆成功。
所用硬件原理图:
编辑
编辑
编辑
编辑
分别是矩阵按键、LED灯、OLED,以及原理接口图。
首先是矩阵按键的原理:
我们有16个按键,但是只有8个IO口,所以我们要通过高低电平去判断单个按键返回什么。
一般的矩阵按键都是按列和行去进行分配IO口的,例如我这个板子就是P8-P11是行的IO口,
P12-P15是列的IO口。此时我们把P8电平进行拉高,P9-P11全部拉低,然后此时判断的按键就是第一行的按键,此时去判断列上按键的按下就可以成功判断单个按键。剩下的可以依次类推,想要判断第二行九八P9拉高,其他全部拉低即可。
OLED是通过IIC进行一个读写操作,所以在CubeMax配置时我们需要把IIC通道打开。
我这边是调用的 一个OLED的库函数去进行显示,但本质是通过IIC的读和写进行操作。
如果大家不太懂IIC这里可以给大家提供一个IIC的链接
IIC详解,包括原理、过程,最后一步步教你实现IIC_iic协议-CSDN博客
转载于 shaguahaha大佬~
OLED.c源码
#include "oledfont.h" #include "oled.h" #define OLED_ADD 0x78 static void oled_cmd(uint8_t i2c_cmd) { uint8_t *cmd; cmd = &i2c_cmd; HAL_I2C_Mem_Write(&hi2c1, OLED_ADD, 0x00, I2C_MEMADD_SIZE_8BIT, cmd, 1, 100); } static void oled_data(uint8_t i2c_data) { uint8_t *data; data = &i2c_data; HAL_I2C_Mem_Write(&hi2c1, OLED_ADD, 0x40, I2C_MEMADD_SIZE_8BIT, data, 1, 100); } static void oled_origin(uint8_t x, uint8_t y) { oled_cmd(0xb0+y); oled_cmd(((x&0xf0)>>4)|0x10); oled_cmd((x&0x0f)|0x01); } void oled_clear() { uint8_t i,n; for(i=0;i<8;i++) { oled_cmd(0xb0+i); oled_cmd (0x00); oled_cmd (0x10); for(n=0;n<128;n++) oled_data(0); } } void oled_full(uint8_t data)//0xff { uint8_t m,n; for(m=0;m<8;m++) { oled_cmd(0xb0+m); //page0-page1 oled_cmd(0x00); //low column start address oled_cmd(0x10); //high column start address for(n=0;n<128;n++) { oled_data(data); } } } void oled_init(void) { HAL_Delay(100); oled_cmd(0xAE); //display off oled_cmd(0x20); //Set Memory Addressing Mode oled_cmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid oled_cmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7 oled_cmd(0xc8); //Set COM Output Scan Direction oled_cmd(0x00); //---set low column address oled_cmd(0x10); //---set high column address oled_cmd(0x40); //--set start line address oled_cmd(0x81); //--set contrast control register oled_cmd(0xff); //áá?èμ÷?ú 0x00~0xff oled_cmd(0xa1); //--set segment re-map 0 to 127 oled_cmd(0xa6); //--set normal display oled_cmd(0xa8); //--set multiplex ratio(1 to 64) oled_cmd(0x3F); // oled_cmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content oled_cmd(0xd3); //-set display offset oled_cmd(0x00); //-not offset oled_cmd(0xd5); //--set display clock divide ratio/oscillator frequency oled_cmd(0xf0); //--set divide ratio oled_cmd(0xd9); //--set pre-charge period oled_cmd(0x22); // oled_cmd(0xda); //--set com pins hardware configuration oled_cmd(0x12); oled_cmd(0xdb); //--set vcomh oled_cmd(0x20); //0x20,0.77xVcc oled_cmd(0x8d); //--set DC-DC enable oled_cmd(0x14); // oled_cmd(0xaf); //--turn on oled panel oled_full(0x00); } void oled_display_char(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size) { unsigned char c=0,i=0; c=chr-' ';//得到偏移后的值 if(x>128-1){x=0;y=y+2;} if(Char_Size == 16) { oled_origin(x,y); for(i=0;i<8;i++) oled_data(F8X16[c*16+i]); oled_origin(x,y+1); for(i=0;i<8;i++) oled_data(F8X16[c*16+i+8]); } else { oled_origin(x,y); for(i=0;i<6;i++) oled_data(F6x8[c][i]); } } void oled_show_string(uint8_t x, uint8_t y, char ch[], uint8_t TextSize) { uint8_t c = 0,i = 0,j = 0; switch(TextSize) { case 1: { while(ch[j] != '\0') { c = ch[j] - 32; if(x > 126) { x = 0; y++; } oled_origin(x,y); for(i=0;i<6;i++) oled_data(F6x8[c][i]); x += 6; j++; } }break; case 2: { while(ch[j] != '\0') { c = ch[j] - 32; if(x > 120) { x = 0; y++; } oled_origin(x,y); for(i=0;i<8;i++) oled_data(F8X16[c*16+i]); oled_origin(x,y+1); for(i=0;i<8;i++) oled_data(F8X16[c*16+i+8]); x += 8; j++; } }break; } }
编辑
编辑
这是cubeMax配置的整体图,其中PA0-PA7是LED的,PA13-PA14是烧录口,PA10-PA9是串口通信,PB7-PB6是OLED所需的IIC通信。PB12-PB15是我们矩阵按键的列按键,PB8-PB11是行按键。
逻辑思维导图:
整体逻辑我做了一个思维导图 大家可以借鉴一下~
编辑
实现效果:
编辑
编辑
编辑
编辑
主要是运用了一个矩阵按键还有OLED。
源码地址
微信关注嵌入式工程之家发送 门锁源码 即可获得完整源码包哦~