比較輸出簡介
比較輸出可以通過比較CNT與CCR寄存器值的關(guān)系,來對輸出電平進(jìn)行置1、置0或翻轉(zhuǎn)的操作,用于輸出一定頻率和占空比的PWM波形,簡稱脈寬調(diào)制,這也是利用微處理器的數(shù)字輸出來對模擬電路進(jìn)行控制的一種非常有效的技術(shù)。簡單一點(diǎn),就是對脈沖寬度的控制,PWM原理如下圖所示:
圖中,我們假定定時(shí)器工作在向上計(jì)數(shù)PWM模式,且當(dāng)CNT
CKS32F4的定時(shí)器除了TIM6和7。其他的定時(shí)器都可以用來產(chǎn)生PWM輸出。其中高級定時(shí)器TIM1和TIM8可以同時(shí)產(chǎn)生多達(dá)7路的PWM輸出。而通用定時(shí)器也能同時(shí)產(chǎn)生多達(dá)4路的PWM輸出。這里僅使用TIM14的CH1產(chǎn)生一路PWM輸出。要使CKS32F4的通用定時(shí)器TIMx 產(chǎn)生PWM輸出,除了上一章介紹的寄存器外,我們還會用到3個(gè)寄存器,來控制PWM的。這三個(gè)寄存器分別是:
捕獲/比較模式寄存器(TIMx_CCMR1/2)、捕獲/比較使能寄存器(TIMx_CCER)、捕獲/比較寄存器(TIMx_CCR1~4)。對于捕獲/比較模式寄存器(TIMx_CCMR1/2),該寄存器一般有2個(gè):TIMx _CCMR1和TIMx _CCMR2,不過TIM14只有一個(gè)。TIMx_CCMR1控制CH1和2,而TIMx_CCMR2控制CH3和4。以下我們將以TIM14為例進(jìn)行介紹。TIM14_CCMR1寄存器各位描述如下圖所示:
該寄存器的有些位在不同模式下,功能不一樣,所以在圖中,我們把寄存器分了2層,上面一層對應(yīng)輸出而下面的則對應(yīng)輸入。關(guān)于該寄存器的詳細(xì)說明,請參考《CKS32F4xx
中文參考手冊》這里我們需要說明的是模式設(shè)置位 OC1M,此部分由3位組成。總共可以配置成7種模式,我們使用的是PWM模式,所以這3位必須設(shè)置為110/111。
這兩種PWM模式的區(qū)別就是輸出電平的極性相反。另外CC1S用于設(shè)置通道的方向(輸入/輸 出)默認(rèn)設(shè)置為0,就是設(shè)置通道作為輸出使用。注意:這里是因?yàn)槲覀兊腡IM14只有1個(gè)通道,所以才只有第八位有效,高八位無效,其他有多個(gè)通道的定時(shí)器,高八位也是有效的,具體請參考《CKS32F4xvx 中文參考手冊》對應(yīng)定時(shí)器的寄存器描述。
接下來,我們介紹TIM14的捕獲/比較使能寄存器(TIM14_CCER),該寄存器控制著各個(gè)輸入輸出通道的開關(guān)。該寄存器的各位描述如下圖所示:
該寄存器比較簡單,我們這里只用到了CC1E位,該位是輸入/捕獲1輸出使能位,要想PWM從IO口輸出,這個(gè)位必須設(shè)置為1,所以我們需要設(shè)置該位為1。因?yàn)門IM14只有1個(gè)通道,所以才只有低四位有效,如果是其他定時(shí)器,該寄存器的其他位也可能有效。
最后,我們介紹一下捕獲/比較寄存器(TIMx_CCR1~4),該寄存器總共有4個(gè),對應(yīng)4 個(gè)通道CH1~4。不過TIM14只有一個(gè),即:TIM14_CCR1,該寄存器的各位描述如下圖所示:
在輸出模式下,該寄存器的值與CNT的值比較,根據(jù)比較結(jié)果產(chǎn)生相應(yīng)動(dòng)作。利用這點(diǎn),我們通過修改這個(gè)寄存器的值,就可以控制 PWM 的輸出脈寬了。
如果是通用定時(shí)器,則配置以上三個(gè)寄存器就夠了,但是如果是高級定時(shí)器,則還需要配置:剎車和死區(qū)寄存器(TIMx_BDTR),該寄存器各位描述如下圖所示:
該寄存器,我們只需要關(guān)注最高位:MOE位,要想高級定時(shí)器的PWM正常輸出,則必須設(shè)置MOE位為1,否則不會有輸出。注意:通用定時(shí)器不需要配置這個(gè)。其他位我們這里就不詳細(xì)介紹了。
PWM實(shí)際跟上一章節(jié)一樣使用的是定時(shí)器的功能,所以相關(guān)的函數(shù)設(shè)置同樣在庫函數(shù)文件 CKS32f4xx_tim.h和CKS32f4xx_tim.c文件中。
1)開啟TIM14和GPIO時(shí)鐘,配置PF9選擇復(fù)用功能AF9(TIM14)輸出
要使用TIM14,我們必須先開啟TIM14的時(shí)鐘,這點(diǎn)相信大家看了這么多代碼,應(yīng)該明白了。這里我們還要配置PF9為復(fù)用(AF9)輸出,才可以實(shí)現(xiàn)TIM14_CH1的PWM經(jīng)過PF9輸出。庫函數(shù)使能 TIM14時(shí)鐘的方法是:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); //>>TIM14 時(shí)鐘使能
這在前面章節(jié)已經(jīng)提到過。當(dāng)然,這里我們還要使能GPIOF的時(shí)鐘。然后我們要配置PF9引腳映射至AF9,復(fù)用為定時(shí)器14,調(diào)用的函數(shù)為:
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //>>GPIOF9 復(fù)用為定時(shí)器 14
這個(gè)方法跟我們串口實(shí)驗(yàn)講解一樣,調(diào)用的同一個(gè)函數(shù),最后設(shè)置PF9為復(fù)用功能輸出這里我們只列出GPIO初始化為復(fù)用功能的一行代碼:
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //>>復(fù)用功能
這里還需要說明一下,對于定時(shí)器通道的引腳關(guān)系,大家可以查看CKS32F4對應(yīng)的數(shù)據(jù)手冊,比如我們PWM實(shí)驗(yàn),我們使用的是定時(shí)器14的通道1,對應(yīng)的引腳PF9可以從數(shù)據(jù)手冊表中查看:
2)初始化TIM14,設(shè)置TIM14的ARR和PSC等參數(shù)
在開啟了TIM14的時(shí)鐘之后,我們要設(shè)置ARR和 PSC兩個(gè)寄存器的值來控制輸出PWM的周期。這在庫函數(shù)是通過TIM_TimeBaseInit函數(shù)實(shí)現(xiàn)的,在上一節(jié)定時(shí)器中斷章節(jié)我們已經(jīng)有講解,這里就不詳細(xì)講解,調(diào)用的格式為:
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置自動(dòng)重裝載值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置預(yù)分頻值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計(jì)數(shù)模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化 TIMx
3)設(shè)置TIM14_CH1的PWM模式,使能TIM14的 CH1輸出
設(shè)置TIM14_CH1為PWM模式(默認(rèn)是凍結(jié)的)通過配置TIM14_CCMR1的相關(guān)位來控制TIM14_CH1的模式。在庫函數(shù)中,PWM通道設(shè)置是通過函數(shù) TIM_OC1Init()~TIM_OC4Init()來設(shè)置的,不同的通道的設(shè)置函數(shù)不一樣,這里我們使用的是通道1,所以使用的函數(shù)是TIM_OC1Init()。
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
這種初始化格式大家學(xué)到這里應(yīng)該也熟悉了,所以我們直接來看看結(jié)構(gòu)體TIM_OCInitTypeDef的定義:
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置自動(dòng)重裝載值 typedef struct { uint16_t TIM_OCMode; uint16_t TIM_OutputState; uint16_t TIM_OutputNState; */ uint16_t TIM_Pulse; uint16_t TIM_OCPolarity; uint16_t TIM_OCNPolarity; uint16_t TIM_OCIdleState; uint16_t TIM_OCNIdleState; } TIM_OCInitTypeDef;
這里我們講解一下與我們要求相關(guān)的幾個(gè)成員變量:參數(shù)TIM_OCMode設(shè)置模式是PWM還是輸出比較,這里我們是PWM模式。
參數(shù)TIM_OutputState用來設(shè)置比較輸出使能,也就是使能PWM輸出到端口。
參數(shù)TIM_OCPolarity用來設(shè)置極性是高還是低。其他的參數(shù)TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState和 TIM_OCNIdleState是高級定時(shí)器才用到的。要實(shí)現(xiàn)我們上面提到的場景,方法是:
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //>>選擇模式 PWM TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //>>比較輸出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //>>輸出極性低 TIM_OC1Init(TIM14, &TIM_OCInitStructure); //>>根據(jù)指定的參數(shù)初始化外設(shè)TIM1 4OC1
4)使能TIM14
在完成以上設(shè)置了之后,我們需要使能TIM14。使能TIM14的方法前面已經(jīng)講解過:
TIM_Cmd(TIM14, ENABLE); //>>使能 TIM14
5)修改TIM14_CCR1來控制占空比
最后,在經(jīng)過以上設(shè)置之后,PWM其實(shí)已經(jīng)開始輸出了,只是其占空比和頻率都是固定的,而我們通過修改TIM14_CCR1則可以控制 CH1的輸出占空比。在庫函數(shù)中,修改TIM14_CCR1占空比的函數(shù)是:
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare2);
理所當(dāng)然,對于其他通道,分別有一個(gè)函數(shù)名字,函數(shù)格式為TIM_SetComparex(x=1,2,3,4)。
通過以上5個(gè)步驟,我們就可以控制TIM14的CH1輸出PWM波了。這里特別提醒一下大家,高級定時(shí)器雖然和通用定時(shí)器類似,但是高級定時(shí)器要想輸出PWM,必須還要設(shè)置一個(gè)MOE位(TIMx_BDTR 的第15位),以使能主輸出,否則不會輸出PWM。庫函數(shù)設(shè)置的函數(shù)為:
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState)
代碼示例
TIM3時(shí)鐘來自于APB1域,我們通過APB1總線下的時(shí)鐘使能函數(shù)來使能TIM3的時(shí)鐘。調(diào)用的函數(shù)是:
//>>TIM14 PWM 部分初始化 //>>PWM 輸出初始化 //>>arr:自動(dòng)重裝值 psc:時(shí)鐘預(yù)分頻數(shù) void TIM14_PWM_Init(u32 arr,u32 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);//TIM14 時(shí)鐘使能 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //使能 PORTF 時(shí)鐘 GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GF9 復(fù)用為 TIM14 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //GPIOF9 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //復(fù)用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度 50MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽復(fù)用輸出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化 PF9 TIM_TimeBaseStructure.TIM_Prescaler=psc; //定時(shí)器分頻 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計(jì)數(shù)模式 TIM_TimeBaseStructure.TIM_Period=arr; //自動(dòng)重裝載值 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStructure);//初始化定時(shí)器 14 //初始化 TIM14 Channel1 PWM 模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM 調(diào)制模式 1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //輸出極性低 TIM_OC1Init(TIM14, &TIM_OCInitStructure); //初始化外設(shè) TIM1 4OC1 TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); //使能預(yù)裝載寄存器 TIM_ARRPreloadConfig(TIM14,ENABLE);//ARPE 使能 TIM_Cmd(TIM14, ENABLE); //使能 TIM14 TIM_SetCompare1(TIM14,300); //>>設(shè)置pwm的占空比為300/500 = 60% }
此部分代碼包含了上面介紹的PWM輸出設(shè)置的前5個(gè)步驟。這里我們關(guān)于TIM14的設(shè)置就不再說了。接下來,我們看看主程序里面的main函數(shù)如下:
int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//>>設(shè)置系統(tǒng)中斷優(yōu)先級分組 2 delay_init(168); //>>初始化延時(shí)函數(shù) TIM14_PWM_Init(500-1,84-1); //>>定時(shí)器時(shí)鐘為 84M,分頻系數(shù)為 84,所以計(jì)數(shù)頻率 //>>為 84M/84=1Mhz,重裝載值 500,所以 PWM 頻率為 1M/500=2Khz. while(1) { } }
這里,我們先設(shè)置好了NVIC終端優(yōu)先級,然后初始化延時(shí)函數(shù)和timer,在timer的初始化參數(shù)中我們把PWM的頻率設(shè)置成2K,將占空比設(shè)置成60%,完成PWM輸出設(shè)置。
審核編輯:湯梓紅
-
mcu
+關(guān)注
關(guān)注
146文章
17002瀏覽量
350322 -
寄存器
+關(guān)注
關(guān)注
31文章
5322瀏覽量
120017 -
微處理器
+關(guān)注
關(guān)注
11文章
2247瀏覽量
82322 -
定時(shí)器
+關(guān)注
關(guān)注
23文章
3241瀏覽量
114478 -
Timer
+關(guān)注
關(guān)注
1文章
63瀏覽量
12774
原文標(biāo)題:MCU微課堂|CKS32F4xx系列產(chǎn)品Timer的基本使用方法-比較輸出
文章出處:【微信號:中科芯MCU,微信公眾號:中科芯MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論