一、题目展示
二、编程解析
1、头文件的相关定义与声明
#ifndef _code_h
#define _code_h
#include "stm32g4xx.h" // Device header
#include "stdio.h"
#include "string.h"
#include "stdint.h"
#include "main.h"
#include "gpio.h"
#include "lcd.h"
#include "adc.h"
#include "i2c_hal.h"
#include "tim.h"
void lcd_proc(void);
void led_proc(u8 led_x,u8 led_mode);
void key_proc(void);
void adc_proc(ADC_HandleTypeDef *hadc);
#endif
2、主函数的相关初始化
#include "code.h"
……
……
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
LCD_Init();
LCD_SetTextColor(White);
LCD_SetBackColor(Black);
LCD_Clear(Black);
HAL_TIM_Base_Start(&htim2);
I2CInit();//不要忘记初始化I2C
extern char Pass[4];
//系统是否初次上电判断
if(i2cread(0x88)!='N'&&i2cread(0x99)!='B')
{
i2cwrite(0x88,'N'-'0');//是初次上电则设置标志,进行密码初始化
i2cwrite(0x99,'B'-'0');
i2cwrite(0x00,'0'-'0');
i2cwrite(0x01,'1'-'0');
i2cwrite(0x02,'2'-'0');
}
Pass[0]=i2cread(0x00);
Pass[1]=i2cread(0x01);
Pass[2]=i2cread(0x02);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
lcd_proc();
key_proc();
adc_proc(&hadc2);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
3、各个模块的编写
#include "code.h"
double adc_val;
/*---------------------------------lcd-----------------------------------*/
u8 ui;
//因为使用strcmp进行字符串比较,不补结束符容易出错,一个用于存储密码进行比较,一个用于实时显示
char Pass[4]="012\0";
char lcd_Pass[4]="***\0";
char lcd_val[30];
void lcd_proc(void)
{
if(ui==0)
{
sprintf(lcd_val," Lock ");
LCD_DisplayStringLine(Line1,(u8 *)lcd_val);
sprintf(lcd_val," Pass Word ");
LCD_DisplayStringLine(Line3,(u8 *)lcd_val);
sprintf(lcd_val," %c %c %c",lcd_Pass[0],lcd_Pass[1],lcd_Pass[2]);
LCD_DisplayStringLine(Line4,(u8 *)lcd_val);
// sprintf(lcd_val," %.2f ",adc_val);
// LCD_DisplayStringLine(Line7,(u8 *)lcd_val);
// sprintf(lcd_val," %c %c %c",i2cread(0x00),i2cread(0x01),i2cread(0x02));
// LCD_DisplayStringLine(Line8,(u8 *)lcd_val);
// sprintf(lcd_val," %c %c %c",Pass[0],Pass[1],Pass[2]);
// LCD_DisplayStringLine(Line9,(u8 *)lcd_val);
}
else
{
sprintf(lcd_val," Set ");
LCD_DisplayStringLine(Line1,(u8 *)lcd_val);
sprintf(lcd_val," Change ");
LCD_DisplayStringLine(Line3,(u8 *)lcd_val);
sprintf(lcd_val," %c %c %c",lcd_Pass[0],lcd_Pass[1],lcd_Pass[2]);
LCD_DisplayStringLine(Line4,(u8 *)lcd_val);
}
led_proc(1,!ui);
led_proc(2,ui);
}
/*---------------------------------led-----------------------------------*/
void led_proc(u8 led_x,u8 led_mode)
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
if(led_mode)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8<<(led_x-1),GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8<<(led_x-1),GPIO_PIN_SET);
}
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
/*---------------------------------key-----------------------------------*/
u8 B1_val;//当前按键电平状态,在Cubemx配置上拉,即没有按下默认高电平
u8 B1_old;//按键的上一次电平状态
u8 Pass_X;//选择密码位
void key_proc(void)
{
B1_val=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
if(B1_val==0&&B1_old==1)
{
HAL_Delay(20);
if(B1_val==0&&B1_old==1)//按键按下
{
Pass_X++;
Pass_X%=3;
TIM2->CNT=0;//按下一次按钮则清零开始计时
if(Pass_X==0)//按下三次进行密码处理
{
if(ui==0)//判断对错
{
if(strcmp(Pass,lcd_Pass)==0)
{
ui=1;
LCD_Clear(Black);
sprintf(lcd_Pass,"***");//正确
}
else
{
sprintf(lcd_Pass,"***");//错误也要复原
}
}
else if(ui==1)//存储密码
{
ui=0;
LCD_Clear(Black);
//存储密码进行比较
sprintf(Pass,"%c%c%c",lcd_Pass[0],lcd_Pass[1],lcd_Pass[2]);
i2cwrite(0x00,lcd_Pass[0]-'0');
i2cwrite(0x01,lcd_Pass[1]-'0');
i2cwrite(0x02,lcd_Pass[2]-'0');
}
}
}
}
B1_old=B1_val;
if(TIM2->CNT>30000&&ui==1)//TIM2->PSC=8000-1,计数10000次为1s
{
ui=0;
LCD_Clear(Black);
}
}
/*---------------------------------adc-----------------------------------*/
void adc_proc(ADC_HandleTypeDef *hadc)
{
HAL_ADC_Start(hadc);
adc_val= 3.3*HAL_ADC_GetValue(hadc)/4095;
if(adc_val<1.5)lcd_Pass[Pass_X]='0';
else if(adc_val<=2.5)lcd_Pass[Pass_X]='1';
else lcd_Pass[Pass_X]='2';
}
char i2cread(u8 addr)
{
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xA1);
I2CWaitAck();
char dat=I2CReceiveByte()+'0';
I2CSendNotAck();
I2CStop();
HAL_Delay(20);
return dat;
}
void i2cwrite(u8 addr,char data)
{
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
HAL_Delay(20);
}
三、结语
这一套我其实去年11月份就写过了,当时写了22KB多,现在再写直接干到18KB了,但距离大佬还是有很大的距离的,第一名直接干到15KB,太有实力,膜拜膜拜,所以我的代码还是有很大的优化空间的 ,现在快10点了,看时间就知道我今天写的不怎么样了,过了这么久该踩的坑还是踩了一编,比如那极其阴人AT24写入需要整形,我两次做题起手都是字符类型写入,想都不带想的,同个地方摔了两次,麻了。
(补:初版代码存在逻辑错误,现在已经修改好了,新的一版同样也是满分,也非常感谢大家对我问题的指出,如果还有什么问题可以在评论区一起多多交流)