我们是基于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; //开启下一次捕获
}
}
}
ultrasonic.c
#include "ultrasonic.h"
#include "sys.h"
void ultrasonic_Init(void){
RCC->APB2ENR |= 1<<2;
GPIOA->CRL &= 0xfff0ffff;
GPIOA->CRL |= 0X00030000;
}
ultrasonic.h
#ifndef __ULTRASONIC_H
#define __ULTRASONIC_H
#include "sys.h"
#define ULTRASONIC_TRIG PAout(4)
void ultrasonic_Init(void);
#endif
timer.c
#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; //清空中断标志位
}
timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
void TIM2_Cap_Init(u16 arr,u16 psc);
#endif
验证效果:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)