個人筆記,不扭扭捏捏,一口氣到位。方便自己也方便大家
00 時鐘線
cubeMX已經完成了大多數工作
01 LED(GPIO輸出)
在使用LED的時候先把SN74HC573鎖存器PD2置高電平,然后寫入LED所要的高低電平,然后置PD2低電平,將數據所存在里面。
void LED_Control(u8 led_ctrl)
{//先熄滅所有LED燈HAL_GPIO_WritePin(GPIOC,0xff00,GPIO_PIN_SET); //讓PC8~PC15輸出高電平,熄滅LEDHAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //打開鎖存器HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //關閉鎖存器//根據led_ctrl來點亮對應的LEDHAL_GPIO_WritePin(GPIOC,led_ctrl<<8,GPIO_PIN_RESET);//根據led_ctrl輸出低電平,點亮LED,<<8的原因是LED對應PC15-8,即數據高位HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //打開鎖存器HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //關閉鎖存器
}
輸出模式有:
推挽輸出(GPIO_MODE_OUTPUT_PP):既可以輸出高電平,也可以輸出低電平。
開漏輸出(GPIO_MODE_OUTPUT_OD):如果沒有上拉電阻,只能輸出低電平,此種模式更多用在IIC協議下。
復用推挽輸出(GPIO_MODE_AF_PP):將gpio用作第二功能,使用片內外設時候的IIC。
復用開漏輸出(GPIO_MODE_AF_OD):將gpio用作第二功能,使用片內外設時候的SPI。
02 獨立KEY(GPIO輸入)
藍橋杯嵌入式:KEY的使用(二)_嵌入式stm32的key代碼-CSDN博客
#define KB1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)
#define KB2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)
#define KB3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)
#define KB4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
#define KEYPORT KB1 | (KB2<<1) | (KB3<<2) | (KB4<<3) | 0xf0u8 Trg; // 全局變量,單次觸發
u8 Cont; // 全局變量,長按
void Key_Read(void)
{u8 ReadData = (KEYPORT)^0xff; // 1Trg = ReadData & (ReadData ^ Cont); // 2 Cont = ReadData; // 3
}
/* 按鍵不觸發的時候都是高電平,相當于就是0xff,當如果按下KB1的時候KB1就是低電平,此時的表達式就是1111 1110--->0xfe,s將0xfe與0xff異或,得出來的結果就是0x01,0x01&(0x01^0x00)-->先異或得出結果是0x01在與自己做&運算(都為1才為1)得出結果0x01返回給單機變量trg,在main函數里面進行就是if(trg&0x01)時進行觸發如果這次按鍵事件是一個長按,則繼續走下面cont變量,cont=ReadData,也就是第一次ReadData的結果如果持續是ReadData,則第二行的trg表達式的異或會一直都是0(在進行第二次判斷的時候),trg就為0了在執行長按的情況下
*/
輸入模式有:
模擬輸入(GPIO_MODE_ANALOG):在比賽中采集ADC的時候常用。
浮空輸入(GPIO_MODE_INPUT):在比賽中通常會拿來寫鍵盤程序。
上拉輸入(GPIO_Mode_IPU):將輸入口上拉到VCC。
下拉輸入(GPIO_Mode_IPD):將輸入口上拉到GND。.Pull = GPIO_NOPULL;
03 串口收發
UART1是直接與C8T6(模擬的DAPlink)連接的,且C8T6還支持了USB串口。
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);return ch;
}
初始化接收中斷:
HAL_UART_Receive_IT(&huart1,rx_buf,1);
回調函數:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart -> Instance == USART1){//接收到的串口一發來的東西就可以在這里進行邏輯操作}HAL_UART_Receive_IT(&huart1,rx_buff,1);//這個不要忘記了,如果沒有中斷就只能發生一次
}
DMA
【STM32】HAL庫 STM32CubeMX教程十一---DMA (串口DMA發送接收)_stm32 串口dma接收-CSDN博客
04 LCD
一、硬件框架
1.?LCD型號兼容性處理
支持兩種控制器:uC8230
和ILI932X
系列(通過REG_8230_Init()
和REG_932X_Init()
區分)
- 初始化時通過讀取寄存器0的值(
dummy = LCD_ReadReg(0)
)判斷控制器型號
dummy = LCD_ReadReg(0); if(dummy == 0x8230){REG_8230_Init();}else{REG_932X_Init(); }
2.GPIO配置
- ?控制信號線:
PB5
: RD(讀使能)PB8
: WR(寫使能)PB9
: CS(片選)PA8
: RS(寄存器/數據選擇)
- ?數據總線:
PC0-PC15
作為16位并行數據總線(通過LCD_BusIn()
/LCD_BusOut()
切換方向)
信號線 | GPIO | 功能描述 |
---|---|---|
D0-D15 | PC0-PC15 | 數據總線 |
CS | PB9 | 片選信號 |
WR | PB8 | 寫使能 |
RD | PB5 | 讀使能 |
RS | PA8 | 命令/數據選擇 |
?? ?LCD_Init();//初始化
?? ?LCD_SetBackColor(Black);//設置背景顏色
?? ?LCD_SetTextColor(White);//設置文字顏色
?? ?LCD_Clear(Black);//刷新屏幕
?
05 ADC與DAC
1.ADC
ADC通道分配表(外部通道)
GPIO引腳 | 對應ADC模塊及通道 | 復用功能備注 |
---|---|---|
?PB15 | ADC2_IN15 | …… |
?PB12 | ADC1_IN11 | …… |
?PB14 | ADC1_IN5 | …… |
VREF+引腳(ADC參考電壓)
基本定義
- ?VREF+:ADC/DAC的參考電壓正極輸入引腳,決定模擬信號轉換的基準電壓上限。
- ?VDDA:?模擬電源引腳?(通常與VDD同電壓,但獨立濾波),為模擬模塊(ADC/DAC、運算放大器等)供電。
VDDA=3.3V,則ADC輸入信號范圍:0~3.3V
誤差處理:
?? ?HAL_ADC_Start(&hadc1);
?? ?adc1_val = HAL_ADC_GetValue(&hadc1);
?? ?volt_r38 = adc1_val/4095.0f*3.3f;還是偏大
考慮volt_r38 = adc1_val/4094.0f*3.3f;
ADC多通道調用規則
ADC的規則組轉換結果會按Rank順序存儲在數據寄存器中。每次調用HAL_ADC_GetValue()
會讀取當前結果并指向下一個被開啟的通道
Rank順序配置:
// 通道5配置為Rank1 sConfig.Channel = ADC_CHANNEL_5; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5; // 長采樣時間提高精度[7](@ref) //640.5周期≈47.2μs(假設ADCCLK=14MHz) // 通道11配置為Rank2 sConfig.Channel = ADC_CHANNEL_11; sConfig.Rank = ADC_REGULAR_RANK_2; // 轉換順序第二[1](@ref)
如何優化代碼效率???
- 使用DMA+連續模式可減少CPU占用(推薦)。
- 避免在循環中頻繁啟動/停止ADC,可設置定時器觸發采樣
輪詢模式(單次觸發)?:uint32_t adc_values[2]; // 存儲兩個通道的結果// 啟動ADC1轉換HAL_ADC_Start(&hadc1);HAL_ADC_PollForConversion(&hadc1, 100); // 等待轉換完成// 讀取所有通道數據adc_values[0] = HAL_ADC_GetValue(&hadc1); // Rank1(通道5)adc_values[1] = HAL_ADC_GetValue(&hadc1); // Rank2(通道11)這種連續轉換需要配置:ContinuousConvMode = ENABLE
/*否則,hadc1.Init.ContinuousConvMode = DISABLE; 需如下手動調用HAL_ADC_Start()啟動后再讀取
HAL_ADC_Start(&hadc1);
adc_values[0] = HAL_ADC_GetValue(&hadc1); // Rank1(通道5)
HAL_ADC_Start(&hadc1);
adc_values[1] = HAL_ADC_GetValue(&hadc1); */// 計算電壓volt_mcp = adc_values[0] / 4096.0f * 3.3f; // 通道5volt_r38 = adc_values[1] / 4096.0f * 3.3f; // 通道11DMA模式(連續觸發)?:// 全局變量uint16_t adc1_dma_buffer[2]; // 存儲ADC1兩個通道的數據// 初始化中啟動DMAHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc1_dma_buffer, 2);// DMA自動更新adc1_dma_buffer數組volt_mcp = adc1_dma_buffer[0] / 4096.0f * 3.3f; // 通道5volt_r38 = adc1_dma_buffer[1] / 4096.0f * 3.3f; // 通道11
其他關鍵參數?配置:
hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 12位分辨率[2](@ref)
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 數據右對齊[3](@ref)
//右對齊時數據寄存器直接存儲0-4095的原始值
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // 每通道轉換完成觸發EOC[1](@ref)誤差處理??:
若電壓偏差超過1%,檢查參考電壓是否穩定(測量VDDA引腳)
高頻干擾時可啟用過采樣:
hadc1.Init.OversamplingMode = ENABLE;
hadc1.Init.Oversample.Ratio = ADC_OVERSAMPLING_RATIO_16;
校準操作??:
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED); // 上電后執行一次[8](@ref)
通道5采樣時間可優化為:
sConfig.SamplingTime = ADC_SAMPLETIME_24CYCLES_5; // 短時間適合低阻抗信號[6](@ref)
四、模式擴展建議
若要實現更復雜的轉換模式,可參考以下配置組合:
應用場景 | 配置參數組合 |
---|---|
定時器觸發連續轉換 | ExternalTrigConv=TIMx_CCx ,?ContinuousConvMode=ENABLE |
注入通道中斷采集 | 配置注入通道組,啟用HAL_ADC_Start_IT() |
雙ADC同步采集 | Mode=ADC_MODE_RegSimult , 配置ADC1和ADC2的同步規則組 |
溫度傳感器采集 | 啟用內部溫度傳感器通道(ADC_CHANNEL_TEMPSENSOR),設置采樣時間≥17.1μs |
2.DAC
STM32G431RBT6學習筆記---DAC入門模塊及ADC和DAC結合_stm32g431rbt6 dac-CSDN博客
u16 dac_ch1_val,dac_ch2_val;
void DAC_Process()
{dac_ch1_val = (1.1f/3.3f*4095);dac_ch2_val = (2.5f/3.3f*4095);HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dac_ch1_val); //0-->0v 4095--> 3.3V 1.1v --> 1365HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_2, DAC_ALIGN_12B_R, dac_ch2_val); //0-->0v 4095--> 3.3V 2.5v --> 2730HAL_DAC_Start(&hdac1, DAC_CHANNEL_2);
}
06 IIC通信
一、24c02
藍橋杯嵌入式:EEPROM(AT89C02)(九)_藍橋杯驅動文件只給.c文件-CSDN博客
實現掉電不丟失
設備地址:
IIC流程:
代碼(比賽時看著手冊寫會簡單很多)
//寫24C02
void EEPROM_Write(u8 add,u8 dat)
{I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(add); I2CWaitAck(); I2CSendByte(dat); I2CWaitAck(); I2CStop();HAL_Delay(5);
}
//讀24C02
u8 EEPROM_Read(u8 add)
{u8 dat;I2CStart(); I2CSendByte(0xa0);I2CWaitAck(); I2CSendByte(add);I2CWaitAck(); I2CStart();I2CSendByte(0xa1); I2CWaitAck();dat = I2CReceiveByte(); I2CSendNotAck();I2CStop();return(dat);
}
二、MCP4017
藍橋杯嵌入式:MCP4017的使用(四)_藍橋杯嵌入式mcp4017-CSDN博客
-
?核心功能:
- MCP4017是一個數字控制的可變電阻,通過I2C接口調節電阻值(0-10kΩ,128級可調0-127)。
??N值(十進制)?? ??阻值(Ω)?? ??電壓分壓值(VDD=3.3V)?? 0 0 0V 64 50.4k 2.45V 127(0x7F) 100k 3.0V(實際約2.9V) - 相當于一個“電子滑動變阻器”,程序可以動態改變其阻值,無需手動調節。
- 阻值計算公式
- MCP4017是一個數字控制的可變電阻,通過I2C接口調節電阻值(0-10kΩ,128級可調0-127)。
- ?MCP4017的作用:生成一個已知電壓供ADC采樣,驗證ADC模塊是否正常工作。
注意ADC測量MCP4017時需要上拉對應的ADC引腳,如下圖:
07 TIM
藍橋杯嵌入式:PWM輸出的使用(六)_藍橋杯方波輸出可以用pwm嗎-CSDN博客
1.PWM
初始化:
MX_TIM17_Init();HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);//A7TIM17->ARR = 499; // 周期是500us,對應頻率2kHzTIM17->CCR1 = 400; // 80%占空比MX_TIM16_Init();HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);//A6TIM16->ARR = 49; // 周期是50us,對應頻率20kHzTIM16->CCR1 = 10; // 20%占空比
/*
->ARR對應.Period;
->CCR1對應.Pulse
*/
法二:
// 動態修改ARR
__HAL_TIM_SET_AUTORELOAD(&htim16, 49); // 立即生效(需禁用預裝載)
// 動態修改CCR1
__HAL_TIM_SET_COMPARE(&htim16, TIM_CHANNEL_1, 10);
?
2.輸入捕獲
藍橋杯嵌入式:輸入捕獲(頻率捕獲,占空比計算)的使用(八)_藍橋杯15屆嵌入式pa15捕獲功能-CSDN博客
?測量原理:捕獲相鄰上升沿之間的計數器差值
htim2.Init.Prescaler = 80; // 預分頻系數
htim2.Init.Period = 0xFFFF; // 自動重裝載值
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; // 上升沿捕獲
- 定時器時鐘 = 80MHz / 80(預分頻) = ?1MHz
- 最大測量周期:65535μs(對應最小頻率≈15.26Hz)
- 最小測量周期:1μs(對應最大頻率≈1MHz)
f40 = 1000000 / cc1_value_2; // 周期(μs)轉頻率(Hz)
?頻率測量:
u32 tim2_cnt1 = 0;
u32 f40 = 0;
u32 tim3_cnt1 = 0;
u32 f39 = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim == &htim2){tim2_cnt1 = __HAL_TIM_GetCounter(&htim2);//獲取CNT,對應CNT(us)__HAL_TIM_SetCounter(&htim2,0); // 設置CNT為0,重新開始計時 f40 = 1000000/tim2_cnt1; //R40的調整的555頻率 HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//開啟TIM2_CH1的輸入捕獲中斷}if(htim == &htim3){tim3_cnt1 = __HAL_TIM_GetCounter(&htim3);//獲取TIM3的CNT,對應CNT(us)__HAL_TIM_SetCounter(&htim3,0); // 設置CNT為0,重新開始計時 f39 = 1000000/tim3_cnt1; //R39的調整的555頻率 HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);//開啟TIM3_CH1的輸入捕獲中斷}
}
頻率+占空比測量:
uint32_t tim2ch1_cnt1 = 0;
uint32_t tim2ch1_cnt2 = 0;
uint32_t tim2ch1_cnt3 = 0;
uint32_t tim3ch1_cnt1 = 0;
uint32_t tim3ch1_cnt2 = 0;
uint32_t tim3ch1_cnt3 = 0;
uint32_t tim2ch1_HighCnt = 0;
uint32_t tim2ch1_LowCnt = 0;
uint32_t tim3ch1_HighCnt = 0;
uint32_t tim3ch1_LowCnt = 0;
float tim2ch1_duty = 0.0;
float tim3ch1_duty = 0.0;
uint32_t tim2ch1_fre = 0;
uint32_t tim3ch1_fre = 0;
int tim2ch1_step = 0;
int tim3ch1_step = 0;void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim -> Instance == TIM2)//判斷是什么定時器{if(htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_1){if(tim2ch1_step == 0){tim2ch1_cnt1 = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);__HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);tim2ch1_step = 1;}else if(tim2ch1_step == 1){tim2ch1_cnt2 = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);if(tim2ch1_cnt2 > tim2ch1_cnt1){tim2ch1_HighCnt = tim2ch1_cnt2 - tim2ch1_cnt1;}else if(tim2ch1_cnt2 < tim2ch1_cnt1){tim2ch1_HighCnt = ((0xffff - tim2ch1_cnt1) +tim2ch1_cnt2) + 1; }tim2ch1_step = 2;__HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);}else if(tim2ch1_step == 2){tim2ch1_cnt3 = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);if(tim2ch1_cnt3 > tim2ch1_cnt2){tim2ch1_LowCnt = tim2ch1_cnt3 - tim2ch1_cnt2;}else if(tim2ch1_cnt3 < tim2ch1_cnt2){tim2ch1_LowCnt = ((0xffff - tim2ch1_cnt2) +tim2ch1_cnt3) + 1; }tim2ch1_step = 0;tim2ch1_fre = (80000000/80)/(tim2ch1_cnt3 - tim2ch1_cnt1);//(tim2ch1_LowCnt+tim2ch1_HighCnt);tim2ch1_duty = 100.0f * tim2ch1_HighCnt / (tim2ch1_LowCnt+tim2ch1_HighCnt);}}}if(htim -> Instance == TIM3)//判斷是什么定時器{if(htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_1){if(tim3ch1_step == 0){tim3ch1_cnt1 = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);tim3ch1_step = 1;}else if(tim3ch1_step == 1){tim3ch1_cnt2 = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);if(tim3ch1_cnt2 > tim3ch1_cnt1){tim3ch1_HighCnt = tim3ch1_cnt2 - tim3ch1_cnt1;}else if(tim3ch1_cnt2 < tim3ch1_cnt1){tim3ch1_HighCnt = ((0xffff - tim3ch1_cnt1) +tim3ch1_cnt2) + 1; }tim3ch1_step = 2;__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);}else if(tim3ch1_step == 2){tim3ch1_cnt3 = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);if(tim3ch1_cnt3 > tim3ch1_cnt2){tim3ch1_LowCnt = tim3ch1_cnt3 - tim3ch1_cnt2;}else if(tim3ch1_cnt3 < tim3ch1_cnt2){tim2ch1_LowCnt = ((0xffff - tim3ch1_cnt2) +tim3ch1_cnt3) + 1; }tim3ch1_step = 0;tim3ch1_fre = (80000000/80)/(tim3ch1_cnt3 - tim3ch1_cnt1);//(tim2ch1_LowCnt+tim2ch1_HighCnt);tim3ch1_duty = 100.0f * tim3ch1_HighCnt / (tim3ch1_LowCnt+tim3ch1_HighCnt);}}}
}
法三:
u32 tim2_cnt1 = 0, tim2_cnt2 = 0;
u32 f40 = 0;
float d40 = 0;u32 tim3_cnt1 = 0, tim3_cnt2 = 0;
u32 f39 = 0;
float d39 = 0;
u8 tim2_state = 0; //0:開始計時,1:獲取T1,2:獲取T2
u8 tim3_state = 0; //0:開始計時,1:獲取T1,2:獲取T2
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim == &htim2){if(tim2_state == 0) //第一個上升沿產生,開始計時{__HAL_TIM_SetCounter(&htim2,0); // 設置CNT為0,重新開始計時TIM2->CCER |= 0x02; //下降沿中斷,CC1P置為1tim2_state = 1; }else if(tim2_state == 1) //獲取T1,并改成上升沿中斷{tim2_cnt1 = __HAL_TIM_GetCounter(&htim2);//獲取T1(us)TIM2->CCER &= ~0x02; //上升沿中斷,CC1P置為0tim2_state = 2;}else if(tim2_state == 2) //第二個上升沿中斷,獲取T2(周期){tim2_cnt2 = __HAL_TIM_GetCounter(&htim2);//獲取T2(us)f40 = 1000000/tim2_cnt2; //R40的調整的555頻率 d40 = tim2_cnt1*100.0f/tim2_cnt2;tim2_state = 0;}HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//開啟TIM2_CH1的輸入捕獲中斷}if(htim == &htim3){if(tim3_state == 0) //第一個上升沿產生,開始計時{__HAL_TIM_SetCounter(&htim3,0); //設置CNT為0,重新開始計時TIM3->CCER |= 0x02; //下降沿中斷,CC1P置為1tim3_state = 1; }else if(tim3_state == 1) //獲取T1,并改成上升沿中斷{tim3_cnt1 = __HAL_TIM_GetCounter(&htim3);//獲取T1(us)TIM3->CCER &= ~0x02; //上升沿中斷,CC1P置為0tim3_state = 2;}else if(tim3_state == 2) //第二個上升沿中斷,獲取T2(周期){tim3_cnt2 = __HAL_TIM_GetCounter(&htim3);//獲取T2(us)f39 = 1000000/tim3_cnt2; //R39的調整的555頻率 d39 = tim3_cnt1*100.0f/tim3_cnt2;tim3_state = 0;}HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);//開啟TIM3_CH1的輸入捕獲中斷}
}
其中:
防止超過cnt緩存區導致計算錯誤的一段源碼:
if(tim2ch1_cnt2 > tim2ch1_cnt1)
{
?? ?tim2ch1_HighCnt = tim2ch1_cnt2 - tim2ch1_cnt1;
}
else if(tim2ch1_cnt2 < tim2ch1_cnt1)
{
?? ?tim2ch1_HighCnt = ((0xffff - tim2ch1_cnt1) +tim2ch1_cnt2) + 1;?
}
特性?? HAL_TIM_ReadCapturedValue()
__HAL_TIM_GetCounter()
??數據來源?? 捕獲事件鎖存的快照值( TIMx_CCRy
)實時計數器值( TIMx_CNT
)??是否需要中斷?? 通常在輸入捕獲中斷中使用 無需中斷,隨時讀取 ??硬件依賴?? 需配置輸入捕獲通道 僅需定時器啟動 ??典型誤差場景?? 未啟用捕獲通道時返回0 計數器溢出時需處理溢出邏輯
3.定時器
HAL_TIM_Base_Start_IT(&htim1);
HAL_TIM_Base_Start(&htim1);
HAL_TIM_Base_Stop(&htim1);__HAL_TIM_SET_COUNTER(&htim3, 0); // 重置計數器
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim -> Instance == TIM3){}
}
08 RTC實時時鐘
//RTC
RTC_TimeTypeDef rtc_time;
RTC_DateTypeDef rtc_date;
void RTC_Process()
{HAL_RTC_GetTime(&hrtc, &rtc_time, RTC_FORMAT_BIN);HAL_RTC_GetDate(&hrtc, &rtc_date, RTC_FORMAT_BIN);
}
09 延時函數
STM32CubeMX | STM32 HAL庫方式的微秒延時函數_hal庫微秒延時-CSDN博客
HAL_DELAY():
10 滴答定時器
(藍橋杯)STM32G431RBT6(SysTick timer)_stm32g431rbt6數據手冊-CSDN博客
HAL_SYSTICK_Config(170000000/10000);if(HAL_GetTick()-temCnt>1000){HAL_GPIO_TogglePin (LED1_GPIO_Port,LED1_Pin);temCnt=HAL_GetTick();}