蓝桥杯嵌入式16届模拟试题一-编程解析

一、题目展示

二、编程解析 

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

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

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值