一、题目展示

 

 

二、编程解析 

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写入需要整形,我两次做题起手都是字符类型写入,想都不带想的,同个地方摔了两次,麻了。

(补:初版代码存在逻辑错误,现在已经修改好了,新的一版同样也是满分,也非常感谢大家对我问题的指出,如果还有什么问题可以在评论区一起多多交流)

(重新发布了一遍,被恶心到了,密码给我文章强制添加 VIP,又不分我作者钱,本来只是想单纯地分享自己的学习经验,好久没更新了结果给我整成这样,恶心的资本,兄弟们且看且珍惜吧)

 

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