历史上的今天
返回首页

历史上的今天

今天是:2025年02月10日(星期一)

正在发生

2020年02月10日 | 基于MSP430F5529单片机实现HC-SR04超声波测距 CCS & IAR

2020-02-10 来源:eefocus

项目介绍

本设计基于TI公司的MSP430F5529单片机与超声波测距模块HC-SR04实现距离测量,使用ccs软件进行编程,利用单片机定时器的捕获模块捕获超声波高电平持续的时间,再根据公式计算出距离值。


项目准备

1. 开发环境(PC、CCS软件)

2. MSP-EXP430F5529LP .

3. HC-sr04

4. 直尺或其他量度工具


实现原理

超声波时序图

如图,只需要提供一个 10uS 以上脉冲触发信号,该模块内部将发出 8 个 40kHz 周期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。 由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。


本项目中通过单片机 IO 口P1.3输出10us的高电平给超声波模块 Trig触发测距,模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回; 有信号返回时 通过 IO 口P1.2 TA0.1捕获 Echo输出一个高电平, 高电平持续的时间就是超声波从发射到返回的时间。通过单片机定时器的捕获模块捕获超声波高电平持续的时间,再根据公式计算出距离值。

距离公式:


距离 = ( 高电平时间 x 声速 (340M/s)) / 2


软件设计

UCS设置

单片机时钟模块默认使用的是内部DCOCLKDIV 1.048576MHZ,本项目中使用XT2外接的4MHz高频晶振,将系统配置为;

MCLK = SMCLK = XT2 = 4MHz


void UCS_Init(void)

{

//    P1DIR |= BIT0;                            // ACLK set out to pins

//    P1SEL |= BIT0;

    P2DIR |= BIT2;                            // SMCLK set out to pins

    P2SEL |= BIT2;

//    P7DIR |= BIT7;                            // MCLK set out to pins

//    P7SEL |= BIT7;


    P5SEL |= BIT2+BIT3;                       // Port select XT2


    UCSCTL6 &= ~XT2OFF;                       // Enable XT2

    UCSCTL3 |= SELREF_2;                      // FLLref = REFO

                                              // Since LFXT1 is not used,

                                              // sourcing FLL with LFXT1 can cause

                                              // XT1OFFG flag to set

    UCSCTL4 |= SELA_2;                        // ACLK=REFO,SMCLK=DCO,MCLK=DCO


    // Loop until XT1,XT2 & DCO stabilizes - in this case loop until XT2 settles

    do

    {

      UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);

                                              // Clear XT2,XT1,DCO fault flags

      SFRIFG1 &= ~OFIFG;                      // Clear fault flags

    }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag


    UCSCTL6 &= ~XT2DRIVE0;                    // Decrease XT2 Drive according to

                                              // expected frequency

    UCSCTL4 |= SELS_5 + SELM_5;               // SMCLK=MCLK=XT2

}


USCI_UART设置

对于给定的BRCLK时钟源,使用的波特率决定了所需的分频因子N:

N = f BRCLK / Baudrate

因子N通常是非整数值,因此,使用至少一个除法器和一个调制器级来尽可能地满足该因子。 如果N等于或大于16,则可以通过设置UCOS16来选择过采样波特率生成模式。


在低频模式下,除数的整数部分由预分频器实现:

UCBRx = INT(N)

并且分数部分由调制器实现,具有以下标称公式:

UCBRSx =round [(N - INT(N))×8]

将UCBRSx设置递增或递减一个计数可以为任何给定位提供较低的最大位错误。 要确定是否是这种情况,必须为每个UCBRSx设置的每个位执行详细的错误计算。


在过采样模式下,预分频器设置为:

UCBRx = INT(N / 16)

并且第一级调制器设置为:

UCBRFx = round([(N / 16) - INT(N / 16)]×16)

当需要更高的精度时,UCBRSx调制器也可以使用0到7的值来实现。要找到给出任何给定位的最低最大误码率的设置,必须对UCBRSx的所有设置执行详细的误差计算。 初始UCBRFx设置为0到7,UCBRFx设置递增并递减1。


在本项目中将通过串口打印距离值到PC端,将串口配置为 115200 8N1

首先配置串口输入时钟,工作模式等,然后配置串口的波特率:

UCBR0 = 4000000 / 115200 = 34.722222222222222222222222222222 则:UCBR0 = 34

UCBRSx =(34.72 - 34)× 8 = 5.76 四舍五入后 UCBRS = 6


void Uart_Init(void)                           // 115200 8N1

