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.

[参考译文] 编译器/MSP432P401R:多通道 ADC 存在问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/673770/compiler-msp432p401r-problem-with-multichannel-adc

器件型号:MSP432P401R

工具/软件:TI C/C++编译器

我尝试通过 ADC 引脚读取2个信号。 每当我运行代码时、只存储第一个 ADC 引脚值。 在调试期间、我发现寄存器 ADC14MEM0和 ADC14MEM1的值发生了变化、但是变化只反映在存储 ADC14MEM0值的变量中。

此外、我不知道这是否有用、但读取的电压值来自一对模拟接近传感器、这对传感器由微控制器提供3.3V 电压。

以下是我的代码设置;

/* DriverLib 包括*/
#include 

/*标准包括*/
#include 

#include 

静态 uint16_t resultsBuffer[2];

int main (void)
{
/*停止 WDT */
MAP_WDT_A_HOLDTimer();
MAP_Interrupt_enableSlepOnIsrExit();

/*零填充缓冲器*/
memset (resultsBuffer、0x00、2);

//![简单 REF 示例]
/*将基准电压设置为2.5并启用基准*//
map_REF_A_setReferenceVoltage (REF_A_VREF2_5V);
map_REF_A_enableReferenceVoltage();
//![简单 REF 示例]

/*初始化 ADC (MCLK/1/1)*/
MAP_ADC14_enableModule();
MAP_ADC14_initModule (ADC_CLOCKSOURCE_MCLK、ADC_PREDIVIDER_1、ADC_DIVIDER_1、
0);

/*在*/中为模拟配置 GPIO
MAP_GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P5、
GPIO_PIN5 | GPIO_PIN4、GPIO_Terti_MODULE_FUNCTION);



/*配置 ADC 存储器(ADC_MEM0 - ADC_MEM7 (A0 - A7)、无需重复)
*具有内部2.5V 基准*
MAP_ADC14_configureMultiSequenceMode (ADC_MEM0、ADC_MEM1、TRUE);
MAP_ADC14_configureConversionMemory (ADC_MEM0、
ADC_VREFPOS_AVCC_VREFNEG_VSS、
ADC_INPUT_A0、false);
MAP_ADC14_configureConversionMemory (ADC_MEM1、
ADC_VREFPOS_AVCC_VREFNEG_VSS、
ADC_INPUT_A1、false);


/*在通道7 (序列结束)上进行转换时启用中断
*已完成并启用转换*/
MAP_ADC14_enableInterrupt (ADC_INT1);

/*启用中断*/
MAP_Interrupt_enableInterrupt (INT_ADC14);
MAP_Interrupt_enableMaster();

/*将采样计时器设置为自动单步执行序列
*转换。
*
MAP_ADC14_enableSampleTimer (ADC_AUTOMATE_DIOTIVation);
//ADC14_setSampleHoldTime (ADC_PULSE_WIDTH_64、ADC_PULSE_WIDTH_64);

/*触发样本开始*/
MAP_ADC14_enableConversion();
MAP_ADC14_toggleConversionTrigger ();

/*正在休眠*/
while (1)
{
MAP_PCM_gotoLPM0 ();
}
}

