本文章多以圖片代替文字,方便大家直接在軟體上實踐,
我們先看題目



- 先分析題目: 一共兩個LCD界面,外設基本上全部配置,II2讀寫EEPROM,同時需要用到串口收發指令
數碼管和AO1/AO2引腳都在拓展板上, 看似可能比較難,我們一步步往下做,
先打開cubemx按照原理圖配置引腳
原理圖如下:


初始化配置
基本所有引腳都需要配置,為了快速配置 我們直接按照原理圖把所有引腳激活

打開System Core →GPIO 簡單的給常用引腳進行一個改名,這里我改了按鍵的名稱和PD2鎖存器啟用/復位引腳 

同樣是System Core 打開RCC 設定HES為系統時鐘源,這里如果不設定,MCU是跑不到最大頻率的

打開頂端 Clock Configuration設定HCLK為170MHZ 回車 ,其他分頻器會自動設定

此時G431的頻率就是為最高運行頻率了,設定完時鐘后,可以開始設定TIM計數器,
再讀一遍題:




我們一共需要五種不同的定時(注:占空比測量需要獨占一個計數器,重繪率可以不管,運行速度夠快
這里可以進一步優化 將一個0.2s的定時器做成同時滿足1s和2s的,后面程式會講,
所以,開始設定TIM計數器吧!
首先配置最重要的占空比測量
查詢拓展板原理圖 PWM2測量引腳為PA7

具體設定如下:
TIM3CH2的信號映射到CH1上, CH2下降沿觸發,CH1上升沿觸發,這樣可以做到單引腳的輸入捕獲
TIM3定時器的分頻值我設為頻率170 000 000 /預分頻值 170-1 /ARR自動復位值 50 000 = 20HZ 也就是最低能測出20*3 =60HZ的方波的頻率和占空比

然后打開TIM3的NVIC中斷,PWM捕捉肯定需要中斷的 ,同時配置TIM1更新中斷

占空比測量配置好后,我們繼續配置TIM,現在需要配置定時0.2s重繪以及其他用于重繪的定時器
頻率170 000 000 /預分頻值 17000-1 /ARR自動復位值 2000 = 5HZ =0.2s中斷一次

配置串口并打開中斷


由于需要收發指令,這里要給串口配置為DMA傳輸
配置AO1/AO2的ADC測量


這里需要打開ADC的回圈掃描模式,啟用軟體觸發模式

設定通道順序

此時以及配置完所有引腳了(注:II2C使用的GPIO模擬信號傳輸資料,不用單獨設定II2C,LCD也是GPIO模擬FSMC)
點擊
配置工程


注意編譯器和版本的選擇,選擇.c和.h檔案獨立生成檔案夾
點擊右上角
生成代碼

Open Project自動使用所對應編譯器打開工程
打開工程第一步,先編譯一次,然后打開stm32g4xx_it.c配置中斷函式,洗掉自帶的USART1中斷函式,后面需要自己寫一個新的,使用空閑中斷DMA傳輸,
新的中斷函式自行添加在main.c檔案里 要放在BEGIN和END之間,序號隨變,如果不在BEGIN和END之間,使用cubemx重新生成檔案時會被清空內容,
1.USART:
串口中斷撰寫
void USART1_IRQHandler(void)
{
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET)
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1); //清除標記
HAL_UART_DMAStop(&huart1); //停止接受 開始處理
UART_RX_STA = BUFF_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx);
RXbuf[UART_RX_STA] = 0;
// UART_RX_STA |= 0X8000;
// if(UART_RX_STA & 0X8000)
// {
if(strcmp((char *)RXbuf,(char *)RX_ST) == 0) //指令決議
{
memset(UARTTEMP,0,30);
sprintf(UARTTEMP,"$%.2f\r\n",DS18B20_TEMP);
HAL_UART_Transmit(&huart1,(uint8_t *)UARTTEMP,sizeof(UARTTEMP),100 );
}
else if(strcmp((char *)RXbuf,(char *)RX_PARA) == 0)
{
memset(UARTTEMP,0,30);
sprintf(UARTTEMP,"#%d,AO%d\r\n",Tmm,Xmm);
HAL_UART_Transmit(&huart1,(uint8_t *)UARTTEMP,sizeof(UARTTEMP),100);
}
// UART_RX_STA = 0; // 清除標記
// }
HAL_UART_Receive_DMA(&huart1, RXbuf, BUFF_SIZE ); // 重新啟動DMA接收
}
}
以下啟動函式在main函式內呼叫
HAL_UART_Receive_DMA(&huart1,RXbuf,BUFF_SIZE); //打開DMA傳輸
__HAL_UART_CLEAR_IDLEFLAG(&huart1); //清除中斷標記
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); //打開UART1空閑中斷
串口已經配置好了 還有對應的變數需要設定
static char BUFF_SIZE = 50; //接收長度
static uint8_t RXbuf[50]; //接收快取
static uint16_t UART_RX_STA = 0; // 第15bit表示一幀資料接收完成,第14~0位表示接收到的資料量
static char UARTTEMP[30];
- USART常用函式:
HAL_UART_Transmit(&huart*,(uint8_t *)字符陣列,sizeof(字符陣列),等待時間);發送資料HAL_UART_DMAStop(&huart*)停止某個串口DMA傳輸 處理資料時一定要關閉防止資料被擠掉HAL_UART_Receive_DMA(&huart*, 字符陣列, 接收大小 );重新打開DMA傳輸并指定寫入記憶體
- 串口定時報警程式
static void UART_TempSend()
{
double linshi =0;
linshi = PWM_Zhankongbi*3.3; //根據題目要求:VIN>k×3.3 時,以 1s 為間隔自動上報當前的溫度資料
if(ADCRead_Num(1)>linshi || ADCRead_Num(2)> linshi)
{
if(led1!=2 ){led1 =1;}
if(time4_1S > 4) //定時達到要求 重新上報
{
time4_1S = 0;
memset(UARTTEMP,0,30);
sprintf(UARTTEMP,"$%.2f\r\n",DS18B20_TEMP);
HAL_UART_Transmit(&huart1,(uint8_t *)UARTTEMP,sizeof(UARTTEMP),100);
}
}
else if(led1!=0 ){led1=5;}
}
static void UART_TN()
{
if( DS18B20_TEMP> Tmm )
{
HAL_TIM_Base_Start_IT(&htim1);
}
else if (DS18B20_TEMP < Tmm )
{
HAL_TIM_Base_Stop_IT(&htim1);
if (tim1_LD8 != 0)tim1_LD8 = 3;
}
}
2.添加重要驅動
我們需要撰寫溫度傳感器和II2的驅動檔案添加進工程(不知道比賽會不會給,自己寫一個也好)
DS18B20驅動
II2C驅動
數碼管驅動

