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.

[参考译文] TM4C123GH6PM:使用定时器实现延迟功能

Guru**** 2763595 points

Other Parts Discussed in Thread: EK-TM4C123GXL

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1020001/tm4c123gh6pm-using-timer-for-delay-function

器件型号:TM4C123GH6PM
Thread 中讨论的其他器件:EK-TM4C123GXL

大家好、

我正在使用 EK-TM4C123GXL launchpad 板并尝试使用 Timer0作为延迟函数、但遇到了一个奇怪的问题、我不太理解我的代码为什么不起作用。 代码非常简单、如下所示:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"


//*****************************************************************************
//
// Delay ms
//
//*****************************************************************************
void Delay_ms(uint16_t ui16ms)
{
    TimerEnable(TIMER0_BASE, TIMER_A);

    while (ui16ms--)
    {
        while (!TimerIntStatus(TIMER0_BASE, TIMER_A))
        {
            TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
        }
    }

    TimerDisable(TIMER0_BASE, TIMER_A);
}

//*****************************************************************************
//
// Configure Timer0A as a 32-bit periodic 
//
//*****************************************************************************
int
main(void)
{
    
	//
	// Config system clock for 80MHz using PLL with external 16MHz oscillator
	//
	SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_16MHZ);

    //
    // Enable Peripheral Clocks for port PB
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	
    //
    // Enable pin PB for GPIOOutput
    //
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_0);
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_1);
    
    //
    // Wait for PB is ready
    //	
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));	

    //
    // Enable The Timer0 peripheral.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
	
	//
	// Wait for Timer0 is ready
	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0));
	
	//
	// Config Timer0 32 bit periodic
	//
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
	//
	// Preload Timer0A for 1ms timeout
	//
    TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet() / 1000);


    //
    // Configure the Timer0A interrupt for timer timeout.
    //
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    //
    // Enable Timer0A.
    //
    TimerEnable(TIMER0_BASE, TIMER_A);

    //
    // Loop forever while the Timer0B runs.
    //
    while(1)
    {
		//
		// Toggle port PB0 every 50ms
		//
		GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 1);
        Delay_ms(1);
        GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0);
        Delay_ms(1);
    }
}

我遇到的问题是 Timer0溢出似乎比我预期的快得多。 我使用示波器查看端口引脚 PB0、看到它在1.5us 左右切换、而不是1ms。 系统时钟以80MHz 的频率运行。 我检查了 Timer0 TIMER_TAILR 寄存 器、预加载值正确、为0x80000十进制。 请大家仔细查看我的代码并告诉我哪里出错了吗?

提前感谢大家、祝您愉快。

此致、

TLN  

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

    您好、TLN、

    我可以帮助查看计时器、但在查看计时器之前、您是否需要使用计时器而不是其他选项? SysCtlDelay API 实现了很多延迟。

    这相当于1ms 延迟:

    SysCtlDelay(SysCtlClockGet() / (1000 / 3));

    如果可以的话、那对您来说就更简单了。 但是、如果您出于特定原因需要计时器、那么我可以帮助了解这一点。

    此致、

    Ralph

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

    您好 Ralph、

    感谢您的快速回复。

    我尝试使用计时器而不是 Tiva 库中的 SysCtlDelay()函数的原因是为了获得更好的延迟精度 了解如何以不同的方式使用计时器。 您看到我的代码有什么问题吗?

    我尝试了您的建议、PB0没有以1ms 的速率切换、而是以18ms 的速率切换、即使 TIMER_TAILR 寄存 器的值为0x0003AA70 = 240240十进制、对应于3ms。

    如果我在这里错了,请纠正我的错误,SysCtlDelay()需要3个机器周期。 对于80MHz 系统时钟、每个周期花费12.5ns、并且1ms 延迟内载入 SysCtlDelay()的正确值为26666。 但是、如果我使用该值、则切换速率为2ms。 如果我使用13333、则切换速率是正确的。 我现在很困惑!!!

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

    您好、TLN、

    在尝试  SysCtlDelay 之前、我将完全禁用计时器的中断。

    我将尝试您的计时器代码、下一次机会我将了解它的运行情况。

    此致、

    Ralph

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="216127" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1020001/tm4c123gh6pm-using-timer-for-delay-function/3769348 #3769348"]但如果使用此值,则切换率为2ms。

    此外、您还看到2ms 打开、2ms 关闭? 还是在1ms 打开和1ms 关闭的情况下、完整周期为2ms?

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

    拉尔夫

    使用 SysCtlDelay (26666)时、我打开了2ms、关闭了2ms。

    对于 SysCtlDelay (13333)、我打开了1ms、关闭了1ms。

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

    已注释掉此行

    //    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    仍然是相同的  

    TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet() / (1000/3));

    无论   是否使用了 TimerIntEnable (TIMER0_BASE、TIMER_TINA_TIMEOUT)函数、只有 SysCtlDelay (13333)提供正确的1ms 开启和关闭。

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

    TimerIntStatus 的第2个参数是一个 bool、记录为:
    [引用]bMasked 在需要原始中断状态时为 false、而在需要屏蔽中断状态时为 true 。[/quot]

     delay_ms()函数循环中的以下命令将 timer_A 作为 bMASed 参数传递给 TimerIntStatus(),看起来是错误的:

            while (!TimerIntStatus(TIMER0_BASE, TIMER_A))
            {
                TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
            }

    但是 、TIMER_A 定义为0xff、这应导致 TimerIntStatus 返回屏蔽的中断状态、这可能是代码所需的中断状态。

    由于如果任何屏蔽的中断挂起、TimerIntStatus 返回非零、while 循环是否应屏蔽来自 TimerIntStatus 的返回、以便仅检查所需的中断 TIMER_TINA_TIMEOUT?

    也就是说、如果有任何其他屏蔽的中断挂起、while 循环不会在不等待所需中断的情况下终止。

    此外、我认为计时器中断只应在发生后清除。

    尝试将循环写为:

            while ((TimerIntStatus(TIMER0_BASE, true) & TIMER_TIMA_TIMEOUT) == 0)
            {
            }
            TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

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

    您好、TLN、

    我测试了切斯特的代码、他是对的。 请遵循他的建议。

    谢谢切斯特!

    最棒的

    Ralph

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

    切斯特、您好!

    我已经尝试过您的代码建议,它运行得很好。 我将深入了解该库、并尝试更深入地了解如何更好地使用它们。

    非常感谢您的帮助、非常感谢您的帮助。  

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

    您好 Ralph、

    是的、我已经尝试了、它成功了。 非常感谢您的帮助!