蓝桥杯嵌入式第15届模拟3-编程解析

一、题目展示

蓝桥杯嵌入式第15届模拟3-编程解析_第1张图片

 二、代码解析

1、头文件的相关定义与声明

#ifndef code_h
#define code_h

#include "stm32g4xx.h"
#include "stdio.h"
#include "string.h"
#include "stdint.h"

#include "main.h"
#include "adc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "lcd.h"

void lcd_proc(void);
void key_proc(void);
void led_proc(u8 led_x,u8 led_mode);
double adc_proc(ADC_HandleTypeDef *hadc);
void usart_proc(void);

#endif

2、主函数的初始化

  #include "code.h"  


  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
  LCD_Init();
  LCD_SetTextColor(White);
  LCD_SetBackColor(Black);
  LCD_Clear(Black);
  //ADC采样校准
  HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
  HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED);

  HAL_TIM_Base_Start(&htim1);
  HAL_TIM_Base_Start(&htim2);
  HAL_TIM_Base_Start(&htim3);

  extern u8 my_pData;
  HAL_UART_Receive_IT(&huart1, &my_pData, 1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    lcd_proc();
    key_proc();
    usart_proc();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

3、 各个模块的编写

#include "code.h"

/*---------------------------------lcd-----------------------------------------*/
u8 ui;
char lcd_buf[30];
double STAN[4] = {2.2, 1.2, 3.0, 1.4}; // R37_MAX,R37_MIN,R38_MAX,R37_MIN
double PASS[2];
void lcd_proc(void)
{
    if (ui == 0)
    {
        LCD_DisplayStringLine(Line1, "        GOODS");
        sprintf(lcd_buf, "     R37:%.2fV    ", adc_proc(&hadc2));
        LCD_DisplayStringLine(Line3, (u8 *)lcd_buf);
        sprintf(lcd_buf, "     R38:%.2fV    ", adc_proc(&hadc1));
        LCD_DisplayStringLine(Line4, (u8 *)lcd_buf);
    }
    else if (ui == 1)
    {
        LCD_DisplayStringLine(Line1, "       STANDARD");
        sprintf(lcd_buf, "    SR37:%.1f-%.1f    ", STAN[1], STAN[0]);
        LCD_DisplayStringLine(Line3, (u8 *)lcd_buf);
        sprintf(lcd_buf, "    SR38:%.1f-%.1f    ", STAN[3], STAN[2]);
        LCD_DisplayStringLine(Line4, (u8 *)lcd_buf);
    }
    else
    {
        LCD_DisplayStringLine(Line1, "        PASS");
        sprintf(lcd_buf, "     PR37:%.1f%%    ", PASS[0] * 100);
        LCD_DisplayStringLine(Line3, (u8 *)lcd_buf);
        sprintf(lcd_buf, "     PR38:%.1f%%    ", PASS[1] * 100);
        LCD_DisplayStringLine(Line4, (u8 *)lcd_buf);
    }
    led_proc(3, !ui);
    led_proc(4, !(ui - 1));
    led_proc(5, !(ui - 2));
}

/*---------------------------------key-----------------------------------------*/
u8 key_val[4];
u8 key_old[4];
u8 key;
u8 STAN_X;             // 用来选择参数
double PASS_CNT[2];    // R37,R38合格率检测次数
double PASS_OK_CNT[2]; // R37,R38合格次数

void key_proc(void)
{
    for (u8 i = 0; i < 4; i++)
    {
        key_val[i] = HAL_GPIO_ReadPin(i < 3 ? GPIOB : GPIOA, GPIO_PIN_0 << i % 3);
        if (key_val[i] == 0 && key_old[i] == 1)
        {
            key = i + 1;
        }
        key_old[i] = key_val[i];
    }
    switch (key)
    {
    case 1:
        ui++;
        ui %= 3;
        LCD_Clear(Black);
        STAN_X = 0; // 题目没说,但一般都会有指定进入设置界面的默认调整参数(R37的上限)
        break;
    case 2:
        if (ui == 0)
        {
            if (adc_proc(&hadc2) <= STAN[0] && adc_proc(&hadc2) >= STAN[1]) // R37合格
            {
                led_proc(1, 1);
                TIM2->CNT = 0;
                PASS[0] = ++PASS_OK_CNT[0] / ++PASS_CNT[0];
            }
            else
                PASS[0] = PASS_OK_CNT[0] / ++PASS_CNT[0];
        }
        else if (ui == 1) // 选择参数
        {
            STAN_X++;
            STAN_X %= 4;
        }
        break;
    case 3:
        if (ui == 0)
        {
            if (adc_proc(&hadc1) <= STAN[2] && adc_proc(&hadc1) >= STAN[3]) // R38合格
            {
                led_proc(2, 1);
                TIM3->CNT = 0;
                PASS[1] = ++PASS_OK_CNT[1] / ++PASS_CNT[1];
            }
            else
                PASS[1] = PASS_OK_CNT[1] / ++PASS_CNT[1];
        }
        else if (ui == 1)
        {
            STAN[STAN_X] += 0.2;
            // 注意浮点型在存储时存在精度误差,不要直接与3.0进行比较,会出错
            if (STAN_X % 2 == 0 && STAN[STAN_X] > 3.1) // R37或R38上限溢出(STAN_X % 2 ==0 -> STAN_X == 0 / 2 )
                STAN[STAN_X] = 2.2;
            else if (STAN_X % 2 == 1 && STAN[STAN_X] > 2.1) // R37或R38下限溢出(STAN_X % 2 ==1 -> STAN_X == 1 / 3 )
                STAN[STAN_X] = 1.2;
            PASS[STAN_X / 2] = PASS_CNT[STAN_X / 2] = PASS_OK_CNT[STAN_X / 2] = 0; // 标准变化置零合格率
        }
        break;
    case 4:
        if (ui == 1)
        {
            STAN[STAN_X] -= 0.2;
            if (STAN_X % 2 == 0 && STAN[STAN_X] < 2.1) // R37或R38上限溢出
                STAN[STAN_X] = 3.0;
            else if (STAN_X % 2 == 1 && STAN[STAN_X] < 1.1) // R37或R38下限溢出
                STAN[STAN_X] = 2.0;
            PASS[STAN_X / 2] = PASS_CNT[STAN_X / 2] = PASS_OK_CNT[STAN_X / 2] = 0; // 标准变化置零合格率
        }
        else if (ui == 2)
        {
            PASS[0] = PASS_CNT[0] = 0;
            PASS[1] = PASS_CNT[1] = 0;
        }
        break;
    }
    key = 0;
    if (TIM2->CNT > 10000)
        led_proc(1, 0);
    if (TIM3->CNT > 10000)
        led_proc(2, 0);
}

/*---------------------------------led-----------------------------------------*/

void led_proc(u8 led_x, u8 led_mode)
{
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
    if (led_mode)
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led_x - 1), GPIO_PIN_RESET);
    else
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led_x - 1), GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}

