高中生
最后登录1970-1-1
在线时间 小时
注册时间2021-9-25
|
#include "hc_sr04.h"
#include "bsp_systick.h"
#include "usart.h"
int count;
#define TRIG_PORT GPIOB //定义TRIG_PORT为PB
#define ECHO_PORT GPIOB //定义ECHO_PORT为PB
#define TRIG_PIN GPIO_Pin_3 //定义TRIG 对应IO口 PB0
#define ECHO_PIN GPIO_Pin_4 //定义ECHO 对应IO口 PB1
//仿原子延时,不进入systic中断
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD = 9*nus;
SysTick->VAL=0X00;//清空计数器
SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
do
{
temp=SysTick->CTRL;//读取当前倒计数值
}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD = 9000*nms;
SysTick->VAL=0X00;//清空计数器
SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
do
{
temp=SysTick->CTRL;//读取当前倒计数值
}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
/**
* @brief 用于定时计算高电平时间
* @param 无 将定时器6设置为1us记一次数,3000us=3ms一个周期 再测量范围内能满足要求
* @retval 无
*/
static void TIM6_Counter(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructer;
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM6,ENABLE); //打开定时器时钟
TIM_TimeBaseInitStructer.TIM_ClockDivision=TIM_CKD_DIV1 ;
TIM_TimeBaseInitStructer .TIM_Prescaler=71;
TIM_TimeBaseInitStructer.TIM_Period=3000;
TIM_TimeBaseInit (TIM6,&TIM_TimeBaseInitStructer );
TIM_Cmd (TIM6,DISABLE );//先关闭定时器,计算距离时再打开
}
/*
* 函数名:UltrasonicWave_Configuration
* 描述 :超声波模块的初始化
*/
void UltrasonicWave_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructer;//定义相关初始化的结构体
EXTI_InitTypeDef EXTI_InitStructer;
NVIC_InitTypeDef NVIC_InitStructer;
//打开外部中断需要使能AFIO时钟
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO ,ENABLE);//打开相应的时钟
//配置相关引脚
GPIO_InitStructer.GPIO_Pin = TRIG_PIN;//超声波触发引脚
GPIO_InitStructer.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructer.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_ResetBits(TRIG_PORT,TRIG_PIN);//先暂时复位超声波触发引脚,防止误发
GPIO_Init(TRIG_PORT,&GPIO_InitStructer);
GPIO_InitStructer.GPIO_Pin = ECHO_PIN;//回收高电平引脚
GPIO_InitStructer.GPIO_Mode = GPIO_Mode_IPD;//输入模式
GPIO_Init(ECHO_PORT,&GPIO_InitStructer);
GPIO_ResetBits(ECHO_PORT,ECHO_PIN);
//对中断进行相关的配置
NVIC_PriorityGroupConfig (NVIC_PriorityGroup_1 );
NVIC_InitStructer .NVIC_IRQChannel = EXTI4_IRQn ;
NVIC_InitStructer .NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructer .NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructer .NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructer );//初始化NVIC
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource4);//进行中断线以及中断初始化配置
EXTI_InitStructer .EXTI_Line = EXTI_Line4 ;//选择中断/事件线
EXTI_InitStructer .EXTI_Mode = EXTI_Mode_Interrupt ;//配置为中断模式
EXTI_InitStructer .EXTI_Trigger = EXTI_Trigger_Rising ;//上升沿触发
EXTI_InitStructer .EXTI_LineCmd = ENABLE;//使能外部中断
EXTI_Init (&EXTI_InitStructer );//外部中断初始化
}
/**
* @brief 开始测距,发送一个>10us的脉冲,然后测量返回的高电平时间
* @param 无
* @retval 无
*/
void UltrasonicWave_StartMeasure(void)
{
GPIO_SetBits(TRIG_PORT,TRIG_PIN); //送一个>10US的高电平
delay_us(17); //延时11US
GPIO_ResetBits(TRIG_PORT,TRIG_PIN);
}
/**
* @brief 中断处理服务函数,计算高电平持续的时间,从而计算距离
* @param 无
* @retval 无
*/
void EXTI1_IRQnHeader(void)
{
if(EXTI_GetITStatus (EXTI_Line4 )!=RESET )//如果EXTI的中断挂起,存在外部中断
{
TIM_SetCounter (TIM1 ,0 );
TIM_Cmd(TIM1, ENABLE); //开启时钟 Tim1
count=1;
while(count)//等待低电平
{
if(TIM_GetCounter (TIM1)>=10)//等待超时
{
TIM_Cmd(TIM1, DISABLE); // 关闭时钟 Tim6
count=0; // 循环数清零
}
else count=GPIO_ReadInputDataBit(ECHO_PORT,ECHO_PIN );//读取电平状态,一旦变成低电平就退出循环
}
TIM_Cmd (TIM1,DISABLE );
}
EXTI_ClearITPendingBit (EXTI_Line4 );//清除线中断
}
/**
* @brief 超声波模块计算距离
* @param 无
* @retval 返回计算得到的数据
*/
float HCSR04_GetDisatnce(void)
{
float distance;
distance=TIM_GetCounter(TIM1)*5*34/200.0;//计算出来的单位为cm
if(distance>=450)//超出测量范围
{
printf("it is erro");
}
return distance;
}
|
|