第十三届蓝桥杯省赛第二场(嵌入式组)真题考场源码

        答主今年大二,第一次参加蓝桥杯,大概花了三个月左右的时间备考,stm32从0入门,考前把15-21年的真题撸了两遍;到后面基本可以不看任何教程完成任一年省赛的全部功能了。

        考前一天晚上睡觉前,答主还把代码都看了一遍,重点看了IIC,以为万无一失了,没想到大意了 (ノへ ̄、) ≡(▔﹏▔)≡ ╯︿╰,把EEPROM读模式和写模式搞混了...........

        十三届的第一场和第二场的题目都蛮简单的,答主前三个小时就已经实现除EEPEROM读数据以外的所有功能了,最后两个小时一直在盯着i2c.c找bug,直到最后十分钟才发现0xa0和0xa1写反了!!!于是迅速改代码,商品库存能实现存储了,价格死活读不出来,考试结束前两分钟带着价格无法存储的小bug提交了设计题。

        然鹅,刚提交完答主就想到浮点型数据要取整后再存储,可惜已经来不及了(ノへ ̄、)(ノへ ̄、)(ノへ ̄、),改完已经没有时间压缩提交了。

        唉~~~就以这一段代码浅浅纪念这三个月吧~~


#include "main.h"
#include "tim.h"
#include "usart.h"
#include "key_led.h"
#include "lcd.h"
#include "i2c_hal.h"
/*******************************子函数声明区*********************************/
void SystemClock_Config(void);
void Key_Process(void);
void Led_Process(void);
void Lcd_Process(void);

/*******************************全局变量声明区*****************************/
__IO uint32_t uwTick_key_speed = 0;
__IO uint32_t uwTick_led_speed = 0;
__IO uint32_t uwTick_lcd_speed = 0;
__IO uint32_t uwTick_LD1_Count = 0;//LD1亮五秒计时
__IO uint32_t uwTick_LD2_Count = 0;//LD2以0.1秒闪烁计时

//按键滤波专用变量
uint8_t key_val, key_down, key_up, key_old;

//Lcd显示专用变量
unsigned char Lcd_DispString[21];

//LED显示专用变量
uint8_t led_disp_value=0;

//串口收发专用变量
uint8_t uart_rx_1B=0;//接收数据一字节
char uart_tx_str[40];//串口数据发送数组

//EEPROM专用变量
uint8_t EEPROM_Write[6] = {10, 10, 1.0, 1.0, 5, 5};//初始值
uint8_t EEPROM_Ctrl[6];//非第一次上电所用值

/***************************本题相关变量**************************/
uint8_t LCD_Page = 0;//LCD显示界面控制

uint16_t Buy_Num_X = 0;//X的购买数量
uint16_t Actually_Buy_Num_X = 0;//X的真实购买数量
uint16_t Buy_Num_Y = 0;//Y的购买数量
uint16_t Actually_Buy_Num_Y = 0;//Y的真实购买数量

float X_Price;//X的价格
float Y_Price;//Y的价格

uint16_t X_Storage_Num;//X的库存数量
uint16_t Y_Storage_Num;//Y的库存数量

uint8_t B4_Uart_Flag = 0;//串口发送控制位

float Total_Price=0;//购买商品总价

int main(void)
{
 
	HAL_Init();
	SystemClock_Config();

	MX_Key_Led_Init();
	MX_TIM2_Init();
	MX_UART1_Init();
	I2CInit();

	LCD_Init();
	LCD_SetTextColor(White);
	LCD_SetBackColor(Black);
	LCD_Clear(Black);
	
	HAL_UART_Receive_IT(&huart1, &uart_rx_1B, 1);//开启串口接收中断
	
	//EEPROM
	IIC_EEPROM_Read(EEPROM_Ctrl, 0, 6);
	if((EEPROM_Ctrl[4]!=5)&&(EEPROM_Ctrl[5]!=5))//第一次上电判别
	{
		IIC_EEPROM_Write(EEPROM_Write, 0, 6);
		HAL_Delay(500);
		IIC_EEPROM_Read(EEPROM_Ctrl, 0, 6);
	}
	
	//启动PWM输出
	__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 25);//输出占空比5%
	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
	
	while (1)
	{
		Key_Process();
		Led_Process();
		Lcd_Process();
	}
 
}

