蓝桥杯嵌入式STM32G431——第六届省赛真题电压测量监控设备

第六届省赛真题电压测量监控设备

第六届省赛真题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

main.c

#include "main.h"
//使用CubeMX配置以下头文件下的模块初始化
#include "rcc.h" //时钟初始化
#include "led_key.h"
#include "lcd.h"
#include "i2c.h"
#include "uart.h"
#include "adc.h"
#include "rtc.h"

//***全局变量区
//*扫描时间速度控制变量
__IO uint32_t uwTick_LED_Set_Point; //控制LED执行一次的时间
__IO uint32_t uwTick_KEY_Set_Point;	//控制KEY执行一次的时间
__IO uint32_t uwTick_LCD_Set_Point;	//控制LCD执行一次的时间
__IO uint32_t uwTick_UART_Set_Point;	//控制UART执行一次的时间
//*LED变量
uint8_t ucLed;
//*按键变量
uint8_t key_value,key_up,key_down;	//按键的三行代码所使用的变量
static uint8_t key_old;
//*LCD变量
uint8_t LCD_Disp_String[21];	
//*串口变量
uint8_t UART_Str[40]; //串口发送时用于存储发送数据的缓冲区
uint8_t rx_buffer;	//串口接收数据的中间缓冲变量
//*ADC2变量
float ADC2_Voltage;	//R37的电压值
//*RTC变量
RTC_TimeTypeDef T;
RTC_DateTypeDef D;

//***用户自定义变量区
uint8_t Interface_ctrl;// 0x00-界面选择 0x11-小时控制 0x12-分钟控制 0x13-秒控制
uint8_t k_value = 1;	//k初始值为1
uint8_t LED_ctrl;; //0x00-打开 0x01-关闭
uint8_t Clock_Comp_Disp[3]={0,0,0}; //时钟对比值 显示
uint8_t Clock_Comp_Ctrl[3]; //时钟对比值 控制
__IO uint32_t uwTick_Clock_Time_Set_Point;	//时钟时间控制变量
uint8_t Time_Set_Ctrl; //0不灭 1灭
uint8_t Uart_Transmit_Times_Ctrl; //串口发送次数控制
uint8_t rx_Buf[100];	//接收数据缓存区
uint8_t rx_Buf_index;	//接收数据的位置
__IO uint32_t uwTick_RX_Dealy_Time;	//用于对接收时间的判断
_Bool Start_Flag = 0; //起始位判断
__IO uint32_t uwTick_LED_Light_Time;	//用于控制LED闪烁时间

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



//***主函数区
int main(void)
{
  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* Configure the system clock */
  SystemClock_Config();
	
	
	//*初始化区
	//LED和按键的初始化
	LED_KEY_Init();
	
	//LCD的初始化
	LCD_Init();
	LCD_Clear(Black);	//清屏
	LCD_SetBackColor(Black);	//设置背景颜色
	LCD_SetTextColor(Magenta);	//设置文本颜色
	
	//I2C初始化
	I2CInit();
	
	I2C_24c02_read(&k_value , 0 , 1);	//EEPROM读数据
	
	//串口初始化
	UART1_Init();
	HAL_UART_Receive_IT(&huart1 , (uint8_t *)(&rx_buffer) , 1);	//打开串口接收中断 进入串口中断回调函数
	
	//ADC2初始化
	ADC2_Init();
	//RTC实时时钟初始化
	RTC_Init();
	
  while (1)
  {
		LED_Proc();
		KEY_Proc();
		LCD_Proc();
		UART_Proc();
  }
}


//***子函数区

