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/MSP430F5529:超声波传感器 HC-SR04和蜂鸣器

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/921964/ccs-msp430f5529-ultrasonic-sensor-hc-sr04-and-a-buzzer

器件型号:MSP430F5529

工具/软件:Code Composer Studio

大家好、我正在尝试使用通用超声波传感器 HC-SR04来检测物体、方法是测量其与传感器的距离;如果物体与该传感器之间的距离小于20cm、我应该用蜂鸣器发出警告、表明物体比实际距离更近。 距离传感器越近(如我之前所述、当距离小于20cm 时开始计数)、蜂鸣器的音调就会按比例增加(使用 PWM)。 因此、我的问题是(来自任何优化建议甚至是错误的一部分)、我想使用计时器 TA0.0 ISR 处理回波信号、我不知道如何考虑上升沿和下降沿。 是否有任何寄存器可在该边沿发生时进行调节? 我的代码中的 HC-SR04数据表中是否有我没有记住的内容? 请告诉我、会发生这种情况。  

此外、我想知道是否有人对将其应用于主项目和更困难项目的应用有任何好的想法。 我将面临一个挑战。  

事先谢谢。

我的代码是:

#include
#include

uint16_t volatile contador_microsegundos;//微秒计数器
uint32_t volatile start_time = 0;//回波脉冲的开始时间
uint32_t volatile end_time = 0;//回波脉冲结束时间  
uint16_t volatile distancia_cm = 0;//测量的距离

void Inicializacion_Relojes (void)//使用 SMCLK --> 16MHz

_bis_SR_register (SCG0);//禁用 FLL 控制循环
UCSCTL0 = 0x0000;// Ponemos el DCOx y MODx al 最小可接受
UCSCTL1 = DCORSEL_5;//选择范围取消 operación DEL DCO 范围去16MHz
UCSCTL2 = FLLD_0 | 487;// Poniendo FLLD_0 hacemos tomamos como 1 el dividesde la frecuencia de entrada del crustal de cuarzo y 487 es el valor multiplicador de FLLN
//(N + 1)*(FLLRef/n)= Fdcomsp430
//(487 + 1)*(32768/1)= 16MHz
UCSCTL3 = 0;// FLL SELREF = XT1CLK y 除数 de FLL = 1 (FLLREFDIV = FLLREFCLK/1)
UCSCTL4 |= SELA_0 | SELM_4 | SELM_4;// tomamos ACLK = XT1CLK (Cuarzo extern DE 2^15位);SMCLK = MCLK = DCOCLKDIV (DCO interno de 16MHz)
UCSCTL5 |= DIV_0 | DIVS_0;//除数参数 SMCLK = f (SMCLK)/1;ACLK = f (ACLK)/1
_BIC_SR_register (SCG0);//启用 FLL 控制环路

void init_pines_ultrasonidos (void)

P1DIR &=~BIT1;//引脚回波作为输入
P1SEL |= BIT1;//模式捕捉输入信号(CCI0A)
P2DIR |= BIT1;//引脚触发作为输出
P2SEL &=~BIT1;// GPIO 引脚
P2OUT &=~BIT1;//引脚触发低电平

void pin_bon蜂 鸣器(void)//引脚 P3.6作为 TB0.6 -> P3DIR.6 = 1;P3SEL.6 = 1 (请参阅表6-48数据表 MSP430F5529)

P3SEL |= BIT6;// P3.6作为替代函数(PARA 定时器 TB0.6 según 数据表 MSP430F5529)
P3DIR |= BIT6;//引脚作为蜂鸣器输出

void delay_microsegundos (uint16_t microsegunds_totales)//微秒延迟函数--> SMCLK

contador_microsegundos = 0;
TA2CTL |= MC_1;//向上计数模式
TA2CCTL0 |= CCIE;  
while (contader_microsegundos < microsegunds_totales);
TA2CTL &=~MC_3;//停止计时器

void TimerA0_CAPTURE (void)//用于捕获超声波传感器回波信号的计时器--> TA0.0 en modo 捕捉输入(CCI0A)

TA0CCTL0 |= CM_3 | SCS | CCIS_0 | CAP | CCIE;// CM_3:捕获信号的上升沿和下降沿;CCIS_0:CCIxA -> TimerA 中的捕获/比较;CAP:启用捕获模式;CCIE:启用中断
TA0CTL |= tassel_2 | MC_2 | ID_0 | TACLR;// tassel_2:SMCLK;MC_2:连续模式;ID_0:F (SMCLK)/1;TACLR:复位计时器

使 TimerA2 (void)//计时器保持微秒

TA2CCR0 = 15;// f (SMCLK)/1 = 16MHz ->(16·10^6个脉冲/段)·(1seg / 10^6us)= 16 - 1 = 15。
TA2CTL |= tassel_2 | ID_0 | MC_0;// tassel_2:SMCLK;ID_0:除数频率->f (SMCLK)/1;MC_0:停止模式

