STM32中定時器配置,HAL_Delay的原理,滴答定時器,微秒延時實現,PWM,呼吸燈

目錄

定時器基本定時功能實現

CubeMX設置

手動書寫代碼部分

定時器啟動

實現溢出回調函數

HAL_Delay介紹

HAL_Delay實現原理

HAL_Delay的優點

HAL_Delay的缺點

利用滴答定時器(SysTick)實現微秒級延時

PWM

?PWM介紹

通用定時器中的重要寄存器

PWM中的捕獲比較通道

什么是定時器通道?

定時器通道如何工作?

為什么需要定時器通道?

PWM實現呼吸燈

CubeMX配置

關于TIMx_PSC和TIMx_ARR的計算

幾種不同方式實現設定PWM的周期

如何選擇不同PSC與ARR的組合?

代碼編寫


定時器基本定時功能實現

CubeMX設置

注意,這里只是對定時器配置實現一個很簡單的定時功能。

時鐘來源

定時器中斷使能?

定時器預分頻值,計數模式,計數周期

手動書寫代碼部分

定時器啟動

下面主要介紹一下關于定時器的簡單運用

關于下面圖片中的初始化函數我們可以不用過于在意,因為在我們上面CUBEMX中已經配置過了,而且定時器的初始化相比于外部中斷要復雜的多,所以就不推薦手動書寫代碼配置了,主要掌握CubeMX中的定時器初始化配置方式就行。

在main.c中讓定時器開始運行

盡管我們在CubeMX或類似的配置工具中配置了定時器,并生成了代碼,但生成代碼僅僅是設置了定時器的參數(如時鐘源、預分頻器、自動重載值、中斷使能等)。這些配置通常在 MX_TIMx_Init() 或類似的初始化函數中完成。

然而,這些初始化函數并不會自動啟動定時器或啟用中斷,需要我們調用相應的啟動函數來手動對定時器開啟。這是一種設計哲學,記住就好,也就是多了一行開啟時鐘代碼。

啟動定時器函數需要一個參數,接受一個TIM_HandleTypeDef類型的地址,

這個參數在我們的TIM2_Init函數中有,是在tim.c中定義的,是一個全局變量。

由于我們的main.c文件中包含了tim.h頭文件,并且tim.h中對于這個變量進行了extern聲明,所以在main中可以直接使用htim2了

htim2 用于表示特定定時器實例(在這里是 TIM2) 的一個句柄 (Handle) 結構體變量,包含了管理特定定時器所需的所有配置信息和狀態,我們對定時器進行配置的時候主要就是對這個變量進行配置。

  • 它是全局的:通常定義在文件作用域,可以在程序的任何地方(只要包含了定義它的文件或聲明它的頭文件)訪問和修改它。
    ?
  • 它是訪問點:所有針對 TIM2 定時器的 HAL 庫函數(如 HAL_TIM_Base_Start_IT(&htim2)、HAL_TIM_PeriodElapsedCallback(&htim) 等)都需要通過這個 htim2 句柄來知道它們正在操作的是哪個定時器

實現溢出回調函數

由于我們使用了CubeMX配置了定時器,所以關于定時器的TIM6_DAC_IRQHander()不需要我們來聲明并實現,這里的邏輯和中斷處理那塊的邏輯差不多,不過定時器這里有很多回調函數,對于簡單的定時功能,我們需要實現的是溢出回調函數——HAL_TIM_PeriodElapsedCallback()。

通過HAL_TIM_PeriodElapsedCallback()可以實現周期性任務:

  • LED 閃爍: 每隔 500ms 翻轉一次 LED 的狀態。
  • 數據采樣: 每隔 10ms 讀取一次傳感器數據。
  • 任務調度: 以固定的頻率觸發一個任務的執行。

關于HAL_TIM_PeriodElapsedCallback這個弱定義函數可以放main.c函數中進行實現。

補充一下main.c文件中函數聲明和實現的寫法

