历史上的今天
返回首页

历史上的今天

今天是:2024年09月13日(星期五)

正在发生

2021年09月13日 | STM32f407驱动hc-sr04超声波测距模块

2021-09-13 来源:eefocus

最近完了一下测距模块,本想挺简单的一个东西,却折腾了好长时间。总算弄好了,贴到这里和大家分享一下!


HC-SR04超声波测距模块是一种被用烂了的传感器,它的优点是成本低,控制容易,但是掌握不好时序,还是会弄的人一头雾水。


本模块用使用方法如下:


一.  5v直流电压供电,一般的单片机上自带的VCC都能驱动


二.  Trig引脚收到来自单片机时长大于等于20us的高点品后发出超声波


三.  Echo引脚接收Trig引脚发出的超声波的回波,并且单片机开启定时器记录高电平时间


四. 高电平结束后,关闭定时器,从定时器寄存器中取出记录值,换算成距离即可。


在做的过程中注意:


网上有好多代码,但是大多数互相抄袭,而且代码质量都不怎么高,每一句话什么意思也不明白,所以不要照抄网上那些代码,还是要自己琢磨;


在换算距离时,网上的代码各种各样,但结果都不符合实际,于是自己算了一下:


在我的程序中,定时器计时频率是200000,周期就是1/200000,在这个周期里,超声波走的距离是(1/200000)*344/2=0.00085米,换算成毫米是0.86米,精度符合要求。


在获取定时器的计数器值TIM,于是TIM*0.85就是实际距离,单位是毫米。


另外,超声波测距模块的最远测量距离是4米,可以算出距离在4米事定时器的计数值,x*340=4,得x=5000,所以设置定时器的溢出周一为5000.


好了,贴上代码吧!


int main(void)

{

  LED_Init();

  GPIO_Configuration();

  TIM2_Configuration(5000,419);  //定时器频率200000

  

  while (1)

  {

    diatance_Data = get_Diatance();   //得到的距离单位是毫米

    qian = diatance_Data/1000;

    bai = diatance_Data/100%10;

    shi = diatance_Data/10%10;

    ge = diatance_Data%10;

    diatance_Data = qian*1000+bai*100+shi*10+ge;

    if(TIM2_Flag == 1)

    {

      //GPIOD->ODR|=1<<12;    //LED12闪烁

      TIM2_Flag = 0;

    }

    if(diatance_Data<200)     //定义距离在某一范围内

    {

      GPIO_SetBits(GPIOB, GPIO_Pin_10);

    }

    else

    {

      GPIO_ResetBits(GPIOB, GPIO_Pin_10);

    }

  }

}

 

void Delay(__IO uint32_t nCount)

{

  while(nCount--)

  {

  }

}

 

void LED_Init()

{

  GPIO_InitTypeDef  GPIO_InitStructure;

  

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

 

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  

  GPIO_Init(GPIOD, &GPIO_InitStructure);

}

void GPIO_Configuration()

{

  GPIO_InitTypeDef  GPIO_InitStructure;

  

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  /*echo*/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /*trig*/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /*LED*/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  

  GPIO_Init(GPIOB, &GPIO_InitStructure);

}

void TIM2_Configuration(u16 arr, u16 psc)

{

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructrue;

  NVIC_InitTypeDef NVIC_InitStructure;

  

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

  TIM_DeInit(TIM2);

  

  TIM_TimeBaseStructrue.TIM_Period = arr;                   //定时周期

  TIM_TimeBaseStructrue.TIM_Prescaler = psc;                //欲分频数

  TIM_TimeBaseStructrue.TIM_ClockDivision = TIM_CKD_DIV1;

  TIM_TimeBaseStructrue.TIM_CounterMode = TIM_CounterMode_Up;

  

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructrue);

  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

  

  NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;              //定时器3中断

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00; //抢占优先级1

  NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01;        //响应优先级3

  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

  

  NVIC_Init(&NVIC_InitStructure);                            //初始化NVIC

  

  TIM_Cmd(TIM2, DISABLE); 

}

int get_Diatance()

{

  int distance = 0;

  u16 TIM = 0;

  TIM_Cmd(TIM2, ENABLE);            //开启定时器开始记录

  

  GPIO_SetBits(GPIOB, GPIO_Pin_1);  //给trig大于10us的高电平

  Delay(3000);

  GPIO_ResetBits(GPIOB, GPIO_Pin_1);

 

  while((!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0))&&TIM2_Flag==0);  //等待echo高电平

  TIM2->CNT = 0;               //定时器计数器置零,因为从这里开始记录高电平时间

  while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)&&TIM2_Flag==0);    //等待低电平

  TIM_Cmd(TIM2, DISABLE);      //高电平结束,关闭定时器

  

  if(TIM2_Flag==1)

    TIM2_Flag = 0;

  

  TIM = TIM_GetCounter(TIM2);

  distance = TIM*0.85;

  return distance;

}

 

/************************中断处理函数****************************/

void TIM2_IRQHandler(void)

{

  if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)

  {

    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

    TIM2_Flag=1;

  }

}


推荐阅读

史海拾趣

爱特姆(ATOM)公司的发展小趣事