void Key_Process(void)
{
	if(uwTick - uwTick_key_speed < 50) return;
	uwTick_key_speed = uwTick;
	
	key_val = Key_Scan();
	key_down = key_val & (key_val ^ key_old);
	key_up = ~key_val & (key_val ^ key_old);
	key_old = key_val;
	
	switch(key_down)
	{
		case 1://界面切换
			if((LCD_Page+1) != 3)
			{
				LCD_Page++;
				LCD_Clear(Black);				
			}
			else 
			{
				LCD_Page=0;
				LCD_Clear(Black);
			}
		break;
		
		case 2://X相关变量控制
			if(LCD_Page == 0)//购买数量界面
			{
				if((Buy_Num_X+1)<=X_Storage_Num)
				{
					Buy_Num_X++;
				}
			}
			else if(LCD_Page == 1)//商品价格界面
			{
				if((int)((X_Price+0.1)*10) <=20)
				{
					X_Price += 0.1;
				}
				else if((int)((X_Price+0.1)*10) >20)
				{
					X_Price = 1.0;
				}
				
				EEPROM_Ctrl[2] = X_Price*10;//更新X价格
				IIC_EEPROM_Write(EEPROM_Ctrl, 0, 6);//将更新价格写进EEPROM
		
			}
			else if(LCD_Page == 2)//商品库存界面
			{
				X_Storage_Num++;
				
				EEPROM_Ctrl[0] = X_Storage_Num;//EEPROM更新
				IIC_EEPROM_Write(EEPROM_Ctrl, 0, 6);//将更新库存写进EEPROM
			}
		break;
		
		case 3://Y相关变量控制
			if(LCD_Page == 0)//购买数量界面
				{
					if((Buy_Num_Y+1)<=X_Storage_Num)
					{
						Buy_Num_Y++;
					}
				}
				else if(LCD_Page == 1)//商品价格界面
				{
					if((int)((Y_Price+0.1)*10) <=20)
					{
						Y_Price += 0.1;
					}
					else if((int)((Y_Price+0.1)*10) >20)
					{
						Y_Price = 1.0;
					}
					
					EEPROM_Ctrl[3] = Y_Price*10;//更新Y价格
					IIC_EEPROM_Write(EEPROM_Ctrl, 0, 6);//将更新价格写进EEPROM
					
				}
				else if(LCD_Page == 2)//商品库存界面
				{
					Y_Storage_Num++;
					
					EEPROM_Ctrl[1] = Y_Storage_Num;//EEPROM更新
					IIC_EEPROM_Write(EEPROM_Ctrl, 0, 6);//将更新库存写进EEPROM
				}
		break;
		
		case 4://确认按键
			if(LCD_Page == 0)
			{
				if(X_Storage_Num>=Buy_Num_X)//库存数量大于购买数量,满足购买
				{
					Actually_Buy_Num_X = Buy_Num_X;
					X_Storage_Num -= Buy_Num_X;
				}
			
				
				if(Y_Storage_Num>=Buy_Num_Y)//库存数量大于购买数量,满足购买
				{
					Actually_Buy_Num_Y = Buy_Num_Y;
					Y_Storage_Num -= Buy_Num_Y;
				}
			
				
				EEPROM_Ctrl[0] = X_Storage_Num;//EEPROM更新
				EEPROM_Ctrl[1] = Y_Storage_Num;//EEPROM更新
				IIC_EEPROM_Write(EEPROM_Ctrl, 0, 6);//将更新库存写进EEPROM
				
				Buy_Num_X = 0;//清零
				Buy_Num_Y = 0;//清零
				B4_Uart_Flag = 1;
				
				uwTick_LD1_Count = uwTick;//LD1亮开始计时
				led_disp_value |= 0x01;
			}
		break;
	}
}