????????聲明在 main() 函數之前: 在 main.c 中,確實經常看到用戶編寫的函數(在 main() 函數之前進行聲明(原型聲明)。

????????實現通常在 main() 函數之后: 而這些函數的實現(函數體)則經常放在 main() 函數的后面,通常是在 /* USER CODE BEGIN 4 */ 和 /* USER CODE END 4 */ 這樣的用戶代碼區域內。

其他模塊的文件一般我們的選擇是:在.h中進行函數的聲明,在.c文件中進行函數的實現。?

HAL_Delay介紹

HAL_Delay實現原理

HAL_Delay() 的實現方式主要基于 SysTick 定時器一個全局的滴答計數變量 (uwTick)

如果是使用CubeMX進行的配置,那么默認會在main()中調用HAL_Init(),里面會自動幫我們啟動滴答定時器(SysTick)

SysTick 是 Cortex-M 系列處理器(包括 STM32)內置的一個 24 位倒計時定時器。它直接集成在 CPU 核心內部。

工作方式:

  • 我們會配置 SysTick 的重裝載值(Reload Value)。
  • 一旦啟用,SysTick 計數器會從這個重裝載值開始遞減,SysTick 計數器一般直接使用系統的主時鐘頻率HCLK。
  • 當計數器遞減到 0 時,它會產生一個 SysTick 中斷,然后自動重新裝載并再次開始遞減。所以?每過 1ms,SysTick 計數器遞減到 0,觸發一次?SysTick 中斷
  • 執行 ISR: 處理器響應 SysTick 中斷,執行相應的 ISR。
  • 調用 HAL_IncTick(): 在 SysTick 的 ISR 內部,HAL_IncTick() 被執行。
  • 更新 uwTick: HAL_IncTick() 將全局變量 uwTick 加 1。
  • HAL_GetTick() 函數的實現非常直接,它只是簡單地返回當前 uwTick 變量的值:

HAL_Delay的偽代碼如下:

void HAL_Delay(uint32_t Delay) {uint32_t tickstart = HAL_GetTick(); // 獲取當前系統滴答值uint32_t wait = tickstart + Delay;   // 計算目標滴答值// 等待直到達到目標滴答值,并處理uwTick可能溢出的情況while((HAL_GetTick() < wait) && ((HAL_GetTick() - tickstart) < Delay)) {// 空循環,CPU在此處忙等待}
}

HAL_Delay的優點

1. 使用簡單,易于上手

HAL_Delay() 的接口非常直觀:你只需要傳入一個你想要延時的毫秒數,函數就會阻塞相應的時長。對于嵌入式編程的初學者來說,這是最容易理解和使用的延時方式,能夠快速實現一些簡單的功能

2. 無需額外配置

一旦 HAL 庫和 SysTick 定時器被初始化(這通常在項目啟動時自動完成),HAL_Delay() 就可以直接調用,無需進行額外的定時器配置,也不需要編寫中斷服務程序。這大大簡化了開發流程,尤其是在快速原型開發或對延時精度要求不高的場景下。

HAL_Delay的缺點

1. 阻塞式操作 (Blocking):

這是最主要的缺點。當調用 HAL_Delay() 時,CPU 會進入一個忙等待循環,不執行任何其他有用的任務,直到延時結束。

2. 不適用于精確的微秒級延時:

HAL_Delay() 的精度是毫秒級,因為它依賴于 1ms 的 SysTick 中斷。對于需要微秒(us)甚至納秒(ns)級別的精確延時,HAL_Delay() 無法滿足要求。

3.不適用于中斷服務程序 (ISR) 中使用:

嚴重問題: 絕對不能在中斷服務程序 (ISR) 中直接調用 HAL_Delay()

HAL_Delay() 依賴于 SysTick 中斷來更新 uwTick 變量。如果 SysTick 中斷的優先級低于(數值上大于)當前執行的 ISR,那么 SysTick 中斷將無法搶占當前 ISR 并執行,導致 uwTick 無法更新。這樣一來,HAL_Delay() 就會陷入無限循環,使系統徹底崩潰。

HAL_Delay()中的SysTick定時器默認的優先級是最低的,所以在ISR中調用HAL_Delay不可能調用成功,會持續阻塞在這里,除非我們手動調整SysTick定時器優先級(讓其變得更高),但是這也是非常非常非常不推薦的!!!

4. 與 RTOS 的兼容性問題:

如果您的項目使用了實時操作系統 (RTOS),如 FreeRTOS,直接使用 HAL_Delay() 是不推薦的。

RTOS 有自己的任務調度機制,它提供的延時函數(例如 FreeRTOS 的 osDelay() 或 vTaskDelay())會在任務延時期間將當前任務掛起,并允許調度器切換到其他任務執行,從而充分利用 CPU 資源。

利用滴答定時器(SysTick)實現微秒級延時

上面說到了使用滴答定時器(SysTick)實現的延遲函數HAL_Delay,只能實現ms級別延時,對于更精確的微秒級別是不支持的,下面我們自己來使用SysTick實現微秒級延時。

下面實現的delay_us 函數是一個典型的忙等待(busy-waiting) 實現,也就是基于查詢方式實現的沒有用到中斷

void delay_us(uint32_t nus){uint32_t ticks;uint32_t told, tnow, tcnt = 0;uint32_t reload = SysTick->LOAD + 1;		//計數個數為重裝載值加1ticks=nus*(SystemCoreClock/1000000);		//nus 微秒總共需要的 SysTick 節拍數told= SysTick->VAL;							//初始計數器值while(1){tnow=SysTick->VAL;if(tnow!= told){if(tnow<told)	tcnt += told- tnow;		//SysTick遞減的計數器else tcnt += reload- tnow + told;told= tnow;if(tcnt>=ticks)	break;					//延時時間已到,退出}}}

這段代碼通過不斷讀取 SysTick 的值,并巧妙地處理了 SysTick 遞減計數和溢出(繞回)的特性,來精確地累加流逝的節拍數。當累加的節拍數達到預設的目標值時,就完成了微秒級的延時。

PWM

下面這個視頻是對pwm比較專業一點的介紹

【STM32】輸出比較模式講解以及STM32CUBEMX+MDK代碼實現_嗶哩嗶哩_bilibili

?下面這篇文章是對pwm比較通俗一點的介紹,更易理解

?PWM原理 PWM頻率與占空比詳解-CSDN博客

?PWM介紹

PWM,全稱是脈沖寬度調制,它通過數字方式來模擬出模擬信號的效果,簡單來說,PWM的原理就是通過快速開關一個數字信號(比如電源),并且控制它在一個周期內“開”的時間長短來達到目的。

脈沖寬度通常就是指在一個完整的 PWM 周期內,信號處于高電平(ON 狀態)的持續時間長度

下面是一些關鍵點:

  • PWM周期(一個PWM完整波需要的時間)(Period):這是指一個完整的PWM波形所需的時間,也就是說,信號從“開”到“關”再回到“開”的總時間。

  • 占空比(Duty Cycle):這是PWM的核心。它表示在一個周期內,信號處于“開”狀態的時間所占的比例。占空比越高,信號“開”的時間就越長。

  • PWM頻率(Frequency):這是指每秒鐘有多少個PWM周期。頻率越高,信號切換得越快,看起來就越平滑,越像一個真正的模擬信號。PWM 的頻率是由 ARR 和 PSC 共同決定的

PWM是如何工作的?

想象一下你有一個燈泡,你想控制它的亮度。

  • 如果你一直給燈泡供電(100%占空比),它就會全亮。

  • 如果你完全不給燈泡供電(0%占空比),它就會熄滅。

  • 如果你以很快的速度,比如每秒鐘開關1000次,每次只讓燈泡亮一半的時間(50%占空比),那么因為你的眼睛無法分辨這么快的開關,燈泡看起來就會是半亮的狀態。

這就是PWM的工作原理。通過調整“開”的時間比例(占空比),我們就可以控制燈泡的亮度、電機的轉速、音頻信號的音量等等。

通用定時器中的重要寄存器

預分頻器寄存器 (TIMx_PSC)

這個寄存器用于設置定時器時鐘的預分頻值,從而設置了定時器的時鐘頻率

PSC (Prescaler Value):定時器時鐘源會通過這個預分頻器進行分頻,從而得到計數器實際使用的時鐘頻率。計算方式:計數器時鐘頻率 = 定時器時鐘源頻率 / (PSC + 1)

自動重載寄存器 (TIMx_ARR)

這個寄存器定義了計數器達到多少時會溢出并重新開始計數(或改變計數方向)。
?

  • ARR (Auto-Reload Value):當計數器達到 ARR 的值時,會發生更新事件。
    ?
  • 計算方式:PWM 的頻率是由 ARR 和 PSC 共同決定的。PWM 頻率 = 計數器時鐘頻率 / (ARR + 1) = 定時器時鐘源頻率 / ((PSC + 1) * (ARR + 1))。
    ?
  • 作用:設置 PWM 信號的周期和頻率ARR 值越大,PWM周期越長頻率越低

捕獲/比較寄存器 (TIMx_CCRx)

每個 PWM 通道都有一個對應的 CCRx 寄存器(如 TIMx_CCR1, TIMx_CCR2 等)。

CCRx (Capture/Compare Register Value):這個寄存器存儲的值與計數器 CNT 的值進行比較,從而決定 PWM 信號的占空比。

  • 計算方式:占空比 = CCRx / (ARR + 1)。
    ?
  • 例如,如果 ARR = 999,CCRx = 500,那么占空比就是 500 / 1000 = 50%。
    ?
  • 作用:設置 PWM 信號的脈沖寬度,進而控制占空比

當然通用定時器中還有一些其他寄存器,很多這些寄存器由CubeMX幫我們自動設置好了,所以不需要很關注。

PWM中的捕獲比較通道

什么是定時器通道?

你可以把一個微控制器里的定時器想象成一個多功能的廚房定時器總機。這個總機本身可以計時(例如,設定每秒滴答一次)。而通道就是這個總機上獨立的定時器插口或功能模塊

每個通道都可以獨立地配置來完成特定的任務,例如:

  • 捕獲輸入(Input Capture): 測量外部信號的脈沖寬度、頻率或邊沿之間的時間間隔。

  • 比較輸出(Output Compare): 在定時器計數到預設值時,改變輸出引腳的狀態(高/低電平),用于產生PWM波形、延時輸出脈沖等。

  • PWM 生成(PWM Generation): 最常見的用途之一,生成可調占空比的脈沖寬度調制信號,用于電機調速、LED調光等。

  • 單脈沖模式(One-Pulse Mode): 在事件發生后產生一個固定寬度的脈沖。

一個定時器通常會有2個、4個或更多個通道,這意味著這個定時器可以同時處理2個、4個或更多個上述的獨立任務。

定時器通道如何工作?

每個定時器通道內部都有一組專門的寄存器來配置它的行為,其中最重要的就是比較/捕獲寄存器 (Capture/Compare Register, CCR)

  • 作為輸出(Output Compare/PWM): 當定時器的內部計數器(通常是TIMx_CNT寄存器)的值與某個通道的CCR寄存器的值相等時,定時器就會觸發該通道預設的動作(例如,翻轉輸出電平、生成PWM脈沖)。你可以為每個通道設置不同的CCR值,從而產生不同的輸出波形或在不同時間點觸發事件。一旦配置好,通道會根據定時器計數器的值自動在引腳上生成PWM波形,無需CPU干預

  • 作為輸入(Input Capture): 當外部引腳上的信號(例如,上升沿或下降沿)發生變化時,定時器會將當前內部計數器(TIMx_CNT)的值“捕獲”到對應通道的CCR寄存器中。通過讀取不同邊沿捕獲到的CCR值,就可以計算出脈沖寬度、周期等。

為什么需要定時器通道?

  1. 多任務并行: 如果一個應用需要同時生成兩個不同頻率或占空比的PWM波形,或者同時測量兩個不同信號的頻率,那么使用一個多通道定時器會比使用兩個獨立的單功能定時器更高效、更節省資源。

  2. 資源優化: 微控制器內部的硬件定時器是有限的寶貴資源。多通道設計允許單個定時器模塊完成多種定時/計數相關的任務,從而節省了片上定時器模塊的數量。

  3. 靈活性: 每個通道都可以獨立配置其工作模式,極大地增加了定時器模塊的靈活性,使其能夠適應各種復雜的應用需求。

  4. 硬件實現: 定時器通道通常通過硬件邏輯實現,這意味著一旦配置完成,它們就能自動、精確地工作,無需CPU干預,從而減輕了CPU的負擔,提高了系統的實時性。

PWM實現呼吸燈

CubeMX配置

PB10 引腳配置成 TIM2_CH3(定時器2的通道3) 的操作,正是屬于 STM32 微控制器中的 輸出復用功能模式

復用功能 (Alternate Function, AF): 一個GPIO引腳除了其通用IO功能外,還可以“復用”為某個片內外設(如定時器、SPI、I2C、USART等)的專用功能引腳。

這樣配置之后的效果

引腳功能特化: PB10 不再是簡單的 GPIO,變成了一個由硬件定時器控制的專用引腳

  • 作為 PWM 輸出,?PB10 引腳將輸出一個脈沖寬度調制(PWM)波形
    ?
  • 作為 輸出比較,當 TIM2 的計數器值與 TIM2_CH3 的比較值(CCR3)相等時,PB10 引腳的電平狀態會按照預設的模式發生變化(例如,翻轉、置高、置低)。
    ?
  • 作為 輸入捕獲,PB10 引腳將作為一個輸入引腳。當外部信號在這個引腳上發生預設的邊沿(上升沿、下降沿或雙邊沿)時,TIM2 定時器的當前計數值會被立即“捕獲”并存儲到 TIM2_CH3 對應的捕獲/比較寄存器(CCR3)中。

我想要讓LED1變成呼吸燈,在我的電路板上,LED1對應的是PB10,然后右鍵查看對應的多路復用模式中對應的正好是TIM2_CH3,我們選擇定時器2的通道3,然后我們需要去配置?TIM2

?

具體的參數配置,主要是要計算分頻系數(TIMx_PSC)和自動重載寄存器 (TIMx_ARR)

?通過設置這兩個寄存器,就實現了設置PWM的周期和頻率

這里我們的主時鐘頻率為100Mhz,假如我想要讓輸入TIM2的時鐘頻率變為100Khz,讓PWM的周期變成20ms,那么此時TIMx_PSC和TIMx_ARR計算方式如下:

TIMx_PSC =?100Mhz/100Khz - 1 = 999;

由于TIM2的時鐘頻率為100Khz,所以一個節拍對應的為1/100000=0.00001s=0.01ms,

20ms/0.01ms=2000,所以TIMx_ARR=2000-1=1999

關于TIMx_PSC和TIMx_ARR的計算

幾種不同方式實現設定PWM的周期

在上面的例子中,要達到 PWM 周期為 20ms 這個目標TIMx_PSC (分頻系數)TIMx_ARR (自動重載寄存器) 的設置并非只有一種固定組合。它們是相互關聯的,我們可以通過調整其中一個,來相應地調整另一個,以達到相同的周期。

  • 定時器時鐘頻率:這是輸入到特定定時器(例如 TIM2)的時鐘頻率,通常是主時鐘頻率經過 APB 分頻器后得到的。在我們的例子中,假設主時鐘是 100MHz。
    ?

  • TIMx_PSC (Prescaler Value):分頻系數。它決定了定時器計數器實際的計數頻率。計數器每經過 (TIMx_PSC + 1) 個定時器時鐘周期,才遞增/遞減一次。
    ?

  • TIMx_ARR (Auto-Reload Register):自動重載值。它決定了定時器計數器的上限。計數器從 0 數到 TIMx_ARR(或從 TIMx_ARR 數到 0),表示一個完整的計數周期,共 (TIMx_ARR + 1) 個節拍。

方法一:我們之前的方法 (分頻后的時鐘頻率為 100 KHz)

  • 選擇分頻系數 TIMx_PSC = 999

    • 此時 (PSC + 1) = 1000

    • 分頻后的定時器計數頻率 = 100?MHz/1000=100?KHz

  • 計算 TIMx_ARR

    • ?(TIMx_ARR + 1) \times 1000 = 2,000,000

    • ?(TIMx_ARR + 1) = 2,000,000 / 1000 = 2000

    • TIMx_ARR=1999

    • 這種組合是:PSC = 999, ARR = 1999?

方法二:讓分頻后的時鐘頻率為 1 MHz

  • 選擇分頻系數 TIMx_PSC = 99

    • 此時 (PSC + 1) = 100

    • 分頻后的定時器計數頻率 = 100?MHz/100=1?MHz

  • 計算 TIMx_ARR

    • (TIMx_ARR + 1) \times 100 = 2,000,000

    • (TIMx_ARR + 1) = 2,000,000 / 100 = 20000

    • TIMx_ARR=19999

    • 這種組合是:PSC = 99, ARR = 19999?

方法三:讓分頻后的時鐘頻率為 50 KHz

  • 選擇分頻系數 TIMx_PSC = 1999

    • 此時 (PSC + 1) = 2000

    • 分頻后的定時器計數頻率 = 100?MHz/2000=50?KHz

  • 計算 TIMx_ARR

    • (TIMx_ARR + 1) \times 2000 = 2,000,000

    • ?(TIMx_ARR + 1) = 2,000,000 / 2000 = 1000

    • TIMx_ARR=999

    • 這種組合是:PSC = 1999, ARR = 999

如何選擇不同PSC與ARR的組合?

雖然有多種組合可以達到相同的 PWM 周期,但在實際應用中,選擇哪種組合通常取決于以下因素:

  1. 占空比精度 (Duty Cycle Resolution):

    • ARR 值越大,表示在一個 PWM 周期內有更多的計數節拍。

    • 這意味著您可以更精細地調整占空比。例如,如果 ARR = 19999,您可以將占空比設置為 (0/20000)(19999/20000) 之間的任何值,有 20000 個可能的占空比級別。

    • 如果 ARR = 999,您只有 1000 個占空比級別。

    • 因此,通常會選擇較大的 ARR 值以獲得更高的占空比精度,前提是 ARR 不超過寄存器的最大值(如 16位定時器 ARR 最大為 65535,32位定時器更大)。

  2. PSCARR 的寄存器大小限制:

    • 大多數通用定時器的 PSCARR 寄存器是 16 位的,這意味著它們的值不能超過 65535。

    • 有些高級定時器或較新的微控制器可能有 32 位的定時器。在選擇 PSCARR 時,需要確保它們不超過對應寄存器的最大值。

    • 在我們的例子中,2,000,000 這個乘積超出了 16 位定時器的單個寄存器范圍,所以必須進行分頻,即 PSCARR 都不能為 0(除非定時器頻率非常低)。

  3. 計算方便性/可讀性:

    • 有時會選擇整數倍的分頻,使得計數頻率成為一個“整”的 KHz 或 MHz 值,方便理解和計算。

綜上所述,我們通常會選擇較大的 ARR 值以獲得更高的占空比精度,但是同時也要注意PSC 和 ARR 設置的值不能超過寄存器大小限制!

代碼編寫

由于CubeMX依舊已經幫我們做了很多工作,所以這里我們需要修改的很少。

呼吸燈的效果是通過 PWM (脈沖寬度調制) 來實現的。我們通過周期性地改變 PWM 波形的占空比(即高電平持續時間與整個周期的比值),來控制 LED 的亮度。

  • 當占空比從 0% 逐漸增加到 100% 時,LED 會從滅逐漸變亮;
  • 當占空比從 100% 逐漸減小到 0% 時,LED 會從亮逐漸變滅。

這個過程循環往復,就形成了“呼吸”的效果。

下面是啟動 PWM 輸出的關鍵函數。它告訴定時器 TIM2 的通道3 開始生成 PWM 波形。請務必在進入 while(1) 循環之前調用它。

HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);

?這個函數會啟動定時器(如果它尚未運行)并使其 PWM 輸出開始在指定的通道引腳上生成波形。

關于調節占空比其實就是在調節比較捕獲寄存器的值:

  • 計算方式:占空比 = CCRx / (ARR + 1)。
  • 例如,如果 ARR = 999,CCRx = 500,那么占空比就是 500 / 1000 = 50%。

設置比較捕獲寄存器TIMx_CCRx的值:

__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, duty);

