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.

[参考译文] EK-TM4C1294XL:读取脉宽时出现问题

Guru**** 2475160 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/684520/ek-tm4c1294xl-trouble-reading-pulse-width

器件型号:EK-TM4C1294XL

您好!

我正在尝试读取提供给 TM4C 的脉冲的长度。 我遇到了很多麻烦、我不确定如何处理、建议会非常有帮助。 我想我可能会遇到几个问题、如果我接地、就没有问题、并且会按预期输出端点= 0、端点=零、长度=零。 但是、当我连接到我的 PWM (不是代码中的 PWM、而是由另一个源生成的 PWM)时、我会得到随机值。 我不确定正在发生什么或如何解决。 我最终要测量的信号频率介于3kHz 至5kHz 之间。 此外、我认为它读取脉冲的顺序可能会有问题-这意味着它可能会读取下降沿、然后是上升沿、 现在我使用50%的 PWM 作为测试信号、这就解决了问题、但将来会出现问题-因此、如果有人有任何建议、这将是一个问题。 我试图找到一种方法让我的时钟在上升沿启动、但我在尝试如何启动时遇到了困难。

我认为我可能使用的中断不正确、我对如何准确地使用中断感到困惑、我尝试将 PD0和 PD1与传入脉冲连接在一起、 然后、当检测到上升沿时、计时器 A 将调用一个保存该值的中断来启动、然后当到达负沿时、计时器 b 将调用一个保存计时器值到结束的中断

请提供任何帮助。 -我将控制电路板上外设的所有代码保存在我发布的代码中,因为我不确定这些线路上是否有任何干扰或其他东西。

#include 
#include 
#include 
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_pwm.h"
#include "driverlib/debug.h"
#driverlib/driverlib#include "driverlib/driver.h"#driverlib#driverlib/driver.h"


#include "driverlib_dive.m#driverlib_timers/driver.h"



#include "driverlib#driverlib#driverlib#driver/h"








// Pulse
uint32_t start = 0、end = 0、length = 0的全局变量;


//函数原型
void configureUART (void);
void Pulse_Length (void);
void DummyDelay (uint32_t Count);
void configurePWM (void);
void FallingEdge (void);
void RisingEdge (void);


//********* //
//本节包含 UART 通信相关性-用于检查所写入的代码,但大多数//
////将从最终代码中注释掉-它将保留为注释,不会被删除以允许程序编辑器访问//
//使用 UART 来检查值和函数 //
//********* //

void
configureUART (void)
{
//
//启用 GPIO 和 UART 0
//
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
SysCtlPeripheralEnable (SYSCTL_Periph_UART0);

//
//为 UART 模式配置 UART 引脚
//
GPIOPinConfigure (GPIO_PA0_U0RX);
GPIOPinConfigure (GPIO_PA1_U0TX);
GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);


//UARTClockSourceSet (UART0_BASE、UART_CLOCK_SYSTEM);


//
//初始化控制台 I/O 的 UART
//
UARTStdioConfig (0、115200、g_ui32SysClock);
}

//********* //
//此部分将设置计时器来测量进入控制器的脉冲长度。 我将尝试
通过将 PD0和 PD1设置为计时器引脚来实现//////。 这些引脚都将连接到比较器。 PD0将"查找"//
上升沿、而 PD1将"查找"下降沿。 每个变量将捕获计时器值以作为开始和结束变量//
//两者之间的差异将是脉冲长度。
// //

void Pulse 长度(void)
{
//
//启用 GPIO 和计时器0
//
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);
SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);

//
//在中配置 GPIO 定时器引脚
//
GPIOPinConfigure (GPIO_PD0_T0CCP0);
GPIOPinConfigure (GPIO_PD1_T0CCP1);
GPIOPinTypeTimer (GPIO_PORTD_base、GPIO_PIN_0 | GPIO_PIN_1);

//
//初始化计时器 A 和 B,以便在边沿计时模式中向上计数
//
TimerConfigure (TIMER0_BASE、(TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP | TIMER_CFG_B_CAP_TIME_UP));

//
//定时器装载值
//
TimerLoadSet (TIMER0_BASE、TIMER_Both、g_ui32SysClock);

//
//同步两个计时器
//
TimerSynchronize (TIMER0_BASE、TIMER_0A_SYNC | TIMER_0B_SYNC);

