蓝桥杯嵌入式组第十二届省赛题目解析+STM32G431RBT6实现源码

news2025/3/14 12:27:15

文章目录

  • 1.题目解析
    • 1.1 分而治之,藕断丝连
    • 1.2 模块化思维导图
    • 1.3 模块解析
      • 1.3.1 KEY模块
      • 1.3.2 LED模块
      • 1.3.3 LCD模块
      • 1.3.4 TIM模块
      • 1.3.5 UART模块
        • 1.3.5.1 uart数据解析
  • 2.源码
  • 3.第十二届题目

前言:STM32G431RBT6实现嵌入式组第十二届题目解析+源码,本文默认读者具备基础的stm32知识。文章末尾有第十二届题目。

1.题目解析

第十二届虽说题目长,难度集中体现在uart接收的数据处理上。

1.1 分而治之,藕断丝连

还是那句话,将不同模块进行封装,通过变量进行模块间的合作。
函数将模块分而治之,变量使模块间藕断丝连。

1.2 模块化思维导图

下图根据题目梳理。还是使用思维导图。
在这里插入图片描述

1.3 模块解析

1.3.1 KEY模块

还是控制按一次处理一次。老朋友了我们就不多说了,题目限制了按键消抖和单次处理,所以我们要加上消抖,和第十一届的处理一模一样。
具体实现看源码

1.3.2 LED模块

ld1:有空闲车位亮,否则灭
ld2:PWM占空比20%输出亮,输出低电平灭
解决办法,设置一个标志位代表ld1~ld8,改变对应位的的值,再将标志位写入ODR寄存器中来控制led的亮灭。
具体实现看源码

1.3.3 LCD模块

lcd显示两个界面,注意首次切换的时候得清屏。
根据B1界面1和界面2切换;
状态0:参数界面;
在这里插入图片描述

状态1:费用设置界面;
在这里插入图片描述
具体实现看源码

1.3.4 TIM模块

TIM2产生1s时基。PSC:16999,ARR:9999;
TIM17通道1产生2kHzPWM。PSC:16,ARR:4999;
PSC和ARR计算公式(计算周期就是频率的倒数):
在这里插入图片描述

/* 定时开启uart接收中断1s */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    HAL_UARTEx_ReceiveToIdle_IT(&huart1, uart_rx_data, 24);
}
/* pa7pwm输出 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    if(pa7_pwm_ctrl == 1) TIM17->CCR1 = 999;
    else TIM17->CCR1 = 0;
}

1.3.5 UART模块

12届题目的难度就在uart的数据处理上。
1.单片机接收来自电脑固定格式的数据,我们就需要数据限制条件来写解析接收的数据,数据长度,停车类别,车牌格式,时间格式。
2.如果格式错误返回Error,else判断是停车还是取车。
2.1 应该先判断取车,这大家都能理解。如果是取车,计算收费,时间,返回给电脑。
2.2 如果是存车,先要判断是否有空闲车位,如果有存车,如果没有不做处理。
具体其他涉及函数代码请看源码

/* uart接收数据处理 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if(analyze_uart_str(uart_rx_data))   //分析数据格式是否正确,错误传输Error
    {
        HAL_UART_Transmit_IT(&huart1, (uint8_t*)"Error", 7); 
    }
    /*
    格式正确处理顺序 :
    判断是否是取车(停车场已有该车)-> 是: 取车+计算收费, 否: 判断是否有空闲车位 -> 是:停车计时,否:不做处理
    */
    else{                                     
        uint8_t i = find_car_in_parking(parking_flag_temporary); 
        if(i != 8){   //表示取车
            if(!strcmp(parking_flag_temporary.parking_type, "VNBR")){    //计算停车费
                parking_fee = caculate_parking_time(i)*V_money;
                parking_spaces.VNBR--;
                parking_spaces.IDLE++;
            }else if(!strcmp(parking_flag_temporary.parking_type, "CNBR")){
                parking_fee = caculate_parking_time(i)*C_money;
                parking_spaces.CNBR--;
                parking_spaces.IDLE++;
            }
            
            sprintf((char*)parking_fee_str, "%4s:%4s:%u:%.2f", parking_flag_temporary.parking_type,
                    parking_flag_temporary.car_num, caculate_parking_time(i), parking_fee);
            HAL_UART_Transmit_IT(&huart1, parking_fee_str, strlen((char*)parking_fee_str));
            
            memset(&parking_flag[i], 0, sizeof(parking_flag[i]));
            memset(&parking_time[i], 0, sizeof(parking_time[i]));
        }
        else{        //停车          
            i = find_free_parking();              
            if(i!=8){               //有空闲车位
                parking_flag[i] = parking_flag_temporary;
                parking_time[i] = parking_time_temporary;
                
                if(!strcmp(parking_flag_temporary.parking_type, "CNBR")){
                    parking_spaces.CNBR++;
                    parking_spaces.IDLE--;
                }
                else if(!strcmp(parking_flag_temporary.parking_type, "VNBR")){
                    parking_spaces.VNBR++;
                    parking_spaces.IDLE--;
                }
            }
            
        }
    }
}
1.3.5.1 uart数据解析