這是一個 HAL 庫的宏(本質上是直接操作寄存器),用于設置指定定時器通道的比較值(CCR 寄存器)

duty_cycle 的值直接決定了 PWM 的占空比。當 duty_cycle 接近 0 時,LED 滅;接近 PWM_MAX_DUTY 時,LED 最亮。

  /* USER CODE BEGIN 2 */HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3); /* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */uint32_t duty;while (1){/* USER CODE END WHILE */for(duty=0; duty<2000; duty += 20){__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, duty);HAL_Delay(20);}for(duty=2000; duty>0; duty-=20){__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, duty);HAL_Delay(20);}/* USER CODE BEGIN 3 */}

?

推薦好文:

STM32定時器詳解:原理、配置與應用實戰-CSDN博客

STM32 定時器TIM-CSDN博客

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

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

相關文章

飛牛NAS(fnOS)詳細安裝教程

以下是飛牛NAS&#xff08;fnOS&#xff09;的詳細安裝教程&#xff0c;結合官方指南和社區實踐整理而成&#xff1a; 一、準備工作 硬件需求 8GB或更大容量的U盤&#xff08;用于制作啟動盤&#xff09;待安裝設備&#xff08;支持x86架構的物理機或迷你主機&#xff0c;如天鋇…

springboot 顯示打印加載bean耗時工具類

