藍橋杯嵌入式組第七屆省賽題目解析+STM32G431RBT6實現源碼

文章目錄

  • 1.題目解析
    • 1.1 分而治之,藕斷絲連
    • 1.2 模塊化思維導圖
    • 1.3 模塊解析
      • 1.3.1 KEY模塊
      • 1.3.2 ADC模塊
      • 1.3.3 IIC模塊
      • 1.3.4 UART模塊
      • 1.3.5 LCD模塊
      • 1.3.6 LED模塊
      • 1.3.7 TIM模塊
  • 2.源碼
  • 3.第七屆題目

前言:STM32G431RBT6實現嵌入式組第七屆題目解析+源碼,本文默認讀者具備基礎的stm32知識。文章末尾有第七屆題目。

1.題目解析

1.1 分而治之,藕斷絲連

還是那句話,將不同模塊進行封裝,通過變量進行模塊間的合作。

1.2 模塊化思維導圖

下圖根據題目梳理。第六屆沒有寫這么詳細(主要是懶😀)。
在這里插入圖片描述

1.3 模塊解析

整合模塊,邏輯思維。

1.3.1 KEY模塊

B1:界面1,2之間切換,方法:計數;0:表示界面1,1:表示界面2。
B2:三種閾值位之間切換,方法:計數;0:表示T1,1:表示T2,2:表示T3。
B3:每次加5,上限95(各閾值之間還應該T1<T2<T3, 但是我沒寫😅)。
B4:每次減5,下限5。

//B1,B4,B3都是同樣的格式
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET) //B1{if(HAL_GetTick() - tick > KEY_REDUCTION){    //按鍵消抖tick = HAL_GetTick();keyS->bits.B1 ^= 1;    
//            keyS->bits.B1++;
//            if(keyS->bits.B1 == 2) keyS->bits.B1 = 0;while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET); //實現按下一次只計數一次}}
//B2多了一種狀態
else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET) //B2{if(HAL_GetTick() - tick > KEY_REDUCTION){tick = HAL_GetTick();keyS->bits.B2++;if(keyS->bits.B2 == 3) keyS->bits.B2 = 0;while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET);}}

1.3.2 ADC模塊

