超聲波手勢識別(STM32四路超聲波獲取)
超聲波手勢識別在市場上已經有見實現,但研究其感測器發現並不是市場上隨意可見的,如果暫且考慮成本,該如何入門實現簡單的手勢識別呢。聊天中老師給出一個很好的提議,就是固定四個超聲波,分別為上下左右,然後進行程式上的對應編號,用微控制器實現四路超聲波的距離資料讀取,然後程式分析讀取的資料進而判斷手勢。STM32微控制器有多個定時器,每個定時器接入一個超聲波,分別接入四個,定時器分別開始工作以計數,將得到的距離資訊一次性發送四個方向的值到串列埠,串列埠連線到PC機,PC機獲取到四組值,然後進行分析解釋。下面將實現第一步,STM32 實現四路超聲波獲取。
實現效果:
Python的串列埠程式上每次從串列埠獲取到上下左右四組值,並輸出在控制檯,相關的串列埠實現可以參考: Python的串列埠通訊(pyserial)
超聲波模組:HC-SR04
微控制器:stm32f103c8t6
注意:程式正常工作的前提是必須按復位鍵
獲取值【上,下,左,右】
對應echo的IO【PA0 , PA11 , PA7 , PB6】
對應trig 的IO【PB12 , PB13 , PB14 , PB15】
對應定時器【定時器2通道1,定時器1通道4,定時器3通道2,定時器4通道1】
串列埠1:A9為TX A10為RX
超聲波使用基本介紹:
(1)採用IO口TRIG觸發測距,給至少10us的高電平訊號;
(2)模組自動傳送8個40khz的方波,自動檢測是否有訊號返回;
(3)有訊號返回,通過IO口ECHO輸出一個高電平,高電平持續的時間就是超聲波從發射到返回的時間。測試距離=(高電平時間*聲速(340M/S)) (未實現)
超聲波時序:
主函式程式碼:
1 #include "stm32f10x.h" //STM32標頭檔案 2 #include "sys.h" 3 #include "delay.h" 4 #include "usart.h" 5 #include "timex.h" 6 #include "trig.h" 7 8 extern u8TIM3CH1_CAPTURE_STA;//輸入捕獲狀態 9 extern u16TIM3CH1_CAPTURE_VAL;//輸入捕獲值 10 extern u8TIM3CH2_CAPTURE_STA;//輸入捕獲狀態 11 extern u16TIM3CH2_CAPTURE_VAL;//輸入捕獲值 12 extern u8TIM2CH1_CAPTURE_STA;//輸入捕獲狀態 13 extern u16TIM2CH1_CAPTURE_VAL;//輸入捕獲值 14 extern u8TIM4CH1_CAPTURE_STA;//輸入捕獲狀態 15 extern u16TIM4CH1_CAPTURE_VAL;//輸入捕獲值 16 extern u8TIM1CH4_CAPTURE_STA;//輸入捕獲狀態 17 extern u16TIM1CH4_CAPTURE_VAL;//輸入捕獲值 18 int main (void){//主程式 19 u32 temp1=0; 20 //u32 temp2=0; 21 u32 temp3=0; 22 u32 temp4=0; 23 u32 temp24=0; 24 RCC_Configuration(); //時鐘設定 25 TR_Init(); //輸出初始化 26 27 USART1_Init(115200); 28 29 TIM3_Cap_Init(0XFFFF,72-1);//以1Mhz的頻率計數//列印總的高點平時間 30 TIM2_Cap_Init(0XFFFF,72-1);//以1Mhz的頻率計數//列印總的高點平時間 31 TIM4_Cap_Init(0XFFFF,72-1);//以1Mhz的頻率計數//列印總的高點平時間 32 TIM1_Cap_Init(0XFFFF,72-1);//以1Mhz的頻率計數//列印總的高點平時間 33 delay_s(1); 34 printf("********** INIT ALL 11*********\r\n"); 35 PBout(12)=1; 36 delay_us(13); 37 PBout(12)=0; 38 39 PBout(14)=1; 40 delay_us(13); 41 PBout(14)=0; 42 43 PBout(15)=1; 44 delay_us(13); 45 PBout(15)=0; 46 47 PBout(13)=1; 48 delay_us(13); 49 PBout(13)=0; 50 51 while(1){ 52 //定時器2通道1 53 if(TIM2CH1_CAPTURE_STA&0X80)//成功捕獲到了一次上升沿 54{ 55temp1=TIM2CH1_CAPTURE_STA&0X3F; 56temp1*=65536;//溢位時間總和 57temp1+=TIM2CH1_CAPTURE_VAL;//得到總的高電平時間 58printf("time2-----:%d \r\n",temp1);//列印總的高點平時間 59TIM2CH1_CAPTURE_STA=0;//開啟下一次捕獲 60PBout(12)=1; 61delay_us(13); 62PBout(12)=0; 63} 64 65 //定時器1通道4 66 if(TIM1CH4_CAPTURE_STA&0X80)//成功捕獲到了一次上升沿 67{ 68temp24=TIM1CH4_CAPTURE_STA&0X3F; 69temp24*=65536;//溢位時間總和 70temp24+=TIM1CH4_CAPTURE_VAL;//得到總的高電平時間 71printf("time14-----:%d \r\n",temp24);//列印總的高點平時間 72TIM1CH4_CAPTURE_STA=0;//開啟下一次捕獲 73PBout(13)=1; 74delay_us(13); 75PBout(13)=0; 76} 77 //定時器3通道2 78 if(TIM3CH2_CAPTURE_STA&0X80)//成功捕獲到了一次上升沿 79{ 80temp3=TIM3CH2_CAPTURE_STA&0X3F; 81temp3*=65536;//溢位時間總和 82temp3+=TIM3CH2_CAPTURE_VAL;//得到總的高電平時間 83printf("time32----:%d \r\n",temp3);//列印總的高點平時間 84TIM3CH2_CAPTURE_STA=0;//開啟下一次捕獲 85PBout(14)=1; 86delay_us(13); 87PBout(14)=0; 88} 89 //定時器4通道1 90 if(TIM4CH1_CAPTURE_STA&0X80)//成功捕獲到了一次上升沿 91{ 92temp4=TIM4CH1_CAPTURE_STA&0X3F; 93temp4*=65536;//溢位時間總和 94temp4+=TIM4CH1_CAPTURE_VAL;//得到總的高電平時間 95printf("time4-----:%d \r\n",temp4);//列印總的高點平時間 96TIM4CH1_CAPTURE_STA=0;//開啟下一次捕獲 97PBout(15)=1; 98delay_us(13); 99PBout(15)=0; 100} 101 102 //傳送最終結果------------------------------------ 103 if((temp1 >0)&&(temp24 >0)&&(temp3 >0)&&(temp4 >0)){ 104 105printf("[%d,%d,%d,%d]",temp1,temp24,temp3,temp4); 106temp1=temp24=temp3=temp4=0; 107PBout(0)=1; 108 } 109 110 } 111}
定時器2通道1程式碼實現:
1 #include"timex.h" 2 #include "usart.h" 3 4 //定時器3通道1輸入捕獲配置 5 6 TIM_ICInitTypeDefTIM2_ICInitStructure; 7 8 void TIM2_Cap_Init(u16 arr,u16 psc) 9 { 10 11 12GPIO_InitTypeDef GPIO_InitStructure; 13TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; 14NVIC_InitTypeDef NVIC_InitStructure; 15printf("---time 222221111 ---\r\n"); 16RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能TIM2時鐘 17RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA時鐘 18 19GPIO_InitStructure.GPIO_Pin= GPIO_Pin_0;//PA0清除之前設定 20GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 輸入 21GPIO_Init(GPIOA, &GPIO_InitStructure); 22GPIO_ResetBits(GPIOA,GPIO_Pin_0);//PA0下拉 23 24//初始化定時器5 TIM5 25TIM_TimeBaseStructure.TIM_Period = arr; //設定計數器自動重灌值 26TIM_TimeBaseStructure.TIM_Prescaler =psc;//預分頻器 27TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設定時鐘分割:TDTS = Tck_tim 28TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上計數模式 29TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的引數初始化TIMx的時間基數單位 30 31//初始化TIM5輸入捕獲引數 32TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01選擇輸入端 IC1對映到TI1上 33TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕獲 34TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //對映到TI1上 35TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置輸入分頻,不分頻 36TIM2_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 37TIM_ICInit(TIM2, &TIM2_ICInitStructure); 38 39//中斷分組初始化 40NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//TIM3中斷 41NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//先佔優先順序2級 42NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//從優先順序0級 43NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 44NVIC_Init(&NVIC_InitStructure);//根據NVIC_InitStruct中指定的引數初始化外設NVIC暫存器 45//printf("***********************************\r\n"); 46TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷 47 48TIM_Cmd(TIM2,ENABLE );//使能定時器5 49 50 51 52 } 53 54 u8TIM2CH1_CAPTURE_STA=0;//輸入捕獲狀態 55 u16 TIM2CH1_CAPTURE_VAL;//輸入捕獲值 56 57 //定時器5中斷服務程式 58 void TIM2_IRQHandler(void) 59 { 60//printf("********************222222***************\r\n"); 61if((TIM2CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲 62{ 63if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) 64 65{ 66if(TIM2CH1_CAPTURE_STA&0X40)//已經捕獲到高電平了 67{ 68if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 69{ 70TIM2CH1_CAPTURE_STA|=0X80;//標記成功捕獲了一次 71TIM2CH1_CAPTURE_VAL=0XFFFF; 72}else TIM2CH1_CAPTURE_STA++; 73} 74} 75if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕獲1發生捕獲事件 76{ 77if(TIM2CH1_CAPTURE_STA&0X40)//捕獲到一個下降沿 78{ 79TIM2CH1_CAPTURE_STA|=0X80;//標記成功捕獲到一次高電平脈寬 80TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2); 81TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC1P=0 設定為上升沿捕獲 82}else//還未開始,第一次捕獲上升沿 83{ 84TIM2CH1_CAPTURE_STA=0;//清空 85TIM2CH1_CAPTURE_VAL=0; 86TIM_SetCounter(TIM2,0); 87TIM2CH1_CAPTURE_STA|=0X40;//標記捕獲到了上升沿 88TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);//CC1P=1 設定為下降沿捕獲 89} 90} 91} 92 93TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中斷標誌位 94 95 }
定時器1通道4實現:
1 #include"timex.h" 2 #include "usart.h" 3 4 5 6 TIM_ICInitTypeDefTIM1_ICInitStructure; 7 8 void TIM1_Cap_Init(u16 arr,u16 psc) 9 { 10 11GPIO_InitTypeDef GPIO_InitStructure; 12TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; 13NVIC_InitTypeDef NVIC_InitStructure; 14printf("---time 111114444 ---\r\n"); 15RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//使能時鐘 16RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 17 18GPIO_InitStructure.GPIO_Pin= GPIO_Pin_8|GPIO_Pin_11;//清除之前設定 19GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 輸入 20GPIO_Init(GPIOA, &GPIO_InitStructure); 21GPIO_ResetBits(GPIOA,GPIO_Pin_8|GPIO_Pin_11);//下拉 22 23//初始化定時器1 24TIM_TimeBaseStructure.TIM_Period = arr; //設定計數器自動重灌值 25TIM_TimeBaseStructure.TIM_Prescaler =psc;//預分頻器 26TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設定時鐘分割:TDTS = Tck_tim 27TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上計數模式 28TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的引數初始化TIMx的時間基數單位 29 30//初始化TIM1 31TIM1_ICInitStructure.TIM_Channel = TIM_Channel_4; //CC1S=01選擇輸入端 IC1對映到TI1上 32TIM1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕獲 33TIM1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //對映到TI1上 34TIM1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置輸入分頻,不分頻 35TIM1_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 36TIM_ICInit(TIM1, &TIM1_ICInitStructure); 37 38//中斷分組初始化 39// Device header 40NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;//中斷 41NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//先佔優先順序2級 42NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//從優先順序0級 43NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 44NVIC_Init(&NVIC_InitStructure);//根據NVIC_InitStruct中指定的引數初始化外設NVIC暫存器 45 46TIM_ITConfig(TIM1,TIM_IT_CC4|TIM_IT_Update,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷 47 48TIM_Cmd(TIM1,ENABLE );//使能定時器1 49 50 } 51 52 53u8TIM1CH4_CAPTURE_STA=0;//輸入捕獲狀態 54 intTIM1CH4_CAPTURE_VAL_0,TIM1CH4_CAPTURE_VAL;//輸入捕獲值 55 //定時器5中斷服務程式 56 void TIM1_UP_IRQHandler(void) 57 { 58 59if((TIM1CH4_CAPTURE_STA&0X80)==0)//還未成功捕獲 60{ 61if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) 62 63{ 64if(TIM1CH4_CAPTURE_STA&0X40)//已經捕獲到高電平了 65{ 66if((TIM1CH4_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 67{ 68TIM1CH4_CAPTURE_STA|=0X80;//標記成功捕獲了一次 69TIM1CH4_CAPTURE_VAL=0XFFFF; 70}else TIM1CH4_CAPTURE_STA++; 71} 72} 73} 74 75TIM_ClearITPendingBit(TIM1, TIM_IT_Update); //清除中斷標誌位 76 77 78 79 } 80 void TIM1_CC_IRQHandler(void) 81 { 82if((TIM1CH4_CAPTURE_STA&0X80)==0)//還未成功捕獲 83{ 84if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET)//捕獲1發生捕獲事件 85{ 86if(TIM1CH4_CAPTURE_STA&0X40)//捕獲到一個下降沿 87{ 88TIM1CH4_CAPTURE_STA|=0X80;//標記成功捕獲到一次上升沿 89TIM1CH4_CAPTURE_VAL=TIM_GetCapture4(TIM1)-TIM1CH4_CAPTURE_VAL_0; 90TIM_OC4PolarityConfig(TIM1,TIM_ICPolarity_Rising); //CC1P=0 設定為上升沿捕獲 91}else//還未開始,第一次捕獲上升沿 92{ 93TIM1CH4_CAPTURE_STA=0;//清空 94TIM1CH4_CAPTURE_VAL_0=TIM_GetCapture4(TIM1);//!!!!!!!!!!!!!!!!!!!!!!! 95//TIM_SetCounter(TIM1,0); 96TIM1CH4_CAPTURE_STA|=0X40;//標記捕獲到了上升沿 97TIM_OC4PolarityConfig(TIM1,TIM_ICPolarity_Falling);//CC1P=1 設定為下降沿捕獲 98} 99} 100} 101 102TIM_ClearITPendingBit(TIM1, TIM_IT_CC1); //清除中斷標誌位 103 104 }
定時器3通道2程式碼實現:
1#include"timex.h" 2#include "usart.h" 3 4 //定時器3通道1輸入捕獲配置 5 6 TIM_ICInitTypeDefTIM3_ICInitStructure; 7 TIM_ICInitTypeDefTIM3_ICInitStructure1; 8 void TIM3_Cap_Init(u16 arr,u16 psc) 9 { 10 11GPIO_InitTypeDef GPIO_InitStructure; 12TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; 13NVIC_InitTypeDef NVIC_InitStructure; 14 15printf("---time 333332222 ---\r\n"); 16RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能時鐘 17RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 18 19GPIO_InitStructure.GPIO_Pin= GPIO_Pin_6|GPIO_Pin_7;//清除之前設定 20GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //輸入 21GPIO_Init(GPIOA, &GPIO_InitStructure); 22GPIO_ResetBits(GPIOA,GPIO_Pin_6 | GPIO_Pin_7);//下拉 23 24//初始化定時器5 TIM5 25TIM_TimeBaseStructure.TIM_Period = arr; //設定計數器自動重灌值 26TIM_TimeBaseStructure.TIM_Prescaler =psc;//預分頻器 27TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設定時鐘分割:TDTS = Tck_tim 28TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上計數模式 29TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的引數初始化TIMx的時間基數單位 30 31//初始化TIM5輸入捕獲引數 32TIM3_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01選擇輸入端 IC1對映到TI1上 33TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕獲 34TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //對映到TI1上 35TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置輸入分頻,不分頻 36TIM3_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 37TIM_ICInit(TIM3, &TIM3_ICInitStructure); 38 39//初始化TIM5輸入捕獲引數 40TIM3_ICInitStructure1.TIM_Channel = TIM_Channel_2; //CC1S=01選擇輸入端 IC1對映到TI1上 41TIM3_ICInitStructure1.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕獲 42TIM3_ICInitStructure1.TIM_ICSelection = TIM_ICSelection_DirectTI; //對映到TI2上!!!!!!!!!!!!!!!!!!! 43TIM3_ICInitStructure1.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置輸入分頻,不分頻 44TIM3_ICInitStructure1.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 45TIM_ICInit(TIM3, &TIM3_ICInitStructure1); 46 47 48 49 50//中斷分組初始化 51NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;//TIM3中斷 52NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//先佔優先順序2級 53NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//從優先順序0級 54NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 55NVIC_Init(&NVIC_InitStructure);//根據NVIC_InitStruct中指定的引數初始化外設NVIC暫存器 56//printf("***********************************\r\n"); 57TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC2,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷 58 59TIM_Cmd(TIM3,ENABLE );//使能定時器5 60 61 62 63 } 64 65 u8TIM3CH1_CAPTURE_STA=0;//輸入捕獲狀態 66 u16TIM3CH1_CAPTURE_VAL;//輸入捕獲值 67 68 u8TIM3CH2_CAPTURE_STA=0;//輸入捕獲狀態 69 u16TIM3CH2_CAPTURE_VAL;//輸入捕獲值 70 71void TIM3_IRQHandler(void) 72 { 73//printf("********************222222***************\r\n"); 74 75if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) 76 77{ 78if((TIM3CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲 79{ 80if(TIM3CH1_CAPTURE_STA&0X40)//已經捕獲到高電平了 81{ 82if((TIM3CH1_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 83{ 84 85TIM3CH1_CAPTURE_VAL=0XFFFF; 86TIM3CH1_CAPTURE_STA|=0X80;//標記成功捕獲了一次 87}else TIM3CH1_CAPTURE_STA++; 88} 89} 90 91 92if((TIM3CH2_CAPTURE_STA&0X80)==0)//還未成功捕獲 93{ 94if(TIM3CH2_CAPTURE_STA&0X40)//已經捕獲到高電平了 95{ 96if((TIM3CH2_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 97{ 98 99TIM3CH2_CAPTURE_VAL=0XFFFF; 100TIM3CH2_CAPTURE_STA|=0X80;//標記成功捕獲了一次 101}else TIM3CH2_CAPTURE_STA++; 102} 103 104} 105}else{ 106 107 108 109 110if((TIM3CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲 111 { 112if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)//捕獲1發生捕獲事件 113{ 114 115if(TIM3CH1_CAPTURE_STA&0X40)//捕獲到一個下降沿 116{ 117TIM3CH1_CAPTURE_STA|=0X80;//標記成功捕獲到一次高電平脈寬 118TIM3CH1_CAPTURE_VAL=TIM_GetCapture1(TIM3); 119TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Rising); //CC1P=0 設定為上升沿捕獲 120}else//還未開始,第一次捕獲上升沿 121{ 122TIM3CH1_CAPTURE_STA=0;//清空 123TIM3CH1_CAPTURE_VAL=0; 124TIM_SetCounter(TIM3,0); 125 126TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Falling);//CC1P=1 設定為下降沿捕獲 127TIM3CH1_CAPTURE_STA|=0X40;//標記捕獲到了上升沿 128} 129} 130} 131 132 133 134 135 if((TIM3CH2_CAPTURE_STA&0X80)==0)//還未成功捕獲 136{ 137if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)//捕獲1發生捕獲事件 138{ 139if(TIM3CH2_CAPTURE_STA&0X40)//捕獲到一個下降沿 140{ 141TIM3CH2_CAPTURE_STA|=0X80;//標記成功捕獲到一次高電平脈寬 142TIM3CH2_CAPTURE_VAL=TIM_GetCapture2(TIM3); 143TIM_OC2PolarityConfig(TIM3,TIM_ICPolarity_Rising); //CC1P=0 設定為上升沿捕獲 144}else//還未開始,第一次捕獲上升沿 145{ 146TIM3CH2_CAPTURE_STA=0;//清空 147TIM3CH2_CAPTURE_VAL=0; 148TIM_SetCounter(TIM3,0); 149 150TIM_OC2PolarityConfig(TIM3,TIM_ICPolarity_Falling);//CC1P=1 設定為下降沿捕獲 151TIM3CH2_CAPTURE_STA|=0X40;//標記捕獲到了上升沿 152} 153} 154 155}} 156 //TIM_SetCounter(TIM3,0); 157TIM_ClearITPendingBit(TIM3, TIM_IT_CC1|TIM_IT_Update|TIM_IT_CC2); //清除中斷標誌位 158 159 }
定時器4通道1程式碼實現:
1 #include"timex.h" 2 #include "usart.h" 3 4 //定時器4通道1輸入捕獲配置 5 6 TIM_ICInitTypeDefTIM4_ICInitStructure; 7 8 void TIM4_Cap_Init(u16 arr,u16 psc) 9 { 10 11 12GPIO_InitTypeDef GPIO_InitStructure; 13TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; 14NVIC_InitTypeDef NVIC_InitStructure; 15printf("---time 444441111 ---\r\n"); 16RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能TIM4時鐘 17RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能GPIOB時鐘 18 19GPIO_InitStructure.GPIO_Pin= GPIO_Pin_6;//清除之前設定 20GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //輸入 21GPIO_Init(GPIOB, &GPIO_InitStructure); 22GPIO_ResetBits(GPIOB,GPIO_Pin_6);// 下拉 23 24//初始化定時器5 TIM5 25TIM_TimeBaseStructure.TIM_Period = arr; //設定計數器自動重灌值 26TIM_TimeBaseStructure.TIM_Prescaler =psc;//預分頻器 27TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設定時鐘分割:TDTS = Tck_tim 28TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上計數模式 29TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的引數初始化TIMx的時間基數單位 30 31//初始化TIM5輸入捕獲引數 32TIM4_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01選擇輸入端 IC1對映到TI1上 33TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕獲 34TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //對映到TI1上 35TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置輸入分頻,不分頻 36TIM4_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 37TIM_ICInit(TIM4, &TIM4_ICInitStructure); 38 39//中斷分組初始化 40NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;//TIM3中斷 41NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//先佔優先順序2級 42NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//從優先順序0級 43NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 44NVIC_Init(&NVIC_InitStructure);//根據NVIC_InitStruct中指定的引數初始化外設NVIC暫存器 45//printf("***********************************\r\n"); 46TIM_ITConfig(TIM4,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷 47 48TIM_Cmd(TIM4,ENABLE );//使能定時器5 49 50 51 52 } 53 54 u8TIM4CH1_CAPTURE_STA=0;//輸入捕獲狀態 55 u16TIM4CH1_CAPTURE_VAL;//輸入捕獲值 56 57 //定時器5中斷服務程式 58 void TIM4_IRQHandler(void) 59 { 60//printf("********************222222***************\r\n"); 61if((TIM4CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲 62{ 63if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) 64 65{ 66if(TIM4CH1_CAPTURE_STA&0X40)//已經捕獲到高電平了 67{ 68if((TIM4CH1_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 69{ 70TIM4CH1_CAPTURE_STA|=0X80;//標記成功捕獲了一次 71TIM4CH1_CAPTURE_VAL=0XFFFF; 72}else TIM4CH1_CAPTURE_STA++; 73} 74} 75if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET)//捕獲1發生捕獲事件 76{ 77if(TIM4CH1_CAPTURE_STA&0X40)//捕獲到一個下降沿 78{ 79TIM4CH1_CAPTURE_STA|=0X80;//標記成功捕獲到一次高電平脈寬 80TIM4CH1_CAPTURE_VAL=TIM_GetCapture1(TIM4); 81TIM_OC1PolarityConfig(TIM4,TIM_ICPolarity_Rising); //CC1P=0 設定為上升沿捕獲 82}else//還未開始,第一次捕獲上升沿 83{ 84TIM4CH1_CAPTURE_STA=0;//清空 85TIM4CH1_CAPTURE_VAL=0; 86TIM_SetCounter(TIM4,0); 87TIM4CH1_CAPTURE_STA|=0X40;//標記捕獲到了上升沿 88TIM_OC1PolarityConfig(TIM4,TIM_ICPolarity_Falling);//CC1P=1 設定為下降沿捕獲 89} 90} 91} 92 93TIM_ClearITPendingBit(TIM4, TIM_IT_CC1|TIM_IT_Update); //清除中斷標誌位 94 95 }