void TimerB0_PWM (void)//用于监控蜂鸣器 PWM 的计时器  

TB0CCR0 = 249;// período DE PWM:250脉动--> 4kHz (o 0、25ms)--> 1000脉冲/ms·0、25ms (4kHz 的倒数)= 250 -1 = 249。
TB0CCTL6 |= OUTMOD_7;// Modo CCR6:PWM 复位/设置-->增大 CCR6值也会增加占空比-->蜂鸣器幅值增大  
TB0CCR6 = 0;//占空比官方值:0 %。 TB0.6 -> TB0CCR6。
TB0CTL |= tassel_2 | ID_0 | MC_1 | TACLR;// tassel_2:SMCLK;ID_2:除数频率->f (SMCLK)/1;MC_1:向上计数模式

void main()

WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
Inicializacion_Relojes();
init_pines_ultrasonidos();
PIN_蜂 鸣器();
TimerA0_capture ();
TimerA2();
TimerB0_PWM ();
_enable_interrupt ();  
while (1){
P2OUT |= BIT1;//生成脉冲触发器  
DELAY_microsegundos (10);// 触发引脚中的10us 脉冲、用于获取测量值(请参阅数据表 HC-SR04)
P2OUT &=~BIT1;//禁用触发脉冲
if (distancia_cm < 20 && distance!= 0){//如果物体与传感器之间的距离小于20cm 并且也不同于零。
TB0CCR6 = 0;//复位决定最终 PWM 值的定时器值
TB0CCR6 += 249 -(distancia_cm * 12);// Aumentamos la frecencia del Tono del 蜂鸣器符合 estamos más certa del objetto (一个 menor distancia)
Delay_microsegundos (60000);// 60ms 测量周期、以防止触发信号进入回波信号(请参阅数据表 HC-SR04)


#pragma vector=TIMER2_A0_vector
_interrupt void timer2_A0_ISR (void)//计时器

contador_microsegundos++;  
TA2CCTL0 &=~CCIFG;  

#pragma vector=TIMER0_A0_VECTOR // ISR DE 捕捉信号 TA0.0
_interrupt void Timer0_A0 (void)

//如果上升沿条件: -->这就是问题所在
START_TIME = TA0CCR0;//在我们中进行第一次测量
//否则-->也在这里
end_time = TA0CCR0;//在我们中进行第二次时间测量
distancia_cm =(end_time - start_time)/58;//要获得以厘米为单位的距离:(以 us/58为单位的时间)

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

    > TA2CCR0 = 15;// f (SMCLK)/1 = 16MHz ->(16·10^6个脉冲/段)·(1seg / 10^6us)= 16 - 1 = 15。

    简短答案:尝试使用计时器计时单微秒不会成功。 更长的答案:进入和退出 ISR 所需的时间超过1 μ s (我通常估计20-30个 CPU 时钟)、因此您的 TA0 ISR 将始终运行(并且仍然不保持运行)。 我建议使用__delay_cycles 来实现10uec 延迟,并可能在 TB0上进行回扫以实现更长的延迟。 以下是__delay_cycles 的建议用法:

    >#define Hz 16000000UL // 16MHz MCLK

    >__DELAY_CYCLES (10*Hz/1000000UL);  //旋转10 μ s (10*16个 CPU 时钟)

    ------

    要回答您的问题:在您的 TA0 ISR 中、检查 CCI 位、它反映了您检查时捕获引脚的状态。 我说"目前"是因为引脚可能在捕获后发生了变化、但我认为最小脉冲宽度是(2*58 μ s)、因此您至少可以使用116*16=1856个时钟、这听起来很充足。

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

    我已经进行了您告诉我的更改、但似乎程序已在_delay_cycles (10)中停止;句子。 为什么会发生这种情况? 如果您看到任何可能给我带来问题的东西、请告诉我。 提前感谢!

    我的新代码是:  

    #include
    #include

    uint16_t volatile contador_milisegundos;//毫秒计数器
    uint32_t volatile start_time = 0;//回波脉冲的开始时间
    uint32_t volatile end_time = 0;//回波脉冲结束时间  
    uint16_t volatile distancia_cm = 0;//测量的距离

    define Hz 16000000UL // 16MHz MCLK

    void Inicializacion_Relojes (void)//使用 SMCLK --> 16MHz

    _bis_SR_register (SCG0);//禁用 FLL 控制循环
    UCSCTL0 = 0x0000;// Ponemos el DCOx y MODx al 最小可接受
    UCSCTL1 = DCORSEL_5;//选择范围取消 operación DEL DCO 范围去16MHz
    UCSCTL2 = FLLD_0 | 487;// Poniendo FLLD_0 hacemos tomamos como 1 el dividesde la frecuencia de entrada del crustal de cuarzo y 487 es el valor multiplicador de FLLN
    //(N + 1)*(FLLRef/n)= Fdcomsp430
    //(487 + 1)*(32768/1)= 16MHz
    UCSCTL3 = 0;// FLL SELREF = XT1CLK y 除数 de FLL = 1 (FLLREFDIV = FLLREFCLK/1)
    UCSCTL4 |= SELA_0 | SELM_4 | SELM_4;// tomamos ACLK = XT1CLK (Cuarzo extern DE 2^15位);SMCLK = MCLK = DCOCLKDIV (DCO interno de 16MHz)
    UCSCTL5 |= DIV_0 | DIVS_0;//除数参数 SMCLK = f (SMCLK)/1;ACLK = f (ACLK)/1
    _BIC_SR_register (SCG0);//启用 FLL 控制环路

    void init_pines_ultrasonidos (void)

    P1DIR &=~BIT1;//引脚回波作为输入
    P1SEL |= BIT1;//模式捕捉输入信号(CCI0A)
    P3DIR |= BIT7; //引脚触发作为输出
    P3SEL &=~BIT7; // GPIO 引脚
    P3SEL &=~BIT4; //引脚触发低电平

    void pin_bon蜂 鸣器(void)//引脚 P3.6作为 TB0.6 -> P3DIR.6 = 1;P3SEL.6 = 1 (请参阅表6-48数据表 MSP430F5529)

    P3SEL |= BIT6;// P3.6作为替代函数(PARA 定时器 TB0.6 según 数据表 MSP430F5529)
    P3DIR |= BIT6;//引脚作为蜂鸣器输出

    void delay_ms (uint16_t tiempo_milisegundos)//延迟时间(毫秒)函数--> SMCLK

    contador_milisegundos = 0;
    TA2CTL |= MC_1;//向上计数模式
    TA2CCTL0 |= CCIE;  
    while (contader_milisegundos < tiempo_milisegundos);
    TA2CTL &=~MC_3;//停止计时器

    void TimerA0_CAPTURE (void)//用于捕获超声波传感器回波信号的计时器--> TA0.0 en modo 捕捉输入(CCI0A)

    TA0CCTL0 |= CM_3 | SCS | CCIS_0 | CAP | CCIE;// CM_3:捕获信号的上升沿和下降沿;CCIS_0:CCIxA -> TimerA 中的捕获/比较;CAP:启用捕获模式;CCIE:启用中断
    TA0CTL |= tassel_2 | MC_2 | ID_0 | TACLR;// tassel_2:SMCLK;MC_2:连续模式;ID_0:F (SMCLK)/1;TACLR:复位计时器

    void init_TimerA1_ms (void)//表示延迟

    TA1CCR0 = 16000-1;// 1毫秒的脉冲
    TA1CTL |= tassel_2 | MC_1;// SMCLK、频率:16MHz;MC_1:向上计数模式

    void TimerB0_PWM (void)//用于监控蜂鸣器 PWM 的计时器  

    TB0CCR0 = 249;// período DE PWM:250脉动--> 4kHz (o 0、25ms)--> 1000脉冲/ms·0、25ms (4kHz 的倒数)= 250 -1 = 249。
    TB0CCTL6 |= OUTMOD_7;// Modo CCR6:PWM 复位/设置-->增大 CCR6值也会增加占空比-->蜂鸣器幅值增大  
    TB0CCR6 = 0;//占空比官方值:0 %。 TB0.6 -> TB0CCR6。
    TB0CTL |= tassel_2 | ID_0 | MC_1 | TACLR;// tassel_2:SMCLK;ID_2:除数频率->f (SMCLK)/1;MC_1:向上计数模式

    void main()

    WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
    Inicializacion_Relojes();
    init_pines_ultrasonidos();
    PIN_蜂 鸣器();
    TimerA0_capture ();
    init_TimerA1_ms ();
    TimerB0_PWM ();
    _enable_interrupt ();  
    while (1){
    P3OUT |= BIT7; //生成脉冲触发器  
    __DELAY_CYCLES (10*Hz/1000000UL); // 触发引脚中10us 的脉冲以获取测量值(请参阅数据表 HC-SR04)
    P3OUT &=~BIT7; //禁用触发脉冲
    if (distancia_cm < 20 && distancia_cm!= 0){//如果物体与传感器之间的距离小于20cm 并且也不同于零。
    TB0CCR6 = 0;//复位决定最终 PWM 值的定时器值
    TB0CCR6 += 249 -(distancia_cm * 12);// Aumentamos la frecencia del Tono del 蜂鸣器符合 estamos más certa del objetto (一个 menor distancia)
    DELAY_ms (60); // 60ms 测量周期、以防止触发信号进入回波信号(请参阅数据表 HC-SR04)

    #pragma vector=Timer1_A0_vector
    _interrupt void Timer1_A0_ISR (void)  

    contador_milisegundos++;
    TA1CCTL0 &=~CCIFG;

    #pragma vector=TIMER0_A0_VECTOR // ISR DE 捕捉信号 TA0.0
    _interrupt void Timer0_A0 (void)

    if (TA0CCTL0 & CCI){
    START_TIME = TA0CCR0;//在我们中进行第一次测量


    否则{
    end_time = TA0CCR0;//在我们中进行第二次时间测量
    distancia_cm =(end_time - start_time)/58;//要获得以厘米为单位的距离:(以 us/58为单位的时间)

    TA0CTL &=~TAIFG;

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

    如果尚未进行捕获(尚未捕获)、则_delay_cycles 是循环将花费大部分时间的地方。 (呼叫完成。)

    1) 1)您没有等待捕获发生。 在4m 时,回波最多可能需要4*100*0.058=23毫秒,因此您不想比这更早地发送新脉冲。 如果你要处理人类、每100ms 一个脉冲可能就足够了。 我建议您向上移动 DELAY_ms (60)以跟随脉冲、因此它有两个(相关)用途。

    2) 2)我看不到您初始化 TA2的位置。 否则、我预计 delay_ms()将挂起。

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

    好的、我更改了代码中您所说的内容(我已经了解 delay 函数、例如 delay_ms (100)、应该在 P3OUT &=~BIT7之后直接运行; //禁用触发脉冲。 但问题尚未得到解决、它会在 delay_ms 函数的 while 循环中每次停止。 所以我的结论是、当我接近它时、传感器不会应答和检测我的手、这就是它在那里停止的原因、因为主函数看不到你说过的任何情况。 但我不知道为什么会发生这种情况? 可能是因为我在 TimerA0.0 ISR 中使用了错误的寄存器? 谢谢。  

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

    啊、我错过了您将 ms 计时器更改为 TA1的机会。 (使用"代码标签"(" "按钮、第二行向右)、使读取操作更加容易。)

    您需要添加到 init_TimerA1_ms:

    >  TA1CCTL0 |= CCIE; //每1ms 生成一次中断

    尽管 DELAY_ms 挂起、捕获仍应(一次)发生。 您在 start_time 中看到了什么吗? 您可能需要在 Timer0_A0()处设置断点。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Hi, i've made a few changes to the code. For example, I have change the capture input signal to P1.2 because of the pin P1.1 is a button and i cannot connect any wire to the ECHO signal then. 
    Also i've created my own delay us function, but when i compile all the code sensor doesn't detect my hand in distance and variable distance_cm keeps in value of 0 everytime.
    I then stop the execution to see where it stops and it appears a message 'ISR_TRAP' (i think related to delay_ms function) but i don't know why, because this function i've used in
    other projects before and hasn't come with any problem. Do you see anything weird in the code that i might not see now? Thanks beforehand!

    #include <msp430.h> #include <stdint.h> uint16_t volatile contador_milisegundos; // miliseconds counter uint32_t volatile start_time = 0; // start time of ECHO pulse uint32_t volatile end_time = 0; // end time of ECHO pulse uint16_t volatile distancia_cm = 0; // distance measured void Inicializacion_Relojes(void) // to use the SMCLK --> 16 MHz { __bis_SR_register(SCG0); // Disable the FLL control loop UCSCTL0 = 0x0000; // Ponemos el DCOx y MODx al minimo posible UCSCTL1 = DCORSEL_5; // Seleccionamos un rango de operación del DCO range de 16MHz UCSCTL2 = FLLD_0 | 487; // Poniendo FLLD_0 hacemos tomamos como 1 el divisor de la frecuencia de entrada del cristal de cuarzo y 487 es el valor multiplicador de FLLN // (N + 1) * (FLLRef/n) = Fdcomsp430 // (487 + 1) * (32768/1) = 16MHz UCSCTL3 = 0; // FLL SELREF = XT1CLK y divisor de FLL = 1 (FLLREFDIV = FLLREFCLK/1) UCSCTL4 |= SELA_0 | SELS_4 | SELM_4; // Tomamos ACLK = XT1CLK (Cuarzo externo de 2^15 bits); SMCLK = MCLK = DCOCLKDIV (DCO interno de 16 MHz) UCSCTL5 |= DIVA_0 | DIVS_0; // Divisor para SMCLK = f(SMCLK)/1; ACLK = f(ACLK)/1 __bic_SR_register(SCG0); // Enable the FLL control loop } void init_pines_ultrasonidos(void) { P1DIR &= ~BIT2; // Pin ECHO as input P1SEL |= BIT2; // mode Capture Input Signal (CCI0A) P3DIR |= BIT7; // Pin TRIGGER as output P3SEL &= ~BIT7; // Gpio pin P3SEL &= ~BIT7; // Pin TRIGGER low } void pin_buzzer_and_LED(void) // pin P3.6 as TB0.6 --> P3DIR.6 = 1; P3SEL.6 = 1 (see Table 6-48 Datasheet MSP430F5529) { P3SEL |= BIT6; // P3.6 as alternative function (para Timer TB0.6 según datasheet MSP430F5529) P3DIR |= BIT6; // Pin as buzzer output P4SEL &= ~BIT7; // Pin GPIO P4DIR |= BIT7; // como salida (Led2, verde) P4OUT &= ~BIT7; // led inicialmente apagado } void delay_ms(uint16_t tiempo_milisegundos) // Function for delay of miliseconds --> SMCLK { contador_milisegundos = 0; TA1CTL |= MC_1; // UP MODE TA1CCTL0 |= CCIE; while(contador_milisegundos < tiempo_milisegundos); TA1CTL &= ~MC_3; // stop the timer }

    void delay_us(uint16_t tiempo_microsegundos) // Function for delay de us --> SMCLK a 16 MHz

    while (tiempo_microsegundos){
    _DELAY_CYCLLES (16);//为16MHz 设置16值
    Tiempo_microsegundos--;

    
    void TimerA0_capture(void) // Timer for capturing ECHO signal of ultrasonic sensor --> TA0.0 en modo Capture Input (CCI0A)
    {
        TA0CCTL1 |= CM_3 | SCS | CCIS_0 | CAP | CCIE; // CM_3: Capture both rising and falling edges of signal; CCIS_0: CCIxA --> Capture/Compare in TimerA; CAP: enable capture mode; CCIE: enable interrupciones
        TA0CTL |= TASSEL_2 | MC_2 | ID_0 | TACLR; // TASSEL_2: SMCLK; MC_2: Continuous Mode; ID_0: f(SMCLK)/1; TACLR: Reset Timer
    }
    
    void init_TimerA1_ms(void) // for delay
    {
        TA1CCR0 = 16000-1; // pulses for 1 milisecond
        TA1CTL |= TASSEL_2 | MC_0; // SMCLK, Freq: 16 MHz; MC_1: Stop Mode
    }
    
    void TimerB0_PWM(void) // Timer for monitoring PWM of buzzer
    {
        TB0CCR0 = 249; // Período de PWM: 250 pulsos --> 4kHz (o 0,25 ms) --> 1000 pulses/ms · 0,25 ms (inverse of 4kHz) = 250 - 1 = 249.
        TB0CCTL6 |= OUTMOD_7; // Modo CCR6: PWM Reset/Set --> increasing CCR6 value will also increase Duty Cycle --> more buzzer amplitude
        TB0CCR6 = 0; // Duty Cycle inicial: 0 %. TB0.6 --> TB0CCR6.
        TB0CTL |= TASSEL_2 | ID_0 | MC_1 | TACLR; // TASSEL_2: SMCLK; ID_2: Divisor freq --> f(SMCLK)/1; MC_1: Up Mode
    }
    
    void main()
    {
        WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
        Inicializacion_Relojes();
        init_pines_ultrasonidos();
        pin_buzzer_and_LED();
        TimerA0_capture();
        init_TimerA1_ms();
        TimerB0_PWM();
        __enable_interrupt();
        while(1){
            P3OUT |= BIT7; // generate pulse TRIGGER
            delay_us(10); // pulse of 10 us in TRIGGER pin for obtaining the measures (see datasheet HC-SR04)
            P3OUT &= ~BIT7; // disable TRIGGER pulse
            delay_ms(100); // delay over 60 ms measurement cycle in order to prevent trigger signal to the echo signal (see Datasheet HC-SR04)
            if(distancia_cm >= 2 && distancia_cm <= 400){ // if distance between sensor range.. 
                P4OUT |= BIT7; // LED green ON
    if(distancia_cm < 50){ TB0CCR6 = 0; // Reset value of Timer that decides the final PWM value TB0CCR6 += 249 - (distancia_cm * 12); // increase amplitude of the buzzer tone as approaching to the sensor
    } } } } #pragma vector=TIMER1_A0_VECTOR __interrupt void timer1_A0_ISR(void) { contador_milisegundos++; TA1CCTL0 &= ~CCIFG; } #pragma vector=TIMER0_A0_VECTOR // ISR de Capture Signal TA0.1 __interrupt void Timer0_A0(void) { if(TA0CCTL1 & CCI){ // Read the CCI bit (ECHO signal) --> CCI reflects the state of Captura pin --> ECHO signal start_time = TA0CCR1; //takes first time measure in us } else{ end_time = TA0CCR1; //takes second time measure in us distancia_cm = (uint16_t)((end_time - start_time)/58); // to obtain distance in centimeters: (time in us/58) --> (see Datasheet HC-SR04) } TA0CCTL1 &= ~CCIFG; }
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    ISR_TRAP 意味着您已启用中断(发生的中断)、但没有用于中断的 ISR。 在本例中:

    >TA0CCTL1 |= CM_3 | SCS | CCIS_0 | CAP | CCIE;

    #pragma vector=TIMER0_A0_VECTOR // ISR DE 捕捉信号 TA0.1

    使用 TA0CCTL1:CCIE 需要一个不同的向量:

    #pragma vector=TIMER0_A1_vector // ISR de Capture Signal TA0.1

    有两个 TimerA 矢量-一个用于 CCR0、另一个用于所有其他矢量。 [参考用户指南(SLAU208Q)第17.2.6.1-2节]

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

    非常感谢! 正如您所说的那样、这就是问题所在。 项目看起来正常工作、但距离值错误、例如我将手放在传感器前面(最大20cm 或30cm)、正如我在 CCS 调试中的表达式中看到的、距离值测量值为134cm。 但无论如何、感谢您的帮助!

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

    BTW 当距离值低于50 (在主函数中、该值应进入第二个 IF 条件、实际上是这样)时、蜂鸣器不会发出声音。 有什么想法、为什么会发生这种情况、不会获得错误的距离值?

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

    >TB0CCR6 += 249 -(distancia_cm * 12);

    我不确定您是否希望看到"12"。 我首先假设距离为50cm,在这种情况下,249-(50*12)=0xFEA1 (-351)。 当被添加到任何0-250值时、会产生一个负(大无符号)值。 如果计数器永远不会达到 CCR6中的值、它不会改变信号、并且永远不会达到0xFEA1。 输出将保持恒定(高电平)、因此没有声音。

    更一般而言、占空比只有250 (=CCR0)个可能值、cm 测量只有400 (标称值)个可能值、因此第一个近似值是2分频、而不是12倍乘。 这只是一个开始的地方、因为您可能会发现某些范围不有趣(太大、太软)。 在任何情况下、您都需要在设置 CCR6之前绑定您计算的值(在0-250范围内)。

    [编辑:更正了拼写错误]

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    I've made a lot of changes in the code, since i realized that, by using 16 MHz frequency on TimerA0_Capture, i will get a Timer overflow with just 4 ms of echo signal. So I decided to apply a frequency divider by 8 (which means that this Timer is now working at 2 MHz and I can avoid overflow in vast majoritity of cases, as i have not overlflow until 32.7 ms).
    Another issue I

    #include <msp430.h> #include <stdint.h> uint16_t volatile contador_milisegundos; // miliseconds counter uint16_t volatile distancia_cm = 0; // distance measured
    uint16_t volatile capture_overflow = 0; // Variable to take into account if an overflow occurs or not --> modified by ISR void Inicializacion_Relojes(void) // to use the SMCLK --> 16 MHz { __bis_SR_register(SCG0); // Disable the FLL control loop UCSCTL0 = 0x0000; // Ponemos el DCOx y MODx al minimo posible UCSCTL1 = DCORSEL_5; // Seleccionamos un rango de operación del DCO range de 16MHz UCSCTL2 = FLLD_0 | 487; // Poniendo FLLD_0 hacemos tomamos como 1 el divisor de la frecuencia de entrada del cristal de cuarzo y 487 es el valor multiplicador de FLLN // (N + 1) * (FLLRef/n) = Fdcomsp430 // (487 + 1) * (32768/1) = 16MHz UCSCTL3 = 0; // FLL SELREF = XT1CLK y divisor de FLL = 1 (FLLREFDIV = FLLREFCLK/1) UCSCTL4 |= SELA_0 | SELS_4 | SELM_4; // Tomamos ACLK = XT1CLK (Cuarzo externo de 2^15 bits); SMCLK = MCLK = DCOCLKDIV (DCO interno de 16 MHz) UCSCTL5 |= DIVA_0 | DIVS_0; // Divisor para SMCLK = f(SMCLK)/1; ACLK = f(ACLK)/1 __bic_SR_register(SCG0); // Enable the FLL control loop } void init_pines_ultrasonidos(void) { P1DIR &= ~BIT2; // Pin ECHO as input P1SEL |= BIT2; // mode Capture Input Signal (CCI0A) P3DIR |= BIT7; // Pin TRIGGER as output P3SEL &= ~BIT7; // Gpio pin P3SEL &= ~BIT7; // Pin TRIGGER low } void pin_buzzer_and_LED(void) // pin P3.6 as TB0.6 --> P3DIR.6 = 1; P3SEL.6 = 1 (see Table 6-48 Datasheet MSP430F5529) { P3SEL |= BIT6; // P3.6 as alternative function (para Timer TB0.6 según datasheet MSP430F5529) P3DIR |= BIT6; // Pin as buzzer output P4SEL &= ~BIT7; // Pin GPIO P4DIR |= BIT7; // como salida (Led2, verde) P4OUT &= ~BIT7; // led inicialmente apagado } void delay_ms(uint16_t tiempo_milisegundos) // Function for delay of miliseconds --> SMCLK { contador_milisegundos = 0; TA1CTL |= MC_1; // UP MODE TA1CCTL0 |= CCIE; while(contador_milisegundos < tiempo_milisegundos); TA1CTL &= ~MC_3; // stop the timer }

    void delay_us(uint16_t tiempo_microsegundos) // Function for delay de us --> SMCLK a 16 MHz

    while (tiempo_microsegundos){
    _DELAY_CYCLLES (16);//为16MHz 设置16值
    Tiempo_microsegundos--;

    
    void TimerA0_capture(void) // Timer for capturing ECHO signal of ultrasonic sensor --> TA0.0 en modo Capture Input (CCI0A)
    {
        TA0CCTL1 |= CM_3 | SCS | CCIS_0 | CAP | CCIE; // CM_3: Capture both rising and falling edges of signal; CCIS_0: CCIxA --> Capture/Compare in TimerA; CAP: enable capture mode; CCIE: enable interrupciones
        TA0CTL |= TASSEL_2 | MC_2 | ID_3 | TACLR; // TASSEL_2: SMCLK; MC_2: Continuous Mode; ID_3: f(SMCLK)/8 --> f = 2 MHz
    }
    
    void init_TimerA1_ms(void) // for delay
    {
        TA1CCR0 = 16000-1; // pulses for 1 milisecond
        TA1CTL |= TASSEL_2 | MC_0; // SMCLK, Freq: 16 MHz; MC_1: Stop Mode
    }
    
    void TimerB0_PWM(void) // Timer for monitoring PWM of buzzer
    {
        TB0CCR0 = 249; // Período de PWM: 250 pulsos --> 4kHz (o 0,25 ms) --> 1000 pulses/ms · 0,25 ms (inverse of 4kHz) = 250 - 1 = 249.
        TB0CCTL6 |= OUTMOD_7; // Modo CCR6: PWM Reset/Set --> increasing CCR6 value will also increase Duty Cycle --> more buzzer amplitude
        TB0CCR6 = 0; // Duty Cycle inicial: 0 %. TB0.6 --> TB0CCR6.
        TB0CTL |= TASSEL_2 | ID_0 | MC_1 | TACLR; // TASSEL_2: SMCLK; ID_2: Divisor freq --> f(SMCLK)/1; MC_1: Up Mode
    }
    
    void main()
    {
        WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
        Inicializacion_Relojes();
        init_pines_ultrasonidos();
        pin_buzzer_and_LED();
        TimerA0_capture();
        init_TimerA1_ms();
        TimerB0_PWM();
        __enable_interrupt();
        while(1){
            P3OUT |= BIT7; // generate pulse TRIGGER
            delay_us(10); // pulse of 10 us in TRIGGER pin for obtaining the measures (see datasheet HC-SR04)
            P3OUT &= ~BIT7; // disable TRIGGER pulse
            delay_ms(100); // delay over 60 ms measurement cycle in order to prevent trigger signal to the echo signal (see Datasheet HC-SR04)
            if(distancia_cm >= 2 && distancia_cm <= 400){ // if distance between sensor range.. 
                P4OUT |= BIT7; // LED green ON
    if(distancia_cm < 50){ TB0CCR6 = 0; // Reset value of Timer that decides the final PWM value TB0CCR6 += 249 - (distancia_cm >> 2); // increase amplitude of the buzzer tone as approaching to the sensor
    } }
    capture_overflow = 0; // reset } } #pragma vector=TIMER1_A0_VECTOR __interrupt void timer1_A0_ISR(void) { contador_milisegundos++; TA1CCTL0 &= ~CCIFG; } #pragma vector=TIMER0_A0_VECTOR // ISR de Capture Signal TA0.1 __interrupt void Timer0_A0(void) { if(TA0CCTL1 & CCI){ // Read the CCI bit (ECHO signal) --> CCI reflects the state of Captura pin --> ECHO signal TA0CTL |= TACLR; //first time measure --> reset timer to begin with zero in order to have more odds to avoid overflow and also avoid using useless start_time variable. } else{ if(TA0CCTL1 & COV){ // if an overflow occurs
    capture_overflow++;
    }
    // distance in cm --> we add to the TA0CCR1 value the times overflow has ocurred and we also know that everytime overflow happens means that we had arrived to 65535 value --> taht's why i multiply
    // also i multiply by 0.5 because is the duration of each pulse signal in us, since i am using 2 MHz freq in capture timer --> 1/(2*10^6) = 0.5 microseconds
    distancia_cm = ((TA0CCR1+(capture_overflow*65535))*0.5)/58; // to obtain distance in centimeters: (time in us/58) --> (see Datasheet HC-SR04) } TA0CCTL1 &= ~CCIFG; }
    但似乎仍然完全不起作用。 您对我所做的更改有何看法? 感谢您的复制!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您可以使用 TA0EX0进一步对 TA0进行分频。 您实际上不需要、因为23ms (现在)为46000、这仍然适用。 另一方面、由于您正在计算 cm、因此您的量子为(58usec/2)。

    COV 并不意味着计数器已缠绕到起始(最后一次捕捉)点、它意味着您没有足够快地进行捕捉、从而丢失了一个捕捉。 (在该程序中、这实际上似乎是不可能的。) 对 COV 的响应将放弃测量、直到下一个脉冲。

    如果您想检测计数器何时返回到起始位置、那么我要做的就是:选择另一个 CCR、比如 CCR1、然后设置 CCIE。 每次捕获时、从捕获的值(CCR0)中减去1并将其存储在 CCR1中。 如果 CCR1上的 CCIFG 曾经关闭(比较匹配),这意味着你已经打包了--实际上是一个超时--你应该放弃该读数。

    尝试计数这些事件(您现在使用 COV 的方式)很诱人、但我的经验是、正确(在所有临界情况下)比看起来更难。 您不需要--它会在超过32ms 的时间内缠绕,这大于传感器的指定范围--因此超时应被视为故障。

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

    感谢所有的帮助! 我有很多你。 BTW、我首先尝试与该传感器进行通信、但我不知道在该传感器上应用更大的项目。 您是否有任何建议需要考虑?  

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

    我很高兴您能正常工作。

    我没有想到任何其他 HC-SR04应用程序、但 Google 可能会发现很多人都在使用它做了富有想象力的事情。

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

    你好! 最后一个问题、最终解决我在计时器捕获模式下发现的所有问题。 我对我的代码进行了这种更改、因为我想尝试考虑溢出、我的想法是:

    首先、我粘贴控制捕获输入信号的定时器函数、在该函数中、我将 TAIE 位置1、以便能够使用 TACTL 的 TAIFG 位来控制溢出情况。 我使用 TimerA0.1、因为在 P1.1中有一个按钮、我无法将任何线缆连接到质子、以确保它也连接到回声引脚。  

    void TimerA0_CAPTURE (void) //用于捕获超声波传感器回波信号的计时器--> TA0.1 en modo 捕捉输入(CCI1A)

          TA0CCTL1 |= CM_3 | SCS | CCIS_0 | CAP | CCIE; // CM_3:捕获信号的上升沿和下降沿;CCIS_0:CCIxA ->捕获/比较中断
          TA0CTL |= tassel_2 | MC_2 | ID_3 | TAIE;// tassel_2:SMCLK;MC_2:连续模式;ID_3:F (SMCLK)/8 -> f = 2MHz;TAIE:启用 TAIFG 中断

    当我使用2MHz 计时器频率时、我认为每个脉冲应该进行测量(以时间为单位)、因此我决定创建一个常量、像偏移一样可以添加到距离中。 该常量计算每次溢出发生时经过的秒数。

    常量浮点溢出=(65535 /(2 * 10^6));// 65535个脉冲/2 MHz = 0.5us

    #pragma vector=TIMER0_A1_vector // ISR DE 捕捉信号 TA0.1:TAIE、CCR1... -->由于来自 CCR1的 TAIE/TAIFG appart 而发生的中断 ISR
    _interrupt void Timer0_A1 (void)

         switch (TAIV){//此行会给我一个执行错误,就像 TAIV 根本不存在一样,但我在用户指南和 TI 示例中看到了它。  
             案例2:// TA0CCR1 (请参阅17.3.5用户指南--> TAxIV 寄存器)
                IF (TA0CCTL1和 CCI){//读取位 CCI (回波信号)  
                   TA0CTL |= TACLR;//回波高电平-->复位时间-->开始对回波信号进行计数
                }
                否则{
                    //距离公式(数据表 HC-SR04)-->距离(单位:cm)=(时间、单位:us)/58
                    //回声低-->停止计数
                    distancia_cm =(TA0CCR1*0.5 + CAPTURE_OVERflow)/58;//:(value_TA0CCR1*脉冲持续时间,单位为 us --> 0.5,因为我以2MHz 的频率工作)/58 -->(请参阅数据表 HC-SR04)
                }
                中断;

             情况14://定时器溢出;中断标志:TAxCTL TAIFG
                caption_overflow += overflow;// TAIFG 产生的中断-->每当它到达其最大值时,它会将计数器重置为0并设置位 TAIFG (请参阅用户指南)
                中断;
             }

    您是如何以这种方式看到它的? 它在 TAIV 寄存器中看起来有问题、因为它看起来不存在。 此外,如果我把其他情况(4、6、8、8)放在这里, 那么、TAIV 的其他部分、即使在他们不关心我的项目的情况下也是如此?

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

    您需要 TA0IV、而不是 TAIV。 您不需要列出所有案例、但最好包含一个"默认:"案例。

    这样做将读数略低(短)、因为您的0点比第一次捕获(延迟)晚了一段时间。 减去两个捕获可以避免这种情况。