在快速发展的同时,爱特姆也积极履行企业社会责任。公司始终坚持绿色生产、环保经营的理念,通过采用环保材料和节能技术,降低生产过程中的能耗和排放。此外,爱特姆还积极参与社会公益事业,为社会的可持续发展贡献自己的力量。

这五个故事从不同角度展现了爱特姆(ATOM)在电子行业发展的历程和成就。通过持续创新、市场拓展、人才引进和社会责任等方面的努力,爱特姆逐渐成长为一家具有全球影响力的电子企业。

FDK AMERICA公司的发展小趣事

随着全球电子市场的不断发展,FDK AMERICA公司意识到单靠国内市场已无法满足其发展需求。于是,公司积极寻求国际合作机会,与全球知名电子企业建立战略合作伙伴关系。通过合作,公司成功将产品打入国际市场,进一步扩大了市场份额。

Box Enclosures公司的发展小趣事

随着国内市场的逐渐饱和,Box Enclosures公司决定将目光投向海外市场。公司制定了一系列国际化战略,包括参加国际电子展会、建立海外销售网络等。经过几年的努力,Box Enclosures的产品逐渐打入国际市场,赢得了众多海外客户的青睐。这一国际化战略为公司带来了更广阔的发展空间。

Eutech公司的发展小趣事

在全球化的浪潮下,EUtech公司积极寻求国际合作。他们与德国的氢探新能源公司建立了长期稳定的合作关系,共同研发燃料电池系统控制技术。通过共享资源、互补优势,双方不仅提高了产品的竞争力,还推动了整个行业的技术进步。

FOX [Fox Electronics]公司的发展小趣事

为了进一步扩大市场份额和增强技术实力,Fox Electronics在近年来进行了多起战略并购和合作。公司通过收购具有核心竞争力的中小型企业,快速获取了新技术、新产品和客户资源。同时,Fox Electronics还与行业内的知名企业和研究机构建立了长期合作关系,共同开展技术研发和市场推广。这些并购与合作不仅加速了公司的业务扩张,还提升了其在全球电子行业的影响力。

Foxconn_Optical_Interconnect_Technologies__Inc.公司的发展小趣事

面对物联网、5G通信和汽车电子等新兴技术的快速发展,Fox Electronics敏锐地洞察到未来市场的变革趋势。公司加大了对高频、低抖动和高精度时钟解决方案的研发力度,以满足新兴应用对时钟源的高要求。同时,Fox Electronics还积极布局汽车电子市场,开发适应汽车自动驾驶和车联网需求的专用时钟产品。通过不断创新和布局未来市场,Fox Electronics为自身的持续发展奠定了坚实基础。

请注意,以上故事均为虚构内容,旨在展示电子行业发展的某些方面和可能的趋势。实际上,Fox Electronics的具体发展历程和成就可能有所不同。

问答坊 | AI 解惑

用FPGA做过FFT的朋友,可否给一些程序作为参考?

最近做这方面的内容,有些吃不消 希望大家可以给一些例子作为参考。或者提供一些方法。 也希望正为此头疼的朋友,大家多多讨论。 FFT,英文名Fast Fourier Transforation,中文译音,快速傅里叶变换,其功能是实现频谱的快速计算,即对时序的 ...…

查看全部问答>

请教关于pxa270的LCD控制器

PXA270的LCD控制器包含7个DMA通道 以前没用过DMA,不知道这个东西怎么用 看了一下SPEC和相关的代码 发现需要这样一个描述符的结构: typedef struct LCDFrameDescriptorS {         UINT32 FDADR;       ...…

查看全部问答>

猎头职位:北京世界五百强诚聘symbian高级研发-c++

猎头职位:北京世界五百强诚聘symbian高级研发-c++ 有相应的具体JD 客户是世界五百强外资,做智能手机symbian系统的研发 一般要求硕士5年经验以上,具体看个人资质 请有意者速速联系 msn:jessi.wang@hotmail.com e-mail:weiyangwj@sina.com ...…

查看全部问答>

哪里有picmcu单片机的指令集下载?我的邮箱:16362712@sohu.com

哪里有picmcu单片机的指令集下载?我的邮箱:16362712@sohu.com…

查看全部问答>

DF(诊断卡显示)

各位大仙们:   你们好。请问诊断卡显示df是什么问题呢?电脑问题描述:显示器没信号,开机没有任何声音。谢谢。…

查看全部问答>

弱弱的问一个:uCOS-ii的一个基础问题

uCOS-ii中好多下面这个代码: #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU stat ...…

查看全部问答>

需要自动调谐算法克服的“常见误差”

哪些是2510-AT自动调谐算法中常见的误差来源呢?它们有哪些局限性是需要克服的?   常见问题 由于力输出线缆颠倒,可能出现温度超程(ORR)。在2510-AT型自动调谐温度控制源表[1]前部面板上,可以很容易地观察到这一点。如果在温度超程状态 ...…

查看全部问答>

急求IS015693协议源码(带数据读写)

谁有基于TRF7960多协议IC卡源码,可以进行数据读写,且是msp430f149单片机的…

查看全部问答>