把檔案添加進工程,順手添加lcd.c
LCD驅動
3.II2C:
在main.c添加自定義的II2C讀寫函式(uint8_t)型別
uint16_t x24c02_read(uint8_t address) //I2C讀
{
uint16_t val;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
val = I2CReceiveByte();
I2CWaitAck();
I2CStop();
return(val);
}
void x24c02_write(uint8_t address,uint16_t info) //I2C寫
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendByte(info);
I2CWaitAck();
I2CStop();
}
讀寫案例:
//從0x00的位置讀取一個字
xxx= x24c02_read(0x00);
//向0x00寫入一個字
x24c02_write(0x00,(uint8_t) xxx);
4.DS18B20:
溫度傳感器讀取案例:
變數 = ds18b20_read(); //注意這里讀取出來的是十六位的數字 要除以16再取整使用
DS18B20_TEMP = ((int)((ds18b20_read()/16.0)*100)) ;
DS18B20_TEMP = DS18B20_TEMP/100;
5.數碼管:
直接呼叫驅動內的函式就好
對應的表如下
// 0 1 2 3 4 5 6 7 8 9 A B C D E F 關
uint8_t Seg7[17] = { 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c, 0x39,0x4f,0x79,0x78,0x00};
SEG_DisplayValue(uint8_t Bit1, uint8_t Bit2, uint8_t Bit3);
- 例:
在這里插入代碼片
6.ADC:
接下來撰寫ADC順序讀取以及按序號取資料的函式,ADC在呼叫時會讀取第一個通道的值,第二次呼叫讀取第二個通道的值,
static double ADCRead(ADC_HandleTypeDef *hadcx)
{
//開啟ADC1
HAL_ADC_Start(&hadc2);
//等待ADC轉換完成,超時為100ms
HAL_ADC_PollForConversion(&hadc2,100);
//判斷ADC是否轉換成功
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc2),HAL_ADC_STATE_REG_EOC))
{
//讀取值
HAL_ADC_GetValue(&hadc2);
}
}
static double ADCRead_Num(uint8_t num)
{
ADC_Value[1]= ADCRead(&hadc2); //讀取第一個通道的值
HAL_Delay(5);
ADC_Value[2]= ADCRead(&hadc2);//讀取第二個通道的值
return ADC_Value[num]; //回傳序號的值
}
這時題目的常用函式基本上都寫好了,開始撰寫邏輯類的函式,按鍵處理以及頁面顯示,TIM中斷類,定時等
7.LED:
LED與LCD復用,所以采用了一個鎖存器來儲存對LED的控制信號