//*LED处理函数
void LED_Proc(void)
{
	if((uwTick - uwTick_LED_Set_Point)<50) return;
		uwTick_LED_Set_Point = uwTick;	//每50ms执行一次
	
	if(LED_ctrl == 0x00)	//打开LED每200ms闪烁功能
	{
		if(ADC2_Voltage > (3.3*k_value*0.1)) //V1>VDD*k VDD=3.3V
		{
			if((uwTick - uwTick_LED_Light_Time)>=200)	//LED每200ms闪烁一次
			{
				uwTick_LED_Light_Time = uwTick;
				
				ucLed ^= 0x01;
			}
		}
		else
			ucLed = 0x00;	//V1<=3.3*k 关闭LED
	}
	else
	{
		ucLed = 0x00;	//LED为OFF 关闭LED
	}
	LED_Disp(ucLed);	//LED显示函数
	
	
}
//*按键处理函数
void KEY_Proc(void)
{
	if((uwTick - uwTick_KEY_Set_Point)<100) return;
		uwTick_KEY_Set_Point = uwTick;	//每100ms执行一次
	
	//按键的三行代码
	key_value = KEY_Scan();
	key_up = ~key_value & (key_value ^ key_old);
	key_down = key_value & (key_value ^ key_old);
	key_old = key_value;
	
	if(key_down == 1)	//按键B1控制LED打开或关闭
	{
		LED_ctrl ^= 0x01;
		
	}
	
	if(key_down == 2)	//按键2控制界面的切换
	{
		Interface_ctrl ^= 0x10;
		LCD_Clear(Black);	//每次切换界面时需清屏
		
		if((Interface_ctrl>>4) == 0)	//当返回主界面时,将将设定的闹钟值赋给闹钟控制值用于判断是否上报
		{
			Clock_Comp_Ctrl[0]=Clock_Comp_Disp[0];
			Clock_Comp_Ctrl[1]=Clock_Comp_Disp[1];
			Clock_Comp_Ctrl[2]=Clock_Comp_Disp[2];
		}
	}
	
	if((Interface_ctrl>>4) == 0x1)	//在设置上报时间界面下
	{
		if(key_down == 3) //按键B3实现时分秒的切换
		{
			Interface_ctrl +=1;
			if(Interface_ctrl == 0x14)
				Interface_ctrl = 0x10;
		}
	}

			
	if(key_down ==4)	//按键B4实现时分秒时间的调整
	{
		if(Interface_ctrl == 0x11)
		{
			Clock_Comp_Disp[0]++;
			if(Clock_Comp_Disp[0] == 24)
			{
				Clock_Comp_Disp[0] = 0;
			}
		}
			
		
		if(Interface_ctrl == 0x12)
		{
			Clock_Comp_Disp[1]++;
			if(Clock_Comp_Disp[1] == 60)
			{
				Clock_Comp_Disp[1] = 0;
			}
		}
		
		if(Interface_ctrl == 0x13)
		{
			Clock_Comp_Disp[2]++;
			if(Clock_Comp_Disp[2] == 60)
			{
				Clock_Comp_Disp[2] = 0;
			}
		}
	}

	
}

//*LCD处理函数
void LCD_Proc(void)
{
	if((uwTick - uwTick_LCD_Set_Point)<100) return;
		uwTick_LCD_Set_Point = uwTick;	//每100ms执行一次
	
	if((Interface_ctrl>>4) == 0x0)	//主界面显示下
	{
		ADC2_Voltage = ADC2_Get_Value()*(3.3/4096);	//ADC2的电压值转换
		HAL_RTC_GetTime(&hrtc , &T ,RTC_FORMAT_BIN);	//打开RTC实时时钟 需要同时获取时间与日期才有效
		HAL_RTC_GetDate(&hrtc , &D ,RTC_FORMAT_BIN);
		
		//*LCD显示
		memset(LCD_Disp_String , 0 ,sizeof(LCD_Disp_String)); 	//清空字符串
		sprintf((char*)LCD_Disp_String , "     V1:%4.2fV  ", ADC2_Voltage);	//打印字符串
		LCD_DisplayStringLine(Line2 , LCD_Disp_String);	//将字符串中的数据打印到屏幕上对应位置
		
		memset(LCD_Disp_String , 0 ,sizeof(LCD_Disp_String));
		sprintf((char*)LCD_Disp_String , "     k:%3.1f ", k_value*0.1);
		LCD_DisplayStringLine(Line4 , LCD_Disp_String);
		
		if(LED_ctrl == 0x00)	//打开LED
		{
				memset(LCD_Disp_String , 0 ,sizeof(LCD_Disp_String));
				sprintf((char*)LCD_Disp_String , "     LED:ON ");
				LCD_DisplayStringLine(Line6 , LCD_Disp_String);
		}
		else	//关闭LED
		{
				memset(LCD_Disp_String , 0 ,sizeof(LCD_Disp_String));
				sprintf((char*)LCD_Disp_String , "     LED:OFF");
				LCD_DisplayStringLine(Line6 , LCD_Disp_String);
		}
		
		memset(LCD_Disp_String , 0 ,sizeof(LCD_Disp_String));
		sprintf((char*)LCD_Disp_String , "     T:%02d-%02d-%02d",T.Hours,T.Minutes,T.Seconds);
		LCD_DisplayStringLine(Line8 , LCD_Disp_String);
		
	}
	else if((Interface_ctrl>>4) == 0x01)	//上报时间设置界面
	{
		
		memset(LCD_Disp_String , 0 ,sizeof(LCD_Disp_String));
		sprintf((char*)LCD_Disp_String , "       Setting");
		LCD_DisplayStringLine(Line2 , LCD_Disp_String);
		
		if(Time_Set_Ctrl == 0x00)
		{
			memset(LCD_Disp_String , 0 ,sizeof(LCD_Disp_String));
			sprintf((char*)LCD_Disp_String , "      %02d-%02d-%02d",Clock_Comp_Disp[0],Clock_Comp_Disp[1],Clock_Comp_Disp[2]);
			LCD_DisplayStringLine(Line5 , LCD_Disp_String);
		}
		
		if((uwTick - uwTick_Clock_Time_Set_Point)>=500) //实现设置时或分或秒时的闪烁功能 每500ms闪烁
		{
			uwTick_Clock_Time_Set_Point = uwTick;
			Time_Set_Ctrl ^= 0x01;
		}
		if(Time_Set_Ctrl == 0x01)	//时间设置控制为0x01为关闭对应位
		{
			if(Interface_ctrl == 0x11)	//小时控制
			{
				memset(LCD_Disp_String , 0 ,sizeof(LCD_Disp_String));
				sprintf((char*)LCD_Disp_String , "        -%02d-%02d",Clock_Comp_Disp[1],Clock_Comp_Disp[2]);
			}
			else if(Interface_ctrl == 0x12)	//分钟控制
			{
				memset(LCD_Disp_String , 0 ,sizeof(LCD_Disp_String));
				sprintf((char*)LCD_Disp_String , "      %02d-  -%02d",Clock_Comp_Disp[0],Clock_Comp_Disp[2]);
			}
			else if(Interface_ctrl == 0x13)	//秒控制
			{
				memset(LCD_Disp_String , 0 ,sizeof(LCD_Disp_String));
				sprintf((char*)LCD_Disp_String , "      %02d-%02d-  ",Clock_Comp_Disp[0],Clock_Comp_Disp[1]);
			}
			else	//时间设置完成 都不闪烁
			{
				sprintf((char*)LCD_Disp_String , "      %02d-%02d-%02d",Clock_Comp_Disp[0],Clock_Comp_Disp[1],Clock_Comp_Disp[2]);
			}
			LCD_DisplayStringLine(Line5 , LCD_Disp_String);		
		}	
	}
}

