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.

[参考译文] TM4C129XNCZAD:从板上的定时器针脚获取转速计计数

Guru**** 2391415 points
Other Parts Discussed in Thread: EK-TM4C1294XL

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1082056/tm4c129xnczad-getting-tachometer-counts-from-timer-pins-on-the-board

部件号:TM4C129XNCZAD
“线程”中讨论的其它部件:EK-TM4C1294XL

大家好,我有一个定制板,可以控制一些风扇并记录它们的 RPM。 风扇通过 PWM 信号进行控制,风扇有一个转速表,该转速表连接到主板上的多个 CCP 针脚。 我将使用连接到 T0CCP1的风扇1来解决此问题,因为所有其它 风扇都应该相同,并为其配置不同的针脚。 这是我目前为止拥有的代码和电路。

与转速表的针脚连接:

风扇转速表输出信息。

设置计时器的代码:

static void InitializeTimer0( uint32_t ui32SysClock )
{

    //Enable timer 0 peripheral
    SysCtlPeripheralEnable( SYSCTL_PERIPH_TIMER0 );
    while(!SysCtlPeripheralReady( SYSCTL_PERIPH_TIMER0 )){

    }

    //Enable GPIO A peripheral since the CCP pins are on there.
    SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA );
    while(!SysCtlPeripheralReady( SYSCTL_PERIPH_GPIOA )){

    }

    //Configure the GPIO pins used for CCP operation.
    GPIOPinConfigure( GPIO_PA1_T0CCP1 );

    //Set the pins as timer pins.
    GPIOPinTypeTimer(PA_FAN_TACHOMETER_PORT, PA1_TCU_FAN_1_TACHOMETER_PIN);

    //Initialize the timer so timer 0B counts the number of positive edges while timer 0A counts up.
    //When timer 0B reaches a preset value check the timer 0A value and get the number of pulses/time.
    TimerConfigure(TIMER0_BASE, ( TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC | TIMER_CFG_B_CAP_TIME ));

    //Set the timers so timerA counts to 0.1S, and timerB counts to 1000 positive edges.
    TimerLoadSet(TIMER0_BASE, TIMER_BOTH, ui32SysClock/10);

    TimerControlEvent(TIMER0_BASE, TIMER_B, TIMER_EVENT_POS_EDGE);

    //set the initial value of the counter to 0.
    TCUFan1TimerValue = 0;

    IntRegister(INT_TIMER0B, InterruptHandlerTimer0B);
    //Configure timerB interrupt to occur when the count is reached.
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    IntEnable(INT_TIMER0A);

    TimerIntEnable(TIMER0_BASE, TIMER_CAPB_EVENT);
    IntEnable(INT_TIMER0B);

    // Enable the timers.
    TimerEnable(TIMER0_BASE, TIMER_A);
    TimerEnable(TIMER0_BASE, TIMER_B);

}

计时器的中断处理程序:

//Timer0B interrupt handler that calculates the RPM of TCU Fan 1.
void InterruptHandlerTimer0A( void ){

    //Clear the interrupt.
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    //read the fan rpm data.
    Laser.Miscellaneous.Monitor.TCUFan1RMP = TCUFan1TimerValue*300;
    TCUFan1TimerValue=0;

    //Reset the value in timer0B to 0
    HWREG(TIMER0_BASE  + TIMER_O_TBV) = 0;

}

//interrupt handler for timer0B.
void InterruptHandlerTimer0B( void ){
    TimerIntClear(TIMER0_BASE, TIMER_CAPB_EVENT);
    TCUFan1TimerValue++;
}

对于在 Timer0A 中断处理程序中设置的名为 TCUFan1RPM 的变量,我获得0。 逻辑是在 信号的位置边缘增加全局变量 TCUFan1TimerValue,并查看每次 timer0A 用完时该变量的大小。 我还尝试这样做,这样我就可以对 POSedge 进行1000次采样,并在超时事件上进行采样, 查看 Timer0A 的值以了解获取1000个位置所需的时间,但此方法不起作用,因为 Timer0B 不想处于“捕获”模式,也不想处于超时状态。  