在啟用LE引腳時,可往鎖存器寫入八位二進制資料,0對應開1關,寫滿后關閉LE引腳,鎖存器可以保持關閉前的八位狀態,
- 運行LCD之前先關閉所有LCD,防止LED亂閃
static void LEDClear() //關閉所有LED
{
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET); //鎖存器開
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9|GPIO_PIN_8,GPIO_PIN_SET); //LED全部熄滅
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//鎖存器關
}
- 閃燈計時
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) //tim1中斷回呼
{
if(htim->Instance == TIM1)
{
if (tim1_LD8 == 0) { tim1_LD8 = 1;}
else if(tim1_LD8 == 2) { tim1_LD8 = 4;}
}
}
所有與LED閃爍有關的函式,整體思路如下
- 計時1次后 判斷需要閃哪個燈,然后進行一次鎖存器復寫,完成標記,
- 計時2次 翻轉狀態,
- 不需要閃燈時,將狀態寫為不在判定區域的任意數,要用時再寫回來即可,
static void Led_bulle()
{
if(tim1_LD8 == 1)
{
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET); //鎖存器開
if(led1 ==2 )
{ HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15|GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_9,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15|GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_9|GPIO_PIN_8,GPIO_PIN_SET);
}
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//鎖存器關
tim1_LD8 = 2;
}
else if (tim1_LD8 == 4)
{
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET); //鎖存器開
if(led1 ==2)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9,GPIO_PIN_SET);
}
else{ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9|GPIO_PIN_8,GPIO_PIN_SET); }
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//鎖存器關
tim1_LD8 = 0;
}
else if (tim1_LD8 == 3)
{
tim1_LD8 = 0;
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET); //鎖存器開
if(led1 ==2)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9,GPIO_PIN_SET);
}
else{ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9|GPIO_PIN_8,GPIO_PIN_SET); }
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//鎖存器關
}
if(led1 ==1 )
{
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET); //鎖存器開
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9,GPIO_PIN_SET);
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//鎖存器關
led1 = 2;
}
else if (led1 == 5)
{
led1 = 0;
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET); //鎖存器開
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9|GPIO_PIN_8,GPIO_PIN_SET);
HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//鎖存器關
}
}
8.PWM

