第十五届蓝桥杯嵌入式模拟考试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',直接发送ERRORsprintf((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);}
}