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.

[参考译文] TM4C129ENCZAD:用于测量 PWM 占空比的通用计时器

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1466229/tm4c129enczad-general-purpose-timers-to-measure-pwm-duty-cycle

器件型号:TM4C129ENCZAD

工具与软件:

您好!
我正在尝试  在边沿计时器配置中使用通用计时器模块的捕获比较模式来测量 PWM 占空比。 测得信号的频率为482Hz。  以下是用于引脚初始化的代码。  

```SysCtlPeripheralEnable (SYSCTL_PERIPH_TIMER2);
TimerConfigure (TIMER2_BASE、
(TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP | TIMER_CFG_B_CAP_TIME_UP);
TimerControlEvent (TIMER2_BASE、TIMER_A、TIMER_EVENT_POS_EDGE);
TimerControlEvent (TIMER2_BASE、TIMER_B、TIMER_EVENT_NEG_EDGE);
TimerEnable (TIMER2_BASE、TIMER_A)
TimerEnable (TIMER2_BASE、TIMER_B);```μ s

上述 init 函数全部属于 tivaware 库。 我认为初始化效果很好、因为我能够在引脚上提供 PWM 信号时获得一些计时器值。  

下面是我用于记录总 PWM 脉冲的代码。

```void SpinMotorImpl::MeasureSpinSpeed (){
静态 uint16_t 计数器= 0;
静态 bool previous_measured = false;
静态 uint32_t spin_mot_hlfb_rising prev=0;
uint32_t STATUS_pos = TimerIntStatus (TIMER2_BASE、FALSE);
if ((STATUS_pos & TIMER_CAPA_EVENT )!= 0){
const uint32_t spin_mot_hlfb_rising =(TimerValueGet (TIMER2_base、TIMER_A)&0x00FFFFFF);
const uint32_t spin_mot_hlfb_falling =(TimerValueGet (TIMER2_base、TIMER_B)&0x00FFFFFF);
if (!previous_measured)

SPIn_mot_hlfb_rising = SPIn_mot_hlfb_rising;
previous_measured=true;
}
设计

计数器++;
if (counter==1000)

syslog->printf (syslog_level_info、"m_evt=MeasureSpinSpeed 时序=%ld、%ld、%ld "、SPIn_mot_hlfb_rising、 SPIn_mot_hlfb_rising prev、spin_mot_hlfb_falling);
计数器= 0;
}
previous_measured = false;
TimerReset (TIMER2_BASE、TIMER_BOTH)
}
TimerIntClear (TIMER2_BASE、TIMER_CAPA_EVENT);
TimerIntClear (TIMER2_BASE、TIMER_CAPB_EVENT);
}
}```

MeasureSpinSpeed 的调用间隔为1ms。 我无法在每个周期进行打印 、因为这会使微型系统崩溃、我猜是因为它过载、这就是为什么我有一个计数高达1000的计数器、并且每秒都会以这种方式进行打印的原因。  
根据此代码、我预计 SPIn_mot_hlfb_rising 会高于 SPIn_mot_hlfb_rising 和 SPIn_mot_hlfb_falling 之间的某个位置(两个上升沿之间应该有一个下降沿)。

但是、我看到的是:

M_evt=MeasureSpinSpeed 时序=27,640,40840830,43379 ca.

根据此日志消息:spin_mot_hlfb_rising 为40830、 spin_mot_hlfb_falling = 43379和 spin_mot_hlfb_rising =  27640。每个日志消息的值都不同、但这些值之间的差异是一致的。

我有两个问题:

1.计时器似乎在65536左右换行。 我不知道如何对它进行预分频。 数据表显示、在边沿定时器模式中、预分频字节只是作为16位信号的额外8位。 我猜这会使它成为24位信号、因此我要使用0x00FFFFFF 提取24位、但它似乎仍然环绕65536。

2.为什么上升沿的当前计时器值始终低于前一个上升沿、而下降沿始终高于两者。 对于482Hz 的信号、轻触1kHz 的信号应该没有问题。 下降沿应该在它们之间、除非它绕在它们之间的某个位置、在这种情况下、弄清楚如何进行预分频确实会在这里有所帮助。  

FYI:TimerReset 会将定时器的 GPTMTAV 和 GPTMTBV 寄存器复位为0、TimerIntClear 设置用于清除定时器的 GPTMRIS 标志的 GPTMICR 标志、TimerValueGet 获取 GPTMTnR 寄存器中的值、TimerIntStatus 获取 GPTMRIS 寄存器的值、以检查是否存在边沿。  