我们可以使用指针加for单个字符判断,也可以使用string.h库中的字符处理函数,strcmp(), strcpy(),strncmp(), strncpy()等函数,将数据先切段,再通过各段的限制条件进行格式判断。

/**
*   @brief 判断uart接收到的数据格式是否正确,这里只有长度判断、车位类型、车位号码、时间格式的判断,
*   还可以加时间的大小比如月份只能是1~12月。还有解析时间的时候,假如说要取车,那取车时间肯定大于停车时间……
*   @para str: uart接收数据
*   @retval 1:数据格式错误,0:正确
*/
uint8_t analyze_uart_str(uint8_t *str)
{
    if(strlen((char*)str) != 24){  //
        return 1;
    }
    else{
        uint8_t *p = str;
        if(*p == 'C' || *p == 'V' && !strncasecmp((char*)p+1, "NBR", 3)) {
            strncpy(parking_flag_temporary.parking_type, (char*)str, 4);  
        }
        else return 1;
        for(p = str+5;p<str+9;p++){
            if(*p<0 || *p>127) return 1;
        }
        strncpy(parking_flag_temporary.car_num, (char*)str+5, 4);
        for(p = str+10; *p!='\0';p++){
            if(*p<'0' || *p > '9') return 1;
        }
        strncpy(parking_flag_temporary.time, (char*)str+10, 14);
        sscanf(parking_flag_temporary.time,"%4hu%2hhu%2hhu%2hhu%2hhu%2hhu", 
                &parking_time_temporary.years, &parking_time_temporary.dates, &parking_time_temporary.days,
                &parking_time_temporary.hours, &parking_time_temporary.minutes, &parking_time_temporary.seconds);
    }
    return 0;
}

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 "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lcd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.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 */
//按键四种状态
enum{
    key_released = 0U,
    key_reduction,
    key_pressed,
    key_wait_released,
};

//停车位状态
typedef struct {
    uint8_t CNBR;
    uint8_t VNBR;
    uint8_t IDLE;
} parking_t;
parking_t parking_spaces = {0, 0, 8};

//存储解析uart数据
typedef struct {
    char parking_type[5];
    char car_num[5];
    char time[15];
}parking_flag_t;
parking_flag_t parking_flag[8] = {0}, parking_flag_temporary = {0};

//将时间字符串解析成数据
typedef struct{
    uint16_t years;
    uint8_t dates;
    uint8_t days;
    uint8_t hours;
    uint8_t minutes;
    uint8_t seconds;
}calendar_t;
calendar_t parking_time[8] = {0},parking_time_temporary = {0};

/*
lcd_show_conv: lcd界面切换
pa7_pwm_ctrl: pwm输出控制
lcd_clear_flag: 清屏标志
ld_flag: ld状态标志
*/
uint8_t lcd_show_conv = 0, pa7_pwm_ctrl = 0, lcd_clear_flag = 0, ld_flag = 0;
/*
uart_rx_data: 接收来自串口的24字节的数据
lcd_str: lcd显示
parking_fee_str: 串口回复收费信息buff
*/
uint8_t uart_rx_data[25] = {0}, lcd_str[21] = {0}, parking_fee_str[25] = {0};
//消抖时间标记
uint32_t key_redu_tim = 0;
/*
keys_volt: 按键电平信息
keys_state: 按键状态信息
*/
uint8_t keys_volt[4] = {0}, keys_state[4] = {0};
/*
C_money: CNBR停车收费元/小时
V_money: VNBR停车收费元/小时
parking_fee: 计算停车费
*/
float C_money = 3.5f, V_money = 2.0f, parking_fee = 0.0f;

