STM32+超声波

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

 

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值