//*串口处理
void UART_Proc(void)
{
	if((uwTick - uwTick_UART_Set_Point)<50) return;
		uwTick_UART_Set_Point = uwTick;	//每50ms执行一次
	
	//当实时时钟的数值与设置的上报时间相等
	if((T.Hours==Clock_Comp_Ctrl[0])&&(T.Minutes==Clock_Comp_Ctrl[1])&&(T.Seconds==Clock_Comp_Ctrl[2]))
	{
		if(Uart_Transmit_Times_Ctrl == 0)
		{
			Uart_Transmit_Times_Ctrl = 1;		//对每秒钟只上报一次数据的处理 每秒钟只传送一次数据 如果不做处理每秒钟会发送20次
			sprintf((char*)UART_Str , "%4.2f+%3.1f+%02d%02d%02d\n",ADC2_Voltage,k_value*0.1,T.Hours,T.Minutes,T.Seconds);
			HAL_UART_Transmit(&huart1 , UART_Str , strlen((char*)UART_Str) ,50);
		}
	}
	else
	{
		Uart_Transmit_Times_Ctrl = 0;	//串口每秒钟输出数据次数标志位清零以便于修改完上报时间后再次做上面的处理
	}
	
	
	//*串口接收数据处理
	if((uwTick - uwTick_RX_Dealy_Time)>=200 && (uwTick - uwTick_RX_Dealy_Time)<=300) //200ms~300ms之内处理一次
	{
		if(rx_Buf_index == 6)//接收到6个数据
		{
			//判断接收的数据是否正确 如果正确通过串口发送OK 不正确不发送
			if((rx_Buf[0]==0x6B) && (rx_Buf[1]==0x30) && (rx_Buf[2]==0x2E) && (rx_Buf[4]==0x5C) && (rx_Buf[5]==0x6E))
			{
				if((rx_Buf[3]<=0x39) && (rx_Buf[3]>=0x31))
				{					
					k_value = rx_Buf[3] - 0x30;	//串口修改后k_value的值
					sprintf((char*)UART_Str , "ok\n");
					HAL_UART_Transmit(&huart1 , UART_Str , strlen((char*)UART_Str) ,50);
					I2C_24c02_write(&k_value , 0 , 1); //EEPROM写数据 将通过串口修改的k_value的值存入EEPROM中					
				}
				
			}
		}
		rx_Buf_index = 0;
		Start_Flag = 0;
	}
		
	
}

