当前位置: 首页 > news >正文

蓝桥杯第十六届嵌入式模拟编程题解析

由硬件框图可以知道我们要配置LED 和按键

LED

先配置LED的八个引脚为GPIO_OutPut,锁存器PD2也是,然后都设置为起始高电平,生成代码时还要去解决引脚冲突问题

按键

按键配置,由原理图按键所对引脚要GPIO_Input

生成代码,在文件夹中添加code文件夹,code中添加fun.c、fun.h、headfile.h文件,去资源包中把lcd.c、lcd.h、fonts.h添加到code中,然后去写按键控制灯亮灭的程序,看是否有问题

按键控制led没有问题后写lcd显示代码,显示没问题后,解决lcd与led引脚冲突问题,方法在我的其他文章中

  HAL_GPIO_WritePin (GPIOD,GPIO_PIN_2,GPIO_PIN_RESET ); //为解决引脚冲突初始化lcd时    LCD_Init ();                                                                                                  要将锁存器锁存器来;
  LCD_Clear (Black);
  LCD_SetBackColor(Black);
  LCD_SetTextColor(White);

LCD显示函数

void lcd_show(void)
{
    sprintf(text,"      hello world");
    LCD_DisplayStringLine (Line0 ,(uint8_t *)text);
}

eeprom

用到eeprom就要用到IIC通信协议就要去资源包中将IIC_hal.c   IIC_hal.h添加进来

然后再main中方初始化IIC

然后写eeprom读和写的函数,用lcd显示测试功能是否好用,没有问题就开始写ADC的功能函数代码。

ADC

由原理图知道ADC测量是由PB15与PB12测量,去配置两引脚为ADCx_INx,去相应ADCx中勾选相对应的INx为single-ended,后编写电压获取函数,其中用到ADC测量量与电压转化公式。

上面把需要用的功能都测试了一次没有问题,就开始按要求写写代码

下面是分别界面显示的代码

void Lock_show(void)
{
  sprintf(text,"        Lock        " );
    LCD_DisplayStringLine (Line2 ,(uint8_t *)text);
    
  sprintf(text,"      Pass Word     "  );
    LCD_DisplayStringLine (Line4 ,(uint8_t *)text);
    
  sprintf(text,"        * * *       "  );
    LCD_DisplayStringLine (Line5 ,(uint8_t *)text);
    
}
void Set_show(void)
{
  sprintf(text,"        Set         " );
    LCD_DisplayStringLine (Line2 ,(uint8_t *)text);
    
  sprintf(text,"       Change       "  );
    LCD_DisplayStringLine (Line4 ,(uint8_t *)text);
    
  sprintf(text,"       * * *        "  );
    LCD_DisplayStringLine (Line5 ,(uint8_t *)text);
    
}

ADC电压值转换成数值密码,将i输出到屏幕就行

