單片機輸出pwm的原理
涉及模塊:GPIO、TIM1
主要寄存器:TIMx_CCR、TIMx_ARR、TIMx_CNT
通用定時器可以利用GPIO引腳進行脈衝輸出,在配置為比較輸出、PWM輸出功能時,捕獲/比較寄存器TIMx_CCR被用作比較功能,下面把它簡稱為比較寄存器。
若配置脈衝計數器TIMx_CNT為向上計數,而重載寄存器TIMx_ARR被配置為N,即TIMx_CNT的當前計數值數值X在TIMxCLK時鐘源的驅動下不斷累加,當TIMx_CNT的數值X大於N時,會重置TIMx_CNT數值為0重新計數。而在TIMxCNT計數的同時,TIMxCNT的計數值X會與比較寄存器TIMx_CCR預先存儲了的數值A進行比較,當脈衝計數器TIMx_CNT的數值X小於比較寄存器TIMx_CCR的值A時,輸出高電平(或低電平),相反地,當脈衝計數器的數值X大於或等於比較寄存器的值A時,輸出低電平(或高電平)。
如此循環,得到的輸出脈衝周期就為重載寄存器TIMx_ARR存儲的數值(N+1)乘以觸發脈衝的時鐘周期,其脈衝寬度則為比較寄存器TIMx_CCR的值A乘以觸發脈衝的時鐘周期,即輸出PWM的佔空比為 A/(N+1) 。
主要程序
根據要使用的外設以及模塊進性程序配置,主要分為三塊:GPIO配置、TIM配置、PWM輸出配置。
程序實例:單片機使用TIM1進行PWM的輸出。
//TIM1 PWM部分初始化
//PWM輸出初始化
//arr:自動重裝值
//psc:時鐘預分頻數
void TIM1_PWM_Init(u32 arr,u32 psc)
{
//此部分需手動修改IO口設置
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); //TIM1時鐘使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA時鐘
//復用不能寫成下面,會出問題
//GPIO_PinAFConfig(GPIOA,GPIO_PinSource8|GPIO_PinSource11,GPIO_AF_TIM1); //GPIO復用為定時器1
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1); //復用GPIOA_Pin8為TIM1_Ch1,
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_TIM1);//復用GPIOA_Pin11為TIM1_Ch4,注意沒有CH4N
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11; //GPIO
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //復用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽復用輸出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化P
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定時器分頻
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計數模式
TIM_TimeBaseStructure.TIM_Period=arr; //自動重裝載值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
//TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;//默認就為0
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);//初始化定時器1
//初始化TIM1 PWM模式
//PWM 模式 1–– 在遞增計數模式下,只要 TIMx_CNT<TIMx_CCR1,通道 1 便為有效狀態,否則為無效狀態。在遞減計數模式下,
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM1為正常佔空比模式,PWM2為反極性模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //輸出極性:TIM輸出比較極性低,有效電平為低電平
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;//在空閒時輸出 低,這裡的設置可以改變TIM_OCPolarity 如果沒這句,第1通道有問題
TIM_OCInitStructure.TIM_Pulse = 2000; //輸入通道1 CCR1(佔空比數值)
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //Ch1初始化
TIM_OCInitStructure.TIM_Pulse = 5000;
TIM_OC4Init(TIM1, &TIM_OCInitStructure);//通道4
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能TIM1在CCR1上的預裝載寄存器,CCR自動裝載默認也是打開的
TIM_ARRPreloadConfig(TIM1,ENABLE);//ARPE使能
TIM_Cmd(TIM1, ENABLE); //使能TIM1
TIM_CtrlPWMOutputs(TIM1, ENABLE);//使能TIM1的PWM輸出,TIM1與TIM8有效,如果沒有這行會問題
}