一 spring的原生接口說明 1.1 接口說明 Aware是Spring框架提供的一組特殊接口&#xff0c;可以讓Bean從Spring容器中拿到一些資源信息。 BeanFactoryAware&#xff1a;實現該接口&#xff0c;可以訪問BeanFactory對象&#xff0c;從而獲取Bean在容器中的相關信息。 Environm…

OpenGL空間站場景實現方案

OpenGL空間站場景實現方案 需求分析 根據任務要求,我需要完成一個基于Nehe OpenGL的空間站場景,實現以下功能: 完整的空間站場景建模(包含多個模型和紋理貼圖)Phong光照模型實現(包含多種光源和材質效果)攝像機鍵盤控制交互功能解決方案設計 技術棧 C++編程語言OpenG…

基于昇騰310B4的YOLOv8目標檢測推理

YOLOv8目標檢測 om 模型推理 本篇博客將手把手教你如何將 YOLOv8 目標檢測模型部署到華為昇騰 310B4 開發板上進行高效推理&#xff08;其他昇騰開發版也可參考此流程&#xff09;。 整個流程包括&#xff1a; 模型格式轉換&#xff08;ONNX → OM&#xff09;昇騰推理環境配…

前端跨域問題解決Access to XMLHttpRequest at xxx from has been blocked by CORS policy

