定時(shí)器-PWM輸出
STM32 PWM工作過(guò)程
ARR寄存器決定PWM周期,CCR寄存器決定占空比
通道1為例的PWM輸出電路圖
CCR1:捕獲比較(值)寄存器(x =1,2,3,4):設(shè)置比較值。
CCMR1:OC1M[2:0]位:對(duì)于PWM方式下,用于設(shè)置PWM模式1【110】 或者PWM模式2【111】
CCER:CC1P位:輸入/捕獲1輸出極性。0:高電平有效,1:低電平有效。
CCER:CC1E位:輸入/捕獲1輸出使能。0:關(guān)閉,1:打開(kāi)。
PWM模式1和模式2的區(qū)別
捕獲/比較模式寄存器 1(TIMx_CCMR1)
有效電平并不是指高電平或者低電平,設(shè)置高電平有效還是低電平有效要看CCER寄存器的CC1P位
CCER:CC1P位:輸入/捕獲1輸出極性。0:高電平有效,1:低電平有效。
如果設(shè)置為高電平有效,那么在PWM模式1的向上計(jì)數(shù)時(shí),TIMx_CNT < TIMx_CCR1時(shí)通道1輸出的就是高電平
如果設(shè)置為低電平有效,那么在PWM模式1的向上計(jì)數(shù)時(shí),TIMx_CNT < TIMx_CCR1時(shí)通道1輸出的就是低電平
PWM模式
脈沖寬度調(diào)制模式可以產(chǎn)生一個(gè)由TIMx_ARR寄存器確定頻率、由TIMx_CCRx寄存器確定占空比的信號(hào)。
在TIMx_CCMRx寄存器中的OCxM位寫(xiě)入’110’(PWM模式1)或’111’(PWM模式2),能夠獨(dú)立地設(shè)置每個(gè)OCx輸出通道產(chǎn)生一路PWM。
必須設(shè)置TIMx_CCMRx寄存器OCxPE位以使能相應(yīng)的預(yù)裝載寄存器,對(duì)應(yīng)的庫(kù)函數(shù)是:
void TIM_OC2PreloadConfig(TIM_TypeDef*TIMx, uint16_t TIM_OCPreload);
最后還要設(shè)置TIMx_CR1寄存器的ARPE位,(在向上計(jì)數(shù)或中心對(duì)稱(chēng)模式中)使能自動(dòng)重裝載的預(yù)裝載寄存器,對(duì)應(yīng)的庫(kù)函數(shù)是:
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx,FunctionalState NewState);
自動(dòng)重載的預(yù)裝載寄存器
ARPE = 1時(shí)的更新事件,意思就是CNT計(jì)數(shù)器在計(jì)數(shù)時(shí),在到達(dá)ARR寄存器值溢出之前,人為的又往ARR寄存器里寫(xiě)入了新值,那這個(gè)新值會(huì)立即生效,計(jì)數(shù)到這個(gè)新值時(shí)產(chǎn)生溢出
ARPE = 0時(shí)更新事件,意思是在CNT計(jì)數(shù)器計(jì)數(shù)過(guò)程中,在計(jì)數(shù)溢出之前,人為改變了ARR寄存器的值,寫(xiě)入了新值,那這個(gè)新值會(huì)在下一個(gè)計(jì)數(shù)周期才生效,在寫(xiě)入新值的當(dāng)前周期里,還是計(jì)數(shù)到舊值就產(chǎn)生溢出
void TIM_ARRPreloadConfig(TIM_TypeDe* TIMx, FunctionalState NewStale);
簡(jiǎn)單的說(shuō), ARPE=1,ARR立即生效;APRE=0,ARR下個(gè)比較周期生效。
PWM輸出庫(kù)函數(shù)
void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OClnitTypeDef* TIM_OCInitStruct);
結(jié)構(gòu)體類(lèi)型
typedef struct
{
uint16_t TM_OCMode; //PWM模式1或者模式2
uint16_t TIM_OutputState; //輸出使能/失能
uint16_t TIM_OutputNState;
uint16_t TIM_Pulse; //比較值,寫(xiě)CCRx
uint16_t TIM_OCPolarity; //比較輸出極性
uint16_t TIM_OCNPolarity;
uint16_t TIM_OCldleState;
uint16_t TIM_OCNldleState;
} TIM_OCInitTypeDef;
初始化示例
TIM_OCInitStructure.TlM_OCMode = TIM_OCMode_PWM2; //PWM模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_Pulse=100;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OC2Init(TIM3,&TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM3 OC2
設(shè)置比較值函數(shù):
void TIM_SetCompareX(TIM_TypeDef* TIMx, uint16_t Compare2);
使能輸出比較預(yù)裝載:
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx,uint16_t TIM_OCPreload);
使能自動(dòng)重裝載的預(yù)裝載寄存器允許位:
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
實(shí)驗(yàn)
使用定時(shí)器3的PWM功能,輸出占空比可變的PWM波,用來(lái)驅(qū)動(dòng)LED燈,從而達(dá)到LED亮度由暗變亮,又從亮變暗,如此循環(huán)。
PWM輸出配置步驟:
1、使能定時(shí)器3和相關(guān)IO口時(shí)鐘。
? 使能定時(shí)器3時(shí)鐘:RCC_APB1PeriphClockCmd();
? 使能GPIOB時(shí)鐘:RCC_ APB2PeriphClockCmd();
2、初始化IO口為復(fù)用功能輸出。函數(shù): GPIO_Init();
? GPIO_InitStructure.GPIO Mode = GPIO_Mode_AF_PP;
3、這里我們是要把PB5用作定時(shí)器的PWM輸出引腳,所以要重映射配置,所以需要開(kāi)啟AFIO時(shí)鐘。同時(shí)設(shè)置重映射。
? RCC_APB2PeriphClockCmd(RCC_APB2Periph_ AFIO,ENABLE);
? GPIO_PinRemapConfig(GPIO_ PartialRemap_TIM3, ENABLE); //定時(shí)器3重映射到相應(yīng)的引腳
4、初始化定時(shí)器: ARR,PSC等: TIM_TimeBaselnit();
5、初始化輸出比較參數(shù): TIM_OC2Init();
6、使能預(yù)裝載寄存器TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
7、使能定時(shí)器。TIM_Cmd();
8、不斷改變比較值CCRx,達(dá)到不同的占空比效果: TIM_SetCompare2();
定時(shí)器PWM初始化示例,C8T6的板
因?yàn)殚_(kāi)發(fā)板的LED燈引腳PA1同時(shí)也是TIM2_CH2引腳,這里使用了引腳復(fù)用功能,沒(méi)有重映射
/**
* @name TIM_PWM_Init
* @brief 定時(shí)器PWM初始化
* @param arr:自動(dòng)重裝值
* psc:時(shí)鐘預(yù)分頻系數(shù)
* @retval None
*/
void TIM_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitTypeDefStructure;
//使能定時(shí)器2時(shí)鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//使能GPIOA時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//PA1配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //設(shè)置為復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//PA1初始化
GPIO_Init(GPIOA,&GPIO_InitStructure);
//把PA1用作定時(shí)器的PWM輸出引腳。初始化定時(shí)器
TIM_TimeBaseInitStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
TIM_TimeBaseInitStructure.TIM_Prescaler = psc;//設(shè)置用來(lái)作為T(mén)IMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
//定時(shí)器2初始化
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
//通道2配置
TIM_OCInitTypeDefStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM模式2
TIM_OCInitTypeDefStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitTypeDefStructure.TIM_Pulse = 100;
TIM_OCInitTypeDefStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
//初始化輸出比較參數(shù)
TIM_OC2Init(TIM2,&TIM_OCInitTypeDefStructure);
//使能預(yù)裝載寄存器
TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);
//使能定時(shí)器
TIM_Cmd(TIM2,ENABLE);
}
main函數(shù)
因?yàn)閐ir初始化為1,所以進(jìn)入while循環(huán)后,led0pwmval++,等led0pwmval增加到大于300時(shí),dir 被置為 0,led0pwmval又開(kāi)始減少,減到0后,dir置為1,led0pwmval再增加,如此反復(fù)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-489730.html
調(diào)用TIM_SetCompare2函數(shù)往CCR2寄存器寫(xiě)入不斷變化的led0pwmval值,輸出PWM,LED燈呈呼吸燈的效果文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-489730.html
#include "PWM.h"
int main()
{
u16 led0pwmval = 0;
u8 dir = 1;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC初始化分組
LED_Init(); //LED初始化
delay_init(); //延時(shí)初始化
TIM_PWM_Init(899,0); //不分頻。PWM頻率=72000000/900=80Khz
while(1)
{
delay_ms(10);
if(dir)
{
led0pwmval++;
}
else
{
led0pwmval--;
}
if(led0pwmval > 300){dir = 0;}
if(led0pwmval == 0){dir = 1;}
//往CCR2寄存器寫(xiě)入不斷變化的led0pwmval值,調(diào)整比較值,就能輸出不斷變化的占空比了
TIM_SetCompare2(TIM2,led0pwmval);
}
}
到了這里,關(guān)于STM32F1定時(shí)器-PWM輸出的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!