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.

[参考译文] MSP432E401Y:使用 ADC 时、GPTM 间隔加载寄存器值显示为1关闭

Guru**** 2524550 points
Other Parts Discussed in Thread: MSP-EXP432E401Y, SYSBIOS

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/978850/msp432e401y-gptm-interval-load-register-value-appears-1-off-when-using-an-adc

器件型号:MSP432E401Y
Thread 中讨论的其他器件:MSP-EXP432E401YSYSBIOS

我使用的 MSP-EXP432E401Y LaunchPad 套件的运行频率为120MHz、我使用 TI 驱动程序来运行周期性计时器以发送事件信号、或使用 ADC 以指定频率定期采样、这会自动使用周期性计时器。

当我直接使用一个周期定时器来发出一个事件信号(不涉及 ADC)并且我查看 GPTM 间隔加载寄存器(GPTMTAILR、a.k.a. TIMER_TAILR)、我注意到计数比我最初预期的值少1、直到我在《MSP432E4技术参考手册》中阅读此部分:


'当定时器递减计数并达到超时事件(0x0)时、定时器重新装载其初值
在下一个周期从 GPTMTnILR 和 GPTMTnPR 寄存器发出"


定时器确实会递减计数、如果0是计数的一部分、则间隔装载寄存器必须减少1。 例如、如果我想以8Hz 的频率向事件发出信号、那么间隔加载寄存器中看到的数字必须为:


120MHz/8Hz - 1 = 14999999 = 0xE4E1BF  、这就是我在 CCS 调试器中看到的结果


当我使用 ADC 以指定频率(例如10kHz)定期采样时、会产生混淆。 如果使用与上述相同的"少1个"计算、我得到:


120MHz/10kHz - 1 = 11999 = 0x2EDF