在前端開發中&#xff0c;跨域資源共享&#xff08;CORS&#xff09;是一個常見的問題。它涉及到瀏覽器安全機制&#xff0c;防止網頁從一個域獲取資源時被另一個域阻止。錯誤信息如“Access to XMLHttpRequest at xxx from origin has been blocked by CORS policy”是典型的跨…

[ linux-系統 ] 軟硬鏈接與動靜態庫

軟硬鏈接 介紹 軟鏈接 通過下圖可以看出軟鏈接和原始文件是兩個獨立的文件&#xff0c;因為軟鏈接有著自己的inode編號&#xff1a; 具有獨立的 inode &#xff0c;也有獨立的數據塊&#xff0c;它的數據塊里面保存的是指向的文件的路徑&#xff0c;公用 inode 硬鏈接 通過…

3D 商品展示與 AR 試戴能為珠寶行業帶來一些便利?

對于珠寶行業而言&#xff0c;長久以來&#xff0c;如何讓消費者在做出購買決策之前&#xff0c;便能真切且直觀地領略到珠寶獨一無二的魅力&#xff0c;始終是橫亙在行業發展道路上的一道棘手難題。而 3D 互動營銷的橫空出世&#xff0c;恰似一道曙光&#xff0c;完美且精準地…

電子電氣架構 --- SOVD功能簡單介紹

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 簡單,單純,喜歡獨處,獨來獨往,不易合同頻過著接地氣的生活,除了生存溫飽問題之外,沒有什么過多的欲望,表面看起來很高冷,內心熱情,如果你身…

