第十五届蓝桥杯嵌入式模拟题三

终于拿满分了

接下来步入正题

一、基本要求


使用大赛组委会提供的嵌入式竞赛实训平台(基于STM32G431RBT6微控制器设计),完成本试题的程序设计与调试。程序编写、调试完成后,选手需通过考试系统提交以准考证号命名的hex文件。

hex文件是唯一成绩评测依据,不符合以上文件提交要求的作品将被评为零分或者被酌情扣分。

二、硬件框图


图1 系统硬件框图

三、功能描述   


3.1 基本功能

1)通过微控制器的ADC功能,检测电位器R37和R38上输出的模拟电压信号,分别模拟某工厂生产的R37和R38两类产品。

2)通过串口完成数据查询功能。

3)根据试题要求,通过按键实现界面切换、产品检测标准调整等功能。

4)根据试题要求,通过LED和LCD完成数据显示和报警功能。

3.2 显示功能

1)产品参数界面

产品参数如图2所示,显示要素包括界面名称(GOODS)、R37产品(R37)、R38产品(R38)。

图2 产品参数界面

备注:

采集的电压值保留小数点后两位,单位为V。

2)标准设置界面

标准设置界面图3所示,显示内容包括界面名称(STANDARD),R37产品检测标准(SR37)和R38产品检测标准(SR38)。

图3 标准设置界面

3)合格率界面

合格率界面如图4所示,显示内容包括界面名称(PASS),R37产品合格率(PR37)和R38产品合格率(PR38)

图4 合格率界面

产品合格标准:

产品检测标准下限≤产品电压值≤产品检测标准上限

合格率计算公式:

合格率保留小数点后一位。

显示说明

(1)显示背景颜色(BackColor):黑色。

(2)显示字体颜色(TextColor):白色。

(3)请严格按照图示要求设计各个信息项的名称(区分字母大小写)和相对行列位置。

3.3 按键功能

1)B1:定义为“切换”按键,按下按键B1,切换“产品参数界面”、“标准设置界面”和“合格率界面”,切换顺序如图5所示。

图5 界面切换顺序

2)B2:

① 在“产品参数界面”下,定义为“R37检测”按键,按下按键B2,检测产品R37是否合格。

② 在“标准设置界面”下,定义为“选择”按键,选择需要调整产品R37、产品R38的检测标准上限或下限,选择顺序如图6所示。

图6 选择顺序

3)B3:

① 在“产品参数界面”下,定义为“R38检测”按键,按下按键B3,检测产品R38是否合格。

② 在“标准设置界面”下,定义为“加”按键,按下按键B3,选择的产品标准上限或下限加0.2,产品标准上限加顺序如图7.1所示。

图7.1 产品标准上限加顺序

产品标准下限加顺序如图7.2所示。

图7.2 产品标准下限加顺序

3)B4:

① 在“合格率界面”下,定义为“清零”按键,按下按键B4,清零当前得出的产品R37和产品R38的合格率。

② 在“标准设置界面”下,定义为“减”按键,按下按键B4,选择的产品标准上限或下限减0.2,产品标准上限减顺序如图8.1所示。

图8.1 产品标准上限减顺序

产品标准下限减顺序如图8.2所示。

图8.2 产品标准下限减顺序

注意:

    • 注意若某一产品标准改变,对应产品的合格率清零;
    • 当前界面下无功能的按键按下,不触发其它界面的功能;
    • 按键应进行有效的防抖处理,避免出现一次按键动作触发多次功能等情形;
    • 按键动作不应影响数据采集过程和屏幕显示效果。

3.4 串口功能

1)使用竞赛平台上的USB转串口完成相关功能设计。

2)串口通信波特率设置为9600bps。

3)串口接收到字符“R37”或“R38”后,向PC端返回对应产品的名称、当前总检测数、合格数及合格率。返回格式如下:

产品名称:总检测数,合格数,合格率

例如:

串口接收到字符:R37

串口向PC端返回:R37:23,20,87.0%

注意:

合格率保留小数点后一位。

串口接收到非法字符,不作返回。除字符“R37”和“RS8”外的字符均为非法字符。

3.5 LED指示灯功能

1)LD1:产品R37检测通过时,LD1点亮1s后熄灭;

2)LD2:产品R38检测通过时,LD2点亮1s后熄灭;

5)LD3:“产品参数界面”下,LD3点亮,否则熄灭;

6)LD4:“标准设置界面”下,LD4点亮,否则熄灭;

7)LD5:“合格率界面”下,LD5点亮,否则熄灭;

6)指示灯LD6~LD8始终处于熄灭状态。

3.6 初始状态说明

