(十)DSP28335基础教程——ECAP实验(超声波测距)

DSP 专栏收录该内容
10 篇文章 25 订阅

0 前言

这一节我们来学习DSP的ECAP模块的功能。实验目标:通过超声波测距模块,将采集所测量距离显示在电脑串口助手上。

本节将分为硬件部分、软件部分和实验展示三个方面进行介绍,不清楚的欢迎留言。

1 硬件部分

需要四个硬件如图1所示:超声波模块HC-SR04、DSP28335核心板、烧写器、USB转串口模块。
在这里插入图片描述

图1 硬件实物图

超声波模块有四个接口,分别为VCC(+5V)、TRIG(控制端)、ECHO(接收端)和GND,其工作原理如下:
(1)采用IO口输入信号到TRIG接口触发测距,给至少10us的高电平信号;
(2)触发后,模块自动发送8个40kHz的方波,自动检测是否有信号返回;
(3)若有信号返回,ECHO接口将输出一个高电平,其高电平的持续时间就是超声波从发射到返回的时间;
(4)测量距离=(高电平时间*声速)/2,其中声速=340m/s。
为了更清楚的表示超声波工作过程,图2给出了输入输出信号的时序图。
在这里插入图片描述

图2 超声波模块工作时序图

因此,在实验过程中,采用DSP的ECAP管脚连接到HC-SR04的ECHO接口,再用一个普通IO口连接到TRIG接口作为触发源管脚即可。其中,具体的硬件连接如图3所示。
在这里插入图片描述

图3 硬件接线图

2 软件部分

在软件部分,分为超声波模块功能和串口显示。

首先我们看超声波模块的代码:(注意:查看代码时双击点进去看,否则会内容不全)。

需要注意:
(1)ECAP要设置为单次模式,不能设置连续模式,因为这里超声波模块每触发一次只输出一次回响信号,因此我们只需要捕获信号的上升沿和下降沿即可,即上升沿捕获计数值储存在捕获寄存器CAP1中,而下降沿计数值储存在寄存器CAP2中。否则,所测量的捕获信号将可能储存在CAP3或CAP4中,对后面计算距离造成不便。在这里,我们设置在捕获事件2发生后重新刷新Mod4计数器,具体过程如图4所示。
在这里插入图片描述

图4 单次和连续捕获过程

(2)测量距离(单位mm)=(高电平时间*声速)/2=(CAP2值-CAP1值)×170/(150×1000)。其中150是代表DSP28335时钟频率为150MHz,1000是米到毫米的单位换算。

bsp_cap.c

/**
 *  ********************************************************************************************
 *  @file                 bsp_cap.c
 *  @file                 SK Electronics
 *  @version           V1.0
 *  @date               2021-xx-xx
 *  @brief               CAP应用函数接口
 *  *******************************************************************************************
 *  @attention
 *  实验平台:SK-F28335Mini   核心板
 *  CSDN博客:https://blog.csdn.net/weixin_46556696
 *  淘宝:https://shop409670932.taobao.com
 */

#include "bsp_cap.h"
#include "bsp_sci.h"
extern Uint32 cap_val,Distan;
extern char Distan_ASCII[2];

/**
 *  @brief                   初始化ECAP1配置
 *  @parameter                  无
 *  @return_value               无
 */
void Init_ECap1(void)
{
    InitECap1Gpio();
    EALLOW;
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0;//普通IO模式
    GpioCtrlRegs.GPADIR.bit.GPIO0 = 1;//配置成输出
    EDIS;

    ECap1Regs.ECEINT.all = 0x0000;    // 关闭所有的CAP中断
    ECap1Regs.ECCLR.all = 0xFFFF;     // 清除所有的CAP中断标志位
    ECap1Regs.ECCTL1.all = 0x0000;   // 复位控制寄存器2
    ECap1Regs.ECCTL2.all = 0x0000;   // 复位控制寄存器2

    ECap1Regs.TSCTR = 0;    // 计数清零
    ECap1Regs.CTRPHS = 0;   // 计数相位寄存器清零

    ECap1Regs.ECCTL1.bit.CAP2POL = 1;//捕获事件2下降沿触发
    ECap1Regs.ECCTL1.bit.CTRRST2 = 1;//捕获事件2发生时计数器复位
    ECap1Regs.ECCTL1.bit.CAP4POL = 1;//捕获事件4下降沿触发
    ECap1Regs.ECCTL1.bit.CTRRST4 = 1;//捕获事件4发生时计数器复位
    ECap1Regs.ECCTL1.bit.CAPLDEN = 1;//使能在捕获事件发生时装载CAP1~CAP4
    ECap1Regs.ECCTL1.bit.FREE_SOFT = 2;//TSCTR不受仿真影响

    ECap1Regs.ECCTL2.bit.STOP_WRAP = 1;//在捕获事件2发生后停止(单次模式)
    ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1;//开始计数
    ECap1Regs.ECCTL2.bit.SYNCO_SEL = 2;//禁止SYNC_OUT输出信号

    ECap1Regs.ECEINT.bit.CEVT2 = 1;  // 使能捕获事件2发生中断
}