//*串口中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if((rx_buffer == 0x6B) && (rx_Buf_index == 0))
	{
		uwTick_RX_Dealy_Time = uwTick;	//接收到第一个数据开始计数的时间
		Start_Flag = 1;	//接收开始标志位
	}
	if(Start_Flag == 1)
	{
		rx_Buf[rx_Buf_index] = rx_buffer;	//每一位接收到的数存入接收缓冲区中
		rx_Buf_index++;
	
	}
	HAL_UART_Receive_IT(&huart1 , (uint8_t *)(&rx_buffer) , 1);	
}
  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: 蓝桥杯是全国性的计算机大赛,旨在提高大学生的计算机技术水平和创新能力。嵌入式STM32G431是一款嵌入式芯片,具有高性能和低功耗的特点。第十二届第一场省赛停车计费系统是蓝桥杯的一道工程题目,要求参赛选手设计一个停车场计费系统。 停车计费系统是指通过嵌入式技术实现对车辆进入和离开停车场的自动检测、计时和计费的系统。对于这个题目,参赛选手可以根据题目要求,使用STM32G431芯片设计一个具有以下功能的系统: 1. 车辆进入检测:使用车辆传感器检测车辆的进入,触发计时。 2. 车辆离开检测:使用车辆传感器检测车辆的离开,停止计时。 3. 计时功能:使用内部时钟模块获取进入和离开的时间,并计算停车时间。 4. 计费功能:根据停车时间,按照一定的计费规则进行计费。 5. 显示功能:使用液晶显示屏显示当前的停车信息,如车牌号、停车时间、费用等。 6. 数据存储功能:使用闪存等储存介质将停车数据进行存储,以便后续的数据分析和查询。 设计一个停车计费系统涉及到硬件设计和软件编程两个方面。硬件方面,参赛选手需要选择合适的传感器、显示屏、存储介质等,以及设计电路和接口进行连接。软件方面,需要使用C语言或者汇编语言编写程序,对芯片进行编程,实现各项功能。 通过此次比赛,选手们可以锻炼嵌入式系统的设计能力和编程能力,了解实际应用中嵌入式系统的工作原理和应用场景。同时,也能提升对STM32G431芯片的理解和运用能力。这对于培养嵌入式技术人才,推动物联网技术的发展都具有积极意义。 ### 回答2: 蓝桥杯是面向计算机爱好者的智力竞赛,而嵌入式STM32G431是一款嵌入式系统开发板。第十二届第一场省赛的停车计费系统真题工程,则是要求参赛选手设计并实现一个能够进行停车计费的系统。 停车计费系统是一种用于自动计费和管理停车场的系统。这个系统可以通过识别车辆的进出以及停车的时间,自动计算并收费。在这个工程中,选手需要使用嵌入式STM32G431开发板以及相关的硬件和软件,来设计一个能够实现停车计费功能的系统。 首先,选手需要使用传感器或摄像头来实现车辆进出的检测。当车辆进入或离开停车场时,传感器会发出信号并通过STM32G431进行检测。接着,选手需要编程实现识别车辆的算法,以便能够识别不同的车辆。当车辆停放时,系统会通过计时器记录停车的时间。 然后,选手需要编写计费算法,根据停车的时间来计算费用。这个算法可以根据停车场的规则来确定费用的计算方式,例如按小时计费或按照不同的时间段采用不同的费率。 最后,选手还需要设计一个界面,使得系统能够与用户进行交互。用户可以通过该界面查询停车费用,并进行付款。同时,选手还需要保证系统的稳定性和安全性,确保数据的准确性和保密性。 总而言之,蓝桥杯嵌入式STM32G431第十二届第一场省赛停车计费系统真题工程要求选手使用硬件和软件开发能力,设计并实现一个完整的停车计费系统。这需要选手具备嵌入式系统开发、传感器技术、算法设计和界面设计等多方面的知识和技能。 ### 回答3: 蓝桥杯嵌入式stm32g431——第十二届第一场省赛停车计费系统真题工程是一个基于STM32G431开发板的停车计费系统设计题目。该系统的主要功能是实现停车场的车辆进入、出场的计费管理。 首先,该系统需要实现一个车辆进入检测的功能。当车辆进入停车场时,系统会通过传感器检测到车辆的到达,并记录下进入的时间。 然后,系统需要实现一个车辆出场的功能。当车辆准备离开停车场时,系统会通过传感器检测到车辆的离开,并记录下离开的时间。 接下来,系统需要计算车辆停留的时间。通过进入时间和离开时间的差值计算得出车辆停留的时长。 最后,系统需要计算停车费用。根据停车场的计费规则,根据车辆停留的时长计算出停车费用,并将费用显示在屏幕上。 在实现上述功能的过程中,需要运用STM32G431开发板的各种功能和模块,包括GPIO口、定时器、中断、串口通信等。通过编写相应的代码,实现按钮的控制、传感器检测、时间的计算以及屏幕的显示等功能。 该项目的设计需要考虑多种情况,比如车辆重复进入出场、车辆进入出场顺序错乱等,要充分考虑这些异常情况并进行相应的处理。在代码编写过程中,还需注意代码的优化和资源的合理利用,以提高系统的性能和效率。 通过完成这个项目的设计与实现,可以加深对STM32G431嵌入式系统的了解和应用,并提升嵌入式系统开发的能力。同时,也能锻炼自己的逻辑思维、问题解决能力和团队合作精神。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lzya.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值