{

    P4SEL |= BIT4+BIT5;                        // P4.4,5 = USA1 TXD/RXD

    UCA1CTL1 |= UCSWRST;                       // **Put state machine in reset**

    UCA1CTL1 |= UCSSEL__SMCLK ;                // SMCLK

    UCA1BR0 = 34;                              // 4MHz 115200 (see User's Guide)

                                               // UCA1BR0 = 输入的时钟源/串口通信速率 (取整)

    UCA1BR1 = 0;                               // 4MHz 115200

    UCA1MCTL = UCBRS_6;                        // 输入的时钟源/串口通信速率的余数*8

    UCA1CTL1 &= ~UCSWRST;                      // **Initialize USCI state machine**

//    __bis_SR_register(GIE);       // Enter LPM0, interrupts enabled

}


TIMER_A设置

本项目中需要用到定时器的捕获模式,通过TAxCTL设置输入时钟、工作模式、中断允许等(TA0CTL)。

图1 TAxCTL 寄存器

本项目通过P1.2即TA0.1捕获超声波模块Echo引脚输出的高电平时长,配置TAxCCTLn设置工作模式、输入设置、中断允许等(TA0CCTL1)。

TAxCCTLn寄存器

配置完定时器的寄存器以后,在中断程序中计算距离值。捕获原理很简单,通过捕获电平的变化,进而得到高电平持续持续时间,首先使用捕获模式的上升沿捕获,当捕获事件发生时会触发中断,在中断中记录TA0CCR1的值并将捕获模式设置为下降沿触发,然后计算距离值,也可在中断外部计算,中断中获取定时器值。


#define Trig1(a)  if(a==1) P1OUT |= BIT3; else P1OUT &= ~BIT3


unsigned int cap_new = 0;           // 首次捕捉的ta0r值

unsigned int cap_old = 0;           // 二次捕捉的ta0r值

//char test_num = 10;                 // 测量次数

char cap_N = 0;                     // 溢出次数

char state = 0x00;                  // zhuangtai

long cap_data = 0;                  // 距离值

//unsigned int dat[test_num];         //通过数组存10次测量值


void Hc_sr_Init(void) // 超声波模块初始化

{

   /*

    *  P1.2 为echo引脚             捕获模式

    *  P1.2 具有端口中断的通用数字I / O ,TA0 CCR1捕获:CCI1A输入,比较:Out1输出  BSL接收输入

    *  P1.3 为Trig          数字i/o模式

    *  P1.3 具有端口中断的通用数字I / O , TA0 CCR2捕获:CCI2A输入,比较:Out2输出

    */

    P1OUT &= ~( BIT2 + BIT3 );

    P1DIR |=  BIT3;

    P1SEL |=  BIT2;

    /*

     * note:由于选用的是P1.2 根据端口定义可知,使用的是TA0CCR1,捕获输入引脚通过TA0CCTL1寄存器控制,

     *-捕获值存储在TA0CCR1中。

     * TASSEL:SNCLK; 分频:4MHz/8 = 500k;计数模式:0  ==> 0xFFFF;

     * TA0CCTL1:上升沿捕获 ;同步捕捉;捕获模式;CCI1A输入;

     */

    TA0CTL   = TASSEL__SMCLK + ID__8 + MC_2 + TACLR + TAIE;

    TA0CCTL1 = CM_1 + SCS +CAP + CCIE + CCIS_0;

}


void Hc_sr_Open(void)           //生成一个持续10us的高电平

{

    Trig1(1);

    __delay_cycles(40);

    Trig1(0);

}


#pragma vector=TIMER0_A1_VECTOR

__interrupt void TIMER0_A1_ISR(void)

