定時器1作爲主模式輸出PWM,定時器4作爲從模式
平臺
STM32F407VGT6
特別記錄兩個問題:
移植通用定時器的程序 沒有看手冊 結果pwm移植無法輸出 磨蹭了一兩天
後來發現 是因爲 高級定時器 有幾個特殊的設置:
- 重複計數設置:
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //重複計數,一定要=0!!!
- 輸出使能:
TIM_CtrlPWMOutputs(TIM1, ENABLE); //高級定時器一定要加上,主輸出使能
當然 這是使用了庫函數的 寄存器的具體設置是:
越過這兩個鴻溝以後 就能正常使用高級定時器輸出PWM了
進入正題 主從模式設置
上圖顯示的是F4的主從配置關係
我的程序是使用的TIM1作爲master TIM4 作爲slave
所以 使用的是table59的第三行的ITR0
具體程序是:
/***定時器1主模式***/
void TIM1_config(u32 Cycle)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_TIM1 , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //TIM1_CH4 PA11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //複用推輓輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = Cycle-1;
TIM_TimeBaseStructure.TIM_Prescaler =71; //設置用來作爲TIMx時鐘頻率除數的預分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鐘分割:TDTS= Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //重複計數,一定要=0!!!
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時器模式:TIM脈衝寬度調製模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_Pulse = Cycle/2-1; //設置待裝入捕獲寄存器的脈衝值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //輸出極性
TIM_OC4Init(TIM1, &TIM_OCInitStructure);
TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
}
/***定時器4從模式***/
void TIM4_config(u32 PulseNum)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseStructure.TIM_Period = PulseNum-1;
TIM_TimeBaseStructure.TIM_Prescaler =0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_SelectInputTrigger(TIM4, TIM_TS_ITR0);
//TIM_InternalClockConfig(TIM4);
TIM4->SMCR|=0x07; //設置從模式寄存器
//TIM_ITRxExternalClockConfig(TIM4, TIM_TS_ITR0);
//TIM_ARRPreloadConfig(TIM4, ENABLE);
TIM_ITConfig(TIM4,TIM_IT_Update,DISABLE);
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void Pulse_output(u32 Cycle,u32 PulseNum)
{
TIM4_config(PulseNum);
TIM_Cmd(TIM4, ENABLE);
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
TIM1_config(Cycle);
TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE); //高級定時器一定要加上,主輸出使能
}
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) // TIM_IT_CC1
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update); // 清除中斷標誌位
TIM_CtrlPWMOutputs(TIM1, DISABLE); //主輸出使能
TIM_Cmd(TIM1, DISABLE); // 關閉定時器
TIM_Cmd(TIM4, DISABLE); // 關閉定時器
TIM_ITConfig(TIM4, TIM_IT_Update, DISABLE);
}
}
#include "delay.h"
#include "sys.h"
#include "timer.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(); //延時函數初始化
uart_init(115200); //串口初始化爲115200
Pulse_output(1000,8000);//1KHZ,8000個脈衝
while(1)
{
}
}
效果
總結
輸出一定數量PWM脈衝,
主要有幾種方法:
1.單脈衝法,需要一個脈衝中斷一次,中斷次數多,影響效率,而且能保證每次的脈衝連續性麼?
2.另一定時器進行中斷計數,與1一樣,需要頻繁中斷;
3.用主從定時器門控方式,比較繁瑣 其實還好 就是有主從關係 需要看好;
4.高級定時器T1、T8的重複計數方式,RCR計數中斷,看手冊好像這種方式最簡單,能滿足一部分人要求,缺點是寄存器只有8位,最多實現255個脈衝計數輸出。只能設置0x00-0xFF