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.

[参考译文] TDA4VM-Q1:如何在 mcu20上使用计时器?

Guru**** 2465890 points


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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1464605/tda4vm-q1-how-can-i-using-timer-on-mcu20

器件型号:TDA4VM-Q1

工具与软件:

尊敬的 TI 专家:

SDK 版本:SDK8.4

我们当前正在尝试实现 GPIO 模拟 PWM 函数。 我们需要使用 MCU20上的计时器来定期翻转 GPIO 端口。 如何使用计时器?

此致。

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

    尊敬的 JC:

    您是指从计时器中断切换 GPIO 输出吗? 我们在 SDK 中没有计时器示例、但可以轻松地添加。 您希望使用哪个计时器 来生成中断?  

    此致、

    Brijesh

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

    您好、Brijesh:

    您的意思是从计时器中断切换 GPIO 输出吗?

    是的、您说得对。

    现在已知、Timer12正在由 MCU30使用、而其他计时器目前不被我们使用。 我们可以使用 MCU20上的 Timer0或 Timer1实现此函数吗?

    此致。

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

    尊敬的 JC:

    是的、如果其他内核不使用 timer0、则可以在 MCU2_0上使用 timer0。 IRQ 编号为289的直接中断、连接到 MCU2_0的 timer0、因此您可以使用 CSL API 寄存器 IRQ 289配置计时器、然后在超时时时调用此 ISR。  

    此致、

    Brijesh

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

    您好、Brijesh、

    您能给我举个例子作为参考吗? 因为我没有在 MCU 20上使用计时器和中断的经验。

    此致。

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

    尊敬的 JC:

    让我来给您分享同样的示例代码。  

    此致、

    Brijesh

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

    尊敬的 JC:

    我认为 J721E 上的 SDK08.04版本支持基于 CSL 的计时器、因此我编写了一个例程来配置计时器、您能否看看这是否是您要找的?


    #define GPTIMER_MAX_RESOLUTION          (0xFFFFFFFFU)
    #define TIMER_INITIAL_COUNT             (0x3C0U)
    #define TIMER_RLD_COUNT                 (0x3C0U)
    
    #define TIMER16_IRQ_NUM                 172
    
    
    void TimerMode_Init(uint32_t baseAddr)
    {
    
        TIMERReset(baseAddr);
        TIMEREmuModeConfigure(baseAddr, TIMER_TIOCP_CFG_EMUFREE_TIMER_FREE);//GPTIMER_FREE);
        TIMERIdleModeConfigure(baseAddr, TIMER_TIOCP_CFG_IDLEMODE_IDLE_MODE_0X1);//GPTIMER_NO_IDLE);
        TIMERPostedModeConfig(baseAddr, TIMER_TSICR_POSTED_POSTED_VALUE_0);//GPTIMER_NONPOSTED);
        TIMERCounterSet(baseAddr, (GPTIMER_MAX_RESOLUTION - TIMER_INITIAL_COUNT));
        TIMERReloadSet(baseAddr, (GPTIMER_MAX_RESOLUTION - TIMER_RLD_COUNT));
        TIMERModeConfigure(baseAddr, TIMER_TCLR_AR_MASK); //GPTIMER_AUTORLD_NOCMP_ENABLE);
        TIMERWakeEnable(baseAddr, TIMER_IRQWAKEEN_OVF_WUP_ENA_MASK);
        TIMERIntEnable(baseAddr, TIMER_INT_OVF_EN_FLAG);
        TIMERDisable(baseAddr);
    }
    
    Timer_PeriodConfig(uint32_t baseAddr, uint32_t wTime)
    {
        HW_WR_REG32(baseAddr + TIMER_TCLR, 0x0002);
        HW_WR_REG32(baseAddr + TIMER_TCRR, (GPTIMER_MAX_RESOLUTION - wTime));
        HW_WR_REG32(baseAddr + TIMER_TLDR, (GPTIMER_MAX_RESOLUTION - wTime));
        HW_WR_REG32(baseAddr + TIMER_TCLR, 0x0003);     /* start timer */
    }
    
    void Timer_IntCfg(void)
    {
        uint32_t baseAddr;
    
        HwiP_Handle hwiHandle;
        OsalInterruptRetCode_e      osalRetVal = 0;
        OsalRegisterIntrParams_t    intrPrms;
    
        /*Timer18*/
        baseAddr = TIMER16_ADDRESS;
        Osal_RegisterInterrupt_initParams(&intrPrms);
        intrPrms.corepacConfig.arg          = (uintptr_t)baseAddr;
        intrPrms.corepacConfig.name         = NULL;
        intrPrms.corepacConfig.isrRoutine   = Timer16_InterruptIsr;
        intrPrms.corepacConfig.priority     = 0x01U;
        intrPrms.corepacConfig.corepacEventNum = 0U; /* NOT USED ? */
        intrPrms.corepacConfig.triggerSensitivity = OSAL_ARM_GIC_TRIG_TYPE_HIGH_LEVEL;
        intrPrms.corepacConfig.intVecNum    = TIMER16_IRQ_NUM;
    
        osalRetVal = Osal_RegisterInterrupt(&intrPrms, &hwiHandle);
    
        if(osalRetVal == 0)
        {
            printf("Timer16_IntCfg success!\n");
        }
        else
        {
            printf("Timer16_IntCfg is fail!\n");
        }
    
    }
    
    

    此致、

    Brijesh

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

    您好、Brijesh:

    我很抱歉没有及时回复、因为我有假期庆祝中国新年。

    感谢您提供示例代码。 我有几个问题想问你:

    1.我认为 Timer_Period 455()是一个重置定时器的操作,但我不确定哪个值更适合设置 wTime 变量;

    Timer16InterruptIsr 指针应该要求我自己执行定时器的中断计数、但是我不知道定时器中断有多长时间? 这是我们可以设置的吗? 如果我想计数33ms 的时间、理论上应该接收多少个计时器中断?

    此致。

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

    尊敬的 Xie JC:

    当然、没问题。 新年快乐!

    #1、 Timer_Period 451API 用于设置超时值。 因此、根据我们的超时值和该计时器正在运行的频率、我们需要计算超时值并 将其提供给此函数。  

    #2、这取决于您设置的超时值。 如果您将33ms 设置为超时值、则您将 以每33ms 的间隔获得中断。  

    此致、

    Brijesh

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

    您好、Brijesh:

    感谢你的评分

    现在我基本上可以使用定时器了、我可以问我如何确定当前的时钟源吗? 我是否需要自行手动选择时钟源? 因为我在 TRM 上找到了一些 CLKSEL 寄存器。

    此致。

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

    尊敬的 Xie JC:

    对于大多数计时器、默认情况下时钟源是输入 SYSCLK、即 EVM 上的19.2MHz。 控制模块中提供了寄存器、可更改所有计时器的时钟源。  

    此致、

    Brijesh