/**
 *  @brief                  计算距离
 *  @parameter                  无
 *  @return_value               无
 */
void ReadDistance(void)
{
    GpioDataRegs.GPASET.bit.GPIO0 = 1;   //Trig引脚输出高电平
    DELAY_US(15);   //至少10us,本实验给15us
    GpioDataRegs.GPACLEAR.bit.GPIO0 = 1;   // Trig引脚输出低
    Distan = cap_val*170/150000;   // 计算距离,此处单位为mm
    scia_msg("当前测距:\0");
    hextoascii(Distan);
    scia_msg(Distan_ASCII);
    scia_msg("mm\r\n");
}

bsp_cap.h

/**
 *  ********************************************************************************************
 *  @file                 bsp_cap.h
 *  @file                 SK Electronics
 *  @version           V1.0
 *  @date               2021-xx-xx
 *  @brief               CAP应用函数接口头文件
 *  *******************************************************************************************
 *  @attention
 *  实验平台:SK-F28335Mini   核心板
 *  CSDN博客:https://blog.csdn.net/weixin_46556696
 *  淘宝:https://shop409670932.taobao.com
 */

#include "DSP28x_Project.h"
void Init_ECap1(void);
void ReadDistance(void);

串口模块显示代码:
bsp_sci.c

/**
 *  ********************************************************************************************
 *  @file                 bsp_sci.c
 *  @file                 SK Electronics
 *  @version           V1.0
 *  @date               2021-xx-xx
 *  @brief               串口通信应用函数接口
 *  *******************************************************************************************
 *  @attention
 *  实验平台:SK-F28335Mini   核心板
 *  CSDN博客:https://blog.csdn.net/weixin_46556696
 *  淘宝:https://shop409670932.taobao.com
 */
#include "bsp_sci.h"
extern char Distan_ASCII[4];
/**
 *  @brief                   初始化SCI串口配置
 *  @parameter                  无
 *  @return_value               无
 */
void Sci_Init(void)
{
    //SCI的工作模式和参数需要用户在后面的学习中,深入的了解一个寄存器底层相关的资料了,多看看芯片手册和寄存器的意思。
    //因为28335的寄存器太多了,所以在以后的学习过程中,就不会对寄存器进行详细的注释了。
    InitSciaGpio();
    SciaRegs.SCICCR.all=0x07;// 1 stop bit,  No loopback
                             // No parity,8 char bits
                             // async mode, idle-line protocol
    SciaRegs.SCICTL1.all=0x03;// enable TX, RX, internal SCICLK,

    #if(CPU_FRQ_150MHZ)
    SciaRegs.SCIHBAUD=0x0001;// 9600 baud @LSPCLK = 37.5MHz.
    SciaRegs.SCILBAUD=0x00E7;
    #endif

    #if(CPU_FRQ_100MHZ)
    SciaRegs.SCIHBAUD=0x0001;// 9600 baud @LSPCLK = 20MHz.
    SciaRegs.SCILBAUD=0x0044;
    #endif

   // SciaRegs.SCICTL2.bit.RXBKINTENA=1;
   // SciaRegs.SCICTL2.bit.TXINTENA=1;
    //SciaRegs.SCICCR.bit.LOOPBKENA=1;
    SciaRegs.SCICTL1.bit.SWRESET=1;

   // PieCtrlRegs.PIECTRL.bit.ENPIE=1;
   // IER|=M_INT9;
   // PieCtrlRegs.PIEIER9.bit.INTx1=1;
   // PieCtrlRegs.PIEIER9.bit.INTx2=1;

}

void scia_xmit(int a)//发送字节的函数
{
    while (SciaRegs.SCICTL2.bit.TXRDY == 0) {}
    SciaRegs.SCITXBUF=a;

}

void hextoascii(unsigned char num)//十位数字转化为对应ASCII格式
{
    char one,ten,hundred,thousand=0;
    one=num/1%10;//取个位
    ten=num/10%10;//取十位
    hundred=num/100%10;//取百位
    thousand=num/1000%10;//取千位
    Distan_ASCII[0]=thousand+0x30;
    Distan_ASCII[1]=hundred+0x30;
    Distan_ASCII[2]=ten+0x30;
    Distan_ASCII[3]=one+0x30;
}
void scia_msg(char * msg)//发送数组的函数
{
    int i;
    i = 0;
    SciaRegs.SCICTL2.bit.TXINTENA=0;
    while(msg[i] != '\0')
    {
        scia_xmit(msg[i]);
        i++;
    }
    SciaRegs.SCICTL2.bit.TXINTENA=1;
}

bsp_sci.h

/**
 *  ********************************************************************************************
 *  @file                 bsp_sci.h
 *  @file                 SK Electronics
 *  @version           V1.0
 *  @date               2021-xx-xx
 *  @brief               串口通信函数接口头文件
 *  *******************************************************************************************
 *  @attention
 *  实验平台:SK-F28335Mini   核心板
 *  CSDN博客:https://blog.csdn.net/weixin_46556696
 *  淘宝:https://shop409670932.taobao.com
 */