void Lock_show(void)
{
    if(get_vo1(&hadc2)<1.5)
    {
        i=0;
    }
    else if(1.5<get_vo1(&hadc2)&&get_vo1(&hadc2)<2.5)
    {
        i=1;
    }
    else
    {
        i=2;
    }

*按键与电压共同输入密码

限定电压的大小可以控制输入的数字为0 1 2,密码一共有三位,这就需要输入第一位后记住并且切换到下一位,切换就需要用到按键,按键按一下且为下一位,再按一下又切换到下一位,再按又回到第一位输入。写代码时参数跨文件使用的就要在.h中外部申明,外部声明的数组在.c中初始化就不可以在.h又初始化

案件代码

uint8_t count;
uint8_t Password[3]={0,1,2};
uint8_t word[3];用于记住输入的密码

//这三个都需要外部声明

void key_scan(void)
{
	B1_state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
 		if(B1_state==0&&B1_last_state==1)  //如果按下就用word[]记住当前数值
		{
	 
			if(get_vo1(&hadc2)<1.5)
			{
				word[count]=0;
			}
			else if(1.5<get_vo1(&hadc2)&&get_vo1(&hadc2)<2.5)
			{
				word[count]=1;
			}
			else
			{
				word[count]=2;
			}
			count++;
			count %=3;
	  }
   	B1_last_state=B1_state;
}

输入密码显示


void Lock_show(void)
{
	
  sprintf(text,"        Lock        " );
	LCD_DisplayStringLine (Line2 ,(uint8_t *)text);
	
  sprintf(text,"      Pass Word     "  );
	LCD_DisplayStringLine (Line4 ,(uint8_t *)text);
	if(get_vo1(&hadc2)<1.5)
	{
		if(count==0)
		{
			sprintf(text,"        %d * *       ",0  );
		}
		else if(count==1)
		{
			sprintf(text,"        %d %d *       ",word[0],0);
		}
		else if(count==2)
		{
			sprintf(text,"        %d %d %d       ",word[0],word[1],0  );
		}
    LCD_DisplayStringLine (Line5 ,(uint8_t *)text);
	}
	else if(1.5<get_vo1(&hadc2)&&get_vo1(&hadc2)<2.5)
	{
    if(count==0)
		{
			sprintf(text,"        %d * *       ",1  );
		}
		else if(count==1)
		{
			sprintf(text,"        %d %d *       ",word[0],1);
		}
		else if(count==2)
		{
			sprintf(text,"        %d %d %d       ",word[0],word[1],1 );
		}
    LCD_DisplayStringLine (Line5 ,(uint8_t *)text);
	}
	else
	{
		if(count==0)
		{
			sprintf(text,"        %d * *       ",2 );
		}
		else if(count==1)
		{
			sprintf(text,"        %d %d *       ",word[0],2);
		}
		else if(count==2)
		{
			sprintf(text,"        %d %d %d       ",word[0],word[1],2);
		}
    LCD_DisplayStringLine (Line5 ,(uint8_t *)text);
	}
}

用一个标志位来修改页面,当密码正确时标志位改变,进入修改页面

uint8_t show_flag;// 标志位,0位输出页面,1位修改页面

if(word[0]==Password[0]&&word[1]==Password[1]&&word[2]==Password[2])
                {
                    show_flag=1;
                }

进入修改页面后重新输入密码,并把修改后的密码覆盖掉原来的密码,这时候就需要区分页面,输出页面输入三位密码后进行判断密码是否正确,修改页面就进行密码覆盖和存到eeprom中(题目要求),下面是页面区分代码

if(B1_state==0&&B1_last_state==1)
		{
	    if(show_flag==0)
			{
				if(get_vo1(&hadc2)<1.5)
				{
					word[count]=0;
				}
				else if(1.5<get_vo1(&hadc2)&&get_vo1(&hadc2)<2.5)
				{
					word[count]=1;
				}
				else
				{
					word[count]=2;
				}
				if(count==2)
				{
					if(word[0]==Password[0]&&word[1]==Password[1]&&word[2]==Password[2])
					{
						show_flag=1;
					}
					
				}
				count++;
				count %=3;
		 }
			else if(show_flag==1)
			{
				if(get_vo1(&hadc2)<1.5)
				{
					word[count]=0;
				}
				else if(1.5<get_vo1(&hadc2)&&get_vo1(&hadc2)<2.5)
				{
					word[count]=1;
				}
				else
				{
					word[count]=2;
				}
				if(count==2)
				{
					
				}
			}
	}

在修改页面中判断是否输入三位数密码后进行密码修改与存储,其中在进入修改页面后还要进行是否三秒问操作。

修改密码,进入修改页面后,输入了新的三位密码后进行密码修改

           if(count==2)  //判断是否输入了新的三位密码
                {
                    for(i=0;i<3;i++)
                    {
                        Password[i]=word[i];
                    }

                      save_password();

                      show_flag=0;密码修改好后回到输出页面


                }

把密码存到eeprom中还需写一个人写入函数,  eeprom_write函数上面我们已经写过了,写好后在修改密码后调用,上面红色代码就是调用,在main中也要调用,题目要求一开始的初始密码也是存到eeprom中

void save_password()
{
  eeprom_write(0x00,Password[0]);
  eeprom_write(0x01,Password[1]);
  eeprom_write(0x02,Password[2]);
}

到此基本功能完成,这时还有个进入修改界面三秒不操作返回原界面功能,指示灯没有写。计算三秒需用到定时器,要配置一下,三秒跳转可以用时间标志位进行实现功能。定时器我这配置10ms的,计算公式位系统频率(PSC+1)*(ARR+1)/Fsys,所以RSC=8000-1,ARR100-1记得开启中断。生成代码记得把.h包含进去

要在maim中开启时钟    HAL_TIM_Base_Start_IT(&htim4);有中断要用IT的

 

之后去找回调函数void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)写函调函数

htim->Instance这是指向定时器的句柄指针 

作用

1.标识具体的定时器实列

2.参数配置和操作

3.中断处理

初始化一个定时器于启用的列子

TIM_HandleTypeDef htim2;

void MX_TIM2_Init(void)
{
    htim2.Instance = TIM2; // 指定定时器实例为TIM2
    htim2.Init.Prescaler = 36000 - 1; // 设置预分频值
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP; // 设置计数模式为向上计数
    htim2.Init.Period = 2000 - 1; // 设置周期值
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 时钟分频因子
    if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
    {
        Error_Handler();
    }
}
配置好定时器后把标志位写到判断密码正确的if语句中,并且赋值

定期进行及时,如果3秒后没有进行操作,返回输入页面

根据最后的要求,输入界面led1亮,否则灭

                            修改界面led2亮,否则灭

相关文章:

  • Android TextView 使用.9图片文字不展示
  • 计算机视觉算法实战——跌倒检测(主页有源码)
  • 【前端】【功能函数】treeMapEach,对每个节点进行自定义转换的实用函数
  • 深入理解 CSS pointer-events: none:穿透点击的魔法
  • 前端兼容处理接口返回的文件流或json数据
  • C++ Primer 容器适配器
  • java基础学习
  • SQL笔记#函数、谓词、CASE表达式
  • JavaScript 中的逻辑运算符
  • 项目实战--网页五子棋(匹配模块)(5)
  • 【网络安全 | 漏洞挖掘】Stripe 子系统 TaxJar 的 ATO 漏洞挖掘之旅
  • 【第五节】C++设计模式(创建型模式)-Prototype(原型)模式
  • 【NLP 23、预训练语言模型】
  • 码率和采样率
  • UE_C++ —— Gameplay Modules
  • C++和OpenGL实现3D游戏编程【连载23】——几何着色器和法线可视化
  • 白帽黑客系列教程之Windows驱动开发(64位环境)入门教程(六)
  • Pytorch实现论文:基于多尺度融合生成对抗网络的水下图像增强
  • Python常见面试题的详解20
  • Starlink卫星动力学系统仿真建模第十讲-基于SMC和四元数的卫星姿态控制示例及Python实现
  • 利用wordpress赚钱/北京seo服务商
  • 申请网页要多少钱/企业网站seo推广
  • 阿里云wordpress教程/seo网站推广实例
  • 中学教材数字化学习资源的建设——教材配套网站的设计及发展趋势/搭建网站需要什么技术
  • 东莞疫情感染人数/google移动服务应用优化
  • wordpress 哪个好用/seo技巧是什么