先看PWM測量 一共要檢測2個上升沿,1個下降沿
- 在檢測到第一個上升沿時,清空計數值,然后等待一個下降沿
- 下降沿到來時,記錄下tim的時間,清空計數值,等待第二個上升沿
- 第二個上升沿來時,記錄tim的時間,激活處理資料的函式,計算出占空比
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) //記錄等待脈沖中的溢位次數
{
if(htim->Instance == TIM3)
{
if(PWMON == 1) //脈沖檢測1階段
{
PWM_YICHU1++;
}
else if (PWMON == 2) //脈沖檢測2階段
{
PWM_YICHU2++;
}
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) // 脈沖捕捉
{
if(htim ->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
if(PWMON == 1 && Setting == 1 )
{
PWMDW1 = __HAL_TIM_GetCounter(&htim3);
__HAL_TIM_SetCounter(&htim3,0);
PWMON = 2;
}
}
else if(htim ->Channel == HAL_TIM_ACTIVE_CHANNEL_2 )
{
if(PWMON == 0)
{
__HAL_TIM_SetCounter(&htim3,0);
PWMON = 1;
}
else if(PWMON == 2)
{
PWMUP2 = __HAL_TIM_GetCounter(&htim3);
__HAL_TIM_SetCounter(&htim3,0);
PWMON = 3;
}
}
}
占空比計算公式 D=PD1/(PD1*頻率/PU2) x 100%
頻率在初始化tim時就決定了 170MHZ/預分頻值170
PU1在我這里默認為0 作為起點
if (PWMON == 3 ) //重新計算占空比
{
PWMDW1 =1000000/ (PWMDW1+50000*PWM_YICHU1); //ARR值為50000,所以真實計數值為 計數值+50000*溢位次數
//PWMUP2 =1000000/ (PWMUP2+50000*PWM_YICHU2);
PWM_Zhankongbi =(100* (PWMDW1 / (PWMDW1+1000000/(PWMUP2+50000*PWM_YICHU2))))+0.5 ; //占空比計算
sprintf(LCDTEMP," PWM2:%d%% ",PWM_Zhankongbi);
LCD_DisplayStringLine(Line5,(uint8_t *)LCDTEMP); //顯示占空比
PWMON = 0;
PWM_YICHU1 = 0;
PWM_YICHU2 = 0;
}
9.按鍵檢測:
我并沒有采用按鍵中斷的方法,這會干擾PWM計算和LCD的寫入,直接用掃描GPIO的方式獲得按鍵值
讀題

設定儲存按鍵狀態和切換模式的狀態值,切換頁面時先重繪LCD,防止字符顯示錯誤,
在檢測中設上一定的延時,防止多次觸發,
static void yemian_JM()
{
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET ) //讀取按鍵狀態
{
Setting++;
HAL_TIM_IC_Stop_IT(&htim3, TIM_CHANNEL_1);
if (Setting == 3){Setting = 1;HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);}
LCD_Clear(White);
while(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET);
}
if(Setting == 2)
{
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET )//讀取按鍵狀態
{
SetOb++;
HAL_Delay(200);
if (SetOb == 3){SetOb =1;}
}
if(SetOb == 1)
{
if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==GPIO_PIN_RESET )//讀取按鍵狀態
{
Tmm++;
HAL_Delay(500);
if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==GPIO_PIN_RESET) {Tmm+=9;}
}
else if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin)==GPIO_PIN_RESET )//讀取按鍵狀態
{
Tmm--;
HAL_Delay(500);
if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin)==GPIO_PIN_RESET) {Tmm-=9;}
}
}
else if(SetOb == 2)
{
if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==RESET )//讀取按鍵狀態
{
Xmm++;
HAL_Delay(200);
}
else if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin)==RESET )//讀取按鍵狀態
{
Xmm++;
HAL_Delay(200);
}
if (Xmm > 2){ Xmm = 1;} //超限設定
else if (Xmm == 0){ Xmm = 1;}
if (Tmm >40){ Tmm = 20;}
else if (Tmm == 0 ){ Tmm = 40;}
}
}
}
然后寫LCD頁面顯示的函式
10.LCD:
LCD_DisplayStringLine(Line1,(uint8_t *)LCDTEMP);顯示一排字符LCD_Init();初始化LCD_Clear(顏色);清空并以特定顏色填充螢屏LCD_SetBackColor(顏色);設定背景顏色LCD_SetTextColor(Blue);設定字符顏色
static void LCDLive()
{
if(Setting == 1) //主頁面
{
LCD_DisplayStringLine(Line0,(uint8_t *)" Main ");
sprintf(LCDTEMP," AO1:%.2lfV ",ADCRead_Num(1));
LCD_DisplayStringLine(Line1,(uint8_t *)LCDTEMP);
sprintf(LCDTEMP," AO2:%.2lfV ",ADCRead_Num(2));
LCD_DisplayStringLine(Line3,(uint8_t *)LCDTEMP);
sprintf(LCDTEMP," TEMP:%.2lf C ",DS18B20_TEMP);
LCD_DisplayStringLine(Line7,(uint8_t *)LCDTEMP);
sprintf(LCDTEMP," N:%d ",N_Num);
LCD_DisplayStringLine(Line9,(uint8_t *)LCDTEMP);
if (PWMON == 3 ) //重新計算占空比
{
PWMDW1 =1000000/ (PWMDW1+50000*PWM_YICHU1);
//PWMUP2 =1000000/ (PWMUP2+50000*PWM_YICHU2);
PWM_Zhankongbi =(100* (PWMDW1 / (PWMDW1+1000000/ (PWMUP2+50000*PWM_YICHU2))))+0.5 ;
sprintf(LCDTEMP," PWM2:%d%% ",PWM_Zhankongbi);
LCD_DisplayStringLine(Line5,(uint8_t *)LCDTEMP);
PWMON = 0;
PWM_YICHU1 = 0;
PWM_YICHU2 = 0;
}
}
else if(Setting == 2) //設定模式
{
if(SetOb == 1)
{
LCD_DisplayStringLine(Line0,(uint8_t *)" Para ");
sprintf(LCDTEMP," T: %d ",Tmm);
LCD_SetTextColor(Red);
LCD_DisplayStringLine(Line2,(uint8_t *)LCDTEMP);
LCD_SetTextColor(Blue);
sprintf(LCDTEMP," X: AO%d ",Xmm);
LCD_DisplayStringLine(Line5,(uint8_t *)LCDTEMP);
}
else if(SetOb == 2)
{
LCD_DisplayStringLine(Line0,(uint8_t *)" Para ");
sprintf(LCDTEMP," T: %d ",Tmm);
LCD_DisplayStringLine(Line2,(uint8_t *)LCDTEMP);
sprintf(LCDTEMP," X: AO%d ",Xmm);
LCD_SetTextColor(Red);
LCD_DisplayStringLine(Line5,(uint8_t *)LCDTEMP);
LCD_SetTextColor(Blue);
}
}
}
11.寫完所有函式
整合工程 在主函式回圈里呼叫就行了,
/* USER CODE BEGIN WHILE */
while (1)
{
DS18B20_TEMP = ((int)((ds18b20_read()/16.0)*100)) ;
DS18B20_TEMP = DS18B20_TEMP/100;
if(IIC_huancun != DS18B20_TEMP) //判斷是否需要從EEPROM寫資料
{
N_Num++;
IIC_huancun = DS18B20_TEMP;
x24c02_write(0x00,N_Num);
}
yemian_JM();
LCDLive();
UART_TempSend();
UART_TN();
Led_bulle();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
最后
本人也是今年參加藍橋杯,寫這個教程就當復習了,祝大家得個好成績,
完整工程
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/272317.html
標籤:其他