//
// Timer A 记录正边沿时间,Timer B 记录负边沿时间
//
TimerControlEvent (TIMER0_BASE、TIMER_A、TIMER_EVENT_POS_EDGE);
TimerControlEvent (TIMER0_BASE、TIMER_B、TIMER_EVENT_NEG_EDGE);

//注册一个在计时器到达正边沿触发 int 时要调用的中断函数
IntRegister (INT_TIMER0A、RisingEdge);
//确保清除中断
TimerIntClear (TIMER0_BASE、TIMER_CAP_EVENT);
//启用指示的定时器中断源。
TimerIntEnable (TIMER0_BASE、TIMER_CAP_EVENT);
//在中断控制器中启用指定的中断。
IntEnable (INT_TIMER0A);

//注册一个中断函数,当计时器到达 neg edge trig int 时调用该函数
IntRegister (INT_TIMER0B、FallingEdge);
//确保清除中断
TimerIntClear (TIMER0_BASE、TIMER_CAPB_EVENT);
//启用指示的定时器中断源。
TimerIntEnable (TIMER0_BASE、TIMER_CAPB_EVENT);
//在中断控制器中启用指定的中断。
IntEnable (INT_TIMER0B);
}

void RisingEdge (void)
{
TimerIntClear (TIMER0_BASE、TIMER_CAP_EVENT);
Start = TimerValueGet (TIMER0_BASE、TIMER_A);
}

void FallingEdge (void)
{
TimerIntClear (TIMER0_BASE、TIMER_CAPB_EVENT);
结束= TimerValueGet (TIMER0_BASE、TIMER_B);
}

//********* //
//********* //
//********* //