#ifndef _BSP_SCI_H_
#define _BSP_SCI_H_
#include "DSP28x_Project.h"

void Sci_Init(void);
void scia_xmit(int a);//发送字节的函数
void scia_msg(char * msg);//发送数组的函数
void hextoascii(unsigned char num);
#endif /*_BSP_SCI_H_ */

main.c

/**
 *  ********************************************************************************************
 *  @file                 main.c
 *  @file                 SK Electronics
 *  @version           V1.0
 *  @date               2020-xx-xx
 *  @brief               ECAP超声波测距实验
 *  *******************************************************************************************
 *  @attention
 *  实验平台:SK-F28335Mini   核心板
 *  CSDN博客:https://blog.csdn.net/weixin_46556696
 *  淘宝:https://shop409670932.taobao.com
 */
#include "DSP28x_Project.h"
#include "bsp_cap.h"
#include "bsp_sci.h"
#define FLASH_RUN 1
#define SRAM_RUN 2
#define RUN_TYPE FLASH_RUN
#if RUN_TYPE==FLASH_RUN
extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadEnd;
extern Uint16 RamfuncsRunStart;
#endif
/**************************************变量定义************************************************/
Uint32 cap_val=0,Distan=0;
char Distan_ASCII[4]={0,0,0,0};//存放测量距离的ASCII转换结果

/**************************************声明区**************************************************/
__interrupt void Ecap1_isr(void);   // Ecap1_isr()函数声明
interrupt void scia_Tx_isr(void);
interrupt void scia_Rx_isr(void);
void delay_1ms(Uint16 t);
/**
 *  @brief                           主函数
 *  @parameter                  无
 *  @return_value               无
 */
void main(void)
{
/*第一步:初始化系统控制:*/
    InitSysCtrl();

/*第二步:初始化GPIO口*/
    InitGpio();

/* 第三步:清除所有中断 和初始化 PIE 向量表:*/
    DINT;// 关闭全局中断
    InitPieCtrl();// 初始化 PIE 控制寄存器到默认状态,默认状态是全部 PIE 中断被禁用和标志位被清除
    IER = 0x0000;// 禁用 CPU 中断和清除所有 CPU 中断标志位:
    IFR = 0x0000;
    InitPieVectTable();// 初始化 PIE 中断向量表

    // 中断重映射,注册中断程序入口(用户按需求添加)
    EALLOW;
    PieVectTable. ECAP1_INT = &Ecap1_isr;   // ECAP1_INT的中断映射
    EDIS;
    //

    /*程序烧录入28335(可选的)*/
#if RUN_TYPE==FLASH_RUN
    MemCopy(&RamfuncsLoadStart,&RamfuncsLoadEnd,&RamfuncsRunStart);
    InitFlash();
#endif
/* 第四步: 初始化片上外设*/
    // InitPeripherals();  //初始化所有外设(本例程不需要)
    Sci_Init();//初始化和配置SCIA串口通信
    Init_ECap1();   // ECap1模块初始化
    IER |= M_INT4;  //使能第一组中断
    PieCtrlRegs.PIEIER4.bit.INTx1 = 1; //使能第四组中断里的第一个中断--CAP1中断

/* 第五步:添加用户功能具体代码*/
    EINT;
    ERTM;

    scia_msg("Hello SK Electronics!\r\n\0");
    scia_msg("更详细的DSP基础教程,请关注支持本人博客哈!\r\n\0");
    scia_msg("CSDN博客:https://blog.csdn.net/weixin_46556696\r\n\0");
    scia_msg("淘宝店铺:https://shop409670932.taobao.com\r\n\0");
    for(;;)
    {
        ReadDistance();   // 计算距离
        delay_1ms(500);   // 延时500ms
    }
}


void delay_1ms(Uint16 t)
{
    while(t--)
    {
        DELAY_US(1000);
    }
}

/**
 *  @brief                  ECAP1中断服务函数
 *  @parameter                  无
 *  @return_value               无
 */
__interrupt void Ecap1_isr(void)
{
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP4; // 清除CAP1的PIE中断标志
    ECap1Regs.ECCLR.bit.INT = 1;      // 清除ECap1中断标志位
    ECap1Regs.ECCLR.bit.CEVT2 = 1;    // 清除事件2标志位
    cap_val=(int32)ECap1Regs.CAP2 - (int32)ECap1Regs.CAP1;   // 计算脉冲
}

3 实验展示

程序烧录进去后,图5所示在串口助手和在CCS变量窗口可以看到超声波所测量的距离。
在这里插入图片描述

图5 实验结果

大家可以参考代码尝试一下, 有疑问的欢迎留言!!

  • 5
    点赞
  • 15
    评论
  • 9
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 15 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页

打赏作者

Sk Electronics

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值