畢業設計需要使用比較多的定時器,但手上的F103C8T6核心板定時器資源比較少,所以被迫使用高級定時器1(一直都是用通用定時器,畢竟以前玩F429的時候管腳資源充足,就沒有去學習高級定時器的用法,以爲完全一樣的用法,但是移植程序過程還是發現好些需要注意的地方)。下面列出程序中與通用定時器有差別的地方。
用到的定時器是TIM1通道4,原型是作爲超聲波捕獲,單獨拿出配置定時器輸入捕獲函數和中斷服務函數來說明,程序都寫了註釋,沒有一一說明的地方可以直接看註釋。
- 高級定時器TIM1和GPIOA時鐘來源都是APB2
由上面兩圖可知,需要使能的是TIM1時鐘和GPIOA時鐘:
//使能TIM1和GPIOA時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);//初始化TIME時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//初始化GPIOA時鐘
2. GPIOA中的PA11配置爲輸入模式,PA12設置爲輸出模式
//配置PA11
GPIOA_Initstructure.GPIO_Pin=GPIO_Pin_11;//PA11
GPIOA_Initstructure.GPIO_Mode=GPIO_Mode_IPD;//輸入
GPIO_ResetBits(GPIOA,GPIO_Pin_11); //PA11 下拉
GPIO_Init(GPIOA,&GPIOA_Initstructure);
//配置PA12
GPIOA_Initstructure.GPIO_Pin=GPIO_Pin_12;//PA12
GPIOA_Initstructure.GPIO_Mode = GPIO_Mode_Out_PP;//輸出
GPIOA_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIOA_Initstructure);
關於GPIO口的八種模式原子論壇有帖子說的很詳細,以前看過的,有興趣可以去搜索。
- 初始化TIM1、置 TIM1 的輸入比較參數、
//初始化 TIM1, 設置 TIM1 的 ARR 和 PSC
TIM1_CH4_Handler.TIM_Prescaler=psc;//預分頻係數
TIM1_CH4_Handler.TIM_Period=arr;//自動重裝載值
TIM1_CH4_Handler.TIM_CounterMode=TIM_CounterMode_Up;//向上計數模式
TIM1_CH4_Handler.TIM_ClockDivision=TIM_CKD_DIV1;//預分頻係數爲1
TIM1_CH4_Handler.TIM_RepetitionCounter=0;//設置重複溢出次數,就是多少次溢出後進入中斷,一般爲0,只有高級定時器纔有用
TIM_TimeBaseInit(TIM1,&TIM1_CH4_Handler);
//設置 TIM1 的輸入比較參數,開啓輸入捕獲
TIM1_IC_Handler.TIM_Channel=TIM_Channel_4;//TIM1通道4
TIM1_IC_Handler.TIM_ICFilter=0x00;//輸入濾波器長度爲0
TIM1_IC_Handler.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕獲
TIM1_IC_Handler.TIM_ICPrescaler=TIM_ICPSC_DIV1;//預分頻係數,不分頻
TIM1_IC_Handler.TIM_ICSelection=TIM_ICSelection_DirectTI; //映射到 TI1 上
TIM_ICInit(TIM1,&TIM1_IC_Handler);
TIM1_CH4_Handler.TIM_RepetitionCounter=0;//設置重複溢出次數,就是多少次溢出後進入中斷,一般爲0,只有高級定時器纔有用到
- 使能捕獲和更新中斷、設置中斷分組、使能定時器
//使能捕獲和更新中斷(設置 TIM1 的 DIER 寄存器)
TIM_ITConfig( TIM1,TIM_IT_Update|TIM_IT_CC4,ENABLE);//允許更新中斷和捕獲中斷
//設置中斷分組
NVIC_Initstructure.NVIC_IRQChannel=TIM1_CC_IRQn;//定時器1
NVIC_Initstructure.NVIC_IRQChannelCmd=ENABLE;//使能TIM1
NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority=2;//搶佔優先級2
NVIC_Initstructure.NVIC_IRQChannelSubPriority=0;//子優先級0
NVIC_Init(&NVIC_Initstructure);
TIM_CtrlPWMOutputs(TIM1,ENABLE); //主輸出使能
//使能定時器(設置 TIM1 的 CR1 寄存器)
TIM_Cmd(TIM1,ENABLE);//使能定時器1
選擇NVIC_IRQChannel中的TIM1_CC_IRQn,即TIM1捕獲比較中斷。
- 定時器1中斷服務函數
//定時器1中斷服務程序
void TIM1_CC_IRQHandler(void)
{
if((TIM1CH4_CAPTURE_STA&0X80)==0)//還未成功捕獲
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
{
if(TIM1CH4_CAPTURE_STA&0X40)//已經捕獲到高電平了
{
if((TIM1CH4_CAPTURE_STA&0X3F)==0X3F)//高電平太長了
{
TIM1CH4_CAPTURE_STA|=0X80;//標記成功捕獲了一次
TIM1CH4_CAPTURE_VAL=0XFFFF;
}else TIM1CH4_CAPTURE_STA++;
}
}
if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET)//捕獲 1 發生捕獲事件
{
if(TIM1CH4_CAPTURE_STA&0X40) //捕獲到一個下降沿
{
TIM1CH4_CAPTURE_STA|=0X80; //標記成功捕獲到一次上升沿
TIM1CH4_CAPTURE_VAL=TIM_GetCapture4(TIM1);
TIM_OC4PolarityConfig(TIM1,TIM_ICPolarity_Rising);
//CC1P=0 設置爲上升沿捕獲
}else //還未開始,第一次捕獲上升沿
{
TIM1CH4_CAPTURE_STA=0; //清空
TIM1CH4_CAPTURE_VAL=0;
TIM_SetCounter(TIM1,0);
TIM1CH4_CAPTURE_STA|=0X40; //標記捕獲到了上升沿
TIM_OC4PolarityConfig(TIM1,TIM_ICPolarity_Falling);
//CC1P=1 設置爲下降沿捕獲
}
}
}
TIM_ClearITPendingBit(TIM1, TIM_IT_CC4|TIM_IT_Update); //清除中斷標誌位
}
定時器中斷函數服務名字選擇:void TIM1_CC_IRQHandler(void);
以上,就是使用TIM1做輸入捕獲的過程。