我们是基于stm32f103系列,超声波模块用的是:HC-SR04(寄存器版的代码)
编译器用的是:keil5
在此:输入捕获用的是TIM2_CH1(用的是PA0,可以从开发板原理图中看到)
由于本文只是简单的介绍超声波测距,并不涉及其他东西,所以没有加载按键,led灯程序
test.c文件(主函数所存在的地方)
timer.c文件(输入捕获初始化的地方)
ultrasonic.c文件(超声波模块初始化)
test.c
#include "sys.h" #include "usart.h" #include "delay.h" #include "timer.h" #include "ultrasonic.h" extern u8 TIM2CH1_CAPTURE_STA; //输入捕获状态 extern u16 TIM2CH1_CAPTURE_VAL; //输入捕获值 int main(void) { u32 temp=0; Stm32_Clock_Init(9); //系统时钟设置 uart_init(72,9600); //串口初始化为0 delay_init(72); //延时初始化 ultrasonic_Init(); TIM2_Cap_Init(0XFFFF,72-1); //以1Mhz的频率计数 while(1) { PAout(4)=1; delay_us(15); PAout(4)=0; if(TIM2CH1_CAPTURE_STA&0X80) //成功捕获到了一次高电平 { temp=TIM2CH1_CAPTURE_STA&0X3F; temp*=65536; //溢出时间总和 temp+=TIM2CH1_CAPTURE_VAL; //得到总的高电平的时间 temp=temp*170/10000; printf("Distance:%d cm\r\n",temp);//打印总的高电平的时间,也就是转换后的高度了 TIM2CH1_CAPTURE_STA=0; //开启下一次捕获 } } }
#include "ultrasonic.h" #include "sys.h" void ultrasonic_Init(void){ RCC->APB2ENR |= 1<<2; GPIOA->CRL &= 0xfff0ffff; GPIOA->CRL |= 0X00030000; }
#ifndef __ULTRASONIC_H #define __ULTRASONIC_H #include "sys.h" #define ULTRASONIC_TRIG PAout(4) void ultrasonic_Init(void); #endif
#include "timer.h" #include "led.h" //定时器2通道1输入捕获配置 //arr:自动重装载值 //psc:时钟分频数 void TIM2_Cap_Init(u16 arr,u16 psc) { RCC->APB1ENR|=1<<0; //TIM2时钟使能 RCC->APB2ENR|=1<<2; //使能A时钟 GPIOA->CRL&=0XFFFFFFF0; GPIOA->CRL|=0X00000008; GPIOA->ODR|=0<<0; TIM2->ARR=arr; //设定计数器自动装载值 TIM2->PSC=psc; //设定预分频数 TIM2->CCMR1|=1<<0; //CC1S=01选择输入端,IC1映射到TI1上 TIM2->CCMR1|=1<<4; //IC1F=0001 配置输入滤波器,以Fck_int采样,2个事件后有效 TIM2->CCMR1|=0<<10; //IC2PS=00 配置输入分频,不分频 TIM2->CCER|=0<<1; //CC1P=0 上升沿捕获 TIM2->CCER|=1<<0; //CC1E=1 允许捕获计数器的值到捕获寄存器中 TIM2->DIER|=1<<1; //允许捕获中断 TIM2->DIER|=1<<0; //允许更新中断 TIM2->CR1|=0x01; //使能计数器2 MY_NVIC_Init(2,0,TIM2_IRQn,2);//抢占2,子优先级0,组2 } //捕获状态2个全局变量 //[7]:0,没有成功捕获,1,成功捕获一次 //[6]:0,还没有捕获到高电平,1,已经捕获到高电平了 //[5:0]:捕获高电平后的溢出次数 u8 TIM2CH1_CAPTURE_STA=0;//输入捕获状态 u16 TIM2CH1_CAPTURE_VAL;//输入捕获值-用来记录捕获到下降沿时,TIM2_CNT的值 //定时器2中断服务程序 void TIM2_IRQHandler(void) { u16 tsr; tsr=TIM2->SR; if((TIM2CH1_CAPTURE_STA&0X80)==0)//还没有成功捕获 { if(tsr&0X01)//溢出 { if(TIM2CH1_CAPTURE_STA&0X40) //已经捕获到高电平了 { if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F) //高电平太长了 { TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获了一次 TIM2CH1_CAPTURE_VAL=0XFFFF; }else TIM2CH1_CAPTURE_STA++; } } if(tsr&0x02)//捕获1发生捕获事件 { if(TIM2CH1_CAPTURE_STA&0X40) //捕获到一个下降沿 { TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平的脉冲宽度 TIM2CH1_CAPTURE_VAL=TIM2->CCR1; //提取当前的捕获值 TIM2->CCER&=~(1<<1); //CC1P=0 设置为上升沿捕获 }else //还未开始,第一次捕获上升沿 { TIM2CH1_CAPTURE_VAL=0; TIM2CH1_CAPTURE_STA=0X40; //标记捕获到了上升沿 TIM2->CNT=0; //计数器清空 TIM2->CCER|=1<<1; //CC1P=1 设置为下降沿捕获 } } } TIM2->SR=0; //清空中断标志位 }
#ifndef __TIMER_H #define __TIMER_H #include "sys.h" void TIM2_Cap_Init(u16 arr,u16 psc); #endif