江科大TIM定時器hal庫實現

定時器相關hal庫函數

hal庫的定時器函數相比于標準庫,多了很多的中斷回調函數,同時對于定時器的初始化也改成使用句柄一次性順帶連帶DMA等功能一起初始化了

typedef struct
{uint32_t Prescaler;         /*定時器的預分頻值*/uint32_t CounterMode;       /*計數方向,向上計數,向下計數或雙邊計數*/uint32_t Period;            /*自動重裝載值*/uint32_t ClockDivision;     /*定時器時鐘分頻*/uint32_t RepetitionCounter;  /*高級定時器特有的重裝載次數*/uint32_t AutoReloadPreload;  /*自動重裝值的更新方式,使能的話,就會使用影子寄存器來等待這次的定時器周期過了才會更新自動重裝值到ARR寄存器,失能的話就是直接更新到ARR*/
} TIM_Base_InitTypeDef;

時基單元的初始化和標準庫的也是幾乎一樣的,多了一個自動重裝值的更新方式。

#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
typedef struct __TIM_HandleTypeDef
#else
typedef struct
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
{TIM_TypeDef                        *Instance;         /*TIMX的地址,選擇我們要的定時器*/TIM_Base_InitTypeDef               Init;              /*定時器初始化結構體*/HAL_TIM_ActiveChannel              Channel;           /*定時器通道使能*/DMA_HandleTypeDef                  *hdma[7];          /*DMA結構體初始化*/HAL_LockTypeDef                    Lock;              /*定時器配置鎖定*/__IO HAL_TIM_StateTypeDef          State;             /*定時器狀態標志*/__IO HAL_TIM_ChannelStateTypeDef   ChannelState[4];   /*定時器四個通道狀態*/__IO HAL_TIM_ChannelStateTypeDef   ChannelNState[4];  /*高級定時器的四個互補通道狀態*/__IO HAL_TIM_DMABurstStateTypeDef  DMABurstState;     /*定時器DMA突發傳輸狀態*/
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)void (* Base_MspInitCallback)(struct __TIM_HandleTypeDef *htim);              /*!< TIM Base Msp Init Callback                              */void (* Base_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);            /*!< TIM Base Msp DeInit Callback                            */void (* IC_MspInitCallback)(struct __TIM_HandleTypeDef *htim);                /*!< TIM IC Msp Init Callback                                */void (* IC_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);              /*!< TIM IC Msp DeInit Callback                              */void (* OC_MspInitCallback)(struct __TIM_HandleTypeDef *htim);                /*!< TIM OC Msp Init Callback                                */void (* OC_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);              /*!< TIM OC Msp DeInit Callback                              */void (* PWM_MspInitCallback)(struct __TIM_HandleTypeDef *htim);               /*!< TIM PWM Msp Init Callback                               */void (* PWM_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);             /*!< TIM PWM Msp DeInit Callback                             */void (* OnePulse_MspInitCallback)(struct __TIM_HandleTypeDef *htim);          /*!< TIM One Pulse Msp Init Callback                         */void (* OnePulse_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);        /*!< TIM One Pulse Msp DeInit Callback                       */void (* Encoder_MspInitCallback)(struct __TIM_HandleTypeDef *htim);           /*!< TIM Encoder Msp Init Callback                           */void (* Encoder_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);         /*!< TIM Encoder Msp DeInit Callback                         */void (* HallSensor_MspInitCallback)(struct __TIM_HandleTypeDef *htim);        /*!< TIM Hall Sensor Msp Init Callback                       */void (* HallSensor_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim);      /*!< TIM Hall Sensor Msp DeInit Callback                     */void (* PeriodElapsedCallback)(struct __TIM_HandleTypeDef *htim);             /*!< TIM Period Elapsed Callback                             */void (* PeriodElapsedHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);     /*!< TIM Period Elapsed half complete Callback               */void (* TriggerCallback)(struct __TIM_HandleTypeDef *htim);                   /*!< TIM Trigger Callback                                    */void (* TriggerHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);           /*!< TIM Trigger half complete Callback                      */void (* IC_CaptureCallback)(struct __TIM_HandleTypeDef *htim);                /*!< TIM Input Capture Callback                              */void (* IC_CaptureHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);        /*!< TIM Input Capture half complete Callback                */void (* OC_DelayElapsedCallback)(struct __TIM_HandleTypeDef *htim);           /*!< TIM Output Compare Delay Elapsed Callback               */void (* PWM_PulseFinishedCallback)(struct __TIM_HandleTypeDef *htim);         /*!< TIM PWM Pulse Finished Callback                         */void (* PWM_PulseFinishedHalfCpltCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM PWM Pulse Finished half complete Callback           */void (* ErrorCallback)(struct __TIM_HandleTypeDef *htim);                     /*!< TIM Error Callback                                      */void (* CommutationCallback)(struct __TIM_HandleTypeDef *htim);               /*!< TIM Commutation Callback                                */void (* CommutationHalfCpltCallback)(struct __TIM_HandleTypeDef *htim);       /*!< TIM Commutation half complete Callback                  */void (* BreakCallback)(struct __TIM_HandleTypeDef *htim);                     /*!< TIM Break Callback                                      */
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
} TIM_HandleTypeDef;

