This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CCS/MSP430FR6989:HC-SR04

Guru**** 2201430 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/822601/ccs-msp430fr6989-hc-sr04

器件型号:MSP430FR6989

工具/软件:Code Composer Studio

你(们)好 我尝试使用 LCD 显示屏运行超声波传感器、以显示电流距离。 无论传感器前面是什么、我的结果都是0 cm。 请帮助我进行故障排除。 谢谢!

/******** //*
uC 和超声波传感器连接
P1.4 -触发
P1.5 -回波 */
******** //*
UC 和 LCD 连接
TP1 - Vcc (+5V)
TP3 - VSS (GND)
P2.2 -中文
P2.3 - RS
P2.4 - D4
P2.5 - D5.
P2.6 - D6
P2.7 - D7
GND - RW
GND - Ve/Vdd -通过1K 电阻器连接到 GND
-此值决定对比度-
即、如果没有电阻器、所有点始终可见、而是
-较高的电阻意味着根本不显示点。
接地- K (LED-)
VCC - A (LED+)+5V -用于背光
时钟:1MHz */
******** /#include


#include 
#include 
#include 

// uC GPIO 端口分配
#define uC_port P2OUT
#define UC_PORT_DIR P2DIR

//外设引脚分配
#define US_TRIG BIT4
#define US_echo Bit5
#define LCD_EN Bit2
#define LCD_RS BIT3
#define LCD_DATA BIT4 | BIT4 | BIT6 | BIT4
#define LCD_D0_OFFSET 4 // BIT4,因此它是4
#define US_MASK US_TRIG | US_ECHO
#define LCD_MASK LCD_EN | LCD_RS | LCD_DATA

unsigned int up_counter;
unsigned int Distance_cm;



// Timer A0捕获中断例程
P1.1 (回波)会导致调用此例程*/
#pragma vector=TIMER0_A0_vector
__interrupt void TimerA0 (void)
{
IF (TA0CCTL0和 CCI) //上升沿
{
UP_COUNTER = TA0CCR0; //将计数器复制到变量
}
其他 //下降沿
{
//公式:以 cm 为单位的距离=(以 uec 为单位的时间)/58
Distance_cm =(TA0CCR0 - UP_COUNTER)/58;
}
TA0CCTL0 &=~CCIFG;
TA0CTL &=~TAIFG; //清除中断标志-已处理
}

void timer_init()
{
//将计时器 A0配置为读取回波信号:
Timer A 捕获/比较控制0 =>
捕捉模式:1 -双边沿+
捕获同步+
捕捉输入选择0 => P1.5 +
捕获模式+
捕获比较中断使能*/
TA0CCTL0 |= CM_3 + SCS + CCIS_0 + CAP + CCIE;

/* Timer A 控制配置=>
计时器 A 时钟源选择:1 - SMClock +
Timer A 模式控制:2 -连续运行+
Timer A 时钟输入分频器0 -无分频器*/
TA0CTL |= tassel_2 + MC_2 + ID_0;

//全局中断启用
_BIS_SR (GIE);

}

void LCD_reset ()
{
uC_port = 0x00;
_DELAY_CYCLES (20000);

uC_port =(0x03 << LCD_D0_offset)| LCD_EN;
uC_port &=~LCD_EN;
_delay_cycles (10000);

uC_port =(0x03 << LCD_D0_offset)| LCD_EN;
uC_port &=~LCD_EN;
_DELAY_CYCLES (1000);

uC_port =(0x03 << LCD_D0_offset)| LCD_EN;
uC_port &=~LCD_EN;
_DELAY_CYCLES (1000);

uC_port =(0x02 << LCD_D0_offset)| LCD_EN;
uC_port &=~LCD_EN;
__DELAY_CYCLES (1000);

}