void key_state_gain();
void key_process();
void lcd_process();
uint8_t analyze_uart_str(uint8_t *str);
uint8_t find_free_parking();
uint8_t find_car_in_parking(parking_flag_t p);
uint32_t caculate_parking_time(uint8_t i);
void led_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);
    LCD_SetBackColor(Black);
    LCD_SetTextColor(White);
  /* 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_TIM2_Init();
  MX_USART1_UART_Init();
  MX_TIM17_Init();
  /* USER CODE BEGIN 2 */
    HAL_TIM_Base_Start_IT(&htim2);
    HAL_TIM_PWM_Start_IT(&htim17, TIM_CHANNEL_1);
    HAL_UARTEx_ReceiveToIdle_IT(&huart1, uart_rx_data, 24);
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
      key_state_gain();
      key_process();
     lcd_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};

  /** 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_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_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 */
/* 获取按键状态 */
void key_state_gain()
{
    keys_volt[0] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
    keys_volt[1] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
    keys_volt[2] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);
    keys_volt[3] = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
    for(int i=0;i<4;i++)
    {
        if(keys_volt[i] == 0)
        {
            if(keys_state[i] == key_released){
                key_redu_tim = HAL_GetTick();
                keys_state[i] = key_reduction;
            }
            else if(keys_state[i] == key_reduction){
                if(HAL_GetTick() - key_redu_tim>=10){
                    keys_state[i] = key_pressed;
                }
            }
            else if(keys_state[i] == key_pressed)
                keys_state[i] = key_wait_released;
        }
        else{
            if(keys_state[i] == key_wait_released || keys_state[i] == key_pressed){
                key_redu_tim = HAL_GetTick();
                keys_state[i] = key_reduction;
            }
            else if(keys_state[i] == key_reduction){
                if(HAL_GetTick() - key_redu_tim>=10){
                    keys_state[i] = key_released;
                }
            }
            else keys_state[i] = key_released;     
        }
    }
}
/* 根据按键状态设置对应标志 */
void key_process()
{
    if(keys_state[0] == key_pressed){ //界面切换
        lcd_show_conv ^= 1;
    }
    if(lcd_show_conv == 1){   //B2B3只在界面1起作用
        if(keys_state[1] == key_pressed){  //++
            C_money+= 0.5;
            V_money+= 0.5;
        }
        if(keys_state[2] == key_pressed){ //--
            C_money-= 0.5;
            V_money-= 0.5;
            if(V_money < 0) {
                C_money = 1.5;
                V_money = 0.0f;
            }
        }
    }
    if(keys_state[3] == key_pressed){   //pwm控制
        pa7_pwm_ctrl ^= 1;
    }
}
/* lcd两种状态 */
void lcd_process()
{
    switch(lcd_show_conv)
    {
        case 0:
            if(lcd_clear_flag == 1)
            {
                lcd_clear_flag = 0;
                LCD_Clear(Black);
            }
            sprintf((char*)lcd_str, "        Data        ");
            LCD_DisplayStringLine(Line2, lcd_str);
            sprintf((char*)lcd_str, "  CNBR:%d            ", parking_spaces.CNBR);
            LCD_DisplayStringLine(Line4, lcd_str);
            sprintf((char*)lcd_str, "  VNBR:%d            ", parking_spaces.VNBR);
            LCD_DisplayStringLine(Line6, lcd_str);
            sprintf((char*)lcd_str, "  IDLE:%d            ", parking_spaces.IDLE);
            LCD_DisplayStringLine(Line8, lcd_str);
            break;
        case 1:
            if(lcd_clear_flag == 0)
            {
                lcd_clear_flag = 1;
                LCD_Clear(Black);
            }
            sprintf((char*)lcd_str, "        Data        ");
            LCD_DisplayStringLine(Line2, lcd_str);
            sprintf((char*)lcd_str, "  CNBR:%.2f         ", C_money);
            LCD_DisplayStringLine(Line4, lcd_str);
            sprintf((char*)lcd_str, "  VNBR:%.2f         ", V_money);
            LCD_DisplayStringLine(Line6, lcd_str);
            break;
    }
}
/**
*   @brief 判断uart接收到的数据格式是否正确,这里只有长度判断、车位类型、车位号码、时间格式的判断,
*   还可以加时间的大小比如月份只能是1~12月。还有解析时间的时候,假如说要取车,那取车时间肯定大于停车时间……
*   @para str: uart接收数据
*   @retval 1:数据格式错误,0:正确
*/
uint8_t analyze_uart_str(uint8_t *str)
{
    if(strlen((char*)str) != 24){  //
        return 1;
    }
    else{
        uint8_t *p = str;
        if(*p == 'C' || *p == 'V' && !strncasecmp((char*)p+1, "NBR", 3)) {
            strncpy(parking_flag_temporary.parking_type, (char*)str, 4);  
        }
        else return 1;
        for(p = str+5;p<str+9;p++){
            if(*p<0 || *p>127) return 1;
        }
        strncpy(parking_flag_temporary.car_num, (char*)str+5, 4);
        for(p = str+10; *p!='\0';p++){
            if(*p<'0' || *p > '9') return 1;
        }
        strncpy(parking_flag_temporary.time, (char*)str+10, 14);
        sscanf(parking_flag_temporary.time,"%4hu%2hhu%2hhu%2hhu%2hhu%2hhu", 
                &parking_time_temporary.years, &parking_time_temporary.dates, &parking_time_temporary.days,
                &parking_time_temporary.hours, &parking_time_temporary.minutes, &parking_time_temporary.seconds);
    }
    return 0;
}
/* 查找是否有空闲车位 */
uint8_t find_free_parking()
{
    for(uint8_t i=0;i<8;i++){
        if(parking_flag[i].parking_type[0] != 'V' && parking_flag[i].parking_type[0] != 'C'){
            return i;
        }
    }
    return 8;
}
/* 查找是否该车要取车 */
uint8_t find_car_in_parking(parking_flag_t p)
{
    for(uint8_t i=0;i<8;i++){
        if(!strncasecmp(parking_flag[i].parking_type, p.parking_type, 4) && 
            !strncasecmp(parking_flag[i].car_num, p.car_num, 4)){
            return i;
        }
    }
    return 8;
}
/* 停车时间计算 */
uint32_t caculate_parking_time(uint8_t i)
{
    uint32_t hour = 0;
    hour = (parking_time_temporary.years - parking_time[i].years)*365*24;
    hour += (parking_time_temporary.dates - parking_time[i].dates)*30*24;
    hour += (parking_time_temporary.days - parking_time[i].days)*24;
    hour += (parking_time_temporary.hours - parking_time[i].hours);
    if((parking_time_temporary.minutes-parking_time[i].minutes) >0 ||
        (parking_time_temporary.seconds-parking_time[i].seconds) > 0){
        hour++;
    }
    return hour;
}
/* led状态更新 */
void led_process()
{
    if(parking_spaces.IDLE > 0){
        ld_flag = 1;
    }else ld_flag = 0;
    if(pa7_pwm_ctrl == 1){
        ld_flag += 1<<1;
    }else ld_flag += 0<< 1;
    HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2, 1);
    GPIOC->ODR = 0xffff ^ ld_flag << 8;
    HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2, 0);
}
/* 定时开启uart接收中断1s */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    HAL_UARTEx_ReceiveToIdle_IT(&huart1, uart_rx_data, 24);
}
/* pa7pwm输出 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    if(pa7_pwm_ctrl == 1) TIM17->CCR1 = 999;
    else TIM17->CCR1 = 0;
}
/* uart接收数据处理 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if(analyze_uart_str(uart_rx_data))   //分析数据格式是否正确,错误传输Error
    {
        HAL_UART_Transmit_IT(&huart1, (uint8_t*)"Error", 7); 
    }
    /*
    格式正确处理顺序 :
    判断是否是取车(停车场已有该车)-> 是: 取车+计算收费, 否: 判断是否有空闲车位 -> 是:停车计时,否:不做处理
    */
    else{                                     
        uint8_t i = find_car_in_parking(parking_flag_temporary); 
        if(i != 8){   //表示取车
            if(!strcmp(parking_flag_temporary.parking_type, "VNBR")){    //计算停车费
                parking_fee = caculate_parking_time(i)*V_money;
                parking_spaces.VNBR--;
                parking_spaces.IDLE++;
            }else if(!strcmp(parking_flag_temporary.parking_type, "CNBR")){
                parking_fee = caculate_parking_time(i)*C_money;
                parking_spaces.CNBR--;
                parking_spaces.IDLE++;
            }
            
            sprintf((char*)parking_fee_str, "%4s:%4s:%u:%.2f", parking_flag_temporary.parking_type,
                    parking_flag_temporary.car_num, caculate_parking_time(i), parking_fee);
            HAL_UART_Transmit_IT(&huart1, parking_fee_str, strlen((char*)parking_fee_str));
            
            memset(&parking_flag[i], 0, sizeof(parking_flag[i]));
            memset(&parking_time[i], 0, sizeof(parking_time[i]));
        }
        else{        //停车          
            i = find_free_parking();              
            if(i!=8){               //有空闲车位
                parking_flag[i] = parking_flag_temporary;
                parking_time[i] = parking_time_temporary;
                
                if(!strcmp(parking_flag_temporary.parking_type, "CNBR")){
                    parking_spaces.CNBR++;
                    parking_spaces.IDLE--;
                }
                else if(!strcmp(parking_flag_temporary.parking_type, "VNBR")){
                    parking_spaces.VNBR++;
                    parking_spaces.IDLE--;
                }
            }
            
        }
    }
}

