1.初始化IO口
void HC_SR04Init(void){
GPIO_InitTypeDef GPIOInit;
TIM_TimeBaseInitTypeDef TIMInit;
NVIC_InitTypeDef NVICInit;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//负责发送高电平PB11
GPIOInit.GPIO_Mode = GPIO_Mode_Out_PP;
GPIOInit.GPIO_Pin = GPIO_Pin_11;
GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIOInit);
//接收引脚
GPIOInit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIOInit.GPIO_Pin = GPIO_Pin_10;
GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIOInit);
TIMInit.TIM_ClockDivision =TIM_CKD_DIV1;//TIM_ClockDivision来设置时钟分割(时钟分频因子),此处不分频
TIMInit.TIM_CounterMode =TIM_CounterMode_Up;
TIMInit.TIM_Prescaler =72-1;
TIMInit.TIM_Period =1000;
TIM_TimeBaseInit(TIM4,&TIMInit);
TIM_Cmd(TIM4,DISABLE);//等检测到低电平再打开
TIM_ITConfig(TIM4,TIM_IT_Update, ENABLE);
NVICInit.NVIC_IRQChannel = TIM4_IRQn;
NVICInit.NVIC_IRQChannelCmd =ENABLE;
NVICInit.NVIC_IRQChannelPreemptionPriority =0;
NVICInit.NVIC_IRQChannelSubPriority =0;
NVIC_Init(&NVICInit);
}
TIM_Period:
定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为 0 至 65535。根据定时器时钟的频率,比如时钟的频率是72MHZ,可以理解为一秒钟STM32会自己数72M次,预分频系数就是将频率分割,比如分频系数是72,则该时钟的频率会变成72MHZ/72=1MHZ,但是在设置的时候要注意,数值应该是72-1。
假定分频系数是72-1,那么频率变成1MHZ,也就意味着STM32在一秒钟会数1M次,即1us数一次。
好了,接下来就是确定预装载值,比如需要定时1ms,由于1ms=1us*1000,那么预装载值就是1000-1;如此类推,在预分频系数确定的情况下,定时的时长就由预装载值确定了。至于要把值减一的原因,估计是计数是从0开始,所以要减一。
2.打开和关闭定时器
void Open_tim4(void){
TIM_SetCounter(TIM4,0);
mscount=0;
TIM_Cmd(TIM4,ENABLE);
}
void Close_tim4(void){
TIM_Cmd(TIM4,DISABLE);
}
3.定时器中断
void TIM4_IRQHandler(void){
if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET){
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
mscount++;
}
}
//检测到中断位出现,执行清楚中断位,并+1
4.得到超声波时间
int GetEcho_time(void){
uint32_t t=0;
t=mscount*1000;
t+=TIM_GetCounter(TIM4);
TIM4->CNT=0;
delay_ms(50);
return t;
}
//乘1000是因为计数周期为Tout = ((arr+1)*(psc+1))/Tclk ;根据公式T=(72)*(1000)/72MHz=1ms
//所以在所有完整周期内计数次数为mscount*1000,在未完成一次周期内计数值IM_GetCounter(TIM4);
//读取后清空CNT的值 TIM4->CNT=0;
5.计算距离
float Getlenth(void){
int i=0;
uint32_t t=0;
float len=0;
float sum=0;
while(i!=5){
TRIG_Send(1);
delay_us(20);
TRIG_Send(0);
while(ECHO_Rec1==0);//等待高电平过来
Open_tim4();
while(ECHO_Rec1==1);//等待低电平过来
Close_tim4();//关闭后CNT的值才读取才准确
i=i+1;
t=GetEcho_time();
len=((float)t/58.0);
sum=sum+len;
}
len=sum/5.0;
return len;
}
//为什么除58?声速正常速度为343m/s,34300/100000cm/us也即是0.0343cm/us,其倒数从单位us/cm,换算
//后得29.15us/cm,意味着291.5us表示10cm的距离,1cm就是29.15us,发送后接收,声音走过两倍距离,实际
//就是1cm,对应58.3us,lenth实际上就是us换算成距离,除以58.3,58和58.3差距不大
6.main的内容
HC_SR04Init();
len=Getlenth();
printf("%.3f\r\n",len);
7.所有内容
#include "stm32f10x.h"
#include "HC_SR04.h"
#include "system.h"
extern uint16_t mscount=0;
void HC_SR04Init(void){
GPIO_InitTypeDef GPIOInit;
TIM_TimeBaseInitTypeDef TIMInit;
NVIC_InitTypeDef NVICInit;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//·¢Ë͸ߵçƽpb11
GPIOInit.GPIO_Mode = GPIO_Mode_Out_PP;
GPIOInit.GPIO_Pin = GPIO_Pin_11;
GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIOInit);
//½ÓÊÜÒý½Å
GPIOInit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIOInit.GPIO_Pin = GPIO_Pin_10;
GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIOInit);
TIMInit.TIM_ClockDivision =TIM_CKD_DIV1;
TIMInit.TIM_CounterMode =TIM_CounterMode_Up;
TIMInit.TIM_Prescaler =72-1;
TIMInit.TIM_Period =1000;
TIM_TimeBaseInit(TIM4,&TIMInit);
TIM_Cmd(TIM4,DISABLE);
TIM_ITConfig(TIM4,TIM_IT_Update, ENABLE);
NVICInit.NVIC_IRQChannel = TIM4_IRQn;
NVICInit.NVIC_IRQChannelCmd =ENABLE;
NVICInit.NVIC_IRQChannelPreemptionPriority =0;
NVICInit.NVIC_IRQChannelSubPriority =0;
NVIC_Init(&NVICInit);
}
void Open_tim4(void){
TIM_SetCounter(TIM4,0);
mscount=0;
TIM_Cmd(TIM4,ENABLE);
}
void Close_tim4(void){
TIM_Cmd(TIM4,DISABLE);
}
void TIM4_IRQHandler(void){
if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET){
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
mscount++;
}
}
int GetEcho_time(void){
uint32_t t=0;
t=mscount*1000;
t+=TIM_GetCounter(TIM4);
TIM4->CNT=0;
delay_ms(50);
return t;
}
float Getlenth(void){
int i=0;
uint32_t t=0;
float len=0;
float sum=0;
while(i!=5){
TRIG_Send(1);
delay_us(20);
TRIG_Send(0);
while(ECHO_Rec1==0);
Open_tim4();
while(ECHO_Rec1==1);
Close_tim4();
i=i+1;
t=GetEcho_time();
len=((float)t/58.0);
sum=sum+len;
}
len=sum/5.0;
return len;
}
7.头文件
#ifndef __HC_SRO4_H
#define __HC_SRO4_H
#include "stm32f10x.h"
void HC_SR04Init(void);
void Open_tim4(void);
void Close_tim4(void);
int GetEcho_time(void);
float Getlenth(void);
#define ECHO_Rec1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)
#define TRIG_Send(a) if(a)\
GPIO_SetBits(GPIOB,GPIO_Pin_11);\
else\
GPIO_ResetBits(GPIOB,GPIO_Pin_11)
#endif