?上面是關于定時器的相關配置和能與定時器聯系起來的DMA的相關配置以及所有的中斷回調函數的注冊。

我們使用CubeMX初始化就行了,在Cubemx生成的代碼里面,我們還能看見定時器時鐘選擇,主從模式的失能等操作。

所有的句柄成員都會在對應的.c文件下有著對應的定義,還有Is_xxx這類型的宏定義,來輔助系統對外設初始化的檢測,所有的句柄初始化成功,就返回HAL_OK,錯誤就返回HAL_ERROR并提供給我們一個錯誤回調函數,我們就能在這里面知道對應的外設初始化失敗,需要我們去調試程序。

定時器的中斷使能和中斷優先級設置cubemx都放在了mspInit初始化回調函數里面,但是我們還需要在主函數前面開啟對應的TIMX中斷,才能正常使用。

定時器中斷

設置定時時間,也就是計數值,然后計數值CNT到達ARR后,清空CNT并且觸發一次定時器溢出中斷,通過設置的預分頻值和自動重裝值,控制我們需要的時間。

中斷服務函數都在it.c文件里面找,void TIM2_UP_IRQHandler(void);TIM2更新中斷觸發的時候,就會進入這個中斷服務函數,在里面調用總的定時器中斷服務函數HAL_TIM_IRQHandler。在里面先對定時器TIMX進行判別,再清除對應的中斷請求位,然后進入對應的中斷回調函數。

在對中斷進行編寫的時候,容易遇到芯片的復位鍵無法使用了,這個時候基本就是遇到

中斷處理異常:中斷服務函數編寫錯誤,如未正確清除中斷標志位,導致中斷一直觸發,干擾正常復位流程。這個問題了,我們需要對我們的程序進行檢查和修改。

還有對于我們的用戶自定義函數也得進行檢查,比如說我們移植的OLED函數,就算我們沒有使用OELD_Init,但是我們依舊可以使用OLED里面的顯示函數,還不會報錯,因為沒有初始化,導致OLED的I2C協議沒有正常運行,使得程序卡死在了我們OLED顯示函數那邊,導致程序運行有誤。

我們使用CubeMx來初始化定時器TIM2,ClockSource選擇 Internal Clock

設置預分頻值為7200-1和自動重裝值10000-1,這樣我們得到的計數時間就是

72000000/7200/10000 = 1s;

一秒產生溢出溢出更新中斷。

在NVIC界面勾選TIM2的中斷允許

其他的配置和前面的一樣就行了。

記得開啟中斷

這里我們得注意了,定時器的中斷,需要我們在主函數前面通過

HAL_TIM_Base_Start_IT(&htim2);

來開啟對應的TIMX中斷,沒開啟時中斷是沒響應的。

我們用到的是定時器TIM2的溢出中斷,在HAL_TIM_IRQHandler里面找

里面有各種中斷的標志位判別,以及他們的中斷回調函數。

在里面我們找到TIM_FALG_UPDATE對應的中斷回調函數,就是HAL_TIM_PeriodElapsedCallback()

中斷回調函數都是weak修飾的,弱定義函數,我們直接對其進行內容修改即可。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim == &htim2){Num++;  // 每秒遞增1}
}

我們是TIM2的更新中斷,所以在這個函數里面我們得對定時器先進行判別,再對數據進行操作

這樣就能成功實現定時器的溢出中斷計時功能了,OLEDInit別忘記了,也會導致芯片的下載出錯的,但不會鎖死芯片。

定時器輸出比較?

TIM的OC功能,我們常見的就是PWM的輸出,

通過計數值CNT和CCR的比較,控制GPIO口的電平在一定時間內高電平的占比,這就是PWM輸出的思路,這里實現PWM的呼吸燈功能

