第十五届蓝桥杯嵌入式模拟考试I

时隔多日,蓝桥杯比赛将之,听老师说还有模拟题这个东西(以前从没听说过),不模拟不知道,一模拟吓一跳,废话不多说直接上图,这是只做编程题的得分满分85,剩下的几分我实在拿不到了

image-20240323011933926

前面2次提交时没有注意lcd的行数,看了评测记录才知道又很多的评测都跟lcd有关,如果显示的行数出错那当然是拿不到分的,后面那次提交是因为题目中lcd是从第一行开始的,而我们的lcd 是从Line0开始的,还是会导致lcd差一行,应该庆幸没有直接比赛,而是进行了模拟,经过这次模拟后才发现了,自己有时粗心大意的毛病,大家做题的时候可不要学我,要仔细审题,不要放过任何一个细节。

下面进行此次题目的分析,其他部分就不多解释,主要是usart_process(),在这个函数中我使用switch case语句实现了一个状态机

下面是对各个状态的解释

状态0

这个状态是为了判断串口是否接收到了数据,如果接收到数据就解析该数据,同时进入状态2,如果没有接收到数据那就继续等待

状态1

这个状态是将收到的指令赋值给model,同时更新接收到数据的时间

状态2

这个状态用于等待5s内是否有按键按下,按键按下则说明左转或者右转成功,然后继续回到状态0,继续等待下一次数据,同时要return出去防止下面的5s内没有按键按下的逻辑也执行,如果5s内没有按键按下,那就要像串口助手发送警告信息,并且继续回到状态0等待

这个题目的状态机并不复杂稍加思考就能想到,关键在每个状态的转换条件以及每个状态应该做什么动作

题目

image-20240323011509614

image-20240323011524476

image-20240323011537863

image-20240323011550074

代码

这里只给出了主要的代码,key,led,myadc的代码,可以看我往期文章

蓝桥杯历年省赛合集

main.c
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "key.h"
#include "led.h"
#include "myadc.h"
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
extern Key key[4];
uint8_t menu = 0;
float distance;
uint8_t lcdtext[30];
char  model = 'S';
float Kval = 300.0f/3.0f;
extern uint8_t buffer[5];
extern uint8_t rxdata[1];
uint8_t printtext[40];
extern uint8_t pointer;
uint64_t rxtime;
uint8_t B3=0,B4=0;
uint32_t led1time,led2time;
uint8_t led;
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void key_process(void)
{
	if(key[0].key_flag&&menu==1)
	{
		key[0].key_flag = 0;
		menu = 0;
		model = 'S';
		sprintf((char *)printtext, "Success\r\n");
    HAL_UART_Transmit(&huart1, printtext, strlen((char *)printtext), 100);
		LCD_Clear(Black);
    LCD_SetBackColor(Black);
    LCD_SetTextColor(White);		
	}
	if(key[2].key_flag)
	{
		key[2].key_flag = 0;
		if(model=='S'&&menu==0)
		{
			sprintf((char *)printtext, "Warn\r\n");
      HAL_UART_Transmit(&huart1, printtext, strlen((char *)printtext), 100);
			menu = 1;
			
		}
		if(model=='L')
		{
			B3 = 1;
		}
		
		LCD_Clear(Black);
    LCD_SetBackColor(Black);
    LCD_SetTextColor(White);
	}
	
	if(key[3].key_flag)
	{
		key[3].key_flag = 0;
		if(model=='S'&&menu==0)
		{
			menu = 1;
			sprintf((char *)printtext, "Warn\r\n");
      HAL_UART_Transmit(&huart1, printtext, strlen((char *)printtext), 100);
		}
		if(model=='R')
		{
			B4 = 1;
		}
		
		LCD_Clear(Black);
    LCD_SetBackColor(Black);
    LCD_SetTextColor(White);
	}
}
void usart_process(void)
{
    static uint8_t state = 0;
    switch(state)
    {
        case 0: // 等待接收数据状态
            if(pointer > 0)
            {
                // 检查是否为'R'或'L'
								sprintf((char *)printtext,"WAIT\r\n");
								HAL_UART_Transmit(&huart1,printtext,strlen((char *)printtext),100);
                if(buffer[0] == 'R' || buffer[0] == 'L')
                {
                    state = 1; // 是'R'或'L',转移到解析数据状态
                }
                else
                {
                    // 不是'R'或'L',直接发送ERROR
                    sprintf((char *)printtext, "ERROR\r\n");
                    HAL_UART_Transmit(&huart1, printtext, strlen((char *)printtext), 100);
                    // 重置指针和缓冲区,准备下一次数据接收
                    pointer = 0;
                    memset(buffer, 0, sizeof(buffer));
                    // 不改变状态,留在0等待下一次数据
                }
            }
            break;
        case 1: // 解析数据状态
            model = buffer[0]; // 此时model已经确定是'R'或'L'
            rxtime = uwTick; // 更新接收时间
            state = 2; // 准备进行下一步的逻辑判断
            break;
        case 2: // 判断数据类型并等待按键按下状态
            if(uwTick - rxtime <= 5000) // 5秒内的逻辑处理
            {
                if((model == 'L' && B3) || (model == 'R' && B4))
                {
                    // 按键成功响应
                    sprintf((char *)printtext, "Success\r\n");
                    HAL_UART_Transmit(&huart1, printtext, strlen((char *)printtext), 100);
                    // 重置按键状态
                    B3 = 0;
                    B4 = 0;
										menu = 0;
										pointer = 0;
										memset(buffer, 0, sizeof(buffer));
										state = 0; // 重置状态,返回等待接收数据状态
										model = 'S';
										return;
                }
                else
                {
                    // 继续等待按键或超时
                    break;
                }
            }
            else
            {
                // 超过5秒,发送超时警告
							menu = 1;
							B3 = 0;
              B4 = 0;
							LCD_Clear(Black);
							LCD_SetBackColor(Black);
							LCD_SetTextColor(White);
              sprintf((char *)printtext, "Warn\r\n");
              HAL_UART_Transmit(&huart1, printtext, strlen((char *)printtext), 100);
            }
            // 重置指针和缓冲区,准备下一次数据接收
            pointer = 0;
            memset(buffer, 0, sizeof(buffer));
            state = 0; // 重置状态,返回等待接收数据状态
            break;
    }
}

	
	