void Led_Process(void)
{
	if(uwTick - uwTick_led_speed < 50) return;
	uwTick_led_speed = uwTick;
	
	if(uwTick - uwTick_LD1_Count > 5000)
	{
		led_disp_value &= ~0x01;//时间到,熄灭LD1
		__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 25);//PWM借用,输出占空比5%
	}
	else 
	{
		__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2 , 150);//PWM借用,输出占空比3%
	}
	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
	
	if((X_Storage_Num == 0)&&(Y_Storage_Num == 0))//库存为0,LD2以0.1S闪烁
	{
		if(uwTick - uwTick_LD2_Count > 100)
		{
			led_disp_value ^= 0x02;
			uwTick_LD2_Count = uwTick;
		}
	}
	else
	{
		led_disp_value &= ~0x02;//熄灭LD2
	}
	
	Led_Disp(led_disp_value);
}


void Lcd_Process(void)
{
	if(uwTick - uwTick_lcd_speed < 50) return;
	uwTick_lcd_speed = uwTick;

    X_Price = (float)EEPROM_Ctrl[2]/10.0;
	Y_Price = (float)EEPROM_Ctrl[3]/10.0;

	X_Storage_Num = EEPROM_Ctrl[0];
	Y_Storage_Num = EEPROM_Ctrl[1];
	
	
	if(LCD_Page == 0)//购买数量页面
	{
		sprintf((char*)Lcd_DispString, "        SHOP");
		LCD_DisplayStringLine(Line1, Lcd_DispString);
		
		sprintf((char*)Lcd_DispString, "     X:%d  ", Buy_Num_X);
		LCD_DisplayStringLine(Line3, Lcd_DispString);
		
		sprintf((char*)Lcd_DispString, "     Y:%d  ", Buy_Num_Y);
		LCD_DisplayStringLine(Line4, Lcd_DispString);
	}
	else if(LCD_Page == 1)//价格页面
	{
		sprintf((char*)Lcd_DispString, "        PRICE");
		LCD_DisplayStringLine(Line1, Lcd_DispString);
		
		sprintf((char*)Lcd_DispString, "     X:%3.1f  ", X_Price);
		LCD_DisplayStringLine(Line3, Lcd_DispString);
		
		sprintf((char*)Lcd_DispString, "     Y:%3.1f  ", Y_Price);
		LCD_DisplayStringLine(Line4, Lcd_DispString);
	}
	else if(LCD_Page == 2)//库存页面
	{
		sprintf((char*)Lcd_DispString, "        REP");
		LCD_DisplayStringLine(Line1, Lcd_DispString);
		
		sprintf((char*)Lcd_DispString, "     X:%02d  ", X_Storage_Num);
		LCD_DisplayStringLine(Line3, Lcd_DispString);
		
		sprintf((char*)Lcd_DispString, "     Y:%02d  ", Y_Storage_Num);
		LCD_DisplayStringLine(Line4, Lcd_DispString);
	}
	
	//串口发送数据借用
	if(B4_Uart_Flag == 1)
	{
		//总价格折算
		Total_Price = Actually_Buy_Num_X*X_Price + Actually_Buy_Num_Y*Y_Price;
		
		sprintf(uart_tx_str, "X:%d, Y:%d, Z:%3.1f\n", Actually_Buy_Num_X, Actually_Buy_Num_Y, Total_Price);
		HAL_UART_Transmit(&huart1, (unsigned char*)uart_tx_str, strlen(uart_tx_str), 50);
		
		
		B4_Uart_Flag = 0;
	}

}


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//接收完成回调函数
{
	if(uart_rx_1B == '?')
	{
		sprintf(uart_tx_str, "X:%3.1f, Y:%3.1f\n", X_Price, Y_Price);
		HAL_UART_Transmit(&huart1, (unsigned char*)uart_tx_str, strlen(uart_tx_str), 50);
	}
	
	HAL_UART_Receive_IT(&huart1, &uart_rx_1B, 1);//开启串口接收中断
}


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

请让我躺平

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

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

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

打赏作者

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

抵扣说明:

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

余额充值