【Java編程動手學】 Java中的運算符全解析

文章目錄 一、引言二、算術運算符1、基本概念2、具體運算符及示例 三、關系運算符1、基本概念2、具體運算符及示例 四、自增減運算符1、基本概念2、具體運算符及示例 五、邏輯運算符1、基本概念2、具體運算符及示例 六、位運算符1、基本概念2、具體運算符及示例 七、移位運算符…

【前端】1 小時實現 React 簡歷項目

近期更新完畢。僅包括核心代碼 目錄結構 yarn.lock保證開發者每次能下載到同版本依賴&#xff0c;一般不需要特別留意 package.json 是 Node.js 項目、前端項目、npm/yarn的配置文件。 Dockerfile 是用來 定義 Docker 鏡像構建過程的文本文件。它是一份腳本&#xff0c;告訴 …

python中的pydantic是什么?

Pydantic 是 Python 中一個用于數據驗證和設置管理的庫&#xff0c;主要通過 Python 類型注解&#xff08;Type Hints&#xff09;來定義數據結構&#xff0c;并自動驗證輸入數據的合法性。它廣泛應用于 API 開發&#xff08;如 FastAPI&#xff09;、配置管理、數據序列化等場…

騰訊云市場目前飽和度

首先我需要理解市場飽和度的概念。市場飽和度通常指一個產品或服務在潛在市場中的滲透程度&#xff0c;高飽和度意味著市場增長空間有限&#xff0c;低飽和度則表明還有較大發展潛力。 從搜索結果看&#xff0c;騰訊云目前在中國云服務市場排名第三&#xff0c;市場份額約為15%…