但是、我在 CCS 调试器的间隔加载寄存器中看到的值比这个值多1:0x2EE0! 当我查看计时器模式寄存器时、该计时器确实在递减计数、那么为什么该数字不是0x2EDF? 这可能是 TI 驱动程序软件中的错误、还是我在这里遗漏了什么?

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

    以下代码说明了我看到的问题。

    它直接取自 simplelink_msp432e4_sdk_3_20_00_10 SDK 中的 adcbuftemperature_MSP_EXP432E401Y_tirtos_ccs 示例、其中我的添加项标记为//* my add *(2个位置)、因此使用不同的 SDK 和 MCU 可以轻松重建。

    ADC 以200Hz 的频率进行采样。  处理器以120MHz 的频率运行。  定时器加载值的直接计算、其中0 (超时值)是序列的一部分、应:

    120MHz/200Hz - 1 = 599999 = 0x927BF

    我看到的是一个大于1的值:600000 = 0x927C0
    但是、如果0是计数序列的一部分、则计数序列中有600001个状态、比它应该大1。 当我直接设置计时器时不会发生这种情况、那么为什么会出现这种差异?

    这似乎是一个微不足道的问题、但我们正在进行一些精确的同步、我想了解正在发生的情况。


    实际的控制台输出为:
    启动 ADCBuf 温度示例
    平均温度为32.0070C
    加载值为0x927c0


    ===== == adcBufTemperature.c ===== ==

    /*
     *版权所有(c) 2015-2017、德州仪器(TI)公司
     *保留所有权利。
     *
     *以源代码和二进制形式重新分发和使用、有无
     *如果满足以下条件、则允许进行修改
     符合*:
     *
     ** 源代码的重新分发必须保留上述版权
     *   注意、此条件列表和以下免责声明。
     *
     * *二进制形式的再发行必须复制上述版权
     *   请注意、中的此条件列表和以下免责声明
     *   随分发提供的文档和/或其他材料。
     *
     * *德州仪器公司的名称和名称均不相同
     *   其贡献者可用于认可或推广衍生产品
     *   未经特定的事先书面许可。
     *
     *本软件由版权所有者和贡献者"按原样"提供
     *以及任何明示或暗示的保证、包括但不限于:
     *特定适销性和适用性的隐含保证
     *不承认目的。 在任何情况下、版权所有者不得或
     *派遣国应对任何直接、间接、偶然、特殊、
     *典型或必然的损害(包括但不限于
     *采购替代货物或服务;丧失使用、数据或利润;
     *或业务中断)、无论原因是什么以及任何责任理论、
     *无论是合同、严格责任还是侵权行为(包括疏忽或)
     *否则)因使用本软件而以任何方式产生、
     *即使被告知可能会发生此类损坏。
     *
    /*
     * ==== adcBufTemperature.c ===
     *
    #include
    #include

    /*驱动程序头文件*/
    #include
    #include
    #include       /*我的添加*/

    #include

    /*显示头文件*/
    #include
    #include

    /*用于睡眠()*/
    #include

    /*示例/板头文件*/
    #include "Board.h"

    #define ADCBUFFERSIZE   (20)

    uint16_t sampleBufferOne[ADCBUFFERSIZE];
    浮点 CBuffer[ADCBUFFERSIZE];
    float avgTemperature;

    /*驱动程序处理任务和回调函数之间共享的*/
    ADCBuf_handle adcBuf;
    ADCBuf_Conversion 连续转换;

    /*显示驱动程序句柄*/
    Display_Handle displayHandle;

    /* ADCBuf 信号量*/
    sem_t adcbufSem;

    /*
     *只要缓冲区已满,就会调用此函数。
     *然后对缓冲区的内容取平均值并转换为摄氏度格式
     并通过 UART 发送到 PC。
     *
    void adcBufCallback (ADCBuf_Handle handle、ADCBuf_Conversion *转换、
       void *完整的 ADCBuffer、uint32_t 完整通道){
       uint_fast16_t i;
       uint16_t * rawTemperatureBuf =(uint16_t *)完整的 ADCBuffer;

       avgTemperature = 0;

       /*计算平均温度*/
       对于(i = 0;i < ADCBUFFERSIZE;i++){
           avgTemperature += rawTemperatureBuf[i];
       }
       avgTemperature = avgTemperature/ADCBUFFERSIZE;

       /*将 ADC 值转换为摄氏度*/
       avgTemperature =(1475*4096 -(75 * 33 * avgTemperature))/ 40960;

       /*后 adcbuf 信标*/
       SEM_post (&adcbufSem);


    /*
     * ==== gpioButtonFxn0 ===
     * Board_GPIO_BUTTON0上 GPIO 中断的回调函数。
     *
    void gpioButtonFxn0 (uint_least8_t 索引)

       /*开始转换。 *
       if (ADCBuf_convert (adcBuf、连续转换、1)!=
           ADCBuf_STATUS_SUCCESS){
           /*未正确启动转换过程。 *
           while (1);
       }


    /*
     * ==== mainThread ====
     *
    void * mainThread (void * arg0)

       ADCBuf_Params adcBufParams;
       Display_Params displayParams;

       /*调用驱动程序初始化函数*/
       ADCBuf_init ();
       GPIO_init();
       display_init();
       int32_t        status;

       /*配置并打开 Display 驱动程序*/
       Display_Params_init (&displayParams);
       displayParams.lineClearMode = display_clear_both;
       displayHandle = Display_open (Display_Type_UART、displayParams);
       if (displayHandle == NULL){
           while (1);
       }

       /*配置按钮引脚并安装按钮回调*/
       GPIO_setConfig (Board_GPIO_BUTTON0、GPIO_CFG_IN_pu | GPIO_CFG_IN_INT_INT_FALLING);
       GPIO_setCallback (Board_GPIO_BUTTON0、gpioButtonFxn0);
       GPIO_enableInt (Board_GPIO_BUTTON0);

       状态= SEM_INIT (&adcbufSem、0、0);
       if (status!= 0){
           display_printf (displayHandle、0、0、"创建 adcbufSem\n"error creating adcbufSem\n");
           while (1);
       }

       display_printf (displayHandle、0、0、"启动 ADCBuf 温度示例");

       /*在 ADCBuf_RECURE_MODE_连续 中设置 ADCBuf 外设*/
       ADCBuf_Params_init (&adcBufParams);
       adcBufParams.callbackFxn = adcBufCallback;
       adcBufParams.RecurrencedMode = ADCBuf_Recurrence_mode_One_Shot;
       adcBufParams.returnMode = ADCBuf_return_mode_callback;
       adcBufParams.samplingFrequency = 200;

       adcBuf = ADCBuf_open (Board_ADCBUF0、&adcBufParams);

       如果(!adcBuf){
           /* AdcBuf 未正确打开。 *
           while (1);
       }

       /*配置转换结构*/
       continuousConversion.arg =空;
       continuousConversion.adcChannel = Board_ADCBUF0CHANNEL2;
       continuousConversion.sampleBuffer = sampleBufferOne;
       continuousConversion.sampleBufferTwo = sampleBufferOne;
       continuousConversion.samplesRequestedCount = ADCBUFFERSIZE;

       /*
        *永久进入前台线程的睡眠状态。 数据将被收集
        *并在后台线程中传输
        *
       while (1){
           /*等待信号量并打印平均温度*/
           SEM_WAIT (&adcbufSem);
          /*打印平均温度信息*/
           Display_printf (displayHandle、0、0、"平均温度为%.3FC"、
            avgTemperature);
           uint32_t loadValue = TimerLoadGet (Timer1_base、timer_A);     /* my add *
           display_printf (displayHandle、0、0、"加载值为0x%x"、//我的加载项*
            loadValue);                                                 /*我的添加*/
       }



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

    我需要更正原始帖子中的错误。  我说过、在以指定的采样率(使用封面下方的计时器)运行 ADC 时、我比较了计时器负载寄存器值与直接运行计时器(无 ADC)以定期发出事件信号(两者均使用 TI 驱动程序接口)。  事实证明、我在第二种情况下使用了 SYSBIOS/hal 接口-直接运行计时器。

    因此、我决定在 simplelink_msp432e4_SDK_3_20_00_10 SDK 中运行 timerled_MSP_EXP432E401Y_tirtos_ccs 示例、该示例使用 TI 驱动程序接口来操作计时器(以1Hz 的频率切换 LED)、并检查它将计时器加载寄存器设置为什么、它也应该大于1!

    该示例将周期设置为1000000微秒或1秒、因此计时器由120MHz 系统时钟计时、必须持续循环至120,000,000个状态。  由于0是计数序列的一部分、因此定时器加载寄存器中的数字应减少1、即119、999、999。  但是、当我检查计时器加载寄存器时、它被设置为0x07270E00 = 120,000,000。

    然后、我重新编程了该示例、以使用 SYSBIOS/hal 接口而不是 TI 驱动程序接口、计时器加载寄存器值应该是:0x07270DFF = 119999,999。

    因此、TI 驱动程序软件中似乎存在一个错误、该错误会影响 ADC 采样频率(进而影响计时器)以及直接设置用于周期性信令的计时器。  或者、我可能在分析中缺少一些东西。  在所有情况下、计时器都会递减计数。

    TI、您在听吗?

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

    您好 Brian、

    感谢您对此进行了详尽的调试。  是的、我将把这个转发给我们的 MSP432 driverlib 软件团队。  他们可能需要一些时间来解决此问题、我真的不知道下次何时发布432 driverlib 更新及修复。

    我现在将关闭此主题、除非您希望提供其他详细信息。  如果您希望保持此主题处于打开状态、请单击"这未解决我的问题"按钮、并使用更多信息回复此主题。
    如果此主题锁定、请单击"提出相关问题"按钮、然后在新主题中描述您的问题的当前状态以及您可能需要帮助我们帮助解决您的问题的任何其他详细信息。

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

    实际上、我认为有错误的是 TI 驱动程序库、而不是 DriverLib 库。  (不知道 DriverLib 是否有相同的问题。)  但您可以继续关闭此线程、但如果错误已修复、则应在将来更新该线程、并提及包含该修复程序的 SDK 版本。

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

    您好 Brian、

    好的地方。  我将深入探讨这个问题并确认问题。  软件团队提供修复程序可用时的估计值后、我将更新此主题。

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

    现在关闭此主题。  新信息可用时将重新打开。