超聲波手勢識別在市場上已經有見實現,但研究其傳感器發現並不是市場上隨意可見的,如果暫且考慮成本,該如何入門實現簡單的手勢識別呢。聊天中老師給出一個很好的提議,就是固定四個超聲波,分別為上下左右,然后進行程序上的對應編號,用單片機實現四路超聲波的距離數據讀取,然后程序分析讀取的數據進而判斷手勢。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 u8 TIM3CH1_CAPTURE_STA; //輸入捕獲狀態 9 extern u16 TIM3CH1_CAPTURE_VAL; //輸入捕獲值 10 extern u8 TIM3CH2_CAPTURE_STA; //輸入捕獲狀態 11 extern u16 TIM3CH2_CAPTURE_VAL; //輸入捕獲值 12 extern u8 TIM2CH1_CAPTURE_STA; //輸入捕獲狀態 13 extern u16 TIM2CH1_CAPTURE_VAL; //輸入捕獲值 14 extern u8 TIM4CH1_CAPTURE_STA; //輸入捕獲狀態 15 extern u16 TIM4CH1_CAPTURE_VAL; //輸入捕獲值 16 extern u8 TIM1CH4_CAPTURE_STA; //輸入捕獲狀態 17 extern u16 TIM1CH4_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 { 55 temp1=TIM2CH1_CAPTURE_STA&0X3F; 56 temp1*=65536;//溢出時間總和 57 temp1+=TIM2CH1_CAPTURE_VAL;//得到總的高電平時間 58 printf("time2-----:%d \r\n",temp1);//打印總的高點平時間 59 TIM2CH1_CAPTURE_STA=0;//開啟下一次捕獲 60 PBout(12)=1; 61 delay_us(13); 62 PBout(12)=0; 63 } 64 65 //定時器1通道4 66 if(TIM1CH4_CAPTURE_STA&0X80)//成功捕獲到了一次上升沿 67 { 68 temp24=TIM1CH4_CAPTURE_STA&0X3F; 69 temp24*=65536;//溢出時間總和 70 temp24+=TIM1CH4_CAPTURE_VAL;//得到總的高電平時間 71 printf("time14-----:%d \r\n",temp24);//打印總的高點平時間 72 TIM1CH4_CAPTURE_STA=0;//開啟下一次捕獲 73 PBout(13)=1; 74 delay_us(13); 75 PBout(13)=0; 76 } 77 //定時器3通道2 78 if(TIM3CH2_CAPTURE_STA&0X80)//成功捕獲到了一次上升沿 79 { 80 temp3=TIM3CH2_CAPTURE_STA&0X3F; 81 temp3*=65536;//溢出時間總和 82 temp3+=TIM3CH2_CAPTURE_VAL;//得到總的高電平時間 83 printf("time32----:%d \r\n",temp3);//打印總的高點平時間 84 TIM3CH2_CAPTURE_STA=0;//開啟下一次捕獲 85 PBout(14)=1; 86 delay_us(13); 87 PBout(14)=0; 88 } 89 //定時器4通道1 90 if(TIM4CH1_CAPTURE_STA&0X80)//成功捕獲到了一次上升沿 91 { 92 temp4=TIM4CH1_CAPTURE_STA&0X3F; 93 temp4*=65536;//溢出時間總和 94 temp4+=TIM4CH1_CAPTURE_VAL;//得到總的高電平時間 95 printf("time4-----:%d \r\n",temp4);//打印總的高點平時間 96 TIM4CH1_CAPTURE_STA=0;//開啟下一次捕獲 97 PBout(15)=1; 98 delay_us(13); 99 PBout(15)=0; 100 } 101 102 //發送最終結果------------------------------------ 103 if((temp1 >0)&&(temp24 >0)&&(temp3 >0)&&(temp4 >0)){ 104 105 printf("[%d,%d,%d,%d]",temp1,temp24,temp3,temp4); 106 temp1=temp24=temp3=temp4=0; 107 PBout(0)=1; 108 } 109 110 } 111 }
定時器2通道1代碼實現:
1 #include"timex.h" 2 #include "usart.h" 3 4 //定時器3通道1輸入捕獲配置 5 6 TIM_ICInitTypeDef TIM2_ICInitStructure; 7 8 void TIM2_Cap_Init(u16 arr,u16 psc) 9 { 10 11 12 GPIO_InitTypeDef GPIO_InitStructure; 13 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 14 NVIC_InitTypeDef NVIC_InitStructure; 15 printf("---time 22222 1111 ---\r\n"); 16 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2時鍾 17 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA時鍾 18 19 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0清除之前設置 20 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 輸入 21 GPIO_Init(GPIOA, &GPIO_InitStructure); 22 GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0下拉 23 24 //初始化定時器5 TIM5 25 TIM_TimeBaseStructure.TIM_Period = arr; //設定計數器自動重裝值 26 TIM_TimeBaseStructure.TIM_Prescaler =psc; //預分頻器 27 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鍾分割:TDTS = Tck_tim 28 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式 29 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數單位 30 31 //初始化TIM5輸入捕獲參數 32 TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 選擇輸入端 IC1映射到TI1上 33 TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲 34 TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上 35 TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻 36 TIM2_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 37 TIM_ICInit(TIM2, &TIM2_ICInitStructure); 38 39 //中斷分組初始化 40 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM3中斷 41 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占優先級2級 42 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優先級0級 43 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 44 NVIC_Init(&NVIC_InitStructure); //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器 45 //printf("***********************************\r\n"); 46 TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷 47 48 TIM_Cmd(TIM2,ENABLE ); //使能定時器5 49 50 51 52 } 53 54 u8 TIM2CH1_CAPTURE_STA=0; //輸入捕獲狀態 55 u16 TIM2CH1_CAPTURE_VAL; //輸入捕獲值 56 57 //定時器5中斷服務程序 58 void TIM2_IRQHandler(void) 59 { 60 //printf("********************222222***************\r\n"); 61 if((TIM2CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲 62 { 63 if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) 64 65 { 66 if(TIM2CH1_CAPTURE_STA&0X40)//已經捕獲到高電平了 67 { 68 if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 69 { 70 TIM2CH1_CAPTURE_STA|=0X80;//標記成功捕獲了一次 71 TIM2CH1_CAPTURE_VAL=0XFFFF; 72 }else TIM2CH1_CAPTURE_STA++; 73 } 74 } 75 if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕獲1發生捕獲事件 76 { 77 if(TIM2CH1_CAPTURE_STA&0X40) //捕獲到一個下降沿 78 { 79 TIM2CH1_CAPTURE_STA|=0X80; //標記成功捕獲到一次高電平脈寬 80 TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2); 81 TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC1P=0 設置為上升沿捕獲 82 }else //還未開始,第一次捕獲上升沿 83 { 84 TIM2CH1_CAPTURE_STA=0; //清空 85 TIM2CH1_CAPTURE_VAL=0; 86 TIM_SetCounter(TIM2,0); 87 TIM2CH1_CAPTURE_STA|=0X40; //標記捕獲到了上升沿 88 TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling); //CC1P=1 設置為下降沿捕獲 89 } 90 } 91 } 92 93 TIM_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_ICInitTypeDef TIM1_ICInitStructure; 7 8 void TIM1_Cap_Init(u16 arr,u16 psc) 9 { 10 11 GPIO_InitTypeDef GPIO_InitStructure; 12 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 13 NVIC_InitTypeDef NVIC_InitStructure; 14 printf("---time 11111 4444 ---\r\n"); 15 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能時鍾 16 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 17 18 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11; //清除之前設置 19 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 輸入 20 GPIO_Init(GPIOA, &GPIO_InitStructure); 21 GPIO_ResetBits(GPIOA,GPIO_Pin_8|GPIO_Pin_11); //下拉 22 23 //初始化定時器1 24 TIM_TimeBaseStructure.TIM_Period = arr; //設定計數器自動重裝值 25 TIM_TimeBaseStructure.TIM_Prescaler =psc; //預分頻器 26 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鍾分割:TDTS = Tck_tim 27 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式 28 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數單位 29 30 //初始化TIM1 31 TIM1_ICInitStructure.TIM_Channel = TIM_Channel_4; //CC1S=01 選擇輸入端 IC1映射到TI1上 32 TIM1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲 33 TIM1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上 34 TIM1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻 35 TIM1_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 36 TIM_ICInit(TIM1, &TIM1_ICInitStructure); 37 38 //中斷分組初始化 39 // Device header 40 NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; //中斷 41 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占優先級2級 42 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優先級0級 43 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 44 NVIC_Init(&NVIC_InitStructure); //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器 45 46 TIM_ITConfig(TIM1,TIM_IT_CC4|TIM_IT_Update,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷 47 48 TIM_Cmd(TIM1,ENABLE ); //使能定時器1 49 50 } 51 52 53 u8 TIM1CH4_CAPTURE_STA=0; //輸入捕獲狀態 54 int TIM1CH4_CAPTURE_VAL_0,TIM1CH4_CAPTURE_VAL; //輸入捕獲值 55 //定時器5中斷服務程序 56 void TIM1_UP_IRQHandler(void) 57 { 58 59 if((TIM1CH4_CAPTURE_STA&0X80)==0)//還未成功捕獲 60 { 61 if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) 62 63 { 64 if(TIM1CH4_CAPTURE_STA&0X40)//已經捕獲到高電平了 65 { 66 if((TIM1CH4_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 67 { 68 TIM1CH4_CAPTURE_STA|=0X80;//標記成功捕獲了一次 69 TIM1CH4_CAPTURE_VAL=0XFFFF; 70 }else TIM1CH4_CAPTURE_STA++; 71 } 72 } 73 } 74 75 TIM_ClearITPendingBit(TIM1, TIM_IT_Update); //清除中斷標志位 76 77 78 79 } 80 void TIM1_CC_IRQHandler(void) 81 { 82 if((TIM1CH4_CAPTURE_STA&0X80)==0)//還未成功捕獲 83 { 84 if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET)//捕獲1發生捕獲事件 85 { 86 if(TIM1CH4_CAPTURE_STA&0X40) //捕獲到一個下降沿 87 { 88 TIM1CH4_CAPTURE_STA|=0X80; //標記成功捕獲到一次上升沿 89 TIM1CH4_CAPTURE_VAL=TIM_GetCapture4(TIM1)-TIM1CH4_CAPTURE_VAL_0; 90 TIM_OC4PolarityConfig(TIM1,TIM_ICPolarity_Rising); //CC1P=0 設置為上升沿捕獲 91 }else //還未開始,第一次捕獲上升沿 92 { 93 TIM1CH4_CAPTURE_STA=0; //清空 94 TIM1CH4_CAPTURE_VAL_0=TIM_GetCapture4(TIM1);//!!!!!!!!!!!!!!!!!!!!!!! 95 //TIM_SetCounter(TIM1,0); 96 TIM1CH4_CAPTURE_STA|=0X40; //標記捕獲到了上升沿 97 TIM_OC4PolarityConfig(TIM1,TIM_ICPolarity_Falling); //CC1P=1 設置為下降沿捕獲 98 } 99 } 100 } 101 102 TIM_ClearITPendingBit(TIM1, TIM_IT_CC1); //清除中斷標志位 103 104 }
定時器3通道2代碼實現:
1 #include"timex.h" 2 #include "usart.h" 3 4 //定時器3通道1輸入捕獲配置 5 6 TIM_ICInitTypeDef TIM3_ICInitStructure; 7 TIM_ICInitTypeDef TIM3_ICInitStructure1; 8 void TIM3_Cap_Init(u16 arr,u16 psc) 9 { 10 11 GPIO_InitTypeDef GPIO_InitStructure; 12 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 13 NVIC_InitTypeDef NVIC_InitStructure; 14 15 printf("---time 33333 2222 ---\r\n"); 16 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能時鍾 17 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 18 19 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //清除之前設置 20 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //輸入 21 GPIO_Init(GPIOA, &GPIO_InitStructure); 22 GPIO_ResetBits(GPIOA,GPIO_Pin_6 | GPIO_Pin_7); //下拉 23 24 //初始化定時器5 TIM5 25 TIM_TimeBaseStructure.TIM_Period = arr; //設定計數器自動重裝值 26 TIM_TimeBaseStructure.TIM_Prescaler =psc; //預分頻器 27 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鍾分割:TDTS = Tck_tim 28 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式 29 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數單位 30 31 //初始化TIM5輸入捕獲參數 32 TIM3_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 選擇輸入端 IC1映射到TI1上 33 TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲 34 TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上 35 TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻 36 TIM3_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 37 TIM_ICInit(TIM3, &TIM3_ICInitStructure); 38 39 //初始化TIM5輸入捕獲參數 40 TIM3_ICInitStructure1.TIM_Channel = TIM_Channel_2; //CC1S=01 選擇輸入端 IC1映射到TI1上 41 TIM3_ICInitStructure1.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲 42 TIM3_ICInitStructure1.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI2上!!!!!!!!!!!!!! !!!!! 43 TIM3_ICInitStructure1.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻 44 TIM3_ICInitStructure1.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 45 TIM_ICInit(TIM3, &TIM3_ICInitStructure1); 46 47 48 49 50 //中斷分組初始化 51 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷 52 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占優先級2級 53 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優先級0級 54 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 55 NVIC_Init(&NVIC_InitStructure); //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器 56 //printf("***********************************\r\n"); 57 TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC2,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷 58 59 TIM_Cmd(TIM3,ENABLE ); //使能定時器5 60 61 62 63 } 64 65 u8 TIM3CH1_CAPTURE_STA=0; //輸入捕獲狀態 66 u16 TIM3CH1_CAPTURE_VAL; //輸入捕獲值 67 68 u8 TIM3CH2_CAPTURE_STA=0; //輸入捕獲狀態 69 u16 TIM3CH2_CAPTURE_VAL; //輸入捕獲值 70 71 void TIM3_IRQHandler(void) 72 { 73 //printf("********************222222***************\r\n"); 74 75 if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) 76 77 { 78 if((TIM3CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲 79 { 80 if(TIM3CH1_CAPTURE_STA&0X40)//已經捕獲到高電平了 81 { 82 if((TIM3CH1_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 83 { 84 85 TIM3CH1_CAPTURE_VAL=0XFFFF; 86 TIM3CH1_CAPTURE_STA|=0X80;//標記成功捕獲了一次 87 }else TIM3CH1_CAPTURE_STA++; 88 } 89 } 90 91 92 if((TIM3CH2_CAPTURE_STA&0X80)==0)//還未成功捕獲 93 { 94 if(TIM3CH2_CAPTURE_STA&0X40)//已經捕獲到高電平了 95 { 96 if((TIM3CH2_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 97 { 98 99 TIM3CH2_CAPTURE_VAL=0XFFFF; 100 TIM3CH2_CAPTURE_STA|=0X80;//標記成功捕獲了一次 101 }else TIM3CH2_CAPTURE_STA++; 102 } 103 104 } 105 }else{ 106 107 108 109 110 if((TIM3CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲 111 { 112 if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)//捕獲1發生捕獲事件 113 { 114 115 if(TIM3CH1_CAPTURE_STA&0X40) //捕獲到一個下降沿 116 { 117 TIM3CH1_CAPTURE_STA|=0X80; //標記成功捕獲到一次高電平脈寬 118 TIM3CH1_CAPTURE_VAL=TIM_GetCapture1(TIM3); 119 TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Rising); //CC1P=0 設置為上升沿捕獲 120 }else //還未開始,第一次捕獲上升沿 121 { 122 TIM3CH1_CAPTURE_STA=0; //清空 123 TIM3CH1_CAPTURE_VAL=0; 124 TIM_SetCounter(TIM3,0); 125 126 TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Falling); //CC1P=1 設置為下降沿捕獲 127 TIM3CH1_CAPTURE_STA|=0X40; //標記捕獲到了上升沿 128 } 129 } 130 } 131 132 133 134 135 if((TIM3CH2_CAPTURE_STA&0X80)==0)//還未成功捕獲 136 { 137 if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)//捕獲1發生捕獲事件 138 { 139 if(TIM3CH2_CAPTURE_STA&0X40) //捕獲到一個下降沿 140 { 141 TIM3CH2_CAPTURE_STA|=0X80; //標記成功捕獲到一次高電平脈寬 142 TIM3CH2_CAPTURE_VAL=TIM_GetCapture2(TIM3); 143 TIM_OC2PolarityConfig(TIM3,TIM_ICPolarity_Rising); //CC1P=0 設置為上升沿捕獲 144 }else //還未開始,第一次捕獲上升沿 145 { 146 TIM3CH2_CAPTURE_STA=0; //清空 147 TIM3CH2_CAPTURE_VAL=0; 148 TIM_SetCounter(TIM3,0); 149 150 TIM_OC2PolarityConfig(TIM3,TIM_ICPolarity_Falling); //CC1P=1 設置為下降沿捕獲 151 TIM3CH2_CAPTURE_STA|=0X40; //標記捕獲到了上升沿 152 } 153 } 154 155 }} 156 // TIM_SetCounter(TIM3,0); 157 TIM_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_ICInitTypeDef TIM4_ICInitStructure; 7 8 void TIM4_Cap_Init(u16 arr,u16 psc) 9 { 10 11 12 GPIO_InitTypeDef GPIO_InitStructure; 13 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 14 NVIC_InitTypeDef NVIC_InitStructure; 15 printf("---time 44444 1111 ---\r\n"); 16 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能TIM4時鍾 17 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB時鍾 18 19 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //清除之前設置 20 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //輸入 21 GPIO_Init(GPIOB, &GPIO_InitStructure); 22 GPIO_ResetBits(GPIOB,GPIO_Pin_6); // 下拉 23 24 //初始化定時器5 TIM5 25 TIM_TimeBaseStructure.TIM_Period = arr; //設定計數器自動重裝值 26 TIM_TimeBaseStructure.TIM_Prescaler =psc; //預分頻器 27 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鍾分割:TDTS = Tck_tim 28 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式 29 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數單位 30 31 //初始化TIM5輸入捕獲參數 32 TIM4_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 選擇輸入端 IC1映射到TI1上 33 TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲 34 TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上 35 TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置輸入分頻,不分頻 36 TIM4_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波 37 TIM_ICInit(TIM4, &TIM4_ICInitStructure); 38 39 //中斷分組初始化 40 NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM3中斷 41 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占優先級2級 42 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優先級0級 43 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 44 NVIC_Init(&NVIC_InitStructure); //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器 45 //printf("***********************************\r\n"); 46 TIM_ITConfig(TIM4,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允許更新中斷 ,允許CC1IE捕獲中斷 47 48 TIM_Cmd(TIM4,ENABLE ); //使能定時器5 49 50 51 52 } 53 54 u8 TIM4CH1_CAPTURE_STA=0; //輸入捕獲狀態 55 u16 TIM4CH1_CAPTURE_VAL; //輸入捕獲值 56 57 //定時器5中斷服務程序 58 void TIM4_IRQHandler(void) 59 { 60 //printf("********************222222***************\r\n"); 61 if((TIM4CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲 62 { 63 if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) 64 65 { 66 if(TIM4CH1_CAPTURE_STA&0X40)//已經捕獲到高電平了 67 { 68 if((TIM4CH1_CAPTURE_STA&0X3F)==0X3F)//高電平太長了 69 { 70 TIM4CH1_CAPTURE_STA|=0X80;//標記成功捕獲了一次 71 TIM4CH1_CAPTURE_VAL=0XFFFF; 72 }else TIM4CH1_CAPTURE_STA++; 73 } 74 } 75 if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET)//捕獲1發生捕獲事件 76 { 77 if(TIM4CH1_CAPTURE_STA&0X40) //捕獲到一個下降沿 78 { 79 TIM4CH1_CAPTURE_STA|=0X80; //標記成功捕獲到一次高電平脈寬 80 TIM4CH1_CAPTURE_VAL=TIM_GetCapture1(TIM4); 81 TIM_OC1PolarityConfig(TIM4,TIM_ICPolarity_Rising); //CC1P=0 設置為上升沿捕獲 82 }else //還未開始,第一次捕獲上升沿 83 { 84 TIM4CH1_CAPTURE_STA=0; //清空 85 TIM4CH1_CAPTURE_VAL=0; 86 TIM_SetCounter(TIM4,0); 87 TIM4CH1_CAPTURE_STA|=0X40; //標記捕獲到了上升沿 88 TIM_OC1PolarityConfig(TIM4,TIM_ICPolarity_Falling); //CC1P=1 設置為下降沿捕獲 89 } 90 } 91 } 92 93 TIM_ClearITPendingBit(TIM4, TIM_IT_CC1|TIM_IT_Update); //清除中斷標志位 94 95 }