蓝桥杯嵌入式组第六届省赛题目深度解析:STM32G431RBT6源码实现详解

文章目录

  • 1.题目解析
  • 1.1 分而治之,藕断丝连
  • 1.2 模块化思维导图
  • 1.3 模块解析
  • 1.3.1 RTC模块
  • 1.3.2 ADC模块
  • 1.3.3 IIC模块
  • 1.3.4 UART模块
  • 1.3.5 LCD模块
  • 1.3.6 LED模块
  • 1.3.7 TIM模块
  • 1.3.8 KEY模块
  • 2.源码
  • 3.第六届题目
  • 前言:STM32G431RBT6实现嵌入式组第六届题目解析+源码,本文默认读者具备基础的stm32知识。文章末尾有第六届题目。

    1.题目解析

    1.1 分而治之,藕断丝连

    我们如果要开发一个多外设协同的项目,开始应该做一个大致的流程图,将各个模块进行大致分析,理清模块间的关系,这样我们在写代码的过程中不至于毫无头绪。蓝桥杯给我们出的题目条理就很清晰,我们可以按照题目进行梳理。
    函数将模块分而治之,变量使模块间藕断丝连。

    1.2 模块化思维导图

    下图根据题目梳理。我们可以将各个模块封装成一个函数例如rtc_process(),adc_process()…。封装成函数之后,各个模块间的条理清晰了,不至于代码多了,写代码的人都看不懂自己写的是什么东西了。

    1.3 模块解析

    当代码写多了之后会发现,使用到一个模块,常常也就那么几个作用,所以最重要的还是思维逻辑,如何做到多模块间的限制与配合,这才是最重要的。

    1.3.1 RTC模块

    这里的目的是,获取时间使用到hal库中的两个函数。
    这两个函数必须的同时调用,而且GetTime()在GetDate()之前。

    RTC_DateTypeDef date = {0};                                                            
    RTC_TimeTypeDef time = {0}, 
    HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
    HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
    

    1.3.2 ADC模块

    采集可调电位器电压。

    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
    {
        adc_vtg_val = HAL_ADC_GetValue(hadc);
    }
    

    1.3.3 IIC模块

    完成eeprom中数据的读写。开发板的PB6和PB7设置为开漏输出,使用软件模拟实现单字节数据的读写。用到i2c_hal.c, i2c_hal.h。

    具体实现看第二部分源码。

    /* 软件模拟实现at24c02单字节写入 */
    void at24c02_write(uint8_t addr, uint8_t data){
      ...
    }
    
    /* 软件模拟实现at24c02单字节读取 */
    uint8_t at24c02_read(uint8_t addr){
      ...
    }
    
    /* i2c向eeprom写入data */
    void i2c_write()
    {
        ...
    }
    ...
    
    

    1.3.4 UART模块

    UART实现数据接受,响应,和定时数据上报。
    具体实现看第二部分源码。

    //中断触发回调函数
    void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
    {
      ...
    }
    //定时上报数据
    void tim_inform_process()
    {
     ...
    }
    

    1.3.5 LCD模块

    将涉及到的数据显示到lcd屏幕上,用到lcd.c, lcd.h, fonts.h。
    我这里使用判断语句显得有些杂乱无章,可以使用状态机改改。
    具体实现看第二部分源码。

    void lcd_process()
    {
    ...
    }
    

    1.3.6 LED模块

    0.2秒闪烁,使用tim2通用定时器完成0.2s的延时。
    注意lcd屏幕也会使用到led涉及到的引脚,要注意PD2控制锁存器使能和失能的使用

    if(key_state.bits.B1 == 1 || (adc_vtg_val*3.3/4096)>i2c_val.num*3.3)
        {
            HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
            GPIOC->ODR = 0xff00;
            HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
        }else{
            HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
            GPIOC->ODR = 0xff00 ^ (led_state_flag << 8);  //使用异或操作只改变PCB电平状态,其他保持高电平。
            led_state_flag ^= 1;       
            HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
        }
    

    1.3.7 TIM模块

    170MHz的频率,预分频值填写16,重装载寄存器填写1999999实现0.2ms时基。
    产生0.2s的时基,定时使能adc, uart中断。
    具体实现看第二部分源码。

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
        ...
    }
    

    1.3.8 KEY模块

    我使用的这种方法不是很好,为了实现按一次,按键状态改变一次(计数值加1),在多状态按键里面使用了while()循环等待按键回到高电平状态,造成不必要的cpu资源浪费。如果有更好的办法,请在评论区分享一下。
    配置按键对应gpio口为上拉输入模式。
    具体实现看第二部分源码。

    while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET); //while等待按键回到高电平状态
    void key_process()
    {
    ...
    }
    

    2.源码

    我所有的实现都在main.c文件中。

    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : main.c
      * @brief          : Main program body
      ******************************************************************************
      * @attention
      *
      * Copyright (c) 2025 STMicroelectronics.
      * All rights reserved.
      *
      * This software is licensed under terms that can be found in the LICENSE file
      * in the root directory of this software component.
      * If no LICENSE file comes with this software, it is provided AS-IS.
      *
      ******************************************************************************
      */
    /* USER CODE END Header */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    #include "adc.h"
    #include "rtc.h"
    #include "tim.h"
    #include "usart.h"
    #include "gpio.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include "stdio.h"
    #include "stdlib.h"
    #include "string.h"
    #include "lcd.h"
    #include "i2c_hal.h"
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* 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 */
    char lcd_vtg_str[30] = {0}, lcd_k_str[30] = {0},lcd_led_str[30] = {0},
         lcd_rtc_str[30] = {0}, uart_rec[5] = {0}, uart_inform[32] = {0};             //lcd显示
    RTC_DateTypeDef date = {0};                                                       //rtc日期       
    RTC_TimeTypeDef time = {0},                                                       //rtc时间
                cmp_time = {0};                                                       
    uint32_t adc_vtg_val = 0;           //adc_vtg_val:adc采集接收
    /*
    led_state_flag:控制led0.2s闪烁
    tim_blink_flag:控制上报时间设置时间位值闪烁 
    lcd_clear_flag:lcd页面转换清屏   
    i2c_rouse_flag:i2c写入唤醒            
    */
    uint8_t led_state_flag = 0, tim_blink_flag = 0, lcd_clear_flag = 0, i2c_rouse_flag = 0,
                infrom_tim_flag = 1;
    /*
    按键状态联合体  
    Bi:按键Bi           
    */        
    typedef union{
      uint8_t keys;
      struct{
          uint8_t B1:1;
          uint8_t B2:2;
          uint8_t B3:4;
          uint8_t B4:1;
      }bits;
    } keys_t;   
    keys_t key_state = {0};
    /*
    eeprom float写入联合体            
    */  
    typedef union{
        float num;
        uint8_t bytes[4];
    }float_t;
    float_t analyze_val = {0}, i2c_val = {0.1};
    
    void lcd_process();
    void rtc_process();
    void key_process();
    void at24c02_write(uint8_t addr, uint8_t data);
    uint8_t at24c02_read(uint8_t addr);
    void i2c_write(float_t *data);
    void i2c_read(float_t *data);
    void tim_inform_process();
    /* 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 */
      LCD_Init();
      LCD_Clear(Black);
      /* 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_RTC_Init();
      MX_TIM2_Init();
      MX_ADC2_Init();
      MX_USART1_UART_Init();
      /* USER CODE BEGIN 2 */
      uint8_t ret;
      HAL_TIM_Base_Start_IT(&htim2);
      HAL_ADC_Start_IT(&hadc2);
      HAL_UARTEx_ReceiveToIdle_IT(&huart1, (uint8_t*)uart_rec, 5);
      
      i2c_read(&analyze_val);
      if(analyze_val.num < 0.1 || analyze_val.num > 0.9)
      {
        i2c_write(&i2c_val);
      } else{
        i2c_read(&i2c_val);
      }     
      for(int i=0; i<4; i++)
      {
        analyze_val.bytes[i] = i2c_val.bytes[i];
      }
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
            rtc_process();      //获取rtc时间
            key_process();      //按键状态监听
            lcd_process();      //lcd显示控制
            if(i2c_rouse_flag ==1)      
            {
                i2c_write(&analyze_val);     //i2c通信向eeprom写入数据
                i2c_read(&i2c_val);
                i2c_rouse_flag = 0;
            }
            //定时上报
            tim_inform_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};
    
      /** Configure the main internal regulator output voltage
      */
      HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
    
      /** Initializes the RCC Oscillators according to the specified parameters
      * in the RCC_OscInitTypeDef structure.
      */
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
      RCC_OscInitStruct.HSEState = RCC_HSE_ON;
      RCC_OscInitStruct.LSIState = RCC_LSI_ON;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
      RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV6;
      RCC_OscInitStruct.PLL.PLLN = 85;
      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_4) != HAL_OK)
      {
        Error_Handler();
      }
    }
    
    /* USER CODE BEGIN 4 */
    /* 获取rtc时间 */
    void rtc_process()
    {
        HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
        HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
    }
    
    /* lcd显示 */
    void lcd_process()
    {
        if(key_state.bits.B2 == 0)      //界面1
        {
            if(lcd_clear_flag == 0){     //条件清屏
                lcd_clear_flag = 1;
                LCD_Clear(Black);
            }
            sprintf(lcd_vtg_str, "   V:%.2fV", adc_vtg_val*3.3/4096);     
            LCD_DisplayStringLine(Line3, (uint8_t*)lcd_vtg_str);
            sprintf(lcd_k_str, "   k%.1f", i2c_val.num);
            LCD_DisplayStringLine(Line4, (uint8_t*)lcd_k_str);
            if(key_state.bits.B1 == 0){
                sprintf(lcd_led_str, "   LED:ON ");
            }else{
                sprintf(lcd_led_str, "   LED:OFF");
            }
            LCD_DisplayStringLine(Line5, (uint8_t*)lcd_led_str);
            sprintf(lcd_rtc_str, "   T:%2d-%2d-%2d", time.Hours, time.Minutes, time.Seconds);
            LCD_DisplayStringLine(Line6, (uint8_t*)lcd_rtc_str);
        }
        else                    //界面2
        {
            if(lcd_clear_flag == 1){    //条件清屏
                lcd_clear_flag = 0;
                LCD_Clear(Black);
            }
            LCD_DisplayStringLine(Line2, "       Setting");
            if(key_state.bits.B3 == 0){
                
                sprintf(lcd_rtc_str, "      %2d-%2d-%2d", cmp_time.Hours, cmp_time.Minutes, cmp_time.Seconds);
                LCD_DisplayStringLine(Line3, (uint8_t*)lcd_rtc_str);
            }
            else if(key_state.bits.B3 == 1){     //Hours位闪烁 && 设置Hours位值
                if(tim_blink_flag == 1){
                    sprintf(lcd_rtc_str, "        -%2d-%2d", cmp_time.Minutes, cmp_time.Seconds);
                    LCD_DisplayStringLine(Line3, (uint8_t*)lcd_rtc_str);
                }
                else{
                    sprintf(lcd_rtc_str, "      %2d-%2d-%2d", cmp_time.Hours, cmp_time.Minutes, cmp_time.Seconds);
                    LCD_DisplayStringLine(Line3, (uint8_t*)lcd_rtc_str);
                }
                if(key_state.bits.B4 == 1){
                    key_state.bits.B4 = 0;
                    cmp_time.Hours ++;
                    if(cmp_time.Hours == 24) cmp_time.Hours = 0;
                }
    
            }
            
            else if(key_state.bits.B3 == 2){        //Minutes位闪烁 && 设置Minutes位值
                if(tim_blink_flag == 1){
                    sprintf(lcd_rtc_str, "      %2d-  -%2d", cmp_time.Hours, cmp_time.Seconds);
                    LCD_DisplayStringLine(Line3, (uint8_t*)lcd_rtc_str);
                }
                else{
                    sprintf(lcd_rtc_str, "      %2d-%2d-%2d", cmp_time.Hours, cmp_time.Minutes, cmp_time.Seconds);
                    LCD_DisplayStringLine(Line3, (uint8_t*)lcd_rtc_str);
                }
                if(key_state.bits.B4 == 1){
                    key_state.bits.B4 = 0;
                    cmp_time.Minutes ++;
                    if(cmp_time.Minutes == 60) cmp_time.Minutes = 0;
                }
    
            }
            else if(key_state.bits.B3 == 3){      //Seconds位闪烁 && 设置Seconds位值
                if(tim_blink_flag == 1){
                    sprintf(lcd_rtc_str, "      %2d-%2d-  ", cmp_time.Hours, cmp_time.Minutes);
                    LCD_DisplayStringLine(Line3, (uint8_t*)lcd_rtc_str);
                }
                else{
                    sprintf(lcd_rtc_str, "      %2d-%2d-%2d", cmp_time.Hours, cmp_time.Minutes, cmp_time.Seconds);
                    LCD_DisplayStringLine(Line3, (uint8_t*)lcd_rtc_str);
                }
                if(key_state.bits.B4 == 1){
                    key_state.bits.B4 = 0;
                    cmp_time.Seconds ++;
                    if(cmp_time.Seconds == 60) cmp_time.Seconds = 0;
                }
                
            }
            if(key_state.bits.B2 == 2){
                key_state.bits.B2 = 0;    //按下B2返回界面1
                infrom_tim_flag = 1;
            }
        }
    }
    
    /* 按键状态获取 */
    void key_process()
    {
        static uint32_t key_red = 0;
        if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET) //B1
        {
            if(HAL_GetTick() - key_red > 20) {   //消抖
                key_red = HAL_GetTick();
                key_state.bits.B1 = 1;
            }
            
        }
        else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET) //B2
        {
            if(HAL_GetTick() - key_red > 20) {
                key_red = HAL_GetTick();
                key_state.bits.B2 += 1;
                if(key_state.bits.B3 == 3) key_state.bits.B3 = 0;
                while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET);  //保证按一次加一次
            }
        }
        else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET) //B3
        {
            
            if(HAL_GetTick() - key_red > 20) {
                key_state.bits.B3 += 1;
                
                if(key_state.bits.B3 == 4) key_state.bits.B3 = 0;
                while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET); 
            }
        }
        else if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) //B4
        {
            if(HAL_GetTick() - key_red > 20) {
                key_red = HAL_GetTick();
                key_state.bits.B4 = 1;
                while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET); 
            }
        }
        
    }
    
    void tim_inform_process()
    {
        if(time.Hours == cmp_time.Hours && time.Minutes == cmp_time.Minutes && time.Seconds == cmp_time.Seconds)  
        {
            if(infrom_tim_flag == 1){
                infrom_tim_flag = 0;
                sprintf(uart_inform, "%.2f+%.1f+%2d%2d%2d\n", adc_vtg_val*3.3/4096, i2c_val.num, cmp_time.Hours, 
                                                            cmp_time.Minutes, cmp_time.Seconds);
                HAL_UART_Transmit_IT(&huart1, (uint8_t*)uart_inform, strlen(uart_inform));
            }
        }
    
    }
    
    /* at24c02单字节写入 */
    void at24c02_write(uint8_t addr, uint8_t data){
      I2CStart();
      I2CSendByte(0xa0);
      I2CWaitAck();
      I2CSendByte(addr);
      I2CWaitAck();
      I2CSendByte(data);
      I2CWaitAck();
      I2CStop();
    }
    
    /* at24c02单字节读取 */
    uint8_t at24c02_read(uint8_t addr){
      uint8_t read_data=0;
      I2CStart();
      I2CSendByte(0xa0);
      I2CWaitAck();
      I2CSendByte(addr);
      I2CWaitAck();
      I2CStart();
      I2CSendByte(0xa1);
      I2CWaitAck();
      read_data = I2CReceiveByte();
      I2CSendNotAck();
      I2CStop();
      return read_data;
    }
    
    /* 读取eeprom数据 */
    void i2c_read(float_t *data)
    {
        uint8_t ret = 0;
        for(int i=0;i<4;i++)
        {
            ret = at24c02_read(i+1);
            data->bytes[i] = ret;
            HAL_Delay(3);
        }
    }
    /* i2c向eeprom写入data */
    void i2c_write(float_t *data)
    {
        for(int i=0;i<4;i++)
        {
            at24c02_write(i+1, data->bytes[i]);
            HAL_Delay(3);       //rom的缺点必须带延时,读写比较慢
        }
    }
    
    /* 定时器0.2s时基中断回调函数 */
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
        static uint8_t temp = 0;
        //led报警闪烁控制
        if(key_state.bits.B1 == 1 || (adc_vtg_val*3.3/4096)>i2c_val.num*3.3)
        {
            HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
            GPIOC->ODR = 0xff00;
            HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
        }else{
            HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
            GPIOC->ODR = 0xff00 ^ (led_state_flag << 8);
            led_state_flag ^= 1;
            HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
        }
        
        HAL_ADC_Start_IT(&hadc2);
        HAL_UARTEx_ReceiveToIdle_IT(&huart1, (uint8_t*)uart_rec, 5);
        //设置上报时间闪烁0.6s
        temp++;
        if(temp ==3){
            tim_blink_flag ^=1;
            temp = 0;
        }
    }
    
    /* adc采集中断回调函数 */
    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
    {
        adc_vtg_val = HAL_ADC_GetValue(hadc);
        
    }
    
    /* uart通信中断回调函数 */
    void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
    {
      HAL_UART_Transmit_IT(huart, "ok\n", 3);
      sscanf(uart_rec, "k%f\n", &analyze_val.num);  //解析浮点k数值
      i2c_rouse_flag = 1;
      
    }
    /* 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 */
      __disable_irq();
      while (1)
      {
      }
      /* 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,
         ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
      /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */
    
    
    

    3.第六届题目




    作者::눈_눈:

    物联沃分享整理
    物联沃-IOTWORD物联网 » 蓝桥杯嵌入式组第六届省赛题目深度解析:STM32G431RBT6源码实现详解

    发表回复