IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 蓝桥杯嵌入式STM32G431——第十届省赛真题 -> 正文阅读

[嵌入式]蓝桥杯嵌入式STM32G431——第十届省赛真题

第十届省赛真题主观题

第十届省赛体研究生组与本科组只是相差了EEPROM模块其他模块完全一样,难度相差不大,只是多了个I2C的使用。通过做研究生组的真题也能熟练一下I2C的使用。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主函数代码(不包含各模块初始化代码)

#include "main.h"
#include "rcc.h"
#include "led_key.h"
#include "i2c.h"
#include "adc.h"
#include "lcd.h"

//***通过滴答定时器实现执行速度控制变量
__IO uint32_t uwTick_LED_Speed_Ctrl;
__IO uint32_t uwTick_KEY_Speed_Ctrl;
__IO uint32_t uwTick_LCD_Speed_Ctrl;
__IO uint32_t uwTick_LED_Bulingbuling_Ctrl;


//***全局变量区***//
uint8_t ucLED; //用于控制LED的变量
uint8_t key_value,key_down,key_up;	//按键的三行代码
static uint8_t key_old;
uint8_t LCD_String_Disp[21];	//LCD字串显示数组

//*状态转换控制变量
//*状态0为数据显示界面
//*状态非0为参数设置界面
//*状态1为高亮并设置电压的上限值
//*状态2为高亮并设置电压的下限值
//*状态3高亮并设置超上限提醒指示灯
//*状态4高亮并设置低下限提醒指示灯
uint8_t State_Ctrl; 

float R37_Volt;	//ADC2对应的R37转换后的电压

//*用于设置界面的4个参数的值
//*Setting_Data[0] Max Volt-状态1-默认值2.4  
//*Setting_Data[1] Min Volt-状态2-默认值1.2
//*Setting_Data[2]	Upper-状态1-默认值LD1 
//*Setting_Data[3]  Lower-状态1-默认值LD2
uint8_t Setting_Data[4]={24,12,1,2}; 

uint8_t Volt_Status; //Upper超过上限-1  Lower低于下限-2  Normal正常-3

//***子函数声明区***//
void SystemClock_Config(void);
void LED_Proc(void);
void KEY_Proc(void);
void LCD_Proc(void);
void Volt_Status_Judge(void);



//***主函数区***//
int main(void)
{
 
  HAL_Init();

  SystemClock_Config();
	
	//**外设初始化区
	LED_KEY_Init();
	
	LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(Magenta);
	
	ADC2_Init();
	
	I2CInit();
	
	I2C_24c02_Read(Setting_Data , 0 ,4); //将初始默认参数读入Setting_Data数组中
	
  while (1)
  {
    LED_Proc();
	KEY_Proc();
	LCD_Proc();
  }
 
}


//***子函数区***//

void LED_Proc(void)
{
	if((uwTick - uwTick_LED_Speed_Ctrl)<200) return;
		uwTick_LED_Speed_Ctrl = uwTick;	//子函数100ms扫描执行一次
	
	if(State_Ctrl!=0)	//在非数据显示状态下LED关闭
		ucLED = 0x00;

	LED_Disp(ucLED);
}



