一、高級(jí)定時(shí)器(TIM1/TIM8)簡(jiǎn)介
1.1 主要特性
- 16位遞增、遞減、中心對(duì)齊計(jì)數(shù)器(計(jì)數(shù)值:0~65535)
- 16位預(yù)分頻器(分頻系數(shù):1~65536)
- 可用于觸發(fā)DAC、ADC
- 在更新事件、觸發(fā)事件、輸入捕獲、輸出比較時(shí),會(huì)產(chǎn)生中斷/DMA請(qǐng)求
- 4個(gè)獨(dú)立通道,可用于:輸入捕獲、輸出比較、輸出PWM、單脈沖模式
- 使用外部信號(hào)控制定時(shí)器且可實(shí)現(xiàn)多個(gè)定時(shí)器互連的同步電路
- 支持編碼器和霍爾傳感器電路等
- 重復(fù)計(jì)數(shù)器
- 死區(qū)時(shí)間帶可編程的互補(bǔ)輸出
- 斷路輸入,用于將定時(shí)器的輸出信號(hào)置于用戶可選的安全配置中
1.2 框圖
-
重復(fù)計(jì)數(shù)器
重復(fù)計(jì)數(shù)器功能在基本和通用定時(shí)器中的作用稍有不同。在具備重復(fù)計(jì)數(shù)器功能的定時(shí)器中,定時(shí)器不會(huì)在每次上溢或下溢時(shí)立即觸發(fā)更新事件。相反,定時(shí)器的重復(fù)計(jì)數(shù)器會(huì)在每次上溢或下溢時(shí)遞減其值,直到計(jì)數(shù)器值降至零。僅當(dāng)重復(fù)計(jì)數(shù)器的值減到零后,下一次定時(shí)器上溢或下溢時(shí),才會(huì)觸發(fā)更新事件。因此,如果重復(fù)計(jì)數(shù)器的設(shè)置值為N,定時(shí)器需要經(jīng)歷N+1次上溢或下溢才能觸發(fā)一次更新事件。
需要注意的是,重復(fù)計(jì)數(shù)器寄存器具有影子寄存器機(jī)制,即RCR寄存器的值在更新事件發(fā)生時(shí)才會(huì)更新到影子寄存器并生效,RCR寄存器本身僅作為緩沖使用。 -
輸出比較
高級(jí)定時(shí)器輸出比較部分和通用定時(shí)器相比,多了帶死區(qū)控制的互補(bǔ)輸出功能。上面的框圖中,第②部分的TIMx_CH1N、TIMx_CH2N和TIMx_CH3N分別是定時(shí)器通道1、通道2和通道3的互補(bǔ)輸出通道,通道4是沒(méi)有互補(bǔ)輸出通道的。DTG是死區(qū)發(fā)生器,死區(qū)時(shí)間有DTG[7:0]位來(lái)配置。如果不使用互補(bǔ)通道和死區(qū)時(shí)間控制,那么高級(jí)定時(shí)器TIM1和TIM8和通用定時(shí)器的輸出比較部分使用方法基本一樣,只是要注意MOE位得置1定時(shí)器才能輸出。 -
斷路功能
斷路功能,也被稱為剎車功能,是電機(jī)控制中用于實(shí)現(xiàn)剎車的一項(xiàng)技術(shù)。斷路的觸發(fā)源可以是外部的剎車輸入引腳(標(biāo)記位TIMx_BKIN)或內(nèi)部的時(shí)鐘失敗事件。這種時(shí)鐘失敗通常是由復(fù)位時(shí)鐘控制器內(nèi)的時(shí)鐘安全系統(tǒng)檢測(cè)并觸發(fā)的。在系統(tǒng)經(jīng)歷復(fù)位后,斷路功能默認(rèn)是關(guān)閉狀態(tài),這可以從MOE位的低電平狀態(tài)中看出。
要啟動(dòng)斷路功能,用戶需要配置TIMx_BDTR寄存器。具體操作是將該寄存器的BKE位設(shè)置為1,這樣就能使能斷路功能。此外,剎車輸入引腳TIMx_BKIN的有效電平是可配置的,可通過(guò)TIMx_BDTR寄存器中的BKP位進(jìn)行設(shè)置。
一旦剎車功能被激活,它將通過(guò)多個(gè)寄存器位來(lái)控制輸出狀態(tài),包括TIMx_BDTR寄存器的MOE、OSSI和OSSR位,TIMx_CR2寄存器的OISx和OISxN位,以及TIMx_CCER寄存器和CCxE和CCxNE位。這些控制位確保在任何情況下,輸出比較通道OCx和OCxN的輸出狀態(tài)都不會(huì)同時(shí)為有效電平。
當(dāng)發(fā)生斷路輸入后,會(huì)怎么樣?
1、MOE位被異步地清零,OCx和OCxN為無(wú)效、空閑或復(fù)位狀態(tài)(由OSSI位選擇)。
2、OCx和OCxN的狀態(tài):由相關(guān)控制位狀態(tài)決定,當(dāng)使用互補(bǔ)輸出時(shí):根據(jù)情況自動(dòng)控制輸出電平。
3、BIF位置1,如果使能了BIE位,還會(huì)產(chǎn)生剎車中斷;如果使能了TDE位,會(huì)產(chǎn)生DMA請(qǐng)求。
4、如果AOE位置1,在下一個(gè)更新事件UEV時(shí),MOE位被自動(dòng)置1。
二、高級(jí)定時(shí)器輸出指定個(gè)數(shù)PWM
2.1 實(shí)驗(yàn)原理
- 配置邊沿對(duì)齊模式輸出PWM
- 指定輸出N個(gè)PWM,則把N-1個(gè)寫入RCR
- 在更新中斷內(nèi),關(guān)閉計(jì)數(shù)器
2.2 配置步驟
- 配置定時(shí)器基礎(chǔ)工作參數(shù):HAL_TIM_PWM_Init()
- 定時(shí)器PWM輸出MSP初始化:HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置PWM模式/比較值等:HAL_TIM_PWM_ConfigChannel()
- 設(shè)置優(yōu)先級(jí),使能中斷:HAL_NVIC_SetPriority()、HAL_NVIC_EnableRQ()
- 使能定時(shí)器更新中斷:__HAL_TIM_ENABLE_IT()
- 使能輸出、主輸出、計(jì)數(shù)器:HAL_TIM_PWM_Start()
- 編寫中斷服務(wù)函數(shù):TIMx_IRQHandler()
- 編寫更新中斷回調(diào)函數(shù):HAL_TIM_PeriodElapsedCallback()
2.3 程序示例
頭文件定義如下:
#include "./SYSTEM/sys/sys.h"
/******************************************************************************************/
/* 高級(jí)定時(shí)器 定義 */
/* TIMX 輸出指定個(gè)數(shù)PWM 定義
* 這里輸出的PWM通過(guò)PC6(TIM8_CH1)輸出, 我們用杜邦線連接PC6和PE5, 然后在程序里面將PE5設(shè)置成浮空輸入
* 就可以 看到TIM8_CH1控制LED1(GREEN)的亮滅, 亮滅一次表示一個(gè)PWM波
* 默認(rèn)使用的是TIM8_CH1.
* 注意: 通過(guò)修改這幾個(gè)宏定義, 可以支持TIM1/TIM8定時(shí)器, 任意一個(gè)IO口輸出指定個(gè)數(shù)的PWM
*/
#define ATIM_TIMX_NPWM_CHY_GPIO_PORT GPIOC
#define ATIM_TIMX_NPWM_CHY_GPIO_PIN GPIO_PIN_6
#define ATIM_TIMX_NPWM_CHY_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PC口時(shí)鐘使能 */
#define ATIM_TIMX_NPWM TIM8
#define ATIM_TIMX_NPWM_IRQn TIM8_UP_IRQn
#define ATIM_TIMX_NPWM_IRQHandler TIM8_UP_IRQHandler
#define ATIM_TIMX_NPWM_CHY TIM_CHANNEL_1 /* 通道Y, 1<= Y <=4 */
#define ATIM_TIMX_NPWM_CHY_CCRX TIM8->CCR1 /* 通道Y的輸出比較寄存器 */
#define ATIM_TIMX_NPWM_CHY_CLK_ENABLE() do{ __HAL_RCC_TIM8_CLK_ENABLE(); }while(0) /* TIM8 時(shí)鐘使能 */
/******************************************************************************************/
void atim_timx_npwm_chy_init(uint16_t arr, uint16_t psc); /* 高級(jí)定時(shí)器 輸出指定個(gè)數(shù)PWM初始化函數(shù) */
void atim_timx_npwm_chy_set(uint32_t npwm); /* 高級(jí)定時(shí)器 設(shè)置輸出PWM的個(gè)數(shù) */
定時(shí)器源文件代碼如下:
#include "./BSP/TIMER/atim.h"
#include "./BSP/LED/led.h"
TIM_HandleTypeDef g_timx_npwm_chy_handle; /* 定時(shí)器x句柄 */
/* g_npwm_remain表示當(dāng)前還剩下多少個(gè)脈沖要發(fā)送
* 每次最多發(fā)送256個(gè)脈沖
*/
static uint32_t g_npwm_remain = 0;
/**
* @brief 高級(jí)定時(shí)器TIMX 通道Y 輸出指定個(gè)數(shù)PWM 初始化函數(shù)
* @note
* 高級(jí)定時(shí)器的時(shí)鐘來(lái)自APB2, 而PCLK2 = 72Mhz, 我們?cè)O(shè)置PPRE2不分頻, 因此
* 高級(jí)定時(shí)器時(shí)鐘 = 72Mhz
* 定時(shí)器溢出時(shí)間計(jì)算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
* Ft=定時(shí)器工作頻率,單位:Mhz
*
* @param arr: 自動(dòng)重裝值
* @param psc: 時(shí)鐘預(yù)分頻數(shù)
* @retval 無(wú)
*/
void atim_timx_npwm_chy_init(uint16_t arr, uint16_t psc)
{
GPIO_InitTypeDef gpio_init_struct;
TIM_OC_InitTypeDef timx_oc_npwm_chy; /* 定時(shí)器輸出 */
ATIM_TIMX_NPWM_CHY_GPIO_CLK_ENABLE(); /* TIMX 通道IO口時(shí)鐘使能 */
ATIM_TIMX_NPWM_CHY_CLK_ENABLE(); /* TIMX 時(shí)鐘使能 */
g_timx_npwm_chy_handle.Instance = ATIM_TIMX_NPWM; /* 定時(shí)器x */
g_timx_npwm_chy_handle.Init.Prescaler = psc; /* 定時(shí)器分頻 */
g_timx_npwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 遞增計(jì)數(shù)模式 */
g_timx_npwm_chy_handle.Init.Period = arr; /* 自動(dòng)重裝載值 */
g_timx_npwm_chy_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; /*使能TIMx_ARR進(jìn)行緩沖 */
g_timx_npwm_chy_handle.Init.RepetitionCounter = 0; /* 重復(fù)計(jì)數(shù)器初始值 */
HAL_TIM_PWM_Init(&g_timx_npwm_chy_handle); /* 初始化PWM */
gpio_init_struct.Pin = ATIM_TIMX_NPWM_CHY_GPIO_PIN; /* 通道y的CPIO口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 復(fù)用推完輸出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(ATIM_TIMX_NPWM_CHY_GPIO_PORT, &gpio_init_struct);
timx_oc_npwm_chy.OCMode = TIM_OCMODE_PWM1; /* 模式選擇PWM 1*/
timx_oc_npwm_chy.Pulse = arr / 2; /* 設(shè)置比較值,此值用來(lái)確定占空比 */
/* 這里默認(rèn)設(shè)置比較值為自動(dòng)重裝載值的一半,即占空比為50% */
timx_oc_npwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH; /* 輸出比較極性為高 */
HAL_TIM_PWM_ConfigChannel(&g_timx_npwm_chy_handle, &timx_oc_npwm_chy, ATIM_TIMX_NPWM_CHY); /* 配置TIMx通道y */
HAL_NVIC_SetPriority(ATIM_TIMX_NPWM_IRQn, 1, 3); /* 設(shè)置中斷優(yōu)先級(jí),搶占優(yōu)先級(jí)1,子優(yōu)先級(jí)3 */
HAL_NVIC_EnableIRQ(ATIM_TIMX_NPWM_IRQn); /* 開啟ITMx中斷 */
__HAL_TIM_ENABLE_IT(&g_timx_npwm_chy_handle, TIM_IT_UPDATE); /* 允許更新中斷 */
HAL_TIM_PWM_Start(&g_timx_npwm_chy_handle, ATIM_TIMX_NPWM_CHY); /* 開啟對(duì)應(yīng)PWM通道 */
}
/**
* @brief 高級(jí)定時(shí)器TIMX NPWM設(shè)置PWM個(gè)數(shù)
* @param rcr: PWM的個(gè)數(shù), 1~2^32次方個(gè)
* @retval 無(wú)
*/
void atim_timx_npwm_chy_set(uint32_t npwm)
{
if (npwm == 0) return;
g_npwm_remain = npwm; /* 保存脈沖個(gè)數(shù) */
HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handle, TIM_EVENTSOURCE_UPDATE); /* 產(chǎn)生一次更新事件,在中斷里面處理脈沖輸出 */
__HAL_TIM_ENABLE(&g_timx_npwm_chy_handle); /* 使能定時(shí)器TIMX */
}
/**
* @brief 高級(jí)定時(shí)器TIMX NPWM中斷服務(wù)函數(shù)
* @param 無(wú)
* @retval 無(wú)
*/
void ATIM_TIMX_NPWM_IRQHandler(void)
{
uint16_t npwm = 0;
/* 以下代碼沒(méi)有使用定時(shí)器HAL庫(kù)共用處理函數(shù)來(lái)處理,而是直接通過(guò)判斷中斷標(biāo)志位的方式 */
if(__HAL_TIM_GET_FLAG(&g_timx_npwm_chy_handle, TIM_FLAG_UPDATE) != RESET)
{
if (g_npwm_remain >= 256) /* 還有大于256個(gè)脈沖需要發(fā)送 */
{
g_npwm_remain = g_npwm_remain - 256;
npwm = 256;
}
else if (g_npwm_remain % 256) /* 還有位數(shù)(不到256)個(gè)脈沖要發(fā)送 */
{
npwm = g_npwm_remain % 256;
g_npwm_remain = 0; /* 沒(méi)有脈沖了 */
}
if (npwm) /* 有脈沖要發(fā)送 */
{
ATIM_TIMX_NPWM->RCR = npwm - 1; /* 設(shè)置重復(fù)計(jì)數(shù)寄存器值為npwm-1, 即npwm個(gè)脈沖 */
HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handle, TIM_EVENTSOURCE_UPDATE); /* 產(chǎn)生一次更新事件,在中斷里面處理脈沖輸出 */
__HAL_TIM_ENABLE(&g_timx_npwm_chy_handle); /* 使能定時(shí)器TIMX */
}
else
{
ATIM_TIMX_NPWM->CR1 &= ~(1 << 0); /* 關(guān)閉定時(shí)器TIMX,使用HAL Disable會(huì)清除PWM通道信息,此處不用 */
}
__HAL_TIM_CLEAR_IT(&g_timx_npwm_chy_handle, TIM_IT_UPDATE); /* 清除定時(shí)器溢出中斷標(biāo)志位 */
}
}
主函數(shù)代碼如下:
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/TIMER/atim.h"
int main(void)
{
uint8_t key = 0;
uint8_t t = 0;
GPIO_InitTypeDef gpio_init_struct;
HAL_Init(); /* 初始化HAL庫(kù) */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 設(shè)置時(shí)鐘, 72Mhz */
delay_init(72); /* 延時(shí)初始化 */
usart_init(115200); /* 串口初始化為115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按鍵 */
/* 將 LED1 引腳設(shè)置為輸入模式, 避免和PC6沖突 */
gpio_init_struct.Pin = LED1_GPIO_PIN; /* LED1引腳 */
gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 設(shè)置為輸入 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct); /* 初始化LED1引腳 */
atim_timx_npwm_chy_init(5000 - 1, 7200 - 1); /* 10Khz的計(jì)數(shù)頻率,2hz的PWM頻率. */
ATIM_TIMX_NPWM_CHY_CCRX = 2500; /* 設(shè)置PWM占空比,50%,這樣可以控制每一個(gè)PWM周期,LED1(BLUE)
* 有一半時(shí)間是亮的,一半時(shí)間是滅的,LED1亮滅一次,表示一個(gè)PWM波
*/
atim_timx_npwm_chy_set(5); /* 輸出5個(gè)PWM波(控制LED1(BLUE)閃爍5次) */
while (1)
{
key = key_scan(0);
if (key == KEY0_PRES) /* KEY0按下 */
{
atim_timx_npwm_chy_set(5); /* 輸出5個(gè)PWM波(控制TIM8_CH1, 即PC6輸出5個(gè)脈沖) */
}
t++;
delay_ms(10);
if (t > 50) /* 控制LED0閃爍, 提示程序運(yùn)行狀態(tài) */
{
t = 0;
LED0_TOGGLE();
}
}
}
三、高級(jí)定時(shí)器互補(bǔ)輸出帶死區(qū)控制
3.1 捕獲/比較通道的輸出部分
3.2 死區(qū)時(shí)間計(jì)算
死區(qū)時(shí)間是由TIMx_CR1寄存器的CKD[1:0]位和TIMx_BDTR寄存器的DTG[7:0]位來(lái)設(shè)置,如下圖所示。
- 通過(guò)CKD[1:0]位確定tDTS。
t D T S = 2 C K D [ 1 : 0 ] T c l k tDTS = \frac{2^{CKD[1:0]}}{Tclk} tDTS=Tclk2CKD[1:0]?
其中:
CKD[1:0],CKD[1:0]位設(shè)置的值
Tclk:定時(shí)器的時(shí)鐘源頻率(單位為MHz)
假設(shè)定時(shí)器時(shí)鐘源頻率是72MHz,我們?cè)O(shè)置CKD[1:0]位的值為2,代入上面的式子可得:
t D T S = 2 C K D [ 1 : 0 ] T c l k = 2 2 72000000 = 4 72000000 = 55.56 n s tDTS = \frac{2^{CKD[1:0]}}{Tclk} = \frac{2^{2}}{72000000} = \frac{4}{72000000} = 55.56ns tDTS=Tclk2CKD[1:0]?=7200000022?=720000004?=55.56ns - 根據(jù)DTG[7:5]選擇公式
- 代入選擇的公式計(jì)算
3.3 配置步驟
- 配置定時(shí)器基礎(chǔ)工作參數(shù):HAL_TIM_PWM_Init()
- 定時(shí)器PWM輸出MSP初始化:HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置PWM模式/比較值等:HAL_TIM_PWM_ConfigChannel()
- 配置剎車功能、死區(qū)時(shí)間等:HAL_NVIC_ConfigBreakDeadTime()
- 使能輸出、主輸出、計(jì)數(shù)器:HAL_TIM_PWM_Start()
- 使能互補(bǔ)輸出、主輸出、計(jì)數(shù)器:HAL_TIMEx_PWMN_Start()
3.4 程序示例
頭文件定義:
#include "./SYSTEM/sys/sys.h"
/* TIMX 互補(bǔ)輸出模式 定義
* 這里設(shè)置互補(bǔ)輸出相關(guān)硬件配置, CHY即正常輸出, CHYN即互補(bǔ)輸出
* 修改CCRx可以修改占空比.
* 默認(rèn)是針對(duì)TIM1
* 注意: 通過(guò)修改這些宏定義,可以支持TIM1/TIM8定時(shí)器, 任意一個(gè)IO口輸出互補(bǔ)PWM(前提是必須有互補(bǔ)輸出功能)
*/
/* 輸出通道引腳 */
#define ATIM_TIMX_CPLM_CHY_GPIO_PORT GPIOE
#define ATIM_TIMX_CPLM_CHY_GPIO_PIN GPIO_PIN_9
#define ATIM_TIMX_CPLM_CHY_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口時(shí)鐘使能 */
/* 互補(bǔ)輸出通道引腳 */
#define ATIM_TIMX_CPLM_CHYN_GPIO_PORT GPIOE
#define ATIM_TIMX_CPLM_CHYN_GPIO_PIN GPIO_PIN_8
#define ATIM_TIMX_CPLM_CHYN_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口時(shí)鐘使能 */
/* 剎車輸入引腳 */
#define ATIM_TIMX_CPLM_BKIN_GPIO_PORT GPIOE
#define ATIM_TIMX_CPLM_BKIN_GPIO_PIN GPIO_PIN_15
#define ATIM_TIMX_CPLM_BKIN_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口時(shí)鐘使能 */
/* TIMX REMAP設(shè)置
* 因?yàn)镻E8/PE9/PE15, 默認(rèn)并不是TIM1的復(fù)用功能腳, 必須開啟完全重映射, 才可以將: TIM1_CH1->PE9; TIM1_CH1N->PE8; TIM1_BKIN->PE15;
* 這樣, PE8/PE9/PE15, 才能用作TIM1的CH1N/CH1/BKIN功能.
* 因此, 必須實(shí)現(xiàn)ATIM_TIMX_CPLM_CHYN_GPIO_REMAP, 通過(guò)sys_gpio_remap_set函數(shù)設(shè)置重映射
* 如果我們使用默認(rèn)的復(fù)用功能輸出, 則不用設(shè)置重映射, 是可以不需要該函數(shù)的! 根據(jù)具體需要來(lái)實(shí)現(xiàn).
*/
#define ATIM_TIMX_CPLM_CHYN_GPIO_REMAP() do{__HAL_RCC_AFIO_CLK_ENABLE();\
__HAL_AFIO_REMAP_TIM1_ENABLE();\
}while(0) /* 通道REMAP設(shè)置, 該函數(shù)不是必須的, 根據(jù)需要實(shí)現(xiàn) */
/* 互補(bǔ)輸出使用的定時(shí)器 */
#define ATIM_TIMX_CPLM TIM1
#define ATIM_TIMX_CPLM_CHY TIM_CHANNEL_1
#define ATIM_TIMX_CPLM_CHY_CCRY ATIM_TIMX_CPLM->CCR1
#define ATIM_TIMX_CPLM_CLK_ENABLE() do{ __HAL_RCC_TIM1_CLK_ENABLE(); }while(0) /* TIM1 時(shí)鐘使能 */
/******************************************************************************************/
void atim_timx_cplm_pwm_init(uint16_t arr, uint16_t psc); /* 高級(jí)定時(shí)器 互補(bǔ)輸出 初始化函數(shù) */
void atim_timx_cplm_pwm_set(uint16_t ccr, uint8_t dtg); /* 高級(jí)定時(shí)器 互補(bǔ)輸出 設(shè)置輸出比較值 & 死區(qū)時(shí)間 */
定時(shí)器源文件代碼如下:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-854101.html
#include "./BSP/TIMER/atim.h"
#include "./BSP/LED/led.h"
TIM_HandleTypeDef g_timx_cplm_pwm_handle; /* 定時(shí)器x句柄 */
TIM_BreakDeadTimeConfigTypeDef g_sbreak_dead_time_config = {0}; /* 死區(qū)時(shí)間設(shè)置 */
/**
* @brief 高級(jí)定時(shí)器TIMX 互補(bǔ)輸出 初始化函數(shù)(使用PWM模式1)
* @note
* 配置高級(jí)定時(shí)器TIMX 互補(bǔ)輸出, 一路OCy 一路OCyN, 并且可以設(shè)置死區(qū)時(shí)間
*
* 高級(jí)定時(shí)器的時(shí)鐘來(lái)自APB2, 而PCLK2 = 72Mhz, 我們?cè)O(shè)置PPRE2不分頻, 因此
* 高級(jí)定時(shí)器時(shí)鐘 = 72Mhz
* 定時(shí)器溢出時(shí)間計(jì)算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
* Ft=定時(shí)器工作頻率,單位:Mhz
*
* @param arr: 自動(dòng)重裝值。
* @param psc: 時(shí)鐘預(yù)分頻數(shù)
* @retval 無(wú)
*/
void atim_timx_cplm_pwm_init(uint16_t arr, uint16_t psc)
{
GPIO_InitTypeDef gpio_init_struct = {0};
TIM_OC_InitTypeDef tim_oc_cplm_pwm = {0};
ATIM_TIMX_CPLM_CLK_ENABLE(); /* TIMx 時(shí)鐘使能 */
ATIM_TIMX_CPLM_CHY_GPIO_CLK_ENABLE(); /* 通道X對(duì)應(yīng)IO口時(shí)鐘使能 */
ATIM_TIMX_CPLM_CHYN_GPIO_CLK_ENABLE(); /* 通道X互補(bǔ)通道對(duì)應(yīng)IO口時(shí)鐘使能 */
ATIM_TIMX_CPLM_BKIN_GPIO_CLK_ENABLE(); /* 通道X剎車輸入對(duì)應(yīng)IO口時(shí)鐘使能 */
gpio_init_struct.Pin = ATIM_TIMX_CPLM_CHY_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_AF_PP;
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH ;
HAL_GPIO_Init(ATIM_TIMX_CPLM_CHY_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_CPLM_CHYN_GPIO_PIN;
HAL_GPIO_Init(ATIM_TIMX_CPLM_CHYN_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_CPLM_BKIN_GPIO_PIN;
HAL_GPIO_Init(ATIM_TIMX_CPLM_BKIN_GPIO_PORT, &gpio_init_struct);
ATIM_TIMX_CPLM_CHYN_GPIO_REMAP(); /* 映射定時(shí)器IO,PE不是本例程所用定時(shí)器的默認(rèn)IO,需要復(fù)用 */
g_timx_cplm_pwm_handle.Instance = ATIM_TIMX_CPLM; /* 定時(shí)器x */
g_timx_cplm_pwm_handle.Init.Prescaler = psc; /* 定時(shí)器預(yù)分頻系數(shù) */
g_timx_cplm_pwm_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 遞增計(jì)數(shù)模式 */
g_timx_cplm_pwm_handle.Init.Period = arr; /* 自動(dòng)重裝載值 */
g_timx_cplm_pwm_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4; /* CKD[1:0] = 10, tDTS = 4 * tCK_INT = Ft / 4 = 18Mhz */
g_timx_cplm_pwm_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; /* 使能影子寄存器TIMx_ARR */
HAL_TIM_PWM_Init(&g_timx_cplm_pwm_handle);
tim_oc_cplm_pwm.OCMode = TIM_OCMODE_PWM1; /* PWM模式1 */
tim_oc_cplm_pwm.OCPolarity = TIM_OCPOLARITY_LOW; /* OCy 低電平有效 */
tim_oc_cplm_pwm.OCNPolarity = TIM_OCNPOLARITY_LOW; /* OCyN 低電平有效 */
tim_oc_cplm_pwm.OCIdleState = TIM_OCIDLESTATE_SET; /* 當(dāng)MOE=0,OCx=1 */
tim_oc_cplm_pwm.OCNIdleState = TIM_OCNIDLESTATE_SET; /* 當(dāng)MOE=0,OCxN=1 */
HAL_TIM_PWM_ConfigChannel(&g_timx_cplm_pwm_handle, &tim_oc_cplm_pwm, ATIM_TIMX_CPLM_CHY);
/* 設(shè)置死區(qū)參數(shù),開啟死區(qū)中斷 */
g_sbreak_dead_time_config.OffStateRunMode = TIM_OSSR_DISABLE; /* 運(yùn)行模式的關(guān)閉輸出狀態(tài) */
g_sbreak_dead_time_config.OffStateIDLEMode = TIM_OSSI_DISABLE; /* 空閑模式的關(guān)閉輸出狀態(tài) */
g_sbreak_dead_time_config.LockLevel = TIM_LOCKLEVEL_OFF; /* 不用寄存器鎖功能 */
g_sbreak_dead_time_config.BreakState = TIM_BREAK_ENABLE; /* 使能剎車輸入 */
g_sbreak_dead_time_config.BreakPolarity = TIM_BREAKPOLARITY_HIGH; /* 剎車輸入有效信號(hào)極性為高 */
g_sbreak_dead_time_config.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE; /* 使能AOE位,允許剎車結(jié)束后自動(dòng)恢復(fù)輸出 */
HAL_TIMEx_ConfigBreakDeadTime(&g_timx_cplm_pwm_handle, &g_sbreak_dead_time_config);
HAL_TIM_PWM_Start(&g_timx_cplm_pwm_handle, ATIM_TIMX_CPLM_CHY); /* 使能OCy輸出 */
HAL_TIMEx_PWMN_Start(&g_timx_cplm_pwm_handle, ATIM_TIMX_CPLM_CHY); /* 使能OCyN輸出 */
}
/**
* @brief 定時(shí)器TIMX 設(shè)置輸出比較值 & 死區(qū)時(shí)間
* @param ccr: 輸出比較值
* @param dtg: 死區(qū)時(shí)間
* @arg dtg[7:5]=0xx時(shí), 死區(qū)時(shí)間 = dtg[7:0] * tDTS
* @arg dtg[7:5]=10x時(shí), 死區(qū)時(shí)間 = (64 + dtg[6:0]) * 2 * tDTS
* @arg dtg[7:5]=110時(shí), 死區(qū)時(shí)間 = (32 + dtg[5:0]) * 8 * tDTS
* @arg dtg[7:5]=111時(shí), 死區(qū)時(shí)間 = (32 + dtg[5:0]) * 16 * tDTS
* @note tDTS = 1 / (Ft / CKD[1:0]) = 1 / 18M = 55.56ns
* @retval 無(wú)
*/
void atim_timx_cplm_pwm_set(uint16_t ccr, uint8_t dtg)
{
g_sbreak_dead_time_config.DeadTime = dtg; /* 死區(qū)時(shí)間設(shè)置 */
HAL_TIMEx_ConfigBreakDeadTime(&g_timx_cplm_pwm_handle, &g_sbreak_dead_time_config); /* 重設(shè)死區(qū)時(shí)間 */
__HAL_TIM_MOE_ENABLE(&g_timx_cplm_pwm_handle); /* MOE=1,使能主輸出 */
ATIM_TIMX_CPLM_CHY_CCRY = ccr; /* 設(shè)置比較寄存器 */
}
主函數(shù)代碼如下:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-854101.html
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/TIMER/atim.h"
int main(void)
{
uint8_t t = 0;
HAL_Init(); /* 初始化HAL庫(kù) */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 設(shè)置時(shí)鐘, 72Mhz */
delay_init(72); /* 延時(shí)初始化 */
usart_init(115200); /* 串口初始化為115200 */
led_init(); /* 初始化LED */
atim_timx_cplm_pwm_init(1000 - 1, 72 - 1); /* 1Mhz的計(jì)數(shù)頻率 1Khz的周期. */
atim_timx_cplm_pwm_set(300, 100); /* 占空比:7:3, 死區(qū)時(shí)間 100 * tDTS */
while (1)
{
delay_ms(10);
t++;
if (t >= 20)
{
LED0_TOGGLE(); /* LED0(RED)閃爍 */
t = 0;
}
}
}
到了這里,關(guān)于STM32 MCU 定時(shí)器詳解(3)--高級(jí)定時(shí)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!