设备上电后,初始状态如下:

1)产品参数界面;

2)选择调整参数R37;

3)产品R37标准:1.2-2.2;

4)产品R38标准:1.4-3.0;

备注:请严格按照此初始状态设计功能。

相关代码如下:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2024 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 "interrupt.h"
#include "myadc.h"
#include "led.h"
#include "lcd.h"
#include "stdio.h"
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

extern struct key_t key[4];
extern struct uart1_t uart1;
extern struct myadc_t myadc;
extern struct interface_t interface;
extern struct data_t data;
extern struct led_t led;
/* USER CODE END PTD */

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

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
void lcd_process(void)
{
		char buf[50];
	  if(interface.flg == 0) //产品参数界面
		{
			sprintf(buf,"       GOODS");
			LCD_DisplayStringLine(Line1,(uint8_t*)buf);
			sprintf(buf,"     R37:%.2fV",myadc.r37);
			LCD_DisplayStringLine(Line3,(uint8_t*)buf);
			sprintf(buf,"     R38:%.2fV",myadc.r38);
			LCD_DisplayStringLine(Line4,(uint8_t*)buf);
		}
		else if(interface.flg == 1)//标准设置界面
		{
		  sprintf(buf,"      STANDARD");
			LCD_DisplayStringLine(Line1,(uint8_t*)buf);
			sprintf(buf,"    SR37:%.1f-%.1f",data.r37_l,data.r37_h);
			LCD_DisplayStringLine(Line3,(uint8_t*)buf);			
			sprintf(buf,"    SR38:%.1f-%.1f",data.r38_l,data.r38_h);
			LCD_DisplayStringLine(Line4,(uint8_t*)buf);				
		}
		else if(interface.flg == 2)//合格率界面
		{
			sprintf(buf,"        PASS");
			LCD_DisplayStringLine(Line1,(uint8_t*)buf);
			sprintf(buf,"     PR37:%.1f%c  ",data.r37_rate,'%');
			LCD_DisplayStringLine(Line3,(uint8_t*)buf);			
			sprintf(buf,"     PR38:%.1f%c  ",data.r38_rate,'%');
			LCD_DisplayStringLine(Line4,(uint8_t*)buf);		
		}
		
}

void key_process(void)
{
		//B1
	  if(key[0].short_flg == 1)
		{
			  LCD_Clear(Black);
			  interface.flg++;
			  if(interface.flg > 2)
				{
						interface.flg = 0;
				}
				key[0].short_flg = 0;
		}
		
	  //B2
	  if(key[1].short_flg == 1 && interface.flg == 0)//检测R37
		{
			 data.r37_flg = 1;
				key[1].short_flg = 0;
		}
	  if(key[1].short_flg == 1 && interface.flg == 1)//选择R38 r37
		{
			  interface.place++;
			  if(interface.place > 3)
				{
						interface.place = 0;
				}
				key[1].short_flg = 0;
		}
		
	  //B3
	  if(key[2].short_flg == 1 && interface.flg == 0)//检测R38
		{
			  data.r38_flg = 1;
				key[2].short_flg = 0;
		}
	  if(key[2].short_flg == 1 && interface.flg == 1)//加R38 r37
		{
			data.r38_sun = 0;
			data.r37_sun = 0;
			data.r37 = 0;
			data.r38 = 0;
			data.r37_rate = 0;
			data.r38_rate = 0;

				if(interface.place == 0)//r37上线加
				{
				  data.r37_h+=0.2f;
					
					if(data.r37_h >= 3.2f)
					{
							data.r37_h = 2.2f;
					}
				}
				else if(interface.place == 1)
				{
				  data.r37_l+=0.2f;
					
					if(data.r37_l >= 2.2f)
					{
							data.r37_l = 1.2f;
					}				
				}
				else if(interface.place == 2)
				{
				  data.r38_h+=0.2f;
					
					if(data.r38_h >= 3.2f)
					{
							data.r38_h = 2.2f;
					}				
				}
				else if(interface.place == 3)
				{
				  data.r38_l+=0.2f;
				
					if(data.r38_l >= 2.2f)
					{
							data.r38_l = 1.2f;
					}							
				}
				key[2].short_flg = 0;
		}
	  //B4
	  if(key[3].short_flg == 1 && interface.flg == 1)//减R38 r37
		{
			data.r38_sun = 0;
			data.r37_sun = 0;
			data.r37 = 0;
			data.r38 = 0;
			data.r37_rate = 0;
			data.r38_rate = 0;
				if(interface.place == 0)//r37上限减
				{
					
				  data.r37_h-=0.2f;
					if(data.r37_h <= 2.0f)
					{
							data.r37_h = 3.0f;
					}
				}
				else if(interface.place == 1)
				{
				  data.r37_l-=0.2f;
					 
					if(data.r37_l <= 1.0f)
					{
							data.r37_l = 2.0f;
					}				
				}
				else if(interface.place == 2)
				{
				  data.r38_h-=0.2f;
					  
					if(data.r38_h <= 2.0f)
					{
							data.r38_h = 3.0f;
					}				
				}
				else if(interface.place == 3)
				{
				  data.r38_l-=0.2f;
					
					if(data.r38_l <= 1.0f)
					{
							data.r38_l = 2.0f;
					}							
				}			  
				key[3].short_flg = 0;
		}
	  if(key[3].short_flg == 1 && interface.flg == 2)//合格率清0
		{
			data.r38_sun = 0;
			data.r37_sun = 0;
			data.r37 = 0;
			data.r38 = 0;
			data.r37_rate = 0;
			data.r38_rate = 0;
				key[3].short_flg = 0;
		}
}