void KEY_Proc(void)
{
	if((uwTick - uwTick_KEY_Speed_Ctrl)<100) return;
		uwTick_KEY_Speed_Ctrl = uwTick;	//子函数100ms扫描执行一次
	
	key_value = KEY_Scan();
	key_down = key_value & (key_value ^ key_old);
	key_up = ~key_value & (key_value ^ key_old);
	key_old = key_value;
	
	switch(key_down)
	{
		case 1:	//B1按下 切换参数设置界面或数据显示界面
			if(State_Ctrl == 0)
			{
				State_Ctrl = 1; //状态1为参数设置界面
				LCD_Clear(Black); //界面切换后清屏
			}
			else
			{
				State_Ctrl = 0;	//状态0为数据显示界面
				LCD_Clear(Black); //界面切换后清屏
				I2C_24c02_Write(Setting_Data , 0 ,4);	//从参数设置界面切换回数据显示后 将设置好的参数存入EEPROM中
			}
		
			break;
		 
		case 2:	//B2按下 在参数设置界面切换各参数状态 1-2-3-4-1
			if(State_Ctrl != 0) //在数据显示界面无效
				State_Ctrl++;
			if(State_Ctrl == 5)
				State_Ctrl = 1;
			break;	
		
		case 3:	//B3按下 对应参数+0.3或+1
			if(State_Ctrl != 0)	//只在参数设置界面下有效
			{
				switch(State_Ctrl)	//选择需要设置的值
				{
					case 1: //上限电压+0.3V 当超过3.3V时不再增加
						Setting_Data[0] += 3;
						if(Setting_Data[0] == 36)	
							Setting_Data[0] = 33;
						break;
					
					case 2: //下限电压+0.3V 当超过上限电压时不再增加
						Setting_Data[1] += 3;
						if(Setting_Data[1] > Setting_Data[0])	//如果下限电压值加到比上限电压值大 则不再增加
							Setting_Data[1] = Setting_Data[0];
						break;		

					case 3: //超上限指示灯+1 当与下限指示灯相等时再次+1
						Setting_Data[2] += 1;
						if(Setting_Data[2] == Setting_Data[3]) //当指示灯序号相等时再次加1
							Setting_Data[2] += 1;
					
						if(Setting_Data[2] >= 9)  //当指示灯加到9时时则等于1且此时如果下限指示灯为1时 还需要再次加1
							Setting_Data[2] = 1;	
						if(Setting_Data[2] == Setting_Data[3])
							Setting_Data[2] += 1;							
						break;

					case 4: //低下限指示灯+1 当与上限指示灯相等时再次+1
						Setting_Data[3] += 1;
						if(Setting_Data[3] == Setting_Data[2]) //当指示灯序号相等时再次加1
							Setting_Data[3] += 1;
					
						if(Setting_Data[3] >= 9)	//当指示灯加到9时时则等于1且此时如果上限指示灯为1时 还需要再次加1
							Setting_Data[3] = 1;	
						if(Setting_Data[3] == Setting_Data[2])
							Setting_Data[3] += 1;									
						break;
				}
			}
		
			break;		
		
		case 4: //B4按下 对应参数-0.3或-1
			if(State_Ctrl != 0)
			{
				switch(State_Ctrl)
				{
					case 1:	//上限电压值-0.3 当低于下限电压时不再减小
						Setting_Data[0]-=3;
						if(Setting_Data[0] < Setting_Data[1])	//如果上限电压值减到比下限电压值小 则不再减小
							Setting_Data[0] = Setting_Data[1];
						break;
					
					case 2: //下线电压值-0.3 当低下限电压减小到0时不再减小
						Setting_Data[1]-=3;
						if(Setting_Data[1] > 200) //由于是无符号数 如果下限电压值减到从零变成253 则为0同理为 下线电压值小于零后不再增加
							Setting_Data[1] = 0;
						break;

					case 3:	//超上限指示灯-1 当与下限指示灯相等时再次-1
						Setting_Data[2] -= 1;
						if(Setting_Data[2] == Setting_Data[3])  //当指示灯序号相等时再次减1
							Setting_Data[2] -= 1;
						
						if(Setting_Data[2] == 0) //当指示灯减到为0时则等于8且此时如果下限指示灯为8时 还需要再次减1
							Setting_Data[2] = 8;	
						if(Setting_Data[2] == Setting_Data[3])
							Setting_Data[2] -= 1;						
						break;

					case 4: 低下限指示灯-1 当与上限指示灯相等时再次-1
						Setting_Data[3] -= 1;
						if(Setting_Data[3] == Setting_Data[2]) //当指示灯序号相等时再次减1
							 Setting_Data[3] -= 1;
			
						if(Setting_Data[3] == 0) //当指示灯减到为0时则等于8且此时如果上限指示灯为8时 还需要再次减1
							Setting_Data[3] = 8;
						if(Setting_Data[3] == Setting_Data[2])
							Setting_Data[3] -= 1;									
						break;
				}
			}
		
			break;		
	}
	
	
}