EDR、NDR、XDR工作原理和架構及區別

大家讀完覺得有幫助記得關注和點贊&#xff01;&#xff01;&#xff01; EDR、NDR、XDR是網絡安全中關鍵的檢測與響應技術&#xff0c;它們在覆蓋范圍、數據源和響應機制上有顯著差異。以下是它們的工作原理和架構詳解&#xff1a; --- ### &#x1f50d; 一、EDR&#xff0…

vue3 + luckysheet 實現在線編輯Excel

效果圖奉上&#xff1a; 引入的依賴&#xff1a; "dependencies": {"types/jquery": "^3.5.32","types/xlsx": "^0.0.36","jquery": "^3.7.1","xlsx": "^0.18.5",}在index.html中…

Linux下MinIO分布式安裝部署

文章目錄 一、MinIO簡單說明二、MinIO分布式安裝部署1、關閉SELINUX2、開啟防火墻2.1、關閉firewall&#xff1a;2.2、安裝iptables防火墻 3、安裝MinIO4、添加MinIO集群控制腳本4.1添加啟動腳本4.2添加關閉腳本 5、MinIO控制臺使用 一、MinIO簡單說明 1、MinIO是一個輕量的對…

Codeforces Round 980 (Div. 2)

ABC 略 D 這個過程一定是由1向后跳的過程中穿插有幾次向前一步一步走。直到跳到一個位置后再把前面所有沒有走過的位置倒序走一遍。總分就等于最大位置的前綴和-前面所有起跳位置和。前綴和固定我們只需要求到每個位置的最小起跳和即可。對于這個向后跳和向前走的過程我們可以…

