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.

[参考译文] TM4C123GH6PGE:定时器延迟功能

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/657691/tm4c123gh6pge-timer-delay-function

器件型号:TM4C123GH6PGE
主题中讨论的其他器件: TM4C123TMP20

大家下午好、

                     我想使用计时器在 tm4c123gh6pge 微控制器中创建延迟函数10分钟。 我请求您建议我如何使用以下时钟频率编写简单的延迟函数。  

SysCtlClockSet (SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHz);

 


谢谢、

此致、

Srinu.V

 

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

    您好 Srinu、

    我将尝试制作一份通用指南:下面简要总结一下如何为您的目标组织项目:

    1) 1) TM4C MCU 上的计时器计算内部"咔嗒声"或时钟周期。 通常、这些咔嗒声来自主处理器的时钟。 因此、基本而言、计数时间(等待10分钟)是等待特定数量的周期发生的问题。 使用定时器有一种"特殊的方法"、其中的咔嗒声来自慢速晶振(32768Hz)、但除非您为此专门配置定时器、否则不会出现这种情况。

    2) 2)您需要知道在一秒内 CPU 中发生了多少个时钟周期。 您提到的函数 SysCtlClockSet()用于配置它。 对于 TM4C123系列、有一个读取此值的函数、即 SysCtlClockGet ()。

    3) 3)在程序期间、您可能需要几次系统时钟值。 因此、最好读取它并将其存储在全局变量中。

    uint32_t mySystemClock;

    mySystemClock = SysCtlClockGet ();

    4) 4)那么、例如、现在假设您的时钟配置为50MHz、变量的值为50、000 000。 这是您的计时器将在一秒内计数的时钟周期数。

    5) 5)您希望计数到10分钟... 即10 x 60秒或600秒。 足够简单。 它指的是多少个时钟周期?

    600 x mySystemClock = 30 000 000 000。

    如果您可以使用该数量的周期配置定时器负载、则任务完成。

    6)问题:ARM M4的"正常"计时器为32位。 这意味着它可以计数的最大数量是2^32 - 1、或4 294 967 295。 如您所述、计算10分钟的 CPU 时钟需要一个大于该值的数字。 以下是两个选项:

    7) OPTION1:累积辅助计数器。 例如、您可以使用计时器每秒触发一次、并在外部变量中计算秒数。 这意味着将您的计时器配置为在50、000个周期结束后触发(并自动从零开始)、并且在计时器中断例程中、添加一秒:

    空 interruptRoutineWhenTimer1触发器(空)

    globalElapsedSeconds +;

    if (globalElapsedSeconds >= 600)

     {

     globalElapsedSeconds = 0;

     doSomeing();

     }

    不过、请注意、即使是5、000万也是一个很大的数字。 某些计时器(实际上是"半计时器")只能计数到2^16 - 1、因此如果这是您的策略、请确保使用320位计时器。

    8)选项2:特别是对于 TM4C123系列、有宽定时器、它可以计数到2^64 -1、这是一个很大的数字。 如果使用宽范围计时器、您只需将计时器加载到该大数字、即10分钟。

    9) 9)无论采用哪种方式、您都需要配置一次计时器。 以下是32位计时器的配置示例:

      TimerConfigure (Timer1_base、timer_CFG_PERIODICRACRACASE);

      TimerLoadSet (Timer1_base、timer_A、50000000);

      TimerIntEnable (Timer1_base、timer_TINA_TIMEOUT);

      TimerEnable (Timer1_base、timer_A);

    (此示例将反复调用 ISR、每秒一次)

    10) 10)更多指针:

    -在尝试配置 Timer1外设之前,必须启用该外设。

    -必须启用系统中断。

    -您需要编辑项目的启动文件,以便将 interruptRoutineWhenTimer1Triggers()设置为 Timer1 ISR。

    -在中断例程(ISR)内,您需要清除中断标志(对于大多数外设中断类型来说是真的)。

    -从 ISR 内部调用 doSomething()并不是一个好的做法。 最好的方法是设置一个标志、例如 thingCanHappen = true;在主循环中、持续检查是否会发生这种情况(运行后不要忘记将 thingCanHappen 设置为 false)。

    时间调度有一种特别不同的方式:一个被称为 SysTick 的更简单 ARM 定时器被配置为每1毫秒触发一次、而一个全局变量累积已经历的 ms。 将来、只要您需要在给定的时间发生某种情况、就计算将是哪个 msCounter 值、并定期检查是否已达到此"时间限制"、然后调用您的事件。

    希望本基本指南对您自己和他人有用。

    布鲁诺

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    主席先生,感谢你提出宝贵的建议。
    根据您的建议、我想使用以下行
    TimerConfigure (Timer1_base、timer_CFG_PERIODICRACRACASE);

    TimerLoadSet (Timer1_base、timer_A、50000000);

    TimerIntEnable (Timer1_base、timer_TINA_TIMEOUT);

    TimerEnable (Timer1_base、timer_A);


    我的代码是------------

    MAIN ()

    SysCtlClockSet (SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHz);

    SysCtlPeripheralEnable (SYSCTL_Periph_Timer1);

    TimerConfigure (Timer1_base、timer_CFG_A_PERIODICRACRACASE);

    TimerLoadSet (Timer1_base、timer_A、50000000);

    IntEnable (INT_TIMER1A);

    TimerIntEnable (Timer1_base、timer_TINA_TIMEOUT);

    TimerEnable (Timer1_base、timer_A);

    while (1)

    LED =打开;
    LED =关闭;



    从上面的代码中、我想在 LED =打开;LED =关闭之间插入10分钟的计时器延迟;
    我请求您建议我如何在两条指令之间插入计时器。


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

    Srinu

    我看到您没有为计时器创建中断服务例程。 查看 TIVAARE 示例文件夹、您必须了解中断的工作原理、并且需要能够在代码中包含工作 ISR。 您知道如何从 Tivaware 导入示例吗? 研究中断示例(以及计时器示例、当您在其中时)。

    我无法检查您的代码以了解详细信息、但为了实现您的目标、您需要首先确定这是连续循环(10分钟打开、10分钟关闭)还是仅一次?

    一次性建议:

    -在 while (1)例程之前、只执行一次"led = on"。
    -每次触发计时器时、使"secondsCounter"全局变量递增1。
    -在 while ()中,检查以下内容:
    if (secondsCounter >= 600){LedOff ();}

    此致

    布鲁诺

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    布鲁诺,这需要一种感觉
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢、Robert!
    我希望 Srinu 能够成功地实施我们的计划!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    希望 "加速、放松和(甚至)加强"这种"成功实施"--提出以下意见。

    我认为  、一个有用/简化的简化是由"简单" (7计数对600)的认可产生的。    (“ 3个以上”后列出了6000个计数- 600个是指。)

    七(7)个简单的32位计数器"翻转"产生10分钟的计时持续时间、 精度为"0.22%"!   这应该证明:"对 G'Ovt 工作有好处-至少对于"概念证明!"   (这一直是一个好主意...)

    先前-在另一个帖子中-出现了单词用法。   ("部分"-适用于任何关心的人。)

    先前的帖子-此主题-已列出、 "7) OPTION1: 累加辅助计数器"

    现在、我完全同意 Robert 的评估-我们的海报 Bruno 在这里做得很好。   然而-"累加 -正如这里使用的-更好地描述了"所选定时器的功能"-辅助计数器应该-更正确-被"选择和/或使用"-它的任务-是 "累加(其它)定时器 (理想的32 位定时器)的溢出。"    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在您的概念证明图示中不应考虑的一点是、Srinu 不希望函数在10分钟内不返回。 我可以认为、在这种情况下、没有 SW 会是合理的行为。 在等待过程中、几乎肯定需要有执行其他任务的能力、而且几乎可以肯定、需要有某种能力来中止等待。

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

    正如您所注意到的、Robert -海报总是强调他们的问题、因为"简单"-但这几乎总是-远离案例!

    简单的是海报"太基本、太有限-掌握所有棘手的问题"-这通常是通过长期的渐进努力、试验和"硬敲"经验而获得的...

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

    感谢您的建议。

    在之前的代码中、我只是通过启用和关闭 LED 来告诉您、实际上、我的应用程序是一个连续执行两个函数、每10分钟的确切延迟。 我将编写以下代码


    MAIN ()

    SysCtlClockSet (SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHz);

    SysCtlPeripheralEnable (SYSCTL_Periph_Timer1);

    TimerConfigure (Timer1_base、timer_CFG_A_PERIODICRACRACASE);

    TimerLoadSet (Timer1_base、timer_A、50000000);

    IntEnable (INT_TIMER1A);

    TimerIntEnable (Timer1_base、timer_TINA_TIMEOUT);

    TimerEnable (Timer1_base、timer_A);

    while (1)

    function_1 ();
    function_2 ();
    延迟(10分钟); ------ 我想在这里延迟10分钟、并在 while 循环中重复执行这两个函数。



    在这里、我不了解如何为上述代码创建10分钟延迟的计时器中断。 我知道如何将其添加到 STARTUP_CCS 中。

    我请求您向我发送一个计时器中断10分钟的示例代码。



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

    如果您能提供更多详细信息来了解您不清楚的内容、我们可能会进一步指导您、但现在我不能确定 Bruno 非常详细的产品中的哪一部分不清楚。

    在提供示例代码方面、我们有许多用于计时器和中断的 TivaWare 示例、可帮助所有用户实现其目标、但我们无法为论坛中出现的每个用例提供独特的示例。 我们慷慨的社区成员也是如此、他们负有其他责任、可能无法为您提供此类配套资料。

    这里有很多建议(因此我没有提前评论)、但如果部件不清楚、请务必要求澄清、我们可以尝试提供进一步的帮助。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    海先生,

    MAIN ()

    SysCtlClockSet (SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHz);

    SysCtlPeripheralEnable (SYSCTL_Periph_Timer1);

    TimerConfigure (Timer1_base、timer_CFG_A_PERIODICRACRACASE);

    TimerLoadSet (Timer1_base、timer_A、50000000);

    IntEnable (INT_TIMER1A);

    TimerIntEnable (Timer1_base、timer_TINA_TIMEOUT);

    TimerEnable (Timer1_base、timer_A);

    while (1)

    function_1 ();
    function_2 ();
    延迟(10分钟);-------- 我想在这里延迟10分钟、并在 while 循环中重复执行这两个函数。




    从上面的代码中,我想执行 function_1 ()和 function_2 (),在执行两个函数后,我想等待我的代码执行,而在循环10分钟延迟后,再次转到 function_1 ()和 function_2 ();再次转到10分钟延迟。 我想连续重复此操作。

    在前面的中、我将用于如下所示的环路

    int di;
    对于(di = 0;di<600;di++)

    SysCtlDelay (SysCtlClockGet ()/3);//针对50MHz 时钟的1秒延迟


    但是、现在我想使用以下行来使用计时器中断来实现延迟

    SysCtlClockSet (SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHz);

    SysCtlPeripheralEnable (SYSCTL_Periph_Timer1);

    TimerConfigure (Timer1_base、timer_CFG_A_PERIODICRACRACASE);

    TimerLoadSet (Timer1_base、timer_A、50000000);

    IntEnable (INT_TIMER1A);

    TimerIntEnable (Timer1_base、timer_TINA_TIMEOUT);

    TimerEnable (Timer1_base、timer_A);


    在这里、我无法理解如何为计时器函数中的延迟编写中断代码10分钟。


    我请求您向我提供建议。


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

    拉尔夫太棒了!   因此需要说。   

    海报必须接受(部分)责任-并致力于自己的"专注工作!"   这种"实践"往往是"试验和错误",甚至是许多此类试验,是真正学习的途径。

    布鲁诺的详细帖子涵盖了海报所寻求的"确切"内容。   以及您提供的附加/链接代码指南-当然-"指南好、直接!"

    海报上的几个"布鲁诺帖子重读"、然后 是"他自己的"编码尝试、证明了" 提高海报理解"的最佳方法(实际上是唯一的方法)、并实现 了真正的学习!  

     通过(请求的指导手册)[努力-轻装] -"剪切和粘贴!"获取"

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

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

    这种情况

    [引用 USER="Srinu Vakada]while (1)

    function_1 ();
    function_2 ();
    延迟(10分钟);-------- 我想在这里延迟10分钟、并在 while 循环中重复执行这两个函数。
    }[/报价]

    与此相矛盾

    [引用 user="Srinu Vakada"]但现在我想使用计时器中断来延迟

    对于您所说的内容、中断有什么好处?

    顺便说一句、您几乎肯定不希望处理器停止响应10分钟、但这就是您想要的。

    Robert

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

    实际上、我的应用程序是使用 GSM 模块将数据发送到服务器。 在这里、我使用两个函数将数据发送到服务器、使用另一个函数从服务器读取数据。因此、我希望在 while 循环中每10分钟执行一次此应用程序。 这就是我希望使用计时器创建精确的10分钟延迟的原因。

    while (1)

    data_send();
    data_receive();
    延迟(10分钟);-------- 我想在这里延迟10分钟、并在 while 循环中重复执行这两个函数。


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

    [引用 user="Srinu Vakada">实际我的应用是使用 GSM 模块将数据发送到服务器。 在这里、我使用两个函数将数据发送到服务器、使用另一个函数从服务器读取数据。

    10分钟内不需要其他任何东西似乎是很不可能的。

    [引用 USER="Srinu Vakada]while (1)

    data_send();
    data_receive();
    延迟(10分钟);-------- 我想在这里延迟10分钟、并在 while 循环中重复执行这两个函数。


    我请求您向我提供建议。[/引述]

    布鲁诺在第一次答复中就这样做了。

    您可以雇用顾问。

    Robert

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

    [引用 user="Robert Adsett"]您可以聘请顾问。[/quot]

    请注意-今天、我们的供应商提供 了"TMP20" Temp 。 传感器-报告 芝加哥 @ 49.4°F.    和... 阅读您的(引用的建议)时...  "闪电闪光 - 雷鸣!"    (克里周末工作人员和 CB1“被罩住” ...   在紧密地离合(更多)的同时-我们的钱包...)

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


    感谢您的所有宝贵建议、
    根据您的所有建议、我了解了如何使用计时器开发1秒延迟的代码。 我将得到精确的1秒延迟、并且将延迟增加到1分钟。我也将得到精确的1分钟。我通过简单的 LED 测试了这一点、并测试了我的代码。 现在、我将把这个延迟10分钟延迟放入我的应用程序代码中、我将检查它是否每10分钟发送一次数据。


    谢谢、
    此致、
    Srinu。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请记住- 32位计时器的"仅七个"翻转-中断"-在10分钟(精确)的0.22%内即可实现!

    并且比计数来自16位计时器的600个"回滚-中断"要快/简单得多...

    也要意识到-所有这些"多余"中断服务都会给您的结果添加错误-"到目前为止、七个滚动条是最佳选择!"
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    小心这条路...
    如果由于某种原因更改了 CPU 时钟配置、则计时器会执行任务。
    另一方面、如果您考虑当前时钟来配置计数器、则不需要依赖"魔术"翻转量(可能不再存在)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    应该挂图更改 MCU 时钟配置-所有设置关闭-除非进行了正确调整。

    用"600" ISR (不是最近发布的6000 ISR)提取的附加"时间成本"是否会因子600/7而减少-通过"较小数量的翻转"?

    为什么您认为7次滚动需要(大于) 600次护理?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [报价 USER="CB1_MOBIT"]为什么您认为7个滚动需要(大于) 600次的护理?[/QUERPLET]

    因为一旦您创建了等待 X 秒的解决方案、您就可以在需要时立即使用它。

    另一方面、当您创建等待10分钟的解决方案时、您只能在等待10分钟时使用该解决方案、更具体地说、就是将时钟设置为50MHz (这甚至不是该 MCU 上可用的最快时钟)。

    因此、如果我要对秒进行计数、我宁愿让全局变量对这些秒进行计数、实现一个简单的 ISR、该 ISR 每秒调用一次、使此类变量递增一次。 超时控制本身只是与时间限制值的比较、这对于任何秒数都很有用。 当然、1秒的计时器负载会在初始配置期间验证 CPU 时钟、因此当您以16MHz 运行 TM4C123或以120MHz 运行更快的 TM4C 时、该工具仍然是很好的...

    但是、为了使生活变得比上述描述更简单、甚至"效率更低": 在一个典型的项目中会发生很多事情、其中很多事情取决于经过的时间-所以在这里完成的任何项目的基础包括一个1ms 的粒度计数器由 SysTick 递增而不是由计时器递增(SysTick 不需要清除中断标志、 这简化了 ISR 内容)。 为了简化编码、宏 system_counter_MS 指向该全局变量。

    OP 的任务将通过以下代码完成:

    uint32_t timeExpire = 0;

    DataSend();

    DataReceive();

    timeExpire = system_counter_MS + 600000;

    while (system_counter_MS < timeExpire){}

    运行 CPU @50MHz 时、我们每毫秒有50、000个周期。 "浪费"大约30个周期绕道/递增全局计数器、相当于系统中永久毫秒计数的0.06%处理能力! 好还是坏?

    此致

    布鲁诺

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我的朋友--我们站在"高度分歧"立场--按照你的意愿行事。

    至于您的 SysTick 建议(相对于常规计时器)- SysTick 是否会受到"不可避免的时间变化"的影响-当"需要关键计时时、会"反对使用 SysTick?"

    您对我的"建议方法"的描述强制执行"限制"-绝不受此类方法的约束。 接受逻辑和论证方面的培训-我对您提供的"证据"印象不深。

    您已经"获得了很好的帮助"这张海报-但现在展示的"支持"超出了我的兴趣...
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 CB1

    [引用 user="CB1_MOBIST"]不受"不可避免的时间变化"[/引用]影响

    这话什么意思???

    SysTick 由系统时钟以及常规计时器驱动。

    配置为每50、000个周期生成一次中断的 SysTick 将在... 嗯... 50、000个周期。 不多一个、少一个。 默认情况下、它设置为更高的优先级、因此其 ISR 内部发生的任何事情都更有可能是"实时"。

    也许你在想 SysCtlDelay()?

    布鲁诺

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

    我们在 ARM 文档中注意到了此类 SysTick 问题-千禧一代员工立即搜索。

    我们在过去2个月内通过另一个 ARM M7确认了这种情况、这就是我"回忆"的方式。 我将在 n ü crüe 找到后发布-并展示他们的调查结果...

    我是个有脚受伤的家——“受影响”,但足够警惕,不要与“SysCtlDelay()”混淆!   (也许,有人希望... 我被警告说,“不要操作重型机械”(像任何有声的人都会相信 Moi -有重型机械),但你对类似名称的“SysCtlDelay()"的建议却受到了启发...)    *** 类似 ***

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

    SysTick 实际上是这些硅片的"深层"、TI 甚至不实施、而是 MCU 的 ARM "部分"实施。 此类基本硬件实现计数器中的故障非常意外。 对 SysTick 勘误表或 SysTick 问题的(非结论性但提示性)搜索不会返回任何事实。 SysTick 几十年来一直在计算脉冲、它在这方面做得很好-同样、在本机情况下、它比 TI 的所有外设具有更高的优先级、并且无需清除 ISR 内部的标志、这是使用 SysTick 的两个极具吸引力的原因。

    Je suis desolee、但您的千禧一代 crüe 将无法回到这个月 AMI 上。

    对于那些需要注意的人、不要过于兴奋地将 SysTick 用于"我的所有即将到来的延迟项目"-最大负载值为2^24、这在缓慢配置的 TM4C123中甚至不是一秒。 它最好由一个递增的全局变量来提供。

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

    我可以在这里知道 system_counter_MS 的初始值是什么??


    此致、
    Srinu。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Srinu、
    我不确定我是否理解这个问题的相关性、但初始值为零。 这是一个变量、我们使用它来计算上电后经过的毫秒数。
    此致
    布鲁诺
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    主席先生,

    我从每10分钟点亮/熄灭 LED 的示例中实施了此代码。


    volatile uint32_t millis = 0;


    void SysTickInt (空)

    uint32_t STATUS=0;

    状态=定时器内部状态(TIMER0_BASE、TRUE);
    TimerIntClear (TIMER0_BASE、STATUS);
    毫秒++;


    空等待(uint32_t 编号)

    volatile uint32_t temp =毫秒;
    while ((millis temp)< number);



    int main()


    SysCtlClockSet (SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHz);


    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
    SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);
    SysCtlDelay(3);

    TimerConfigure (TIMER0_BASE、TIMER_CFG_PERIODICASE);
    TimerLoadSet (TIMER0_BASE、TIMER_A、50000000);

    TimerIntRegister (TIMER0_BASE、TIMER_A、SysTickInt);

    TimerIntEnable (TIMER0_BASE、TIMER_TINA_TIMEOUT);

    TimerEnable (TIMER0_BASE、TIMER_A);

    GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_1 | GPIO_PIN_2);

    while (1)

    GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_1、GPIO_PIN_1);
    GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、~GPIO_PIN_2);

    等待(600);//等待600秒延迟

    GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、GPIO_PIN_2);
    GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_1、~GPIO_PIN_1);

    等待(600); //延迟600秒




    在我的应用中使用延迟为10分钟的发送和接收数据是好的。


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

    Srinu、

    虽然我可以看到您的代码起作用、但以下是一些改进代码的建议:

    -不要将 Timer0 ISR 命名为"SysTickInt()"。 该名称建议使用不同的计时器。 您应该将其命名为类似于 Timer0ISR()的名称。
    -不要将秒变量的名称命名为“毫秒”。 此类变量会统计秒数、而不是毫秒、因此所选名称不是那么方便。
    -不要在 SysCtlPeripheralEnable 之后使用 SysCtlDelay。 外设确实需要一些时间才能准备就绪、但等待它准备就绪的正确方法是使用 while (SysCtlPeripheralReady())。
    -在 TimerLoadSet 上,您使用的是50000000的硬编码值。 该数字对于您的特定时钟设置是正确的、但如果您将时钟设置存储在代码开头的变量中(类似于 systemClockHz)、则会更巧妙、 并在您的定时器负载上使用该变量(同样、它不会产生任何功能差异-但是、如果您决定将 CPU 重新配置为在80MHz 下工作、代码仍能完美运行、而无需再担心)。
    在等待函数内,您可以在 while 之前进行一次计算。 例如"expireTime = millis + temp"、然后是"while (millis < expireTime)"。 此外、这在这里没有什么不同、因为您的 MCU 不执行任何其他操作、但这只是一个"良好做法"、需要更少的处理、计算值不需要具有易失性。

    此致

    布鲁诺

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

    非常感谢您提出的所有建议。 我使用计时器每隔10分钟就开发一次 LED 打开和关闭代码。现在我已将其应用于主应用程序、其工作正常、数据发送到服务器的确切延迟为每10分钟一次。
    我是通过学习大家的宝贵建议和 Tiva 教程的示例而开发的。

    此致、
    Srinu。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您的反馈和客气话。
    布鲁诺
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您必须首先回答几个问题。

    例如、如果您预计代码将被阻止。 这似乎是可以的、但这么长时间的阻断并不是非常明智的。

    然后、您会遇到使用哪个时间的问题。 在我的应用中、我通常会让 SysTick 运行以提供自由时间戳。 可在此处使用。

    您还有16、32或64位计时器以及预分频器。 使用32位或更多位计时器可以轻松完成任务。 对于16位计时器、它需要一点编程。 但没有什么特别的。

    然后是 dwt -一个32位自由运行计数器。 很少被人们使用、但非常有用。

    然后、您会遇到一个有关您需要多少抖动的问题。 您可以对周期精确延迟进行编程。 或者、您可以在更短的延迟时间内构建代码。 例如、您可以编写一个延迟一秒的片段。 然后、写一个延迟一分钟的片段、然后得到10个延迟...

    很高兴为您提供一些代码示例。

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

    我要做的是、通过16位拆分定时器(在本例中为 TIMER2)实现"阻断"延迟例程。

    1.将 timer2初始化为16位拆分定时器。 我选择了1个预分频器、顶部为0xFFFF -这对我们的应用没有影响。

    //global define
    #define TMRxTIMER2//我们使用 timer2作为时基
    
    //全局变量
    
    //重置 timer2a - split计时 器
    //16/32位计时器:8位预分频器,16位周期寄存
    器 void tmr2a_init (uint32_t ps、uint32_t pr){//_ispr->RC1
    –/syrtr2</>RCr=/r1</syrtscr&r1<r=/rtrl=/rtrl=/rtrl=/rtscr1&trl=/rtrl=/rtscr1&trl=/r&trl=/rt
    
    
    TIMER0/1/2/3/4/5
    
    //停止计时器
    TMRx->CTL &=~(1<0);//0->禁用计时器,1->启用计时器
    //配置计时器,拆分,递增计数
    器 TMRx->CFG = 0x04;//0x00->32/64位、0x01->RTC、0x02-0x03->保留、0x04->16/32位拆分定时器
    TMRx-> Tamr =(0<11)|//0->传统操作
    (0<10)|//0->在下一个周期更新匹配寄存器、1 ->立即更新匹配寄存器
    (0)|禁用 PWM<9
    |中断0 | 0 1>立即更新加载寄存
    器(0<<7)|//0->禁用快照,1>启用快照
    (0<<6)|//0->立即计数计时器; 1->计数前计时器等待触发
    (0<5)|/0->匹配中断被禁用,1->匹配中断被启用
    (1<4)|//0->倒计数,1->递增计数
    (0<3)|//0->捕获/比较启用1->PWM (0<2|/0->0x02-
    
    >捕获、0x02->边沿计数;0x02->保留0x02->捕获时间;0x02>0x02->捕获
    
    
    //设置预分频
    器 TRXM->TAPR =(ps - 1)& 0xff;//设置预分频
    器 TRXMX->TAILR=(pr - 1)& 0xFFFF;//设置顶部
    //重置计数
    器 TRXM-> TAR = 0;
    
    //清除 ISR 标志,禁用
    所有中断 TRXM</>IMR<>0XM0
    ;~//启用中断0XM1-中断
    //1->清除中断标志,0->无效
    
    //启动计时器
    TMRx->CTL |=(1<0);//0->禁用计时器,1->启用计时
    器}
    

    2. delay64()使用64位参数提供精确到周期的延迟。 实际上限制更少。

    //用户 tmrx 延迟64位
    //由上方的 TMRx 指定的时基
    //假设初始化为16位计时器
    char delay64 (uint64_t tick){
    TMRx ->TAR = 0;//重置计时器计数
    器 TMRx->TAILR=(ticks & 0xFFFF);//设置顶部
    TRX->ICR = 0<01-
    (TRX0);中断= 0<TRIS = 0X0<TRIS =(CONTINUE);//继续)//等待计时器溢出
    滴答=滴答和~0xFFFF;//屏蔽最低的16位
    TMRx->TAILR= 0xFFFF;//顶部在0x10000
    ,而(滴答= 0x10000ul){
    TMRx->ICR =(1<0);//在
    (((TMRx-> RIS 和0x01))时复位标志;//等待计时器返回
    
    
    1);//继续溢出
    

    3.将64位参数传递到 delay64()将提供所需的延迟。 每个"SystemCoreClock"相当于1秒的延迟。 "SystemCoreClock"被定义为 CMSIS 框架的一部分。

    //示例:延迟2.5秒
    #define LED_DLY(SystemCoreClock * 2.5)//长延迟周期计数,1 SystemCoreClock = 1秒
    
    //主循环
    
    //配置 tmrx
    tmr2a_init (1、0xFFFF);//将 tmr2a 初始化为16位拆分计时器
    
    // ei ();//启用中断
    while (
    time/dlp_LED)/delayePort
    
    (1、dlpy);// dlp_yt (1)/delayeLp (64)
    
    

    经测试可在 LM4F120上工作。

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

    你在这里做了很好的努力-谢谢。    不过、在本主题的(现在已发布了35个深帖子)案例中、海报已 "表明他接受 了"同行海报 Bruno 的方向"、甚至授予了"已解决我的问题" 帖子亮点。

    请注意、您(我认为是正确的)似乎对"阻止延迟"提出质疑(在大多数"现实世界"应用中都是不可接受的)。 -然后继续演示(另一个)阻塞代码示例。   

    您的大部分代码都采用了" 长时间不喜欢这里/其他地方-"DRM"编码方法"、该方法被称为低效和错误诱导。    当然、这家供应商 的广泛   API 从未如此有用、而且 API "久经考验、真实可靠、经过严格测试"。    (虽然您注意到"您的测试"(在 EOL MCU 上)、但"一人测试"(  不能"希望比较") 与供应商(广泛) API 所经历的"千"(可能成千上万)的测试相比。   

    我们注意到您的专业知识和"愿意提供帮助"、但(确实存在)有多个"未回答的帖子"、这似乎"更值得关注..."    (再次-此主题已(标记很长)"已解决!")

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    海先生,
    根据建议和 Tiva 教程、我制作了如下代码600秒。


    volatile uint32_t sec = 0;


    空 timer0intHandler (空)

    uint32_t STATUS=0;

    状态=定时器内部状态(TIMER0_BASE、TRUE);
    TimerIntClear (TIMER0_BASE、STATUS);
    sec++;


    空等待(uint32_t 编号)

    volatile uint32_t temp = sec;
    while (sec-temp)< number);



    int main()


    SysCtlClockSet (SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHz);


    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
    SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);

    TimerConfigure (TIMER0_BASE、TIMER_CFG_PERIODICASE);
    TimerLoadSet (TIMER0_BASE、TIMER_A、系统时钟集());

    TimerIntRegister (TIMER0_BASE、TIMER_A、timer0intHandler);

    TimerIntEnable (TIMER0_BASE、TIMER_TINA_TIMEOUT);

    TimerEnable (TIMER0_BASE、TIMER_A);

    GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_1 | GPIO_PIN_2);

    while (1)

    GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_1、GPIO_PIN_1);
    GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、~GPIO_PIN_2);

    等待(600);//等待600秒延迟

    GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、GPIO_PIN_2);
    GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_1、~GPIO_PIN_1);

    等待(600);//等待600秒延迟




    此致、
    Srinu。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您的方法将在概念上起作用-我实际上没有测试您的代码。

    但是、请注意、计时将具有抖动:+/-大约1秒、最大值。

    减少这种情况的一种方法是以更快的速度前进。 例如、"SystemClockGet ()/10"(100ms)、甚至"SystemClockGet ()/100"(10ms)处的中断。

    尽管如此、我强烈建议使用基于 SysTick 的方法或基于 DWT 的方法、即使这些芯片具有大量的计时器。 或基于64位计时器的方法。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    此处是有关使用 DWT 计时器的快速跟进:

    //使用 DWT 进行定时
    //返回标志:1>时间已满,0->尚未耗尽的时间
    char delay64DWT (uint64_t ticks64){
    static uint64_t ticks64_prev = 0;//以前的 coreticks,64位
    静态 uint64_t ticks64_now = 0;
    /t ticks64_eons/eons/eone-now;
    //32位时钟
    
    //时间戳当前时钟- 32位
    时钟现在= DWT->2a CCNT;//coreticks();//读取 DWT 周期计数器(32位)
    ticks64_now +=(MRx_NOW > ticks_prev)?(ticks_now - ticks_prev):(0x1ticks_now
    
    = 32位时钟周期/ ticks/ ticks-现在用作32位时钟周期前/时钟)//16位 timer2a 作为时基
    //ticks64_now +=(ticks_now > ticks_prev)?(ticks_now - ticks_prev):((0x1ull << 16)-(ticks_prev - ticks_now));//对于32位翻转
    //备选2:使用 Syticks+(ntick_ticks)
    –ticksprise_ticks=24
    (ticksprick (ticks_now)//对于32位翻转
    
    //时间戳电流节拍- 64位
    ticks_prev = ticks_now;//更新 ticks_prev
    if ((ticks64_now - ticks64_prev)< ticks64)返回0;
    否则{ticks64_prev = ticks64_now;return 1;}//时间为 up
    }
    

    上述代码提供三种替代方法:

    使用 DWT 作为计数器。 它是一个32位计数器;

    2.使用16位定时器作为计数器;代码已注释掉

    3.使用 SysTick 作为转换器;24位宽。

    当所需的时间(以节拍为单位)过去时、该函数返回1。 0否则。

    IF (delay64DWT (LED_DLY)) IO_FLP (LED_PORT、LED);//翻转 LED
    

    在这种情况下、当 LED_DLY 过期时、它会翻转 LED。

    经测试可在 LM4F120上工作。 并且应该能够处理任何具有 DWT 的 cm3/4/4F/7芯片、或者任何 CMx 芯片(如果 SysTick 被用作时基)。

    重点是要说明有许多方法可以做同样的事情。 没有理由将自己局限于一种特定的方法。