void adc_process(void)
{
		myadc.r37 = get_adec(&hadc2);
	  myadc.r38 = get_adec(&hadc1);
}

void datetion_process(void)
{
		//r38检测
	  if(data.r38_flg)
		{
			  data.r38_sun++;//检测一次总数加1
			  if(myadc.r38 >= data.r38_l && myadc.r38 <= data.r38_h)//检测通过
				{
					  led.r38 = 1;
						data.r38++;
				}
				data.r38_rate = (data.r38*1.0f/data.r38_sun*1.0f)*100.0f;
				data.r38_flg = 0;
		}
		//r37检测
	  if(data.r37_flg)
		{
			  data.r37_sun++;//检测一次总数加1
			  if(myadc.r37 >= data.r37_l && myadc.r37 <= data.r37_h)//检测通过
				{
					  led.r37 = 1;
						data.r37++;
				}
				data.r37_rate = (data.r37*1.0f/data.r37_sun*1.0f)*100.0f;
				data.r37_flg = 0;
		}
}

void myprintf(uint8_t *buf)
{
		while(*buf != 0)
		{
				HAL_UART_Transmit(&huart1,buf++,1,0xffff);
		}
}

void uart_process(void)
{
	  uint8_t str[5];
	  char buf[40];
		if(uart1.place > 0)
		{
				uart1.lenght = uart1.place;
			  HAL_Delay(1);
			  if(uart1.place == uart1.lenght)
				{
					  if(uart1.place == 3)
						{
						   sscanf((char*)uart1.buf,"%3s",str);
							 if(!strcmp((char*)str,"R37"))
							 {
									sprintf(buf,"%s:%d,%d,%.1f%c",str,data.r37_sun,data.r37,data.r37_rate,'%');
								  myprintf((uint8_t*)buf);
							 }
							 else if(!strcmp((char*)str,"R38"))
							 {
									sprintf(buf,"%s:%d,%d,%.1f%c",str,data.r38_sun,data.r38,data.r38_rate,'%');
								  myprintf((uint8_t*)buf);
							 }
						}
					  uart1.place = 0;
						memset(uart1.buf,0,sizeof(uart1.buf));
				}
		}
}

void led_process(void)
{
		uint8_t mode = 0;
	  if(interface.flg == 0)
		{
		      mode |= 0x04;
		}
		else
		{
				mode &= 0xfb;
		}
	
	  if(interface.flg == 1)
		{
		    mode |= 0x08;
		}
		else
		{
		   mode &= 0xf7;
		}

	  if(interface.flg == 2)
		{
		   mode |= 0x10;
		}
		else
		{
		   mode &= 0xef;
		}
		
		if(led.r37)
		{
				mode |= 0x01;
		}
		else
		{
				mode &= 0xfe;
		}
		
		if(led.r38)
		{
				mode |= 0x02;
		}
		else
		{
				mode &= 0xfd;
		}
		LED_Disp(mode);
}

/* 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 */

/* 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_ADC1_Init();
  MX_ADC2_Init();
  MX_TIM4_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	data.r37_l = 1.2f;
	data.r37_h = 2.2f;
	data.r38_l = 1.4f;
	data.r38_h = 3.0f;
	LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
  HAL_TIM_Base_Start_IT(&htim4);
	 HAL_UART_Receive_IT(&huart1,&uart1.data,1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
lcd_process();
		key_process();
		adc_process();
		datetion_process();
		uart_process();
		led_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 CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV3;
  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 busses 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_3) != 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****/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DENG YIRU

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

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

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

打赏作者

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

抵扣说明:

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

余额充值