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.

[参考译文] CCS/MSP-EXP430FR2311:ADC 电压偏差模拟问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/966681/ccs-msp-exp430fr2311-adc-voltage-devider-analog-issue-issue

器件型号:MSP-EXP430FR2311
主题中讨论的其他器件:MSP430FR2311

工具/软件:Code Composer Studio

大家好、

我在 msp430fr2311上的 ADC 读数有问题。 我有两个正在运行的 ADC (A5和 A7)、如果我直接读出3.3V 或0V、它们工作正常。 由于我的最终设计需要一个到模拟输出 TRIMM 的电压偏差(ADC 的读取值)、因此我在试验电路板上设置了一个电压偏差、它将电压除以2 (见下文)。 这个分压器正在执行他的工作、并将我的3.3V 电压平均分配。

如果我现在连接了 ADC (无论是一个还是两个都没关系)、那么电压会从1.65下降到0.14V。 我在这里出了什么问题? 我使用不同的电阻器进行了试验、并且还将 ADC 输入视为与第二个电阻器并联的另一个电阻器。 仍然没有变化。 我真的需要你的帮助。 如果您想了解更多信息、请告诉我。

祝你一切顺利

FABI

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

    ADC 输入对源电阻有限制、因为您必须在采样时间内为采样电容充电。 该文档包含所有详细信息。

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

    嗨、David、

    感谢你的答复。 您是指下表中的电阻吗? 这是哪一个?

    感谢你的帮助。

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

    高阻抗输入更慢地填充采样电容器、因此您需要更长的采样/保持周期。  

    解决方案是增加 ADC 中的 SHT"设置和/或减小分压器中的电阻值。  用户指南(SLAU445I)第21.2.5.3节提供了基于电路参数计算采样/保持时间的公式。 作为第一个实验、只需将 SHT"设置得非常高、看看它是否会改变您的结果。

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

    电阻器的值是多少?

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

    您好、Bruce、

    感谢您的回复。 我的问题不是 ADC 测量、因为我使用万用表验证我的电压。

    我在当前设置中添加了一些信息。 如果 R1和 R2之间没有连接 ADC、则一切正常。 我在 R2处测量1.65V 电压:很酷、电压偏差器工作正常。 现在、我在 R1和 R2之间插入 ADC 以测量1.65V (U2)、但电压降至0.1V。

    从用户指南(SLAU445I)第21.2.5.3节中、我可以看到有一个输入 R =内部多路复用器开启输入电阻、该电阻假设为2k Ω。 但是、如果我考虑测量的电压、这是不可能的。

    因此、此时我甚至不使用我的 ADC。 我只需连接它、就会看到该压降。 有趣的是、如果让他测量、0.1V 的测量值是正确的红色。

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

    在您将端口配置为与 ADC 配合使用之前、它只是一个 GPIO 端口、如果设置为该端口、则完全能够下拉引脚。

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

    我的引脚已配置且 MSP430正在运行。 如果我在没有分压器的情况下测量其他电压、就不会出现问题。

    只有当我设置上述电压偏差时、它们才会出现。

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

    您好、Keith、请参阅您答案下方的图形。

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

    引脚是如何(确切地)配置的? 您的 MCU 在运行时会做什么(确切)? 您使用的平台是什么? (Launchpad?)

    这是一种异常现象、因此我怀疑您在做一些异常的事情。

    如果您可以发布/附加您的代码、可能有人会看到一些内容。 有时、它所做的只是一个拼写错误。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Bruce、 
    这是我的 adc.c 文件、我在其中定义了我的 ADC 函数。

    myadc.c

    #include #include "driverlib/MSP430FR2xx_4xx/driverlib.h" / *@fn ENABLE_ADC5 * *@简短介绍 在端口1 A5 ->引脚1.5 * *@param 上启用 ADC void * *@return 失效 / void enable_ADC5 (void){ //初始化 ADC 模块 // * ADC 模块的基地址 *使用内部 ADC 位作为采样/保持信号来启动转换 *使用 MODOSC 5MHZ 数字振荡器作为时钟源 *使用默认的时钟分频 器1 */ ADC_init (ADC_base、ADC_SAMPLEHOLDSOURCE_ADC_SOURCE_ADC_BASE );ADC_ADC_SOURCE_ADC_1;ADC_SOURCE_DIVIDER /* ADC 模块的基地址 * 16个时钟周期的采样/保持 *不启用多采样 */ ADC_setupSamplingTimer (ADC_base、 ADC_CYCLEHOLD_16_cycles、 ADC_MULTIPLESAMPLESDISABLE); //配置存储器缓冲 器// * ADC 模块的基地址 *使用输入 A5 *使用 AVcc 的正基准 *使用 AVss 的负基准 */ ADC_configureMemory (ADC_base、 ADC_INPUT_A5、 ADC_VREFPS_AVCC、 ADC_VREFNEG_AVSS); ADC_clearInterrupt (ADC_base、 ADC_Completed_interrupt); //启用存储器缓冲器中断 ADC_enableInterrupt (ADC_base、 ADC_completed_interrupt); } /********* *@fn ENABLE_ADC6 * *@简短介绍 在端口1 A6 ->引脚1.6 * *@param 上启用 ADC void * *@return 失效 / void enable_ADC7 (void){ //初始化 ADC 模块 // * ADC 模块的基地址 *使用内部 ADC 位作为采样/保持信号来启动转换 *使用 MODOSC 5MHZ 数字振荡器作为时钟源 *使用默认的时钟分频 器1 */ ADC_init (ADC_base、ADC_SAMPLEHOLDSOURCE_ADC_SOURCE_ADC_BASE );ADC_ADC_SOURCE_ADC_1;ADC_DIVIDER /* ADC 模块的基地址 * 16个时钟周期的采样/保持 *不启用多采样 */ ADC_setupSamplingTimer (ADC_base、 ADC_CYCLEHOLD_16_cycles、 ADC_MULTIPLESAMPLESDISABLE); //配置存储器缓冲 器// * ADC 模块的基地址 *使用输入 A7 *使用 AVcc 的正基准 *使用 AVss 的负基准 */ ADC_configureMemory (ADC_base、 ADC_INPUT_A7、 ADC_VREFPS_AVCC、 ADC_VREFNEG_AVSS); ADC_clearInterrupt (ADC_base、 ADC_Completed_interrupt); //启用存储器缓冲器中断 ADC_enableInterrupt (ADC_base、 ADC_completed_interrupt); } /********* *@fn disable_adc * *@简短说明 通常禁用 ADC * *@param void * *@return 失效 / void disable_adc (void){ adc_disableConversions (adc_base、0); adc_disable (adc_base); } / *@fn SAMPLE_ADC5 * **@简介 读取端口1 A5 ->引脚1.5 * *@param 上的 ADC void * *@return 失效 / void sample_adC5 (void){ /*启用 ADC 并进行设置*/ ENABLE_ADC5 (); /*等待 ADC 设置15个周期*/ _DELAY_CYCLES (15); /*在单通道、单次转换模式中启用和启动转换*/ ADC_startConversion (ADC_base、 ADC_SINGLECHANNEL); /* LPM3、ADC 转换完成将强制退出*/ _bis_SR_register (LPM3_bits + GIE); /*清除 ADC */ disable_adc (); } /********* *@fn SAMPLE_ADC6 * *@简短介绍 读取端口1 A6 ->引脚1.6 * *@param 上的 ADC void * *@return 失效 / void sample_adc6 (void){ /*启用 ADC 并进行设置*/ ENABLE_ADC6 (); /*等待 ADC 设置15个周期*/ _DELAY_CYCLES (15); /*在单通道、单次转换模式中启用和启动转换*/ ADC_startConversion (ADC_base、 ADC_SINGLECHANNEL); /* LPM3、ADC 转换完成将强制退出*/ _bis_SR_register (LPM3_bits + GIE); /*清除 ADC */ disable_adc(); }

    这是我的 main.c 文件:
    /*------------------------------------------------
    * 包括
    *----------------------------------------------
    */
    #include 
    #include 
    #include "driverlib/MSP430FR2xx_4xx/driverlib.h"
    #include "VoltLib/voltLib.h"
    
    /*----------------------------------------------------------------------------------------
    * 常数
    *----------------------------------------------------------------
    */
    
    
    //***---------------------------------------------------------------------------------------------------------------------------
    * 全局
    变量*----------------------------------------------------------
    //
    //*计时器120秒*/
    uint8_t Timer_120_cnt = 0;
    bool Timer_120_flag = false;
    
    // ADC 变量
    * ADC 转换结果0 - 1023 (0h - 0ffh)
    */
    int adc_conversion_results = 0;
    float adc_factor = 0.0032;
    float _arr_adc_voltage [5]
    = 0;float adc_voltage = 0;float adc_cal_voltage = 0;float adc_voltage = 0_cal adc_
    
    float ADC_VOLTAGE = 0;
    
    // I2C
    * TXData =要发送的数据字节
    * TXByteCtr =用于作为 I2C 主设备发送多个字节的附加字节编号。 请参见 ISR
    */
    int DAC0_TXdata = 0;
    uint8_t TXData0 = 0x00;
    uint8_t TXData1 = 0x00;
    uint8_t TXByteCtr = 1;
    
    
    int main (void)
    {
    
    
    /*
    初始化
    *
    //停止看门狗计时器
    WDTCTL = WDTPW | WDTHOLD;
    initGPIO();
    initTimerB (32768);
    initi2C();
    
    while (1){
    /*进入低功耗模式3并启用 gi */
    _bis_SR_register (LPM3_bits + GIE);
    
    /*请求计时器。 如果设置了标志、则开始测量并通过 I2C */发送数据
    if (Timer_120_FLAG){
    
    /*-----------------
    * 读取 ADC5
    ---------------------------------------- *
    
    /*如果计时器执行 ping 操作,则获取5个样本并将其写入数组中*/
    int i = 0;
    for (i=0;i<5;i++){
    /*读取 ADC */
    SAMPLE_ADC5 ();
    /*计算实际值*/
    ADC_VOLTGE_cal =(ADC_Factor * ADC_Conversion_Result);
    /*在数组中写入值*/
    _arr_adc_voltage [i]= adc_volte_cal;
    }
    
    /*获取数组的平均值。 将大小固定为5 */
    ADC_VOLTAGE = ADC_avarage (_arr_ADC_VOLTAGE);
    
    
    /*-----------------
    * 读取 ADC7
    ---------------------------------------- *
    
    //尝试 ADC 6 (第二个)
    /*如果计时器执行 ping 操作,则获取5个样本并将其写入数组中*/
    for (i=0;i<5;i++){
    /*读取 ADC */
    SAMPLE_ADC6 ();
    /*计算实际值*/
    ADC_VOLTGE_cal =(ADC_Factor * ADC_Conversion_Result);
    /*在数组中写入值*/
    _arr_adc_voltage [i]= adc_volte_cal;
    }
    
    /*获取数组的平均值。 将大小固定为5 */
    ADC_VOLTAGE = ADC_avarage (_arr_ADC_VOLTAGE);
    
    }
    
    
    }
    
    返回0;
    }/*--><!--kadov_tag{{</spaces>}--><!--kadov_tag{</spaces>}}-->
    
    
    * ISR
    *----------------------------------------------
    /*
    ADC 中断服务例程
    *--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    //
    #if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
    #pragma vector=adc_vector
    __interrupt void adc_isr (void)
    #elif defined (__GNU__)
    void __attribute__((interrupt (adc_vector)))) adc_isr (void
    
    编译器#else not supported!
    #endif
    {
    //获取先前的写保护设置
    uint8_t state = HWREG8 (SYS_base + OFS_SYSCFG0_L);
    #ifdef DFWP
    uint8_t WP = DFWP | PFWP;
    #else
    uint8_t WP = PFWP;
    #endif
    
    #ifdef FRWPPW
    HWREG16 (SYS_BASE + OFS_SYSCFG0)= FWPW |(~和 Δ V WP);
    #else
    HWREG8 (SYS_BASE + OFS_SYSCFG0_L)&&~WP;
    #endif
    
    //获取转换结果
    ADC_Conversion_Result = ADCMEM0;
    
    
    //恢复以前的写保护设置
    #ifdef FRWPPW
    HWREG16 (SYS_BASE + OFS_SYSCFG0)= FWPW | STANY;
    #else
    HWREG8 (SYS_BASE + OFS_SYSCFG0_L)=状态;
    #endif
    //睡眠定时器退出 LPM3
    __BIC_SR_REGISTER_ON_EXIT (LPM3_BITS);
    }
    
    
    我有一个计时器正在运行、几秒钟后我运行采样。 正如我说过的、如果没有电压偏差、我可以测量正确的电压。 我认为这是 ADC 输入互阻抗方面的一个模拟问题。 但我实在不明白。
    
    

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

    adc_init()函数不会改变引脚配置,因此它将保留 initgpio()函数设置的任何内容。

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

    它看起来好像 initGPIO()中有一些有趣的东西。 我正在寻找一条类似的线路:

    > GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P1、 GPIO_PIN5|GPIO_PIN7、 GPIO_ternary_MODULE_Function);// A5/7

    此外、如果您使用的是 Launchpad、请不要忘记从 J101 ("桥接"接头)上移除 RXD/TXD 跳线。 我不确定 TXD 的另一端是什么样的。

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

    大家好、

    最后、我想我将在 ADC 之前放置一个运算放大器、而不是电压偏差器。

    也许由于 ADC 的输入阻抗、我必须重新计算 ADC 的偏移/增益。 我认为这会更容易、我可以直接测量电压。

    最好

    FABI

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

    我只是在 Launchpad 上设置了一个类似的实验、我没有看到您的症状。

    我在3V3和 GND 上构建了一个"飞行寄存器"分频器(1K+1K)、并将中点馈入 P1.5和 P1.7 (一次一个)。  

    我构建了一个 initGPIO()函数,该函数可以选择包含上面那行代码。  我没有添加实际运行 ADC 所需的计时器代码、因此该程序位于 LPM3中。

    无论有没有该线路、我的 DMM 在 TAP 位置看到1.65V 电压(连接到 P1.5或 P1.7)。

    我怀疑还有其他事情发生(未显示)。 我仍然想知道 initGPIO()函数的作用是什么。

    [编辑:更正了拼写错误]

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

    您好、Bruce、

    非常感谢您的支持。 您可以在此处看到我的 initGPIO()函数。 这是我在 MSP430上的第一个项目、因此请原谅我的研究错误。 也许您也可以发布您的代码、以便我可以比较所做的设置。 也许这也与我的 GPIO 设置有关。

    #include 
    include "driverlib/MSP430FR2xx_4xx/driverlib.h"
    
    void initGPIO (void){
    /*
    PxDIR ->端口 x 方向
    PxOUT ->端口 x 输出
    *
    P1DIR |= 0xFF;
    P1OUT = 0x00;
    P2DIR |= 0xFF;
    P2OUT = 0x00;
    
    GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0);
    GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN0);
    
    //将 A5设置为输入引脚。
    //设置适当的模块功能
    /*GPIO_setPeripheralModuleFunctionInputPin (
    GPIO_PORT_P1、
    GPIO_PIN5、
    GPIO_ternary_module_function);*/
    
    
    /* I2C init */
    GPIO_setPeripheralModuleFunctionInputPin (
    GPIO_PORT_P1、
    GPIO_PIN2 + GPIO_PIN3、
    GPIO_PRIMARY_MODULE_FUNCTION
    );
    
    
    /*
    *禁用 GPIO 上电默认高阻抗模式以激活
    *先前配置的端口设置
    *
    PMM_unlockLPM5 ();
    
    
    
    /*
    标记正确的初始化
    *
    GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN0);
    _delay_cycles (30000);
    GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN0);
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    >    P1DIR |= 0xFF;
    >    P1OUT = 0x00;
    这会将 P1.5/7驱动为低电平、因此您将在 A5/A7处读取为低电平(与分频器进行或进行轻微的对抗)。
    我提到的代码行被注释掉、因此实际上并不存在代码行。 当我取消注释时、我在 A5 (但不是 A7)上得到正确的行为。
    我建议您插入我提到的代码行(用于配置两个引脚)并保留在此处。 该调用将取消其上面的 P1DIR 设置、但要正确、您应该具有更类似的内容、这样您甚至不会有几微秒的总线争用:
    >    P1DIR |= 0xFF &μ~(BIT5 | BIT7);  //除 A5/A7之外的所有输出
    [编辑:与论坛格式器的更多争议]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    全能的布鲁斯!! 这是个工作的人! 非常感谢!

    我认为 GPIO 的设置会被 ADC 引脚的标准设置覆盖。

    我也尝试过这种方法,但没有帮助。

    //将 A7设置为输入引脚。
       //设置适当的模块功能
       GPIO_setPeripheralModuleFunctionInputPin (
               GPIO_PORT_ADC7、
               GPIO_PIN_ADC7、
               GPIO_Function_ADC7);

    我喜欢他们的支持、感谢大家、尤其是 Bruce! 祝您幸福!