stm32學習筆記(十)輸入捕獲實驗
阿新 • • 發佈:2019-01-23
#include "timer.h" #include "led.h" #include "usart.h" #include "sys.h" ////////////////////////////////////////////////////////////////////////////////// //本程式只供學習使用,未經作者許可,不得用於其它任何用途 //ALIENTEK Mini STM32開發板 //PWM 驅動程式碼 //正點原子@ALIENTEK //技術論壇:www.openedv.com //修改日期:2010/12/03 //版本:V1.0 //版權所有,盜版必究。 //Copyright(C) 正點原子 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// //PWM輸出初始化 //arr:自動重灌值 //psc:時鐘預分頻數 void TIM1_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //時基結構體 TIM_OCInitTypeDef TIM_OCInitStructure; //輸出比較結構體 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);// TIM1時鐘使能,掛載在APB2高速總線上 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外設時鐘使能 //設定該引腳為複用輸出功能,輸出TIM1 CH2的PWM脈衝波形 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //複用推輓輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO輸出頻率50MHZ GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = arr; //設定在下一個更新事件裝入活動的自動重灌載暫存器週期的值 80K TIM_TimeBaseStructure.TIM_Prescaler =psc; //設定用來作為TIMx時鐘頻率除數的預分頻值 不分頻 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設定時鐘分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的引數初始化TIMx的時間基數單位 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //選擇定時器模式:TIM脈衝寬度調製模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能 TIM_OCInitStructure.TIM_Pulse = 0; //設定待裝入捕獲比較暫存器的脈衝值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高 TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根據TIM_OCInitStruct中指定的引數初始化外設TIMx TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主輸出使能 TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1預裝載使能 TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的預裝載暫存器 TIM_Cmd(TIM1, ENABLE); //使能TIM1 } //定時器2通道1輸入捕獲配置 TIM_ICInitTypeDef TIM2_ICInitStructure; void TIM2_Cap_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2時鐘在APB1低速總線上 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA時鐘 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 清除之前設定 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 輸入 下拉輸入 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 下拉 //初始化定時器2 TIM2 TIM_TimeBaseStructure.TIM_Period = arr; //設定計數器自動重灌值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //預分頻器 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設定時鐘分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的引數初始化TIMx的時間基數單位 //初始化TIM2輸入捕獲引數 TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 選擇輸入端 IC1對映到TI1上 TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲 TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //對映到TI1上 TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻 TIM2_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 TIM_ICInit(TIM2, &TIM2_ICInitStructure); //中斷分組初始化 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2中斷 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先佔優先順序2級 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優先順序0級 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //根據NVIC_InitStruct中指定的引數初始化外設NVIC暫存器 TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷 TIM_Cmd(TIM2,ENABLE ); //使能定時器2 } u8 TIM2CH1_CAPTURE_STA=0; //輸入捕獲狀態 u16 TIM2CH1_CAPTURE_VAL; //輸入捕獲值 //定時器5中斷服務程式 void TIM2_IRQHandler(void) { if((TIM2CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲 { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { if(TIM2CH1_CAPTURE_STA&0X40)//已經捕獲到高電平了 { if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 { TIM2CH1_CAPTURE_STA|=0X80;//標記成功捕獲了一次 TIM2CH1_CAPTURE_VAL=0XFFFF; }else TIM2CH1_CAPTURE_STA++; } } if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕獲1發生捕獲事件 { if(TIM2CH1_CAPTURE_STA&0X40) //捕獲到一個下降沿 { TIM2CH1_CAPTURE_STA|=0X80; //標記成功捕獲到一次上升沿 TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2); TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC1P=0 設定為上升沿捕獲 }else //還未開始,第一次捕獲上升沿 { TIM2CH1_CAPTURE_STA=0; //清空 TIM2CH1_CAPTURE_VAL=0; TIM_SetCounter(TIM2,0); TIM2CH1_CAPTURE_STA|=0X40; //標記捕獲到了上升沿 TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling); //CC1P=1 設定為下降沿捕獲 } } } TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中斷標誌位 }
#include "led.h" #include "delay.h" #include "sys.h" #include "timer.h" #include "usart.h" //ALIENTEK Mini STM32開發板範例程式碼9 //輸入捕獲實驗 //技術支援:www.openedv.com //廣州市星翼電子科技有限公司 extern u8 TIM2CH1_CAPTURE_STA; //輸入捕獲狀態 extern u16 TIM2CH1_CAPTURE_VAL; //輸入捕獲值 int main(void) { u32 temp=0; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 設定中斷優先順序分組2 delay_init(); //延時函式初始化 uart_init(9600); //9600 LED_Init(); //初始化與LED連線的硬體介面 TIM1_PWM_Init(899,0); //不分頻。PWM頻率=72000/(899+1)=80Khz TIM2_Cap_Init(0XFFFF,72-1); //以1Mhz的頻率計數 while(1) { delay_ms(10); TIM_SetCompare1(TIM1,TIM_GetCapture1(TIM1)+1); if(TIM_GetCapture1(TIM1)==300)TIM_SetCompare1(TIM1,0); if(TIM2CH1_CAPTURE_STA&0X80)//成功捕獲到了一次高電平 { temp=TIM2CH1_CAPTURE_STA&0X3F; temp*=65536; //溢位時間總和 temp+=TIM2CH1_CAPTURE_VAL; //得到總的高電平時間 printf("HIGH:%d us\r\n",temp); //列印總的高點平時間 TIM2CH1_CAPTURE_STA=0; //開啟下一次捕獲 } } }