使用Cubemx來初始化TIM2作為PWM的輸出定時器,使用通道1的PWM模式(pwm模式就是oc的一種功能,只不過運用的比較廣泛,單獨作為一個功能拎出來了),預分頻值和自動重裝載值設置為719和99,自動重裝載值就是一個PWM的周期。

下面的Pulse就是我們要控制的CCR了,控制CCR就能控制PWM的占空比,如果我們一直循環控制CCR從0~100,再從100~0,就能實現我們的呼吸燈功能了。

別忘記? HAL_TIM_PWM_Start_IT(&htim2,TIM_CHANNEL_1);//開啟定時器TIM2的通道1中斷

不開啟的話,是使用不了的,這個函數的功能就是啟動定時器的 PWM 輸出并啟用中斷。

也可以使用 HAL_TIM_PWM_Start,不開啟中斷,開啟PWM輸出,這兩個的區別就是是否啟用中斷,但必須有一個使用,來開啟PWM輸出。

HAL_TIM_PWM_Start_IT(&htim2,TIM_CHANNEL_1);//開啟定時器TIM2的通道1中斷while (1){for(i=0;i<100;i++){__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_1,i);//設置CCR值HAL_Delay(10);}for(i=100;i>0;i--){__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_1,i);//設置CCR值HAL_Delay(10);}}

和江科大一樣的芯片連線就行,使用的是TIM2的通道1,按照硬件電路上看,就是PA0作為PWM的輸出端口。

PWM驅動舵機和直流電機就按照上面的代碼照壺畫瓢就行了。

定時器輸入捕獲

這里需要我們上面的PWM生成的代碼,IC輸入捕獲來測量PWM的頻率,

IC輸入捕獲通過捕獲輸入TIM通道的信號上升沿下降沿,雙邊沿,來觸發中斷,在中斷里面把CNT的值獲取得到對應的時間,這個時間就是我們輸入信號的周期,頻率就是周期的倒數,得到頻率。

CNT是按照時基單元的設置一直自增的。

按照江科大的設置來,定時器2通道1作為PWM的輸出PA0

定時器3通道1 PA6作為輸入引腳。

預分頻值和自動重裝值是決定頻率的值,我們會在主函數里面進行修改,來控制頻率可調,這邊給一個72,得到的頻率就是100000Hz的頻率,自動重裝載值我們給最大值,這樣我們能測量的時間就更大,如果CNT溢出了還沒有接收到信號,我們就定義一個Count值在溢出中斷的時候自增,得到更大的計數值。

捕獲極性這些就用默認設置的即可。

最后設置TIM3的從觸發模式,TI1FP1:表示將 TI1 引腳的信號連接到通道 1的輸入捕獲模塊,作為捕獲源,在這里就是把TIM2的通道1的引腳信號作為TIM3的通道1的輸入捕獲。

TIm2通道1信號到達上升沿后,TIM3收到信號,會自動存儲CNT的值到CCR里面,并重置CNT計數值,我們讀取CCR保存的部分即可。

這邊調用上面的PWM部分的時候不要弄錯預分頻值和自動重裝值,PWM的為719和99

控制為1000HZ的頻率,我們可以在主函數前面通過hal庫的宏定義來修改這兩個參數來獲得不同的PWM頻率,在TIM3處IC捕獲,然后顯示到我們的OLED上。

但是注意,在設置自動重裝值值的時候,自動重裝值不能小于我們的占空比CCR的值,或者說我們修改自動重裝值ARR的時候,順帶修改CCR的值,不然會造成錯誤。

  /* USER CODE BEGIN 2 */HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);//開啟TIM2的通道1PWM輸出功能HAL_TIM_IC_Start(&htim3,TIM_CHANNEL_1);//開啟TIM3的通道1IC輸入功能/* USER CODE END 2 */OLED_ShowString(1, 1, "Freq:00000Hz");		//1行1列顯示字符串Freq:00000Hz/* Infinite loop */__HAL_TIM_SET_PRESCALER(&htim2,359);//修改TIM2頻率__HAL_TIM_SET_AUTORELOAD(&htim2,99);//設置自動重裝值__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,50);//修改TIM2通道1的PWM占空比,TIM2的CCR值/* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */
//      OLED_ShowString(2,1,"ADDR");
//      OLED_ShowString(3,1,"CCR");
//      OLED_ShowNum(2,6,__HAL_TIM_GET_AUTORELOAD(&htim2),4);
//      OLED_ShowNum(3,6,__HAL_TIM_GetCompare(&htim2,TIM_CHANNEL_1),4);OLED_ShowNum(1, 6, IC_GetFreq(), 5);	//不斷刷新顯示輸入捕獲測得的頻率/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}uint32_t IC_GetFreq(void){return 1000000/(__HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_1)+1);
}

