第十五届蓝桥杯嵌入式模拟考试I
时隔多日,蓝桥杯比赛将之,听老师说还有模拟题这个东西(以前从没听说过),不模拟不知道,一模拟吓一跳,废话不多说直接上图,这是只做编程题的得分满分85,剩下的几分我实在拿不到了
前面2次提交时没有注意lcd的行数,看了评测记录才知道又很多的评测都跟lcd有关,如果显示的行数出错那当然是拿不到分的,后面那次提交是因为题目中lcd是从第一行开始的,而我们的lcd 是从Line0开始的,还是会导致lcd差一行,应该庆幸没有直接比赛,而是进行了模拟,经过这次模拟后才发现了,自己有时粗心大意的毛病,大家做题的时候可不要学我,要仔细审题,不要放过任何一个细节。
下面进行此次题目的分析,其他部分就不多解释,主要是usart_process(),在这个函数中我使用switch case语句实现了一个状态机
下面是对各个状态的解释
状态0
这个状态是为了判断串口是否接收到了数据,如果接收到数据就解析该数据,同时进入状态2,如果没有接收到数据那就继续等待
状态1
这个状态是将收到的指令赋值给model,同时更新接收到数据的时间
状态2
这个状态用于等待5s内是否有按键按下,按键按下则说明左转或者右转成功,然后继续回到状态0,继续等待下一次数据,同时要return出去防止下面的5s内没有按键按下的逻辑也执行,如果5s内没有按键按下,那就要像串口助手发送警告信息,并且继续回到状态0等待
这个题目的状态机并不复杂稍加思考就能想到,关键在每个状态的转换条件以及每个状态应该做什么动作
题目
代码
这里只给出了主要的代码,key,led,myadc的代码,可以看我往期文章
蓝桥杯历年省赛合集
main.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© 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);
}
}