/// DummyDelay ()仅在调试
void DummyDelay (uint32_t Count)
{时使用
volatile uint32_t x;

对于(x = 0;x "\nstart="%d\n"," start);="" uartprintf("\nend="%d\n"," end);="" uartprintf("\nlength="%d\n"," length);="" 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我只是想让您知道、我正在处理您的问题。 我将在今天晚些时候(接下来的5小时)向您提供最新信息。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    非常感谢、我已经在这里停留了一段时间
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、下面是我修改代码的方式:

    首先、您将加载计时器0、其最大计数值为120000000。 它在拆分时仅为16位计数器值。 我将加载值更改为0xFFFF、这是一个16位计数器的最大值。

    2.无需同步计时器,它们一起启动时保持同步。

    3.您需要考虑计数器何时在上升沿和下降沿之间溢出。 在这种情况下、为上升沿捕获的值大于为下降沿捕获的值。 在计算长度之前、我通过在下降边沿值小于上升边沿值时添加0x10000来解决此问题。 请注意、如果您测量的脉冲长度足够长、16位计数器可以第二次溢出、则这是不够的。

    4.您需要计算下降沿中断例程中的长度、或者至少在下一个上升沿发生之前计算长度。 由于打印到终端所花费的时间比测量脉冲所花费的时间要长、因此捕获的上升沿值可能会在主例程中计算长度之前更新。 希望这对您有所帮助。

    #include 
    #include 
    #include 
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    #include "inc/hw_pwm.h"
    #include "driverlib/debug.h"
    #driverlib/driverlib#include "driverlib/driver.h"#driverlib#driverlib/driver.h"
    
    
    #include "driverlib_dive.m#driverlib_timers/driver.h"
    
    
    
    #include "driverlib#driverlib#driverlib#driver/h"
    
    
    
    
    
    
    
    
    // Pulse
    uint32_t start = 0、end = 0、length = 0的全局变量;
    
    
    //函数原型
    void configureUART (void);
    void Pulse_Length (void);
    void DummyDelay (uint32_t Count);
    void configurePWM (void);
    void FallingEdge (void);
    void RisingEdge (void);
    
    
    //********* //
    //本节包含 UART 通信相关性-用于检查所写入的代码,但大多数//
    ////将从最终代码中注释掉-它将保留为注释,不会被删除以允许程序编辑器访问//
    //使用 UART 来检查值和函数 //
    //********* //
    
    void
    configureUART (void)
    {
    //
    //启用 GPIO 和 UART 0
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
    SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
    
    //
    //为 UART 模式配置 UART 引脚
    //
    GPIOPinConfigure (GPIO_PA0_U0RX);
    GPIOPinConfigure (GPIO_PA1_U0TX);
    GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
    
    
    //UARTClockSourceSet (UART0_BASE、UART_CLOCK_SYSTEM);
    
    
    //
    //初始化控制台 I/O 的 UART
    //
    UARTStdioConfig (0、115200、g_ui32SysClock);
    }
    
    //********* //
    //此部分将设置计时器来测量进入控制器的脉冲长度。 我将尝试
    通过将 PD0和 PD1设置为计时器引脚来实现//////。 这些引脚都将连接到比较器。 PD0将"查找"//
    上升沿、而 PD1将"查找"下降沿。 每个变量将捕获计时器值以作为开始和结束变量//
    //两者之间的差异将是脉冲长度。
    // //
    
    void Pulse 长度(void)
    {
    //
    //启用 GPIO 和计时器0
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);
    SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);
    
    //
    //在中配置 GPIO 定时器引脚
    //
    GPIOPinConfigure (GPIO_PD0_T0CCP0);
    GPIOPinConfigure (GPIO_PD1_T0CCP1);
    GPIOPinTypeTimer (GPIO_PORTD_base、GPIO_PIN_0 | GPIO_PIN_1);
    
    //
    //初始化计时器 A 和 B,以便在边沿计时模式中向上计数
    //
    TimerConfigure (TIMER0_BASE、(TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP | TIMER_CFG_B_CAP_TIME_UP));
    
    //
    //定时器装载值
    //
    TimerLoadSet (TIMER0_BASE、TIMER_Both、0xFFFFFFU);
    
    //
    // Timer A 记录正边沿时间,Timer B 记录负边沿时间
    //
    TimerControlEvent (TIMER0_BASE、TIMER_A、TIMER_EVENT_POS_EDGE);
    TimerControlEvent (TIMER0_BASE、TIMER_B、TIMER_EVENT_NEG_EDGE);
    
    //注册一个在计时器到达正边沿触发 int 时要调用的中断函数
    IntRegister (INT_TIMER0A、RisingEdge);
    //确保清除中断
    TimerIntClear (TIMER0_BASE、TIMER_CAP_EVENT);
    //启用指示的定时器中断源。
    TimerIntEnable (TIMER0_BASE、TIMER_CAP_EVENT);
    //在中断控制器中启用指定的中断。
    IntEnable (INT_TIMER0A);
    
    //注册一个中断函数,当计时器到达 neg edge trig int 时调用该函数
    IntRegister (INT_TIMER0B、FallingEdge);
    //确保清除中断
    TimerIntClear (TIMER0_BASE、TIMER_CAPB_EVENT);
    //启用指示的定时器中断源。
    TimerIntEnable (TIMER0_BASE、TIMER_CAPB_EVENT);
    //在中断控制器中启用指定的中断。
    IntEnable (INT_TIMER0B);
    }
    
    void RisingEdge (void)
    {
    TimerIntClear (TIMER0_BASE、TIMER_CAP_EVENT);
    Start = TimerValueGet (TIMER0_BASE、TIMER_A);
    }
    
    void FallingEdge (void)
    {
    TimerIntClear (TIMER0_BASE、TIMER_CAPB_EVENT);
    结束= TimerValueGet (TIMER0_BASE、TIMER_B);
    if (结束<开始)
    {
    结束=结束+ 0x10000;
    }
    长度=结束-开始;
    }
    
    //********* //
    //********* //
    //********* //
    
    /// DummyDelay ()仅在调试
    void DummyDelay (uint32_t Count)
    {时使用
    volatile uint32_t x;
    
    对于(x = 0;x "\nstart="%d\n"," start);="" uartprintf("\nend="%d\n"," end);="" uartprintf("\nlength="%d\n"," length);="" 
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢您、我从来没有想过您能实际编辑我的代码、非常感谢。

    我刚才有几个额外的快速问题:
    我是否正确地考虑了这一点、但我有120MHz 计时器、并且我使用的是16位计时器、因此我可以读取的最大脉冲长度为:
    (1/(120*10^6)*2^16,那么大约546.3ms?

    这意味着我要将长度值转换为时间、我必须将该值乘以(1/(120*10^6))才能使脉冲长度(以毫微秒为单位)正确吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 USER="Hisham Hafeza)]我是否正确地思考了这一点,但我有120MHz 计时器,我使用的是16位计时器,因此我可以读取的最大脉冲长度为:
    (1/(120*10^6)*2^16,大约546.3ms?[/引述]

    是的。

    [引用 user="Hisham Hafez"]这意味着对于我来说,要将长度值转换为时间,我必须将该值乘以(1/(120*10^6))才能使毫微秒的脉冲长度正确?

    答案几乎是几秒钟。