void adc_process(void)
{
	float adcval = get_adc(&hadc2);
	if(adcval>=0&&adcval<=3.0f)
	{
		distance = adcval*Kval;
	}else if(adcval>3.0){
		distance = 300;
	}
}
void lcd_process(void)
{
	switch(menu)
	{
		case 0:
		{
			sprintf((char *)lcdtext,"       DATA  ");
			LCD_DisplayStringLine(Line1,lcdtext);
			
			sprintf((char *)lcdtext,"   N:%c",model);
			LCD_DisplayStringLine(Line3,lcdtext);
			sprintf((char *)lcdtext,"   D:%.1f",distance);
			LCD_DisplayStringLine(Line4,lcdtext);
		}break;
		case 1:
		{
			sprintf((char *)lcdtext,"        WARN");
			LCD_DisplayStringLine(Line4,lcdtext);
		}break;
	}
}
void led_process(void)
{
	static uint8_t led1state = 0;
	static uint8_t led2state = 0;
	if(menu==0&&model=='L')
	{
		
		
		if(uwTick-led1time>100)
		{
			led1time = uwTick;
			if(led1state)
			{
				led1state = 0;
				led&=~0x01;
			}else{
				led1state = 1;
				led|=0x01;
			}
			led_display(led);
		}
	}else{
		led&=~0x01;
		led_display(led);
	}
	
	if(menu==0&&model=='R')
	{
		if(uwTick-led2time>100)
	{
		led2time = uwTick;
		if(led2state)
		{
			led2state = 0;
			led&=~0x02;
		}else{
			led2state = 1;
			led|=0x02;
		}
		led_display(led);
	}
	
	}else{
		led&=~0x02;
		led_display(led);
	}
	
	if(menu==1)
	{
		led|=0x80;
		led_display(led);
	}else{
		led&=~0x80;
		led_display(led);
	}
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC2_Init();
  MX_TIM2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

    LCD_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

    LCD_Clear(Black);
    LCD_SetBackColor(Black);
    LCD_SetTextColor(White);
		HAL_TIM_Base_Start_IT(&htim2);
		HAL_UART_Receive_IT(&huart1,rxdata,1);
		led_display(0x00);
    while (1)
    {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
			adc_process();
			led_process();
			key_process();
			usart_process();
			lcd_process();
    }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_ADC12;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

usart1.c
#include "usart1.h"
#include <stdio.h>
#include <string.h>
uint8_t buffer[5];
uint8_t rxdata[1];
uint8_t pointer = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
		buffer[pointer++] = rxdata[0];
		HAL_UART_Receive_IT(huart,rxdata,1);
	}
}



Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