如果有任何帮助,我希望第二个逻辑能够正常工作,但如果我们能使第一个版本正常工作,我也会很高兴。

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

    您好,

     首先,我看不到你们的捕获。 如果显示有用信息,请上传。  

     您在代码中的注释表示您要使用 timerB 计算1000条边线。 该评论是否正确描述了您希望在申请中实现的目标? 如果是这种情况,则需要使用边线计数模式,而不是边线时间模式。 您可以使用 timer_CFG_B_CAP_COUNT_UP 来计算输入的边缘。 您还需要设置载荷寄存器并匹配寄存器以计算最多的边线数。 到达匹配寄存器后,它将生成中断。 有关说明,请参阅数据表。 如果您有问题,我会以红色突出显示以下文本。 您可以执行如下类似代码的操作。 如果边缘计数模式不是您要寻找的模式,请说明您为什么要使用边缘计时模式。 在边线时间模式下,只要检测到输入边线,就会保存当前计时器计数值,以便您可以确定两条边线之间经过的时间量。 如果您正在寻找这种方法,则可以参考 C:\ti\TiaWare_C_Series-2.2.0.295\Examples\boards\EK-tm4c1294xl\TIMER _Edge_capture 中的示例,该示例就是这样做的。 在这种模式下,如果在计时器到期前确实出现了边缘,则还需要检查范围的输入。 您的代码中只使用16位计数器。 您没有使用预校准器将计时器延长到24位。

        TimerControlEvent(TIMER4_BASE, TIMER_A, TIMER_EVENT_POS_EDGE);
        TimerLoadSet(TIMER0_BASE, TIMER_B,1000);
        TimerMatchSet(TIMER0_BASE, TIMER_B,1000);
        IntEnable(INT_TIMER0B);
        TimerIntEnable(TIMER0_BASE, TIMER_CAPB_MATCH);

    在边缘计数模式下,计时器配置为24位上/下计数器,包括可选的
    在 GPTM Timer n Pressale (GPTMTnPR)寄存器中存储了计数值上限的预校准器
    和 GPMTnR 寄存器中的下位。 在此模式下,计时器可以捕获三个
    事件类型:上升边缘,下降边缘或两者。 要将计时器置于边缘计数模式,请执行
    必须清除 GPMTnMR 寄存器的 TnCMR 位。 计时器计算的边线类型
    由 GPTMCTL 寄存器的 TnEVENT 字段确定。 在初始化过程中,计数下降
    将 GPMTnMATCHR 和 GPMTnPMR 寄存器配置为区别
    在 GPMTnILR 和 GPMTnPR 寄存器中的值与 GPMTnMATCHR 和之间
    GPMTnPMR 寄存器等于必须计数的边缘事件数。 在加计数模式下,
    计时器从0x0计数到 GPMTnMATCHR 和 GPMTnPMR 寄存器中的值。 注
    在执行向上计数时,GPMTnPR 和 GPMTnILR 的值必须大于
    与 GPMTnPMR 和 GPMTnMATCHR 的值相比。 第963页的表13-7显示了这些值
    在启用计时器时加载到计时器寄存器中的。

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

    我在发布这条非常抱歉的消息后发现了边缘计数与边缘时间的错误, 使用您发送的代码,我可以执行我的预期操作,但现在我考虑使用边线时间模式,并查看边线之间的距离,然后将此值用作 RPM 的表示可能会更好,因此我正在考虑这样做 一个镜头。

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

    您好,

     好的,在这种情况下, 我认为你 真的不需要时间。 您只需要在边缘时间模式下使用 timerB。 请参考我在上一次答复中提到的边线时间示例。  

    C:\ti\tiaWare_C_Series-2.2.0.295\examples\boards\EK-tm4c1294xl\timer_Edge_capture

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

    谢谢你的帮助。