/*---------------------------------adc-----------------------------------------*/

double adc_proc(ADC_HandleTypeDef *hadc)
{
    double adc_val;
    HAL_ADC_Start(hadc);
    adc_val = 3.3 * HAL_ADC_GetValue(hadc) / 4096;
    return adc_val;
}

/*---------------------------------usart-----------------------------------------*/

u8 my_pData;
char usart_buf[10];
u8 usart_cnt;
u8 rx_flag;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    usart_buf[usart_cnt] = my_pData;
    usart_cnt++;
    rx_flag = 1;
    TIM1->CNT = 0;
    HAL_UART_Receive_IT(&huart1, &my_pData, 1);
}

void usart_proc(void)
{
    if (!rx_flag)
        return;
    if (TIM1->CNT < 20)
        return;
    if (strstr(usart_buf, "R37") != NULL)
    {
        sprintf(usart_buf, "R37:%.0f,%.0f,%0.1f%%", PASS_CNT[0], PASS_OK_CNT[0], PASS[0] * 100);
        HAL_UART_Transmit(&huart1, (u8 *)usart_buf, strlen(usart_buf), 50);
    }
    else if (strstr(usart_buf, "R38") != NULL)
    {
        sprintf(usart_buf, "R38:%.0f,%.0f,%.1f%%", PASS_CNT[1], PASS_OK_CNT[1], PASS[1] * 100);
        HAL_UART_Transmit(&huart1, (u8 *)usart_buf, strlen(usart_buf), 50);
    }
    memset(usart_buf, NULL, sizeof(usart_buf));
    usart_cnt = 0;
    rx_flag = 0;
}

 三、结语

非常答辩,尤其按键部分,对参数的设置非常不合理,明天就比赛,终于要结束了,前前后后准备快3个月,上学期就开始,然后寒假因为太忙没有练习,这篇文章应该是最后一篇了,可能吧,如果比赛结束后还有心情的话会考虑优化优化一下代码,最后就祝大家一切顺利,国赛见!

你可能感兴趣的:(蓝桥杯,算法,c#,嵌入式)