void LCD_cmd (char cmd)
{
//发送上半字节
uC_port =((((cmd >> 4)& 0x0F)<< LCD_D0_offset)| LCD_EN;
uC_port &=~LCD_EN;

//发送低位半字节
uC_port =((cmd & 0x0F)<< LCD_D0_offset)| LCD_EN;
uC_port &=~LCD_EN;

__delay_cycles (4000);
}

void LCD_data (unsigned char dat)
{
//发送上半字节
uC_port =((((dat >> 4)和0x0F)<< LCD_D0_offset)| LCD_EN | LCD_RS);
uC_port &=~LCD_EN;

//发送低位半字节
uC_port =(((dat 和0x0F)<< LCD_D0_offset)| LCD_EN | LCD_RS);
uC_port &=~LCD_EN;

__DELAY_CYCLES (4000);//较小的延迟可能会导致缺少字符显示
}

void LCD_init ()
{
LCD_RESET(); //调用 LCD 复位

LCD_cmd (0x28); // 4位模式- 2行- 5x7字体。
LCD_cmd (0x0C); //不显示光标-不闪烁。
LCD_cmd (0x06); //自动增量—无显示移位。
LCD_cmd (0x80); //地址 DDRAM、偏移量为80h。
LCD_cmd (0x01); //清除屏幕

}

void display_line (char *line)
{
while (*行)
LCD_DATA (*线++);
}

void display_distance (char *线、int len)
{
while (len-)
如果(*行)
LCD_DATA (*线++);
其他
lcd_data ('');
}
int main()
{
char Distance_string[4];
WDTCTL = WDTPW + WDTHOLD; //停止看门狗计时器
PM5CTL0 &=~LOCKLPM5;
uC_PORT_DIR = LCD_MASK; // LCD 连接的输出方向
P1DIR |= US_TRIG; //触发到传感器的输出方向
P1DIR &=~US_ECHO; //传感器回波的输入方向
P1DIR &=~US_TRIG; //将触发器保持在低电平
P1SEL1 = US_ECHO; //从端口1将 US_echo 设置为计时器的触发器

//初始化 LCD
lcd_init();

//初始化用于超声波距离感应的计时器
timer_init();

LCD_cmd (0x80);//选择第一行(0x80 + addr)-这里的 addr = 0x00
display_line ("距离计");
LCD_cmd (0xce);//选择第二行(0x80 + addr)-这里的 addr = 0x4e
display_line ("cm");

while (1)
{
//测量距离
P1OUT ^= US_TRIG; //断言
_DELAY_CYCLES (10); // 10us 宽
P1OUT ^= US_TRIG; //断言
//_delay_cycles (60000); // 60ms 测量周期
_delay_cycles (60000); // 0.5sec 测量周期

//显示当前距离
sprintf (distance 字符串、"%d"、distance cm);
LCD_cmd (0xcb);//选择第二行(0x80 + addr)-这里的 addr = 0x4b
Display_Distance (Distance_string、3);
}

}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你(们)好

     您使用哪种超声波?  

    您使用的通信接口是什么?

    可以在调试模式下获取正确的数据吗?

    此致

    Gary  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    >      P1SEL1 = US_ECHO;                // set US_ECHO as trigger for Timer from Port-1

    根据数据表(SLAS789C)表6-21、这会将 P1.5设置为 UCA0CLK (自动输出)。 添加:

    >     P1SEL0 |= US_ECHO;                // P1.5 as TA0.0 (CCI0A) per SLAS789C Table 6-21

    ------

    >         sprintf(distance_string, "%d", distance_cm);

    65536/58 = 1129 (4位)、在这种情况下、此调用将溢出 Distance_string 并进入堆栈。

    不要使用 sprintf (以前)。 请改用 snprintf。 并使 Distance_string[]更长。

    ------

    [Edit: Noted in passing]

    >          P1OUT ^= US_TRIG;                 // assert

    P1OUT 在复位时的值未定义、因此您不知道这条线在做什么。 (a)确保 P1OUT.4最初为低电平、或(b)改为使用"|="和"&="。 我建议(b)养成良好的习惯。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是我的更新代码。 它不再显示0 cm。 它在338cm 处初始化。 几秒钟后、它显示118 cm、然后在118和119之间进行翻转斩波。 它不响应我的手移动。

    /******** //*
    项目:具有 LCD 显示屏的基于超声波的距离计 //
    *微控制器:MSP-EXP430G2 Launchpad 上的 MSP430G2231 */
    /*超声波测距模块:HC-SR04 //
    //* 16x2 LCD 显示屏:1602K27-00 */
    ******** /
    / //*
    uC 和超声波传感器连接
    P1.4 -触发
    P1.5 -回波 */
    ******** //*
    UC 和 LCD 连接
    TP1 - Vcc (+5V)
    TP3 - VSS (GND)
    P2.2 -中文
    P2.3 - RS
    P2.4 - D4
    P2.5 - D5.
    P2.6 - D6
    P2.7 - D7
    GND - RW
    GND - Ve/Vdd -通过1K 电阻器连接到 GND
    -此值决定对比度-
    即、如果没有电阻器、所有点始终可见、而是
    -较高的电阻意味着根本不显示点。
    接地- K (LED-)
    VCC - A (LED+)+5V -用于背光
    时钟:1MHz */
    ******** /#include
    
    
    #include 
    #include 
    #include 
    
    // uC GPIO 端口分配
    
    //外设引脚分配
    #define US_TRIG BIT4
    #define US_echo Bit5
    #define LCD_EN Bit2
    #define LCD_RS BIT3
    #define LCD_DATA BIT4 | BIT4 | BIT6 | BIT4
    #define LCD_D0_OFFSET 4 // BIT4,因此它是4
    #define US_MASK US_TRIG | US_ECHO
    #define LCD_MASK LCD_EN | LCD_RS | LCD_DATA
    
    unsigned int up_counter = 0;
    unsigned int distance _cm = 0;
    
    
    
    // Timer A0捕获中断例程
    P1.1 (回波)导致调用此例程*/
    #pragma vector=TIMER0_A0_vector
    __interrupt void TimerA0 (void)
    {
    IF (TA0CCTL0和 CCI) //上升沿
    {
    UP_COUNTER = TA0CCR0; //将计数器复制到变量
    }
    其他 //下降沿
    {
    //公式:以 cm 为单位的距离=(以 uec 为单位的时间)/58
    Distance_cm =(TA0CCR0 - UP_COUNTER)/58;
    }
    TA0CCTL0 &=~CCIFG;
    TA0CTL &=~TAIFG; //清除中断标志-已处理
    }
    
    void timer_init()
    {
    //将计时器 A0配置为读取回波信号:
    Timer A 捕获/比较控制0 =>
    捕捉模式:1 -双边沿+
    捕获同步+
    捕捉输入选择0 => P1.5 +
    捕获模式+
    捕获比较中断使能*/
    TA0CCTL0 |= CM_3 + SCS + CCIS_0 + CAP + CCIE;
    
    /* Timer A 控制配置=>
    计时器 A 时钟源选择:1 - SMClock +
    Timer A 模式控制:2 -连续运行+
    Timer A 时钟输入分频器0 -无分频器*/
    TA0CTL |= tassel_2 + MC_2 + ID_0;
    
    //全局中断启用
    _BIS_SR (GIE);
    
    }
    
    void LCD_reset ()
    {
    P2OUT = 0x00;
    _DELAY_CYCLES (20000);
    
    P2OUT =(0x03 << LCD_D0_OFFSET)| LCD_EN;
    P2OUT &=~LCD_EN;
    _delay_cycles (10000);
    
    P2OUT =(0x03 << LCD_D0_OFFSET)| LCD_EN;
    P2OUT &=~LCD_EN;
    _DELAY_CYCLES (1000);
    
    P2OUT =(0x03 << LCD_D0_OFFSET)| LCD_EN;
    P2OUT &=~LCD_EN;
    _DELAY_CYCLES (1000);
    
    P2OUT =(0x02 << LCD_D0_OFFSET)| LCD_EN;
    P2OUT &=~LCD_EN;
    __DELAY_CYCLES (1000);
    
    }
    
    void LCD_cmd (char cmd)
    {
    //发送上半字节
    P2OUT =((((cmd >> 4)& 0x0F)<< LCD_D0_OFFSET)| LCD_EN;
    P2OUT &=~LCD_EN;
    
    //发送低位半字节
    P2OUT =((CMD 和0x0F)<< LCD_D0_OFFSET)| LCD_EN;
    P2OUT &=~LCD_EN;
    
    __delay_cycles (4000);
    }
    
    void LCD_data (unsigned char dat)
    {
    //发送上半字节
    P2OUT =(((((dat >> 4)& 0x0F)<< LCD_D0_OFFSET)| LCD_EN | LCD_RS);
    P2OUT &=~LCD_EN;
    
    //发送低位半字节
    P2OUT =((((dat 和0x0F)<< LCD_D0_OFFSET)| LCD_EN | LCD_RS);
    P2OUT &=~LCD_EN;
    
    __DELAY_CYCLES (4000);//较小的延迟可能会导致缺少字符显示
    }
    
    void LCD_init ()
    {
    LCD_RESET(); //调用 LCD 复位
    
    LCD_cmd (0x28); // 4位模式- 2行- 5x7字体。
    LCD_cmd (0x0C); //不显示光标-不闪烁。
    LCD_cmd (0x06); //自动增量—无显示移位。
    LCD_cmd (0x80); //地址 DDRAM、偏移量为80h。
    LCD_cmd (0x01); //清除屏幕
    
    }
    
    void display_line (char *line)
    {
    while (*行)
    LCD_DATA (*线++);
    }
    
    void display_distance (char *线、int len)
    {
    while (len-)
    如果(*行)
    LCD_DATA (*线++);
    其他
    lcd_data ('');
    }
    int main()
    {
    char Distance_string[10];
    WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器
    PM5CTL0 &=~LOCKLPM5;
    P2DIR = LCD_MASK; // LCD 连接的输出方向
    P1DIR |= US_TRIG; //触发到传感器的输出方向
    P1DIR &=~US_ECHO; //传感器回波的输入方向
    P1DIR &=~US_TRIG; //将触发器保持在低电平
    P1SEL1 = US_ECHO; //从端口1将 US_echo 设置为计时器的触发器
    P1SEL0 |= US_ECHO;
    
    //初始化 LCD
    lcd_init();
    
    //初始化用于超声波距离感应的计时器
    timer_init();
    
    LCD_cmd (0x80);//选择第一行(0x80 + addr)-这里的 addr = 0x00
    display_line (" distance ");
    LCD_cmd (0xce);//选择第二行(0x80 + addr)-这里的 addr = 0x4e
    display_line ("cm");
    
    while (1)
    {
    //测量距离
    P1OUT |= US_TRIG; //断言
    _DELAY_CYCLES (10); // 10us 宽
    P1OUT |= US_TRIG; //断言
    //_delay_cycles (60000); // 60ms 测量周期
    _DELAY_CYCLES (50000); // 0.5sec 测量周期
    
    //显示当前距离
    snprintf (Distance_string、10、"%d"、Distance_cm);
    LCD_cmd (0xcb);//选择第二行(0x80 + addr)-这里的 addr = 0x4b
    Display_Distance (Distance_string、3);
    }
    
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    >      P1DIR &= ~US_TRIG;            // keep trigger at low

    这会将触发器重新转换为输入。 我怀疑您的意思是相反

    >      P1OUT &= ~US_TRIG;            // keep trigger at low

    ------------------

    >          P1OUT |= US_TRIG;                 // deassert

    这只会使引脚保持高电平。 尝试:

    >          P1OUT &= ~US_TRIG;                 // deassert (low)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢! 超声波无法正常工作的解决方案!