采集可調電位器電壓。默認10次為一組進行一次濾波。
假如使用0.2s時基來開啟adc采集,采集10次需2s響應太慢,放在systick中斷中,程序寫到后面時間1ms顯短,我就多使用了一個tim產生0.5s時基,不用白不用。也可使用一個0.5的就行,累計4次就執行一次需0.2s時基模塊。也可使用dma采集。

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{if(adc_smp_flag < (FILTER_LEN+1)){adc_smp_flag++;adc_smp_vtg.smp_val[adc_smp_flag] = HAL_ADC_GetValue(hadc);if(adc_smp_flag == (FILTER_LEN+1)){adc_smp_flag =0;filter_process(&adc_smp_vtg);    //累加相除}}
}typedef struct{uint32_t smp_val[FILTER_LEN];uint32_t filter_val;
} adc_smp_t;

1.3.3 IIC模塊

完成eeprom中數據的讀寫。開發板的PB6和PB7設置為開漏輸出,使用軟件模擬實現單字節數據的讀寫。注意:魔術棒->c\c+±>optimization選項要設置成-O0,要不然代碼執行后得不到想要的結果。
在這里插入圖片描述
具體實現看第二部分源碼。

/* 軟件模擬實現at24c02單字節寫入 */
void at24c02_write(uint8_t addr, uint8_t data){...
}/* 軟件模擬實現at24c02單字節讀取 */
uint8_t at24c02_read(uint8_t addr){...
}/* i2c向eeprom寫入data */
void iic_write()
{...
}
...

1.3.4 UART模塊

UART接收PC端查詢碼’C’, ‘S’,做出相應的回應。
具體實現看第二部分源碼。

//中斷觸發回調函數
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{...
}
//定時上報數據
void uart_inform_PC()
{...
}

1.3.5 LCD模塊

將涉及到的數據顯示到lcd屏幕上,份界面1和界面2。
具體實現看第二部分源碼。

void lcd_process()
{if{//1:if 界面1,2切換清屏//2:LCD顯示數據//3:if設置閾值成功后切換到界面1,將set_thros寫入eeprom}else{//1:if 界面1,2切換清屏//2:if 顯示thros1為綠色+設置該閾值//3:else if 顯示thros2為綠色+設置該閾值//4:else if 顯示thros3為綠色+設置該閾值}
}

1.3.6 LED模塊

這屆題目我感覺難度就在led的處理上面,看著題目要求非常簡單,正常思路當事件發生的時候,使用HAL_GPIO_TogglePin()翻轉led對應引腳電平就行,但是我們使用到了lcd屏幕,lcd屏幕也使用到PC8-PC15這些引腳,所以我們每次寫入led狀態的時候對其他led引腳也得考慮。我就被繞進去了,整了我2個多小時。還是因為邏輯思維不夠強,代碼寫少了😶。
在這里插入圖片描述
三種事件相互之間保持獨立。我們分析一下三個事件之間的關系:
LD1:每隔1s亮滅閃爍,事件周期性觸發。
LD2:0.2s間隔閃爍5次,但是事件觸發沒有周期性,液位等級變化觸發一次。
LD3:0.2s間隔閃爍5次,但是事件觸發沒有周期性,接收到查詢指令觸發一次。
所以三事件相互獨立,可能同時觸發,可以一次觸發其中的隨機兩個,也可能是一個,也可能是都沒發生。所以這樣就構成了8種情況。
我們假設一個uint8_t temp變量,LD1代表第1位(事件1),LD2代表第2位(事件2),LD3代表第3位(事件3),對應位置1表示該事件發生,需執行該事件。這樣我就得到了8種情況:
111:代表三種事件同時發生;
110:代表事件3,事件2發生;
依此類推…
000:代表都不發生。
最后根據這八種情況寫入對應的電平狀態就可以了。

void led_process()
{uint8_t temp = 0;uint8_t new_liq_level = liq_level_process(iic_liq_thros);ld1_tim_flag++;if(ld1_tim_flag == 5){temp |= 1;     ld1_state_flag ^= 1;}if(old_liq_level != new_liq_level){temp |= 2;ld2_tim_flag++;ld2_state_flag ^= 1;if(ld2_tim_flag == 1) uart_inform_PC(new_liq_level);}if(uart_rec_flag == 1){temp |= 4;ld3_tim_flag++;ld3_state_flag ^= 1;}HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);if(temp == 0) GPIOC->ODR = 0xff00;else if(temp == 1){        GPIOC->ODR = 0xfe00 ^ (ld1_state_flag << 8);}else if(temp == 2){GPIOC->ODR = 0xfd00 ^ (ld2_state_flag << 9);}else if(temp == 3){GPIOC->ODR = 0xfc00 ^ ((ld1_state_flag + (ld2_state_flag << 1)) << 8);}else if(temp == 4){GPIOC->ODR = 0xfb00 ^ (ld3_state_flag << 10);       }else if(temp == 5){GPIOC->ODR = 0xfa00 ^ ((ld1_state_flag + (ld3_state_flag << 2)) << 8);}else if(temp == 6){GPIOC->ODR = 0xfa00 ^ (((ld2_state_flag<<1) + (ld3_state_flag << 2)) << 8);}else if(temp == 7){GPIOC->ODR = 0xfa00 ^ ((ld1_state_flag + (ld2_state_flag<<1) + (ld3_state_flag << 2)) << 8);  }HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);//事件完成之后結束設置對應標志位。if(ld1_tim_flag == 5){ld1_tim_flag = 0;}if(ld2_tim_flag == 10){old_liq_level = new_liq_level;ld2_tim_flag = 0;}if(ld3_tim_flag == 10){uart_rec_flag = 0;ld3_tim_flag = 0;}
}

1.3.7 TIM模塊

170MHz的頻率,預分頻值填寫16,重裝載寄存器填寫1999999實現0.2s時基;
預分頻值填寫16,重裝載寄存器填寫499999實現0.05s時基。
0.2s的時基,用在led模塊。
0.05s的時基用在uart,adc上。
具體實現看第二部分源碼。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{static uint8_t test_val = 0;if(htim == &htim2)   //tim2{led_process();    //led處理函數}else{     //tim3HAL_ADC_Start_IT(&hadc2);HAL_UARTEx_ReceiveToIdle_IT(&huart1, &uart_rec_char, 1);}
}

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 "tim.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "i2c_hal.h"
#include "lcd.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define FILTER_LEN 10
#define KEY_REDUCTION 20
/* 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 */
typedef struct{uint32_t smp_val[FILTER_LEN];uint32_t filter_val;
} adc_smp_t;
adc_smp_t adc_smp_vtg = {0};        //將ADC采集的數據收集FILTER_LEN個,之后會進行均值濾波typedef union{uint8_t keys;struct{uint8_t B1:2;uint8_t B2:2;uint8_t B3:2;uint8_t B4:2;}bits;
}key_state_t;
key_state_t key_state = {0};       //表示按鍵狀態/*
adc_smp_flag:保證采集FILTER_LEN個數據之后進行濾波
key_add_sub_flag, b3_b4_flag:控制按鍵B3,B4加減操作。
lcd_clear_flag:在界面1和界面2之間切換時候的清屏標志位。
set_thros_flag:B1按下返回界面1后,設置閾值成功,將設置閾值寫入eeprom
uart_rec_flag:接收到pc查詢指令后,控制ld3標志
old_liq_level:記住上一次的level值,通知pc端時知道是U還是D,還有配合控制ld2
*/
uint8_t adc_smp_flag = 0, key_add_sub_flag = 100, b3_b4_flag = 100, lcd_clear_flag = 0, set_thros_flag = 0, uart_rec_flag = 0, old_liq_level = 0;
/* 在lcd上顯示數據,配合sprinf使用 */
char lcd_HOR[30] = {0}, lcd_thros[30] = {0}, uart_resp[30] = {0};
/*iic_liq_thros:實時值set_thros:更改閾值時做中間值
*/
uint8_t iic_liq_thros[3] = {30, 50, 70}, set_thros[3] = {0};
/*ldi_tim_flag:0.2s加一,控制ldi閃爍次數ldi_state_flag:改變對應ldi的狀態標志,對應周期等間隔1010...交替變化
*/
uint16_t ld1_tim_flag = 0,   ld2_tim_flag = 0,   ld3_tim_flag = 0,ld1_state_flag = 0, ld2_state_flag = 0, ld3_state_flag = 0;
/* 接收pc端發來的查詢信號 */
uint8_t uart_rec_char;void filter_process(adc_smp_t *adcSmp);
void lcd_process();
void at24c02_write(uint8_t addr, uint8_t data);
uint8_t at24c02_read(uint8_t addr);
void iic_write(uint8_t* data);
void iic_read(uint8_t* data);
void key_process(key_state_t *keyS);
void set_thros_process(uint8_t *des, uint8_t index);
void led_process();
uint8_t cmp_thros(uint8_t *a);
uint32_t liq_level_process(uint8_t* liq_thros);
void iic1_process();
void uart_inform_PC(uint8_t level);
/* 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_ADC2_Init();MX_TIM2_Init();MX_TIM3_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */HAL_TIM_Base_Start_IT(&htim2);    //tim2產生200ms時基HAL_TIM_Base_Start_IT(&htim3);    //tim3產生50ms時基HAL_ADC_Start_IT(&hadc2);HAL_UARTEx_ReceiveToIdle_IT(&huart1, &uart_rec_char, 1);//檢查eeprom對應數據內存中數據是否符合要求,應對第一次在板子下載該程序,eeprom對應內存位置數據不正確的問題iic_read(set_thros);if(cmp_thros(set_thros)){iic_write(iic_liq_thros);}else{iic_read(iic_liq_thros); }for(int i=0;i<3;i++){set_thros[i] = iic_liq_thros[i];}   old_liq_level = liq_level_process(iic_liq_thros);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */key_process(&key_state);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};/** 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 lcd_process()
{if{1:if 界面1,2切換清屏2:LCD顯示數據3:if設置閾值成功后切換到界面1,將set_thros寫入eeprom}else{1:if 界面1,2切換清屏2:if 顯示thros1為綠色+設置該閾值3:else if 顯示thros2為綠色+設置該閾值4:else if 顯示thros3為綠色+設置該閾值}
}
*/
void lcd_process()
{if(key_state.bits.B1 == 0){if(lcd_clear_flag == 0){LCD_Clear(Black);lcd_clear_flag = 1;}LCD_DisplayStringLine(Line1, "  Liquid Level");sprintf(lcd_HOR, "  Height:%dcm", adc_smp_vtg.filter_val*100/4096);LCD_DisplayStringLine(Line2, (uint8_t*)lcd_HOR);sprintf(lcd_HOR, "  ADC:%.2fV", adc_smp_vtg.filter_val*3.3/4096);LCD_DisplayStringLine(Line3, (uint8_t*)lcd_HOR);sprintf(lcd_HOR, "  Level: %d", liq_level_process(iic_liq_thros));LCD_DisplayStringLine(Line4, (uint8_t*)lcd_HOR);if(set_thros_flag==1){set_thros_flag = 0;iic_write(set_thros);iic_read(iic_liq_thros);}}else{if(lcd_clear_flag == 1){LCD_Clear(Black);lcd_clear_flag = 0;}LCD_DisplayStringLine(Line1, "    Parameter Setup");if(key_state.bits.B2 == 0){LCD_SetTextColor(Green);sprintf(lcd_thros, "  Throsouth 1:%2dcm", set_thros[0]);LCD_DisplayStringLine(Line3, (uint8_t*)lcd_thros);LCD_SetTextColor(Black);sprintf(lcd_thros, "  Throsouth 2:%2dcm", set_thros[1]);LCD_DisplayStringLine(Line4, (uint8_t*)lcd_thros);sprintf(lcd_thros, "  Throsouth 2:%2dcm", set_thros[2]);LCD_DisplayStringLine(Line5, (uint8_t*)lcd_thros);if(b3_b4_flag != key_add_sub_flag){set_thros_process(set_thros, 0);}}else if(key_state.bits.B2 == 1){sprintf(lcd_thros, "  Throsouth 1:%2dcm", set_thros[0]);LCD_DisplayStringLine(Line3, (uint8_t*)lcd_thros);LCD_SetTextColor(Green);sprintf(lcd_thros, "  Throsouth 2:%2dcm", set_thros[1]);LCD_DisplayStringLine(Line4, (uint8_t*)lcd_thros);LCD_SetTextColor(Black);sprintf(lcd_thros, "  Throsouth 2:%2dcm", set_thros[2]);LCD_DisplayStringLine(Line5, (uint8_t*)lcd_thros);if(b3_b4_flag != key_add_sub_flag){ set_thros_process(set_thros, 1);}}else if(key_state.bits.B2 == 2){sprintf(lcd_thros, "  Throsouth 1:%2dcm", set_thros[0]);LCD_DisplayStringLine(Line3, (uint8_t*)lcd_thros);sprintf(lcd_thros, "  Throsouth 2:%2dcm", set_thros[1]);LCD_DisplayStringLine(Line4, (uint8_t*)lcd_thros);LCD_SetTextColor(Green);sprintf(lcd_thros, "  Throsouth 2:%2dcm", set_thros[2]);LCD_DisplayStringLine(Line5, (uint8_t*)lcd_thros);LCD_SetTextColor(Black);if(b3_b4_flag != key_add_sub_flag){ set_thros_process(set_thros, 2);}}}}/* 軟甲模擬iic協議寫入1byte */
void at24c02_write(uint8_t addr, uint8_t data)
{I2CStart();I2CSendByte(0xa0);I2CWaitAck();I2CSendByte(addr);I2CWaitAck();I2CSendByte(data);I2CWaitAck();I2CStop();
}
/* 軟件模擬iic協議讀取1byte */
uint8_t at24c02_read(uint8_t addr)
{uint8_t data;I2CStart();I2CSendByte(0xa0);I2CWaitAck();I2CSendByte(addr);I2CWaitAck();I2CStart();I2CSendByte(0xa1);I2CWaitAck();data = I2CReceiveByte();I2CSendNotAck();I2CStop();return data;
}/* 寫入數據 */
void iic_write(uint8_t* data)
{for(int i=0; i<3; i++){at24c02_write(i, data[i]);HAL_Delay(3);}
}/* 讀取數據 */
void iic_read(uint8_t* data)
{uint8_t temp = 0;for(int i=0; i<3; i++){temp = at24c02_read(i);data[i] = temp;HAL_Delay(3);}
}/* 驗證讀出數據是否正常 */
uint8_t cmp_thros(uint8_t *a)
{for(int i=0; i<3; i++){if(a[i] < 5 || a[i] > 95) return 1;}return 0;
}/* 檢測液深等級 */
uint32_t liq_level_process(uint8_t* liq_thros)
{uint32_t temp = adc_smp_vtg.filter_val*100/4096;if(temp <= liq_thros[0]) return 0;else if(temp > liq_thros[0] && temp <= liq_thros[1]) return 1;else if(temp > liq_thros[1] && temp <= liq_thros[2]) return 2;else return 3;
}/* 讀取Bi按鍵狀態 */
void key_process(key_state_t *keyS)
{uint32_t tick = 0;if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET) //B1{if(HAL_GetTick() - tick > KEY_REDUCTION){tick = HAL_GetTick();keyS->bits.B1 ^= 1;
//            keyS->bits.B1++;
//            if(keyS->bits.B1 == 2) keyS->bits.B1 = 0;while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET);}}else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET) //B2{if(HAL_GetTick() - tick > KEY_REDUCTION){tick = HAL_GetTick();keyS->bits.B2++;if(keyS->bits.B2 == 3) keyS->bits.B2 = 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() - tick > KEY_REDUCTION){tick = HAL_GetTick();keyS->bits.B3 ^= 1;
//            keyS->bits.B3++;
//            if(keyS->bits.B3 == 2) keyS->bits.B3 = 0;key_add_sub_flag++;while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET);}}else if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) //B1{if(HAL_GetTick() - tick > KEY_REDUCTION){tick = HAL_GetTick();keyS->bits.B4 ^= 1;
//            keyS->bits.B4++;
//            if(keyS->bits.B4 == 2) keyS->bits.B4 = 0;key_add_sub_flag--;while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET);}}
}/* 設置閾值 */
void set_thros_process(uint8_t *des, uint8_t index)
{if(key_add_sub_flag>b3_b4_flag && (des[index]>=5 && des[index]<=95)){        des[index] += 5;if(des[index] == 100) des[index] = 95;}else if(key_add_sub_flag<b3_b4_flag && (des[index]>=5 && des[index]<=95)){des[index] -= 5;if(des[index] == 0) des[index] = 5;}set_thros_flag = 1;b3_b4_flag = key_add_sub_flag;}/* 
void led_process()
{1:前面3if設置3種事件是否發生2:3種事件相互組合形成8種混合事件3:最后3if設置相關標志位
}
*/
void led_process()
{uint8_t temp = 0;uint8_t new_liq_level = liq_level_process(iic_liq_thros);ld1_tim_flag++;if(ld1_tim_flag == 5){temp |= 1;     ld1_state_flag ^= 1;}if(old_liq_level != new_liq_level){temp |= 2;ld2_tim_flag++;ld2_state_flag ^= 1;if(ld2_tim_flag == 1) uart_inform_PC(new_liq_level);}if(uart_rec_flag == 1){temp |= 4;ld3_tim_flag++;ld3_state_flag ^= 1;}HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);if(temp == 0) GPIOC->ODR = 0xff00;else if(temp == 1){        GPIOC->ODR = 0xfe00 ^ (ld1_state_flag << 8);}else if(temp == 2){GPIOC->ODR = 0xfd00 ^ (ld2_state_flag << 9);}else if(temp == 3){GPIOC->ODR = 0xfc00 ^ ((ld1_state_flag + (ld2_state_flag << 1)) << 8);}else if(temp == 4){GPIOC->ODR = 0xfb00 ^ (ld3_state_flag << 10);       }else if(temp == 5){GPIOC->ODR = 0xfa00 ^ ((ld1_state_flag + (ld3_state_flag << 2)) << 8);}else if(temp == 6){GPIOC->ODR = 0xfa00 ^ (((ld2_state_flag<<1) + (ld3_state_flag << 2)) << 8);}else if(temp == 7){GPIOC->ODR = 0xfa00 ^ ((ld1_state_flag + (ld2_state_flag<<1) + (ld3_state_flag << 2)) << 8);  }HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);if(ld1_tim_flag == 5){ld1_tim_flag = 0;}if(ld2_tim_flag == 10){old_liq_level = new_liq_level;ld2_tim_flag = 0;}if(ld3_tim_flag == 10){uart_rec_flag = 0;ld3_tim_flag = 0;}
}/* 向pc端發送數據 */
void uart_inform_PC(uint8_t level)
{if(old_liq_level<level){sprintf(uart_resp, "A:H%2d+L%1d+U\r\n", adc_smp_vtg.filter_val*100/4096, liq_level_process(iic_liq_thros));HAL_UART_Transmit_IT(&huart1, (uint8_t*)uart_resp, 12);}else if(old_liq_level>level){sprintf(uart_resp, "A:H%2d+L%1d+D\r\n", adc_smp_vtg.filter_val*100/4096, liq_level_process(iic_liq_thros));HAL_UART_Transmit_IT(&huart1, (uint8_t*)uart_resp, 12);}
}/* 定時器時基中斷回調函數 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{static uint8_t test_val = 0;if(htim == &htim2){led_process();}else{HAL_ADC_Start_IT(&hadc2);HAL_UARTEx_ReceiveToIdle_IT(&huart1, &uart_rec_char, 1);}}/* uart接收事件中斷回調函數 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{if(uart_rec_char == 'C'){uart_rec_flag = 1;sprintf(uart_resp, "C:H%2d+L%1d\r\n", adc_smp_vtg.filter_val*100/4096, liq_level_process(iic_liq_thros));HAL_UART_Transmit_IT(huart, (uint8_t*)uart_resp, 9);}else if(uart_rec_char == 'S'){uart_rec_flag = 1;sprintf(uart_resp, "S:TL%2d+TM%2d+TH%2d\r\n", iic_liq_thros[0], iic_liq_thros[1], iic_liq_thros[2]);HAL_UART_Transmit_IT(huart, (uint8_t*)uart_resp, 18);}
}/* adc規則組轉換完成中斷回調函數 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{if(adc_smp_flag < (FILTER_LEN+1)){adc_smp_flag++;adc_smp_vtg.smp_val[adc_smp_flag] = HAL_ADC_GetValue(hadc);if(adc_smp_flag == (FILTER_LEN+1)){adc_smp_flag =0;filter_process(&adc_smp_vtg);}}
}/* adc采集值進行濾波 */
void filter_process(adc_smp_t *adcSmp)
{uint32_t temp = 0;for(int i=0;i<FILTER_LEN;i++){temp += adcSmp->smp_val[i];}adcSmp->filter_val = temp/10;}/* 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.pswp.cn/pingmian/71888.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/71888.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/71888.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

DeepSeek技術名詞全解析:一場屬于中國AI的“覺醒時刻”

在2025年的人工智能浪潮中&#xff0c;一個名為DeepSeek的中國團隊&#xff0c;用一系列技術突破改寫了全球AI競爭的敘事。從“頓悟時刻”到“群體策略優化”&#xff0c;從“冷啟動”到“長鏈思考”&#xff0c;這些晦澀的技術術語背后&#xff0c;是一場關乎人類智能邊界的革…

【Go語言圣經1.1】

目標 學習Go 的編譯方式、包的組織方式以及工具鏈的統一調用方式 概念與定義 package Go 語言通過包來組織代碼。包類似于其它語言的庫librarries或模塊modules&#xff0c;每個包通常對應一個目錄&#xff0c;目錄中的所有 .go 文件都屬于同一個包。特殊的 main 包 : 當代碼…

主流大語言模型中Token的生成過程本質是串行的

主流大語言模型中Token的生成過程本質是串行的 flyfish 1. 串行生成 自回歸模型的核心邏輯&#xff1a; 大模型&#xff08;如GPT-2&#xff09;采用自回歸架構&#xff0c;每個Token的生成必須基于已生成的完整歷史序列。例如&#xff0c;生成“今天天氣很好”時&#xff1a…

基于PySide6的CATIA零件自動化著色工具開發實踐

引言 在汽車及航空制造領域&#xff0c;CATIA作為核心的CAD設計軟件&#xff0c;其二次開發能力對提升設計效率具有重要意義。本文介紹一種基于Python的CATIA零件著色工具開發方案&#xff0c;通過PySide6實現GUI交互&#xff0c;結合COM接口操作實現零件著色自動化。該方案成…

Python——計算機網絡

一.ip 1.ip的定義 IP是“Internet Protocol”的縮寫&#xff0c;即“互聯網協議”。它是用于計算機網絡通信的基礎協議之一&#xff0c;屬于TCP/IP協議族中的網絡層協議。IP協議的主要功能是負責將數據包從源主機傳輸到目標主機&#xff0c;并確保數據能夠在復雜的網絡環境中正…

Python實例:PyMuPDF實現PDF翻譯,英文翻譯為中文,并按段落創建中文PDF

基于PyMuPDF與百度翻譯的PDF翻譯處理系統開發:中文亂碼解決方案與自動化排版實踐 一 、功能預覽:將英文翻譯為中文后創建的PDF 二、完整代碼 from reportlab.lib.pagesizes import letter from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle

xunruicms失敗次數已達到5次,已被禁止登錄怎么處理?

針對遇到的“xunruicms失敗次數已達到5次&#xff0c;已被禁止登錄”的問題以下是幾種處理方法&#xff1a; 開啟開發者模式&#xff1a; 您可以開啟開發者模式來忽略賬號的禁止登錄限制。具體操作步驟如下&#xff1a; 訪問迅睿CMS的官方文檔&#xff0c;找到如何開啟開發者模…

復現 MODEST 機器人抓取透明物體 單目 ICRA 2025

MODEST 單目透明物體抓取算法&#xff0c;來自ICRA 2025&#xff0c;本文分享它的復現過程。 輸入單個視角的RGB圖像&#xff0c;模型需要同時處理深度和分割任務&#xff0c;輸出透明物體的分割結果和場景深度預測。 論文地址&#xff1a;Monocular Depth Estimation and Se…

新手學習爬蟲的案例

首先你的電腦上肯定已經安裝了python,沒安裝的去官網安裝,我使用的是Pycharm作為操作的IDE 環境準備 安裝必要的庫 爬蟲需要用到requests和beautifulsoup4 使用命令行或者終端運行下面的命令 pip install requests beautifulsoup4 -i https://mirrors.aliyun.com/pypi/sim…

Octave3D 關卡設計插件

課程參考鏈接 這位大佬有在視頻合集中有詳細的講解&#xff0c;個人體驗過&#xff0c;感覺功能很強大 https://www.bilibili.com/video/BV1Kq4y1C72P/?share_sourcecopy_web&vd_source0a41d8122353e3e841ae0a39908c2181 Prefab資源管理 第一步 在場景中創建一個空物體…

【Transformer優化】Transformer的局限在哪?

自2017年Transformer橫空出世以來&#xff0c;它幾乎重寫了自然語言處理的規則。但當我們在享受其驚人的并行計算能力和表征能力時&#xff0c;是否真正理解了它的局限性&#xff1f;本文將深入探討在復雜度之外被忽視的五大核心缺陷&#xff0c;并試圖在數學維度揭示其本質。 …

SpringBoot(一)--搭建架構5種方法

目錄 一、?Idea從spring官網下載打開 2021版本idea 1.打開創建項目 2.修改pom.xml文件里的版本號 2017版本idea 二、從spring官網下載再用idea打開 三、Idea從阿里云的官網下載打開 ?編輯 四、Maven項目改造成springboot項目 五、從阿里云官網下載再用idea打開 Spri…

Python爬蟲實戰:一鍵采集電商數據,掌握市場動態!

電商數據分析是個香餑餑&#xff0c;可市面上的數據采集工具要不貴得嚇人&#xff0c;要不就是各種廣告彈窗。干脆自己動手寫個爬蟲&#xff0c;想抓啥抓啥&#xff0c;還能學點技術。今天咱聊聊怎么用Python寫個簡單的電商數據爬蟲。 打好基礎&#xff1a;搞定請求頭 別看爬蟲…

樂鑫打造全球首款 PSA Certified Level 2 RISC-V 芯片

樂鑫科技 (688018.SH) 榮幸宣布 ESP32-C6 于 2025 年 2 月 20 日獲得 PSA Certified Level 2 認證。這一重要突破使 ESP32-C6 成為全球首款基于 RISC-V 架構獲此認證的芯片&#xff0c;體現了樂鑫致力于為全球客戶提供安全可靠、性能卓越的物聯網解決方案的堅定承諾。 PSA 安全…

圖像滑塊對比功能的開發記錄

背景介紹 最近&#xff0c;公司需要開發一款在線圖像壓縮工具&#xff0c;其中的一個關鍵功能是讓用戶直觀地比較壓縮前后的圖像效果。因此&#xff0c;我們設計了一個對比組件&#xff0c;它允許用戶通過拖動滑塊&#xff0c;動態調整兩張圖像的顯示區域&#xff0c;從而清晰…

tcc編譯器教程2 編譯lua解釋器

本文主要介紹了使用tcc編譯器編譯lua解釋器源碼。 1 介紹 lua是一門編程語言,開源且源碼很容易編譯,我平時用來測試C語言編程環境時經常使用。一般能編譯成功就說明編程環境設置正常。下面用之前設置好的tcc編程環境進行測試。 2 獲取源碼 我一般有保留多個版本的lua源碼進…

Unity DOTS從入門到精通之 自定義Authoring類

文章目錄 前言安裝 DOTS 包什么是Authoring1. 實體組件2. Authoring類 前言 DOTS&#xff08;面向數據的技術堆棧&#xff09;是一套由 Unity 提供支持的技術&#xff0c;用于提供高性能游戲開發解決方案&#xff0c;特別適合需要處理大量數據的游戲&#xff0c;例如大型開放世…

comctl32!ListView_OnSetItem函數分析LISTSUBITEM結構中的image表示圖標位置

第一部分&#xff1a; BOOL ListView_SetSubItem(LV* plv, const LV_ITEM* plvi) { LISTSUBITEM lsi; BOOL fChanged FALSE; int i; int idpa; HDPA hdpa; if (plvi->mask & ~(LVIF_DI_SETITEM | LVIF_TEXT | LVIF_IMAGE | LVIF_STATE)) { …

【算法】大數據查重

大數據查重 哈希表 找出第一個出現重復的數字 || 找所有重復出現的數字 #include <iostream> #include <vector> #include <unordered_map> #include <unordered_set> #include <stdlib.h> #include <time.h> #include <string> …

模型微調-基于LLaMA-Factory進行微調的一個簡單案例

模型微調-基于LLaMA-Factory進行微調的一個簡單案例 1. 租用云計算資源2. 拉取 LLaMa-Factory3. 安裝依賴環境4. 啟動 LLaMa-Factory 界面5. 從 Huggingface 下載模型6. 模型驗證7. 模型微調 1. 租用云計算資源 以下示例基于 AutoDL 云計算資源。 在云計算平臺選擇可用的云計…