void Volt_Status_Judge(void)	//电压状态判断子函数 
{
	if(R37_Volt > (float)Setting_Data[0]/10) //如果电压值大于上限电压值
	{
		Volt_Status = 1; //Upper超过上限-状态1
		if((uwTick - uwTick_LED_Bulingbuling_Ctrl)>200)
		{
			uwTick_LED_Bulingbuling_Ctrl = uwTick; 
			ucLED ^= (1<<(Setting_Data[2]-1));  //超过上限值对应LED按200ms时间间隔闪烁
		}
	}		
	else if(R37_Volt < (float)Setting_Data[1]/10) 如果电压值小于下限电压值
	{
		Volt_Status = 2; //Lower低于下限-状态2
		if((uwTick - uwTick_LED_Bulingbuling_Ctrl)>200)
		{
			uwTick_LED_Bulingbuling_Ctrl = uwTick;	
			ucLED ^= (1<<(Setting_Data[3]-1));		//低于下限值对应LED按200ms时间间隔闪烁
		}
	}
	else
	{
		Volt_Status = 3; //Normal正常-状态3
		ucLED = 0x00; //正常状态下LED关闭
	}
	
	
}


void LCD_Proc(void)
{
	if((uwTick - uwTick_LCD_Speed_Ctrl)<150) return;
		uwTick_LCD_Speed_Ctrl = uwTick;	//子函数150ms扫描执行一次
	
	R37_Volt = Get_ADC_Value()*3.3/4096; //将采集到的AD值转换为电压值
	Volt_Status_Judge(); //调用电压状态判断子函数 
	
	if(State_Ctrl == 0)	//在数据显示界面下
	{
		memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp , "        Main");
		LCD_DisplayStringLine(Line1 , LCD_String_Disp);
		
		memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp , "    Volt: %4.2fV",R37_Volt);
		LCD_DisplayStringLine(Line4 , LCD_String_Disp);
		
		switch(Volt_Status)	//选择电压状态 Upper超过上限-1  Lower低于下限-2  Normal正常-3
		{
			case 1:
				memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
				sprintf((char*)LCD_String_Disp , "    Status: Upper  ");
				LCD_DisplayStringLine(Line6 , LCD_String_Disp);
				break;
			
			case 2:
				memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
				sprintf((char*)LCD_String_Disp , "    Status: Lower  ");
				LCD_DisplayStringLine(Line6 , LCD_String_Disp);
				break;

			case 3:
				memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
				sprintf((char*)LCD_String_Disp , "    Status: Normal  ");
				LCD_DisplayStringLine(Line6 , LCD_String_Disp);
				break;			
		}
	
	}
	else //参数设置界面
	{
		memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp , "       Setting");
		LCD_DisplayStringLine(Line1 , LCD_String_Disp);		
		
		if(State_Ctrl == 1) LCD_SetBackColor(Yellow); //状态1电压上限值高亮
		memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp , " Max Volt: %3.1f",(float)Setting_Data[0]/10);
		LCD_DisplayStringLine(Line3 , LCD_String_Disp);
		LCD_SetBackColor(Black);
//		LCD_DisplayChar(Line3 , (320-(16*1)) , ' ');
		
		if(State_Ctrl == 2) LCD_SetBackColor(Yellow); //状态2电压下限值高亮
		memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp , " Min Volt: %3.1f",(float)Setting_Data[1]/10);
		LCD_DisplayStringLine(Line5 , LCD_String_Disp);
		LCD_SetBackColor(Black);

		if(State_Ctrl == 3) LCD_SetBackColor(Yellow); //状态3超上限指示灯高亮
		memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp , " Upper: LD%1d",Setting_Data[2]);
		LCD_DisplayStringLine(Line7 , LCD_String_Disp);
		LCD_SetBackColor(Black);

		if(State_Ctrl == 4) LCD_SetBackColor(Yellow); //状态4低下限指示灯高亮
		memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp , " Lower: LD%1d",Setting_Data[3]);
		LCD_DisplayStringLine(Line9 , LCD_String_Disp);	
		LCD_SetBackColor(Black);		
	}
	
}


按键与LCD逻辑图(仅供参考)

在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-19 01:20:04  更:2022-02-19 01:21:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:28:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码