001 藍橋杯嵌入式賽道備賽——基礎

個人筆記,不扭扭捏捏,一口氣到位。方便自己也方便大家

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型號兼容性處理

支持兩種控制器:uC8230ILI932X系列(通過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-D15PC0-PC15數據總線
CSPB9片選信號
WRPB8寫使能
RDPB5讀使能
RSPA8命令/數據選擇

?? ?LCD_Init();//初始化
?? ?LCD_SetBackColor(Black);//設置背景顏色
?? ?LCD_SetTextColor(White);//設置文字顏色
?? ?LCD_Clear(Black);//刷新屏幕
?

05 ADC與DAC

1.ADC

ADC通道分配表(外部通道)

GPIO引腳對應ADC模塊及通道復用功能備注
?PB15ADC2_IN15……
?PB12ADC1_IN11……
?PB14ADC1_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博客

      1. ?核心功能

        • MCP4017是一個數字控制的可變電阻,通過I2C接口調節電阻值(0-10kΩ,128級可調0-127)。
          ??N值(十進制)????阻值(Ω)????電壓分壓值(VDD=3.3V)??
          000V
          6450.4k2.45V
          127(0x7F)100k3.0V(實際約2.9V)
        • 相當于一個“電子滑動變阻器”,程序可以動態改變其阻值,無需手動調節。
        • 阻值計算公式

      2. ?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();}

        本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
        如若轉載,請注明出處:http://www.pswp.cn/diannao/78963.shtml
        繁體地址,請注明出處:http://hk.pswp.cn/diannao/78963.shtml
        英文地址,請注明出處:http://en.pswp.cn/diannao/78963.shtml

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

        相關文章

        案例-索引對于并發Insert性能優化測試

        前言 最近因業務并發量上升,開發反饋對訂單表Insert性能降低。應開發要求對涉及Insert的表進行分析并提供優化方案。 ??一般對Insert 影響基本都在索引,涉及表已按創建日期做了分區表,索引全部為普通索引未做分區索引。 優化建議: 1、將UNIQUE改為HASH(64) GLOBAL IND…

        【技術文章的標準結構與內容指南】

        技術文章的標準結構與內容指南 技術文章是傳遞專業知識、分享實踐經驗的重要媒介。一篇高質量的技術文章不僅能夠幫助讀者解決問題&#xff0c;還能促進技術交流與創新。以下是技術文章通常包含的核心內容與結構指南。 1. 標題 一個好的技術文章標題應當&#xff1a; 簡潔明…

        豪越消防一體化安全管控平臺:構建消防“一張圖”新生態

        在城市化進程加速、建筑規模與功能日益復雜的當下&#xff0c;消防救援工作面臨著諸多嚴峻挑戰。火災隱患如同隱藏在暗處的“定時炸彈”&#xff0c;廣泛分布于城市的各個角落&#xff0c;想要快速、精準定位絕非易事。信息傳遞的不順暢更是雪上加霜&#xff0c;導致救援效率大…

        重學Redis:Redis常用數據類型+存儲結構(源碼篇)

        一、SDS 1&#xff0c;SDS源碼解讀 sds (Simple Dynamic String)&#xff0c;Simple的意思是簡單&#xff0c;Dynamic即動態&#xff0c;意味著其具有動態增加空間的能力&#xff0c;擴容不需要使用者關心。String是字符串的意思。說白了就是用C語言自己封裝了一個字符串類型&a…

        抖音IP屬地可以隨便選擇地址嗎?深度解析

        在當今社交媒體盛行的時代&#xff0c;抖音作為受歡迎的短視頻平臺之一&#xff0c;其IP屬地顯示功能引發了廣泛關注。許多用戶好奇&#xff1a;抖音的IP屬地是否可以隨意更改&#xff1f;是否存在方法可以“偽裝”自己的位置&#xff1f;?本文將深入探討這一話題。 一、抖音I…

        SOLID原則詳解:提升軟件設計質量的關鍵

        前言 關于設計原則SOLID具體指的是什么&#xff0c;怎么理解這些設計原則&#xff0c;我覺得有必要記錄一筆&#xff0c;畢竟這個設計原則確實經常在關鍵技術文檔中提及&#xff0c;在編程思想中提及&#xff0c;在日常的開發中使用&#xff0c;但是對我來說&#xff0c;似乎知…

        如何使用 ONLYOFFICE 恢復之前的文件版本?

        如何使用 ONLYOFFICE 恢復之前的文件版本&#xff1f; https://www.onlyoffice.com/blog/zh-hans/2023/04/how-to-use-version-history

        簡簡單單實現一個Python+Selenium的自動化測試框架

        什么是Selenium&#xff1f; Selenium是一個基于瀏覽器的自動化測試工具&#xff0c;它提供了一種跨平臺、跨瀏覽器的端到端的web自動化解決方案。Selenium主要包括三部分&#xff1a;Selenium IDE、Selenium WebDriver 和Selenium Grid。 Selenium IDE&#xff1a;Firefox的…

        Java設計模式之中介者模式:從入門到架構級實踐

        一、什么是中介者模式&#xff1f; 中介者模式&#xff08;Mediator Pattern&#xff09;是一種行為型設計模式&#xff0c;其核心思想是通過引入一個中介對象來封裝多個對象之間的交互關系。這種模式將原本復雜的網狀通信結構轉換為星型結構&#xff0c;類似于現實生活中的機…

        Trinity三位一體開源程序是可解釋的 AI 分析工具和 3D 可視化

        一、軟件介紹 文末提供源碼和程序下載學習 Trinity三位一體開源程序是可解釋的 AI 分析工具和 3D 可視化。Trinity 提供性能分析和 XAI 工具&#xff0c;非常適合深度學習系統或其他執行復雜分類或解碼的模型。 二、軟件作用和特征 Trinity 通過結合具有超維感知能力的不同交…

        LeetCode 熱題 100_單詞拆分(86_139_中等_C++)(動態規劃)

        LeetCode 熱題 100_單詞拆分&#xff08;86_139&#xff09; 題目描述&#xff1a;輸入輸出樣例&#xff1a;題解&#xff1a;解題思路&#xff1a;思路一&#xff08;動態規劃&#xff09;&#xff1a; 代碼實現代碼實現&#xff08;思路一&#xff08;動態規劃&#xff09;&a…

        VM虛擬機安裝及Ubuntu安裝配置

        VM虛擬機安裝及Ubuntu安裝配置 1、VM虛擬機安裝2、創建虛擬機3、Ubuntu系統安裝4、編譯環境配置4.1 、Ubuntu和 Windows文件互傳 文件互傳4.1.1、 開啟Ubunt下的FTP服務 4.2、 Ubuntu下NFS和SSH服務開啟4.2.1、 NFS服務開啟4.2.2、 SSH服務開啟 4.3、 交叉編譯器安裝4.3.1 安裝…

        【KWDB 創作者計劃】_產品技術解讀_1

        【KWDB 創作者計劃】_產品技術解讀_1 一、存儲引擎:高性能混合存儲架構1. 存儲模型設計2. 存儲壓縮與編碼3. 持久化策略二、KWDB 組件源碼解析1. 核心模塊分層架構2. 關鍵組件源碼剖析三、KWDB 特性代碼通讀1. 實時分析能力(Real-Time OLAP)2. 混合負載隔離(HTAP)3. 智能索…

        高速電路中的電阻、電容的選型及應用

        2.1 電阻的應用 2.1.1 與電阻相關的經典案例 如果說芯片是電路的骨架&#xff0c;那么電阻就是在芯片之間起連接作用的關節。電阻的阻值、布放位置等&#xff0c;對設計的成功起著至關重要的作用。 【案例2.1】串聯電阻過大&#xff0c;導致板間告警失敗 某產品由業務板和主…

        springBoot接入文心一言

        文章目錄 效果接入步驟項目接入配置類&#xff1a;WenXinYiYan前端vue代碼js代碼 后端mapper層service層controller層 測試代碼 效果 先來看一下最后實現的效果 &#xff08;1&#xff09;未點擊前的功能頁面 &#xff08;2&#xff09;點擊后的頁面 &#xff08;3&#xff…

        css解決邊框四個角有顏色

        效果 html <div class"gradient-corner">2021年</div>css background:/* 左上角橫線 */linear-gradient(90deg, rgb(5, 150, 247) 9px, transparent 0) 0 0,/* 左上角豎線 */linear-gradient(0deg, rgb(5, 150, 247) 9px, transparent 0) 0 0,/* 右上…

        自動化三維掃描:CASAIM外觀尺寸智能檢測

        制造業向智能化、數字化加速轉型&#xff0c;傳統檢測方式因效率低、精度差、數據斷層等問題&#xff0c;已難以滿足現代工業對精密測量與實時質控的需求。CASAIM依托前沿技術實力&#xff0c;以自動化三維掃描為核心&#xff0c;為工業檢測提供了從數據采集到智能分析的全流程…

        突破亞馬遜壁壘,Web Unlocker API 助您輕松獲取數據

        目錄 一、Web Unlocker API簡介二、開始使用Web Unlocker API1、首先進入控制臺頁面&#xff0c;點擊左側第一個tab鍵“代理 & 抓取基礎設施”&#xff0c;找到“網頁解鎖器”&#xff0c;開始使用。2、進入網頁解鎖器頁面后&#xff0c;填寫通道名稱&#xff0c;添加簡短描…

        【力扣05】最長回文子串

        0. 引言 ●子串(substring&#xff09;&#xff1a;原始字符串的一個連續子集; ●子序列&#xff08;subsequence&#xff09;&#xff1a;原始字符串的一個子集。 1. 什么叫回文串&#xff1f; 如果一個字符串正著讀和反著讀是一樣的&#xff0c;那它就是回文串。[1] 例如&…

        統計銷量前十的訂單

        傳入參數&#xff1a; 傳入begin和end兩個時間 返回參數 返回nameList和numberList兩個String類型的列表 controller層 GetMapping("/top10")public Result<SalesTop10ReportVO> top10(DateTimeFormat(pattern "yyyy-MM-dd") LocalDate begin,Dat…