TIM注意事項

?TIM的注意點還是挺多的,首先就是使用CubeMx初始化完成TIm后,我們要使用他的相關功能,就得在主函數前面進行對應的定時器使能,使用普通的計數計時功能,就只需要時基使能,需要中斷功能的加入,就得中斷使能,運用輸出功能就得OC使能,或者對應的功能使能如PWM使能,IC輸入就得IC使能,普通的Start和startIT的區別就是普通的STart只開啟功能,而startIT不僅會開啟功能,還會開啟對應的相關中斷。

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

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

相關文章

CentOS 10:啟動telnet服務

參考&#xff0c; 鳥哥私房菜 - 第七章、網路安全與主機基本防護&#xff1a;限制埠口, 網路升級與 SELinux 7.3.3 埠口與服務的啟動/關閉及開機時狀態設定 我們知道系統的 Telnet 服務通常是以 super daemon 來控管的&#xff0c;請您啟動您系統的 telnet 試看看。 1 要啟動 …

Taro 安全區域

目錄 一、問題描述 二、問題解決 1、頂部劉海區 2、底部小黑條 一、問題描述 安全區域主要是為了避免劉海屏或底部欄遮擋&#xff0c;而造成的不良顯示效果。 本次將針對以下兩點進行考量&#xff1a; 1、頂部劉海屏區 2、蘋果X底部小黑條 二、問題解決 通過Taro.getS…

【Java微服務組件】分布式協調P1-數據共享中心簡單設計與實現

歡迎來到啾啾的博客&#x1f431;。 記錄學習點滴。分享工作思考和實用技巧&#xff0c;偶爾也分享一些雜談&#x1f4ac;。 歡迎評論交流&#xff0c;感謝您的閱讀&#x1f604;。 目錄 引言設計一個共享數據中心選擇數據模型鍵值對設計 數據可靠性設計持久化快照 &#xff08…

在SpringBoot項目中,使用單元測試@Test

1.引入依賴 <!--單元測試Test的依賴--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>3.2.1</version> </dependency> 2.在src/test/java目錄…

在Java中,將Object對象轉換為具體實體類對象

在Java中&#xff0c;將Object對象轉換為具體實體類對象可以通過以下幾種方法實現&#xff1a; 1?.使用instanceof關鍵字進行類型檢查和轉換?&#xff1a; 首先&#xff0c;使用instanceof關鍵字檢查Object對象是否為目標實體類的類型。 如果是&#xff0c;則進行強制類型…

JAVA學習-練習試用Java實現“音頻文件的讀取與寫入 :使用Java音頻庫處理音頻數據”

問題&#xff1a; java語言編輯&#xff0c;實現音頻文件的讀取與寫入 &#xff1a;使用Java音頻庫處理音頻數據。 解答思路&#xff1a; 在Java中處理音頻文件通常需要使用第三方庫&#xff0c;例如javax.sound.sampled包&#xff0c;它提供了處理音頻文件的基本功能。以下是一…

Flink架構概覽,Flink DataStream API 的使用,FlinkCDC的使用

一、Flink與其他組件的協同 Flink 是一個分布式、高性能、始終可用、準確一次&#xff08;Exactly-Once&#xff09;語義的流處理引擎&#xff0c;廣泛應用于大數據實時處理場景中。它與 Hadoop 生態系統中的組件可以深度集成&#xff0c;形成完整的大數據處理鏈路。下面我們從…

linux 查看java的安裝路徑

一、驗證Java安裝狀態 java -version正常安裝會顯示版本信息&#xff1a; openjdk version "1.8.0_65" OpenJDK Runtime Environment (build 1.8.0_65-b17) OpenJDK 64-Bit Server VM (build 25.65-b01, mixed mode)二、檢查環境變量配置 若已配置JAVA_HOME&#…

2025-5-21 個人筆記篇matlab小筆記和clang基礎使用(簡單記錄)

個人筆記篇 再不記錄就找不到了&#xff0c;之前學的一點基礎&#xff0c;看看就行,請不要提問,因為很久了>_<(至少我看來是這樣的) matlab小筆記 % 開繪制(新建) figure % 設置繪制標題 title(標題); % 設置繪制的X軸Lable xlabel(x); % 設置繪制的y軸Lable ylabel(cos…

前端JavaScript-嵌套事件