{

    switch(__even_in_range(TA0IV,14))

    {

      case  0:break;                                 // No interrupt

      case  2:

          state =  TA0CCTL1 >> 14;

          TA0CCTL1 &= ~CCIFG;

          if( TA0CCTL1 & CM_1){

              cap_new = TA0CCR1;

              TA0CCTL1 &= ~CM_1;

              TA0CCTL1 |=  CM_2;

          }else if ( TA0CCTL1 & CM_2){

              cap_old = TA0CCR1;

              cap_data = ( cap_old - cap_new ) * 0.34;

              UARTprintf("nncap_data: %u mm",cap_data);

              TA0CCTL1 &= ~CM_2;

              TA0CCTL1 |=  CM_1;

          }else UARTprintf("nstate: %x",state);     // 判断CM位捕捉模式

//          UARTprintf("n yes! ccr1 nTA0 CCR1: %u  TA0R: %u",TA0CCR1,TA0R);

          break;                          // CCR1 not used

      case  4: break;                          // CCR2 not used

      case  6: break;                          // reserved

      case  8: break;                          // reserved

      case 10: break;                          // reserved

      case 12: break;                          // reserved

      case 14:

          TA0CTL &= ~TAIFG;

          if(cap_old   < cap_new ){

              cap_N += 1;

推荐阅读

史海拾趣

Gore公司的发展小趣事
在隔离型中压大容量直流变换器中,可能存在直流偏磁问题,导致变压器磁路饱和、励磁电流增加、局部过热和噪声增大等问题。
宜源科技(ETERNAL)公司的发展小趣事

随着国内市场的饱和,宜源科技公司积极寻求海外市场的发展机会。公司加强与国际知名企业的合作,共同开发新产品,拓展市场份额。同时,宜源科技还积极参加国际展会和论坛,提升品牌知名度和影响力。通过不懈的努力,宜源科技的产品已经成功进入多个国家和地区,实现了国际化发展。

Euvis Inc公司的发展小趣事

Euvis Inc公司自成立以来,始终将技术创新作为发展的核心动力。公司投入大量研发资源,成功开发出一款具有革命性意义的新型半导体材料,该材料具有更高的导电性能和更低的能耗,极大地提升了电子产品的性能。随着这款材料的广泛应用,Euvis Inc公司在半导体材料市场迅速崛起,成为行业内的领军企业。

振宝佳(DMBJ)公司的发展小趣事

随着电子产业的不断发展,SMT贴片技术逐渐成为电子信息产业的支柱技术之一。振宝佳公司紧跟时代步伐,在网络、通信、军事、工业控制以及汽车电子、家电等所有电子领域里全部采用了SMT贴片技术。这一技术的应用不仅提高了产品的集成度和可靠性,也为客户提供了更加优质的产品和服务。

Allied Wire & Cable Inc公司的发展小趣事

为了保持市场竞争力,Allied公司始终注重技术升级和品质提升。公司投入大量资金引进先进的生产设备和技术,不断提高产品的技术含量和附加值。同时,公司还建立了严格的质量管理体系,从原材料采购到产品出厂的每一个环节都进行严格把控,确保产品的品质和性能达到最高标准。

Aplus Flash Technology Inc公司的发展小趣事

Aplus Flash Technology Inc公司自成立以来,一直致力于闪存技术的研发与生产。在电子行业的激烈竞争中,公司凭借对技术的深入理解和持续创新,成功研发出了一款高性能、低成本的闪存芯片,迅速占据了市场份额。这款芯片不仅满足了消费者对电子设备存储容量和速度的需求,还因其出色的稳定性和耐用性赢得了客户的广泛好评。Aplus Flash Technology Inc公司因此成为了闪存市场的佼佼者,为公司的进一步发展奠定了坚实基础。

问答坊 | AI 解惑

双模式CORDIC算法的FPGA实现

双模式CORDIC算法的FPGA实现pdf 论文…

查看全部问答>

I²C总线的发展及I²C配置及仿真

本文主要介绍I²C总线的发展及I²C配置及仿真,以简化总线上主机与从机之间的通信。应用实例提供了原理图和程序代码. 引言 80年代初期,Philips Semiconductor为减少电子产品内部并行数据总线的数量,开发了Inter IC (I²C)总线。199 ...…

查看全部问答>

PFC的原理及分析

PFC的原理及分析…

查看全部问答>

PCB的惨痛经历,值得工程师借鉴(转)

PCB即印刷电路板,是电子电路的承载体。在现代电子产品中,几乎都要使用PCB。 PCB设计是电路设计的最后一个环节,也是对原理电路的再设计。一些新的工程师往往低估PCB设计的重要性,将这一即烦琐又费事的工作完全交由技术员去完成。在这里我先讲 ...…

查看全部问答>

三网融合,高清网络摄像机让您的家居焕然一新!

    三网融合试点方案已经通过,试点城市的名单也即将公布,这一跨世纪举措离我们已越来越近。三网融合改变的不仅仅是我们的生活形态,更是我们的生活习惯。扔掉我们的电话、电视、电脑,把它们放进火炉,熔炼出新的工具,新的生活 ...…

查看全部问答>

PC

我用盛博STA-1040板,运行程序后突然显示:No bootable device avilable  r-reboot s-setup r-reset,哪位大侠遇到相同的问题,为什么,怎么解决?我的邮箱:awater8.3@163.com,谢谢啦!…

查看全部问答>

请问VHDL中bit_vector的位号问题:a(0)是从a的左边数还是右边数第一位啊?

请问VHDL中bit_vector的位号问题: a:bit_vector(7 downto 0) 那么a(0)是从a的左边数还是右边数第一位啊?…

查看全部问答>

cepc+eboot 不能下载nk,请高手帮帮我。

我用的是pcm3370板子,想通过eboot启动nk 1.用cf卡做了个dos启动盘 2.启动cepc进入dos,之后选择第二个选项: 。 。 2. CEPC_1024, Boot CE/PC (ether via eboot.bin with /L:1024x768x8) 。 。 3.vs2005菜单中选择 target->connectivity o ...…

查看全部问答>

各位大虾帮帮忙拉~

我想做一个单片机控制步进电机的板子 大侠们给我推荐一些比较实惠的芯片啊~网上找的是各人说各人的好处~小弟初来咋到~先谢谢各位拉!!!…

查看全部问答>