Langchain實現rag功能

RAG&#xff08;檢索增強生成&#xff09;的核心是通過外部知識庫增強大模型回答的準確性和針對性&#xff0c;其工作流程與優化策略如下&#xff1a; 一、RAG 核心流程 ?知識庫構建? ?文檔加載與分割?&#xff1a;將非結構化文檔&#xff08;PDF、Markdown等&#xff09;…

算法筆記上機訓練實戰指南刷題

算法筆記上機訓練實戰指南刷題記錄 文章目錄 算法筆記上機訓練實戰指南刷題記錄模擬B1001 害死人不償命的(3n1)猜想B1011 AB 和 CB1016 部分ABB1026 程序運行時間B1046劃拳B1008數組元素循環右移問題B1012 數字分類B1018 錘子剪刀布A1042 Shuffling Machine 每天兩題&#xff0…

MYSQL基礎內容

一、介紹 1.不用數據庫&#xff1a;使用IO流對數據進行管理 2.使用數據庫&#xff1a;使用SQL語句對開發的數據進行管理&#xff0c;能儲存上億條數據 3.MYSQL&#xff1a; 是流行的關系型數據庫管理系統之一&#xff0c;將數據保存在不同的數據表中&#xff0c;通過表與表之…

音視頻會議服務搭建(設計方案)-01

前言 最近在做音視頻會議系統服務搭建的工作任務&#xff0c;因為內容過多&#xff0c;我會逐篇分享相關的設計方案、開發思路、編程語言、使用的組件集合等等。如果你也有大型音視頻會議系統搭建架構的需求&#xff0c;希望這些可以對你有所幫助。 EchoMeet 音視頻會議系統架構…