點擊 如果在多層嵌套中&#xff0c;對每層都設置事件監視器&#xff0c;試試看 <!DOCTYPE html> <html lang"cn"> <body><div id"container"><button>點我&#xff01;</button></div><pre id"output…

網感驅動下開源AI大模型AI智能名片S2B2C商城小程序源碼的實踐路徑研究

摘要&#xff1a;在數字化浪潮中&#xff0c;網感已成為內容創作者與商業運營者必備的核心能力。本文以開源AI大模型、AI智能名片及S2B2C商城小程序源碼為技術載體&#xff0c;通過解析網感培養與用戶需求洞察的內在關聯&#xff0c;提出"數據驅動-場景適配-價值重構"…

AG-UI:重構AI代理與前端交互的下一代協議標準

目錄 技術演進背景與核心價值協議架構與技術原理深度解析核心功能與標準化事件體系典型應用場景與實戰案例開發者生態與集成指南行業影響與未來展望1. 技術演進背景與核心價值 1.1 AI交互的三大痛點 當前AI應用生態面臨三大核心挑戰: 交互碎片化:LangGraph、CrewAI等框架各…

游戲引擎學習第301天:使用精靈邊界進行排序

回顧并為今天的內容做準備 昨天&#xff0c;我們解決了一些關于排序的問題&#xff0c;這對我們清理長期存在的Z軸排序問題很有幫助。這個問題我們一直想在開始常規游戲代碼之前解決。雖然不確定是否完全解決了問題&#xff0c;但我們提出了一個看起來合理的排序標準。 有兩點…

Ajax快速入門教程

輸入java時&#xff0c;頁面并沒有刷新但是下面自動聯想出了跟java有關的東西&#xff0c;像這種就叫異步交互 它不會妨礙你的輸入&#xff0c;同時還能夠同步進行對于java相關聯想詞的推送 發送異步請求需要借助工具axios 引入axios&#xff0c;可以直接在scripts中引入 get和…

Anti Spy安卓版:智能防護,守護手機安全

Anti Spy安卓版是一款專為安卓設備設計的智能防護應用&#xff0c;旨在幫助用戶實時防護手機安全&#xff0c;抵御間諜軟件、惡意軟件和其他潛在威脅。它基于人工智能和啟發式搜索方法的引擎&#xff0c;能夠檢測并阻止已知和未知的間諜軟件、后門程序、賬單欺詐、短信欺詐、電…

超低延遲音視頻直播技術的未來發展與創新

引言 音視頻直播技術正在深刻改變著我們的生活和工作方式&#xff0c;尤其是在教育、醫療、安防、娛樂等行業。無論是全球性的體育賽事、遠程醫療、在線教育&#xff0c;還是智慧安防、智能家居等應用場景&#xff0c;都離不開音視頻技術的支持。為了應對越來越高的需求&#x…

系統架構設計(十二):統一過程模型(RUP)

簡介 RUP 是由 IBM Rational 公司提出的一種 面向對象的軟件工程過程模型&#xff0c;以 UML 為建模語言&#xff0c;是一種 以用例為驅動、以架構為中心、迭代式、增量開發的過程模型。 三大特征 特征說明以用例為驅動&#xff08;Use Case Driven&#xff09;需求分析和測…

海康相機連接測試-極簡版

文章目錄 1、下載客戶端 1、下載客戶端 海康機器人官網下載軟件 軟件下載地址 先下載客戶端測試連接 按照你的相機的類型選擇客戶端 安裝完畢后&#xff0c;確保USB線插的是3.0的端口 軟件會自動識別相機型號 在上方有播放按鈕&#xff0c;可以采集圖像信息顯示

Linux 磁盤擴容實戰案例:從問題發現到完美解決

Linux 磁盤擴容實戰案例&#xff1a;從問題發現到完美解決 案例背景 某企業服務器根目錄 (/) 空間不足&#xff0c;運維人員通過 df -h 發現 /dev/vda1 分區已 100% 占滿&#xff08;99G 已用&#xff09;。檢查發現物理磁盤 /dev/vda 已擴展至 200G&#xff0c;但分區和文件…

深入解析FramePack:高效視頻幀打包技術原理與實踐

摘要 本文深入探討FramePack技術在視頻處理領域的核心原理&#xff0c;解析其在不同場景下的應用優勢&#xff0c;并通過OpenCV代碼示例演示具體實現方法&#xff0c;為開發者提供可落地的技術解決方案。 目錄 1. FramePack技術背景 2. 核心工作原理剖析 3. 典型應用場景 …