//每当转换完成并放置在
* ADC_MEM7中时,就会触发此中断。 这表示转换结束、结果数组
被*抓取并放置在 resultsBuffer */
void ADC14_IRQHandler (void)
{中
uint64_t status;

STATUS = MAP_ADC14_getEncableInterruptStatus();
MAP_ADC14_clearInterruptFlag (status);

IF (STATUS & ADC_INT1)
{
MAP_ADC14_getMultiSequenceResult (resultsBuffer);
}
}


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    最后我听说在 ROM_ADC14_getMultiSequenceResult 的 ROM 版本中有一个错误:

    e2e.ti.com/.../2383657

    在该帖子中有几个建议的解决方法。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您使用的是哪个版本的 SDK? 您可以在此处找到最新的:

    www.ti.com/.../SIMPLELINK-MSP432-SDK

    在更改日志中、您可以看到 API (MSP432DVR-464)的更新:
    dev.ti.com/.../changelog.html

    如果您有最新的 SDK、但仍遇到问题、请告诉我。

    此致、
    Chris
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Bruce、
    谢谢! 这解决了问题
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我能够解决这个问题、但我遇到了另一个问题。 每当代码运行时、我都会注意到它永远不会进入循环(while (1))。 我设置一个 LED 以在永久环路中打开、但它永远不会打开。 我只能使 LED 在 ADC 中断中打开
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Akin、
    在程序开始时使用 API map_Interrupt_enableSlepOnIsrExit();这意味着当器件退出 ISR 时、它返回睡眠模式而不是活动状态、因此一旦器件进入睡眠模式(lpm0)、就永远不会重新进入超级循环。

    Chris
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Chris、
    我删除了它、但仍然有相同的问题
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    与进入、执行和退出 ISR 所需的时间相比、您是否知道进行这两次测量需要多长时间?

    Chris
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    静态 uint16_t resultsBuffer[3];
    uint16_t DirNav [2];
    
    
    int main (void)
    {
    /*停止 WDT */
    MAP_WDT_A_HOLDTimer();
    MAP_Interrupt_disableSlepOnIsrExit();
    
    // MAP_Interrupt_enableSlepOnIsrExit();
    
    /*零填充缓冲器*/
    resultsBuffer[0]= 0;
    resultsBuffer[1]= 0;
    resultsBuffer[2]= 0;
    
    DirNav [0]= 0;//确定是否停止
    DirNav [1]= 0;//确定要转向哪一侧
    
    map_REF_A_enableReferenceVoltage();
    
    /*初始化 ADC (MCLK/1/1)*/
    MAP_ADC14_enableModule();
    MAP_ADC14_initModule (ADC_CLOCKSOURCE_MCLK、ADC_PREDIVIDER_1、ADC_DIVIDER_1、
    0);
    
    /*配置 GPIO (1.0输出)、(5.5 A0)*/
    MAP_GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0);
    MAP_GPIO_setAsOutputPin (GPIO_PORT_P2、GPIO_PIN1);
    MAP_GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN0);
    
    
    /*在*/中为模拟配置 GPIO
    MAP_GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P5、
    GPIO_PIN5 | GPIO_PIN4、GPIO_Terti_MODULE_FUNCTION);
    MAP_GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P4、
    GPIO_PIN7、GPIO_TICE_MODULE_FUNCTION);
    
    /*使用 Repeat 配置 ADC 内存)*/
    MAP_ADC14_configureMultiSequenceMode (ADC_MEM0、ADC_MEM6、TRUE);
    MAP_ADC14_configureConversionMemory (ADC_MEM0、
    ADC_VREFPOS_AVCC_VREFNEG_VSS、
    ADC_INPUT_A0、false);
    MAP_ADC14_configureConversionMemory (ADC_MEM1、
    ADC_VREFPOS_AVCC_VREFNEG_VSS、
    ADC_INPUT_A1、false);
    MAP_ADC14_configureConversionMemory (ADC_MEM6、
    ADC_VREFPOS_AVCC_VREFNEG_VSS、
    ADC_INPUT_A6、false);
    
    MAP_ADC14_setComparatorWindowValue (ADC_COMP_WINDOW0、5000、5000);
    MAP_ADC14_enableComparatorWindow (ADC_MEM0、ADC_COMP_WINDOW0);
    MAP_ADC14_enableComparatorWindow (ADC_MEM1、ADC_COMP_WINDOW0);
    MAP_ADC14_enableInterrupt (ADC_HI_INT | ADC_LO_INT);
    MAP_ADC14_clearInterruptFlag (ADC_HI_INT | ADC_LO_INT);
    
    /*在通道7 (序列结束)上进行转换时启用中断
    *已完成并启用转换*/
    MAP_ADC14_enableInterrupt (ADC_INT6);
    
    /*启用中断*/
    MAP_Interrupt_enableInterrupt (INT_ADC14);
    MAP_Interrupt_enableMaster();
    
    /*将采样计时器设置为自动单步执行序列
    *转换。*/
    MAP_ADC14_enableSampleTimer (ADC_AUTOMATE_DIOTIVation);
    //ADC14_setSampleHoldTime (ADC_PULSE_WIDTH_64、ADC_PULSE_WIDTH_64);
    
    /*触发样本开始*/
    MAP_ADC14_enableConversion();
    MAP_ADC14_toggleConversionTrigger ();
    
    /*正在休眠*/
    //map_Interrupt_disableSlepOnIsrExit();
    while (1)
    {
    if (DirNav [0]= 0)
    MAP_GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN0);
    否则 if (DirNav [0]= 1)
    MAP_GPIO_setOutputHighOnPin (GPIO_PORT_P1、GPIO_PIN0);
    MAP_PCM_gotoLPM0 ();
    
    //__no_operation();
    }
    }
    
    
    void ADC14_IRQHandler (void)
    {
    uint64_t status;
    
    STATUS = MAP_ADC14_getEncableInterruptStatus();
    MAP_ADC14_clearInterruptFlag (status);
    MAP_ADC14_clearInterruptFlag (ADC_HI_INT | ADC_LO_INT);
    
    IF (STATUS 和 ADC_HI_INT)
    {
    DirNav [0]= 1;
    MAP_GPIO_setOutputHighOnPin (GPIO_PORT_P2、GPIO_PIN1);
    resultsBuffer[0]= MAP_ADC14_getResult (ADC_MEM0);
    resultsBuffer[1]= MAP_ADC14_getResult (ADC_MEM1);
    resultsBuffer[2]= MAP_ADC14_getResult (ADC_MEM6);
    }
    
    否则{
    DirNav [0]= 0;
    MAP_GPIO_setOutputLowOnPin (GPIO_PORT_P2、GPIO_PIN1);
    resultsBuffer[0]= 0;
    resultsBuffer[1]= 0;
    resultsBuffer[2]= 0;
    }
    } 

    我不知道如何确定它。

    下面的代码设置了两个由 ADC 中断触发的 LED。 中断中的一个、while 环路中的第二个、但只有中断中的一个触发 LED。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    不,我不知道如何确定。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您可以重复使用以下功能:

    MAP_GPIO_setOutputHighOnPin (GPIO_PORT_P1、GPIO_PIN0);
    MAP_GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN0);

    并测量 P1.0上的脉冲宽度。

    此外、在代码中、您实际上测量的是7个通道、即通道0至通道6。 最好将其更改为通道0至2、并将输入6转至存储器位置2。 您可以在 以下位置了解 API:dev.ti.com/.../group__adc14__api.html

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

    我很确定 MCLK 在 LPM0中停止、SLAU356G sec 20.2.1.1似乎建议 ADC14的请求不会启动它(MCLK_EN)。

    请尝试改用 SMCLK 或 MODCLK。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您正在持续运行转换(CONSEQ=3、MSC=1)。 每次转换使用 SHT=0 (4个 MCLK)采样时间+ 16个 MCLK 转换时间=总共20个 MCLK。 其中有7x 个、即140个 MCLK。

    您的 ISR 似乎需要大约360个 MCLK、这意味着当它完成另一个转换时、ISR 就会持续运行。 (我很确定这正是 Chris Sterzik 所说的。) 您还可以在 ADC 运行时获取结果、这可能会在实际应用中产生不一致的结果。

    您可能会因为使用较慢的 ADC 时钟或大于2的 ADC_divider 而离开。

    我建议您切换到单序列(CONSEQ=1,即 MultiSequenceMode(false)),并在每次通过 main 中的 while ()循环时启动新的转换。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我找到了问题。 我必须对时钟进行分频。 我想我的采样速度太快了