/* 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.第十二届题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2314866.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32上实现简化版的AUTOSAR DEM模块

文章目录 摘要摘要 在一些可以不使用AUTOSAR的项目中,往往也有故障检测和DTC存储的需求,开发一套类似于AUTOSAR DEM模块的软件代码,能够满足DTC的检出和存储,使用FalshDB代替Nvm模块,轻松构建持久化存储,如果你也有这样的需求,请阅读本篇,希望能够帮到你。 /*********…

如何用终端运行一个SpringBoot项目

在项目开发阶段&#xff0c;为了能够快速测试一个SpringBoot项目的执行结果&#xff0c;就可以采用终端&#xff08;黑窗&#xff09;运行查看&#xff0c;因为我们不能要求每一个客户都安装idea并且适配我们的项目版本。 下面将展示打包运行这两个方面的过程&#xff1a; 创建…

多线程与并发编程 面试专题

多线程与并发编程 面试专题 线程的基础概念基础概念线程的创建线程的状态线程的终止方式start 与 run 区别线程的常用方法 锁锁的分类深入synchronized深入ReentrantLock死锁问题 阻塞队列线程池 线程的基础概念 基础概念 进程与线程 进程&#xff1a;指运行中的程序。 比如我…

米尔电子-LR3568-烧录鸿蒙

最近开始搞鸿蒙&#xff0c;用的是米尔的LR3568。 开贴记录。 首先要在LR3568上烧录鸿蒙 一、安装准备 1.从米尔电子上下载资料 网址:米尔开发者中心 注册完成后&#xff0c;进入页面&#xff0c;选择我的产品&#xff0c;添加PN和SN PN和SN可以在包装盒上找到 添加到这里…

基于Flink SQL的实时指标多维分析模型

数据流程介绍 1.创建源表kafka接入消息队列数据&#xff0c;定义字段映射规则&#xff1b; 2.创建目标表es_sink配置Elasticsearch输出&#xff1b; 3.通过多级视图&#xff08;tmp→tmp_dedup→tmp1/tmp2→tmp3→tmp_groupby&#xff09;实现数据清洗、去重、状态计算&#x…

【从零开始学习计算机科学】数据库系统(二)关系数据库 与 关系代数

【从零开始学习计算机科学】数据库系统(二)关系数据库 与 关系代数 关系数据库结构化查询语言SQL数据定义语言(DDL)数据查询语言(Data Query Language, DQL)数据操纵语言(Data Manipulation Language, DML)数据控制语言(Data Control Language, DCL)关系型数据库的优…

Linux驱动开发实战(四):设备树点RGB灯

Linux驱动开发实战&#xff08;四&#xff09;&#xff1a;设备树点RGB灯 文章目录 Linux驱动开发实战&#xff08;四&#xff09;&#xff1a;设备树点RGB灯前言一、驱动实现1.1 驱动设计思路1.2 关键数据结构1.3 字符设备操作函数1.4 平台驱动探测函数1.5 匹配表和平台驱动结…

vue中,watch里,this为undefined的两种解决办法

提示&#xff1a;vue中&#xff0c;watch里&#xff0c;this为undefined的两种解决办法 文章目录 [TOC](文章目录) 前言一、问题二、方法1——使用function函数代替箭头函数()>{}三、方法2——使用that总结 前言 ‌‌‌‌‌尽量使用方法1——使用function函数代替箭头函数()…

设计模式C++

针对一些经典的常见的场景, 给定了一些对应的解决方案&#xff0c;这个就叫设计模式。 设计模式的作用&#xff1a;使代码的可重用性高&#xff0c;可读性强&#xff0c;灵活性好&#xff0c;可维护性强。 设计原则&#xff1a; 单一职责原则&#xff1a;一个类只做一方面的…

前端构建工具进化论:从Grunt到Turbopack的十年征程

前端构建工具进化论&#xff1a;从Grunt到Turbopack的十年征程 一、石器时代&#xff1a;任务自动化工具&#xff08;2012-2014&#xff09; 1.1 Grunt&#xff1a;首个主流构建工具 // Gruntfile.js 典型配置 module.exports function(grunt) {grunt.initConfig({concat: {…

设备预测性维护:企业降本增效的关键密码​

在当今竞争激烈的商业战场中&#xff0c;企业犹如一艘在波涛汹涌大海上航行的巨轮&#xff0c;要想乘风破浪、稳步前行&#xff0c;降本增效便是那至关重要的 “船锚”&#xff0c;帮助企业在复杂的市场环境中站稳脚跟。而设备预测性维护&#xff0c;正是开启企业降本增效大门的…

css基本功

为什么 ::first-letter 是伪元素&#xff1f; ::first-letter 的作用是选择并样式化元素的第一个字母&#xff0c;它创建了一个虚拟的元素来包裹这个字母&#xff0c;因此属于伪元素。 grid布局 案例一 <!DOCTYPE html> <html lang"zh-CN"><head&…

信号处理抽取多项滤波的数学推导与仿真

昨天的《信号处理之插值、抽取与多项滤波》&#xff0c;已经介绍了插值抽取的多项滤率&#xff0c;今天详细介绍多项滤波的数学推导&#xff0c;并附上实战仿真代码。 一、数学变换推导 1. 多相分解的核心思想 将FIR滤波器的系数 h ( n ) h(n) h(n)按相位分组&#xff0c;每…

C++双端队列知识点+习题

在C中&#xff0c;双端队列&#xff08;Deque&#xff0c;发音为“deck”&#xff09;是标准模板库&#xff08;STL&#xff09;中的一种容器适配器&#xff0c;其全称为Double-Ended Queue。它结合了队列和栈的特点&#xff0c;允许在容器的两端&#xff08;前端和后端&#x…

【递归、搜索和回溯算法】专题二 :二叉树中的深搜

二叉树中的深搜 深度优先遍历&#xff08;DFS&#xff09;&#xff1a;一种沿着树或图的深度遍历节点的算法&#xff0c;尽可能深地搜索树或图的分支&#xff0c;如果一条路径上的所有结点都被遍历完毕&#xff0c;就会回溯到上一层&#xff0c;继续找一条路遍历。 在二叉树中…

【vue3学习笔记】(第150-151节)computed计算属性;watch监视ref定义的数据

尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通 本篇内容对应课程第150-151节 课程 P150节 《computed计算属性》笔记 写一个简单的 姓、名输入框效果&#xff1a; 用vue2的形式定义一个计算属性 fullName&#xff1a; 测试页面展示无问题&#xff1a; 但是&#xff0c;在vue…

MySQL 8 设置允许远程连接(Windows环境)

&#x1f31f; MySQL 8 设置允许远程连接&#xff08;Windows环境&#xff09; 在开发和部署应用时&#xff0c;经常需要从远程主机连接到MySQL数据库。默认情况下&#xff0c;MySQL仅允许本地连接&#xff0c;因此需要进行一些配置才能允许远程访问。今天&#xff0c;我将详细…

我又又又又又又更新了~~纯手工编写C++画图,有注释~~~

再再再次感谢Ttcofee提的问题 本次更新内容&#xff1a; 鼠标图案&#xff08;切换&#xff09;&#xff0c;版本号获取&#xff0c;输入框复制剪切板 提前申明&#xff1a;如果运行不了&#xff0c;请到主页查看RedpandaDevc下载&#xff0c;若还是不行就卸了重装。 版本号&…

全面解析:将采购入库单数据集成到MySQL的技术实施

旺店通旗舰版-采购入库单集成到MySQL的技术案例分享 在数据驱动的业务环境中&#xff0c;如何高效、准确地实现系统间的数据对接是企业面临的重要挑战。本文将聚焦于一个具体的系统对接集成案例&#xff1a;将旺店通旗舰奇门平台上的采购入库单数据集成到MySQL数据库中&#x…

12. Pandas :使用pandas读Excel文件的常用方法

一 read_excel 函数 其他参数根据实际需要进行查找。 1.接受一个工作表 在 11 案例用到的 Excel 工作簿中&#xff0c;数据是从第一张工作表的 A1 单元格开始的。但在实际场景中&#xff0c; Excel 文件可能并没有这么规整。所以 panda 提供了一些参数来优化读取过程。 比如 s…