不确定我是否澄清了上述问题、但想回答您对我的问题可能有的任何问题。
提前感谢您的帮助。

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

    您好!

     我认为你一定要做的第一件事就是在代码中使用 printf。 printf 需要大量时间通过 CIO 发送、这会影响实时操作。 您应该使用 UARTprintf 将消息发送到 UART 端口。  

     您要测量的是占空比还是输入的周期。 您似乎是在尝试使用等于1kHz 的输入周期来测量占空比。 请阐明您要测量的内容。 如果您正在测量占空比、那么它会变化、对吧? 如果您要测量周期、为什么要为正边沿使用一个计时器、而为负边沿使用另一个计时器? 周期测量应从正到正边沿或负到负边沿。  

    您需要使用 TimerPrescalerSet 来配置预分频器。  

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

    我实际上将尝试测量信号的占空比。 我将尝试通过 除以正负边沿 时间差和正边沿时间差来测量它。 pos - pos_prev 应该为我提供总计、(neg - pos_prev)/(pos-pos_prev)应该为我提供占空比。 但是、它与我在这些时间看到的数据不一致。 负边沿时间始终高于所有三个值、并且 pos_prev 高于 pos。 我不明白这是怎么可能的。  

    关于预分频器、请通读以下文档:


     

    根据我的理解、在边沿定时模式中、预分频器字节是16位定时器的扩展、使其成为一个24位定时器、因为它保存计数的最高有效字节。 根据该逻辑、我需要像我在代码中所做的那样提取24位或0x00FFFFFF。 如果我的理解有误、请纠正我。

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

    我刚刚尝试了 TimerPrescaleSet 设置为4、但我仍然看到相同的值和相同的值之间的差异、因此它实际上不会进行任何预分频。 然后、我在操作期间尝试检查预分频寄存器、看看它是否包含计数的8个最高有效位、该寄存器也不会这么做、并且始终报告0。 它既不用作扩展、也不用作实际的预分频器。 不确定这里发生了什么。

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

    您好!

    我实际上是在尝试测量信号的占空比。 我将尝试通过 除以正负边沿 时间差和正边沿时间差来测量它。 [报价]

    感谢您的澄清。  

    [报价 userid="638171" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1466229/tm4c129enczad-general-purpose-timers-to-measure-pwm-duty-cycle/5627612 #5627612"]根据我的理解、在边沿计时模式下、预分频器字节是16位计时器的扩展、由于它保存了计数的最高有效字节、因此预分频器字节是一个24位计时器。 根据该逻辑、我需要像我在代码中所做的那样提取24位或0x00FFFFFF。 如果我的理解有误、请更正我。

     您能试用以下工具吗?  

    TimerPrescaleSet (TIMER0_BASE、TIMER_A、0xFF);
    TimerLoadSet (TIMER0_BASE、TIMER_A、0xFFFF)

    这将创建一个完整的24位计时器、因为预加载值将为0xFF_FFFF。 自由运行计数器将在再次复位为零之前从0计数到0xFF_FFFF。 24位计数器在120MHz 上的最大值为139.25ms。

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

    并延长了计时器。 谢谢你。 我认为它确实也能解决这个问题、因为根本原因是一直存在预分频器。 但我仍然感到困惑、因为我多次浏览过该文档、我无法理解这一诀窍。 文档中是否有我遗漏的内容?

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

    您好!

     预加载值定义了上限值、如果超过该上限、计数器在从0向上计数时将复位。 通过将预加载值设置为 FF_FFFF、这将为计数器提供最多24位的计数。 在递减计数时、预加载值定义计数器的起始值。 计数器达到0后、再次重新加载编程的预加载值。 我知道在用于递增计数的输入捕获时间模式上的 d/s 不是很清楚。  

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

    您好!
    感谢您到目前为止提供的帮助。

    在 TimerEdgeTime 模式下、我仍然遇到计时器复位问题。 计时器复位函数的外观如下:

    空洞
    TimerReset (uint32_t ui32Base、uint32_t ui32Timer)

    if (((ui32Timer & timer_A)== TIMER_A)

    HWREG (ui32Base + TIMER_O_TAV)= 0x00FFFFFF;
    }
    if (((ui32Timer & timer_B)== TIMER_B)

    HWREG (ui32Base + TIMER_O_TBV)= 0x00FFFFFF;
    }
    }

    但是、这不会将计时器复位为0。 不清楚为什么?
    这是我参考的文档  

    它清楚地表明我需要写入 TNV 寄存器、但它不起作用。 我还尝试过:

    TimerDisable (TIMER2_BASE、TIMER_BOTH)
    TimerPrescaleSet (TIMER2_BASE、TIMER_BOTH、0xFF);
    TimerLoadSet (TIMER2_BASE、TIMER_BOTH、0xFFFF);
    TimerEnable (TIMER2_BASE、TIMER_BOTH)

    但这不会重置计时器。 如果我能得到这方面的帮助就好了。 如果我需要创建一个单独的帖子、请告诉我。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [报价 userid="638171" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1466229/tm4c129enczad-general-purpose-timers-to-measure-pwm-duty-cycle/5633687 #5633687"]

    在 TimerEdgeTime 模式下、我仍然遇到计时器复位问题。 计时器复位函数的外观如下:

    空洞
    TimerReset (uint32_t ui32Base、uint32_t ui32Timer)

    if (((ui32Timer & timer_A)== TIMER_A)

    HWREG (ui32Base + TIMER_O_TAV)= 0x00FFFFFF;
    }
    if (((ui32Timer & timer_B)== TIMER_B)

    HWREG (ui32Base + TIMER_O_TBV)= 0x00FFFFFF;
    }
    }

    [报价]

    当向 GPTMTAV 寄存器写入值时、该值会在下一个时钟周期加载到 GPTMTAR 寄存器中。 GPTMTAR 寄存器记录了已经发生的边沿的个数。 例如、如果定时器检测到10个边沿、则 GPTMTAR 寄存器将保持该值10。 为什么尝试写入  GPTMTAV 寄存器? 假设向 GPTMTAV 写入100、在下一个周期、值100加载到 GPTMTAR 中。 换句话说、 GPTMTAR 寄存器将从10变为100? 您的目的是什么? 如果要复位 GPTMTAR、为什么不向 GPTMTAV  寄存器写入0?  

    另外请注意、以下注意事项:写入时、高8位无效。

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

    很抱歉这么晚才回复。 嗯、我实际上是想将0写入寄存器、这也不起作用。 TAV 值从不会清零。 它仍然从它最后获得的值继续。 我还尝试了在两者之间启用和禁用计时器和负载设置、以便再次从0开始、这也不起作用。  
    您如何建议我将我现在用作24位计时器的16位计时器设置为0?

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

    尊敬的 Akash:

     由于您为同一问题打开了新主题、我将在此处回答并关闭该主题。