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.

[参考译文] MSP430FR2311:读取多个 ADC 通道

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/759130/msp430fr2311-reading-multiple-adc-channels

器件型号:MSP430FR2311

好的、所以我认为这很容易、但显然我做了一些错误的事情、这并不是问题的根本原因。  我从 out_for_box 示例开始。  我可以轻松地只读取一个通道。  然后、我尝试将其设置为读取一系列通道 P1.1、然后读取 P1.0。  我的理解是、您选择的最高信道、序列发生器会对信道进行倒计数、因此我应该获得两个读数。  我还没有解析读数的逻辑、这对现在来说还不错。  我可以处理它。  这似乎不起作用、因为我希望获得交替的 ADC 读数值、但情况并非如此。  我在这里必须缺少一些细节。  注意: ADC 中断例程中的额外内容只是从开箱即用示例中的剩余部分、在该示例中、它们将 ADC 结果写入 FRAM。

/*
main.c
*/
int main (void){
//停止 WDT
WDT_A_HOLD (WDT_A_base);
initClockTo16MHz();
inituart();

/*初始化外设*/
initGPIO();
initPWM();
initi2C();

//在启动期间切换 LED1
GPIO_setOutputHighOnPin (GPIO_PORT_P1、GPIO_PIN0);
_delay_cycles (10000);
GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN0);

EUSCI_A_UART_ENABLE (EUSCI_A0_BASE);

initSlepTimer (timer_rate);// 128Hz

while (1){
//lightSample();
n0Sample();

uintoa( buf、adc_Conversion_result );
transmitString( buf );

_bis_SR_register (LPM3_bits + GIE);

}



void initSlepTimer (uint16_t period){
//启动计时器
Timer_B_clearTimerInterrupt (timer_B0_BASE);

Timer_B_initUpModeParam ={0};
param.clockSource = timer_B_CLOCKSOURCE_ACLK;
param.clockSourceDivider = timer_B_CLOCKSOURCE_divider;
param.timerPeriod =周期;
param.timerInterruptEnable_TBIE = Timer_B_TBIE_INTERRUPT_DISABLE;
param.captureCompareInterruptEnable_CCR0_CCIE = TIMER_B_CAPTURECMPARE INTERRUPT_ENABLE;
param.timerClear = timer_B_do_clear;
param.startTimer = true;
Timer_B_initUpMode (timer_B0_BASE、&param);
}

void enable_ADC10 (uint8_t ADC_CHANNEL){
//初始化 ADC 模块
//
* ADC 模块的基地址
*使用内部 ADC 位作为采样/保持信号来启动转换
*使用 MODOSC 5MHZ 数字振荡器作为时钟源
*使用 ADC_SOURCE_ADCC_INIT

1、ADC_SOURCE_ADCC_RAPIDER *默认值*使用 ADC_OCE_ADCC_INIT 1、ADCC_CL1、ADC_SOURCE_SOURCE_ADC_SC_SOURCE_ADCC_CL1

ADC_setDataReadBackFormat (ADC_base、 ADC_UNsigned_binary);//AP

ADC_ENABLE (ADC_base);
//
* ADC 模块的基地址
* 16个时钟周期的采样/保持
*不启用多个采样
*/
ADC_setupSamplingTimer (ADC_base、ADC_CYCLEHOLD_16_cycles、ADC_MULTIPLESAMPLESENABLE)、ADC_CELPM_16个时钟周期
;ADC_CYCL_CL_CL_CLUST_HOLLE_CYCLE、ADC_CYCLUST_CYCLUST_CYCLUSH ADC_MULTIPLESAMPLESDISABLE);

ADC_CONFIGureMemory (ADC_base、ADC_CHANNEL、ADC_VREFPS_AVCC、ADC_VREFNEG_AVSS); // driverlib 中 A1的通道错误映射?

ADC_clearInterrupt (ADC_base、ADC_completed_interrupt);

//启用存储器缓冲器中断
ADC_enableInterrupt (ADC_base、ADC_completed_interrupt);
}

void disable_ADC10 (void){
ADC_disableConversions (ADC_base、0);
ADC_disable (ADC_base);
}


void n0Sample (void)
{void
ENABLE_ADC10 (ADC_INPUT_VEREF_N);

_DELAY_CYCLES (15);

//启用并开始转换
//在单通道、单次转换模式中
//ADC_startConversion (ADC_base、ADC_SINGLECHANNEL);

ADC_startConversion (ADC_base、ADC_SEQOFCHANNELS);//将此更改为单个序列不适用于 ADC_SEQOFCHANNELS

//LPM3、ADC 转换完成将强制退出
_bis_SR_register (LPM3_bits + GIE);

disable_ADC10 ();
}

void initGPIO (void){

//将 Px.x 设定为输出方向
//P1DIR |= 0xFF;//输出
//P1OUT = 0x00;
P1DIR |= 0x00;//输入
//P2DIR |= 0xFF;
P2DIR |= 0b00000011;
P2OUT = 0x00;

//选择 P2.0作为 PWM 计时器输出功能
GPIO_setPeripheralModuleFunctionOutputPin (GPIO_PORT_P2、GPIO_PIN0、GPIO_PRIMARY_MODULE_Function);

// AP 配置 GPIO
P1SEL1 &=~(BIT6 | BIT4); // USCI_A0 UART 操作
P1SEL0 |= BIT6 | BIT7;

GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0);

// I2C 引脚
P1SEL0 |= BIT2 | BIT3;
P1SEL1 &=~(BIT2 | BIT3);

//ADC 引脚
P1SEL0 |= BIT0 | BIT1;
P1SEL1 |= BIT0 | BIT1;
/*
*禁用 GPIO 上电默认高阻抗模式以激活
*先前配置的端口设置
*
PMM_unlockLPM5 ();
}

// ADC 中断服务例程
#if defined (__TI_Compiler_version__)|| defined (__IAR_systems_ICC__)
#pragma vector=ADC_vector
__interrupt void ADC_ISR (void)
#Elif defined (__GIC_)
void ___attribute_isr (
nc
)(void)(nc) interrupt!
#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

__BIC_SR_REGISTER_ON_EXIT (LPM3_BITS); //睡眠定时器退出 LPM3
}






  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    > ENABLE_ADC10 (ADC_INPUT_VEREF_N);
    正如您在另一天观察到的、这是 ADCINCH_0。 您是指:
    > ENABLE_ADC10 (ADC_INPUT_VEREF_P);
    (就个人而言、我只会在这里插入 ADCINCH_1、因为很明显抽象是如何工作的。)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是一个错误、因为我尝试使用不同的信道来查看是否存在不同的行为。 我尝试过这种方法、但它仍然不起作用。  我只是得到假值、就好像多路复用器一起尝试两个通道或将其悬空一样。  完全不同的值、如果我只为一个通道配置它。  此外、更改采样保持时钟周期的数量也会完全改变行为。

    我甚至尝试在 main()中串联运行两个不同的采样例程。 n0sample 和 n1sample。 一个配置为 A1、另一个配置为 A0。 它仍然仅为我提供了一个通道的输出。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    >n0sample 和 n1sample。 一个配置为 A1、另一个配置为 A0。
    它们都是单通道吗? 如果是、可能(部分)问题在其他地方。

    >更改采样保持时钟周期数会完全改变行为。
    FR2 ADC 的一个难题是只有一个 MEM 寄存器、没有 DMA。 这意味着、对于突发采样、您需要在样本(N+1)覆盖之前抓取样本 N、这需要一些策略。

    ADC 振荡器的运行频率约为5MHz、因此当 SHT=16时钟时、您可以(16+14+1)/5MHz =~6uS 来获取给定的样本。 这是6*16=96个 MCLK、但对于 FRAM 等待状态、您可能应该降低一半的速率、如图50个时钟。 您可能仅在 ISR 开销中就会丢失20个时钟、因此根据您的观察结果、我怀疑 ISR 中的混乱状况会将您推到最后。 建议:
    1) 1)清理 ISR 中任何不需要的代码。
    2)考虑将 SHTs 设置延长至少足以获取值。 您可能需要测量/试验来确定该值是多少。 添加大量填充、因为(我想)这将进入更繁忙的程序。
    3) 3)将样本捕获到数组中、而不是单个字。 我记得、在 FR2中、ADC 会在您处于断点时继续运行、因此调试很复杂。
    4)考虑设置 MSC=0 (ADC_MULTIPLESAMPLESDISABLE)并发送多个 SC 触发器(ADC_startConversion)或使用计时器触发器(SHS>0)。 此时、您可能只需使用 CONSEQ=3、因为 CPU 正在对 ADC 进行定步。
    5) 5)在极端情况下、使用非常慢的 ADC 时钟。 ACLK 足够慢、足以避免竞争、但数据输入速度下降了150倍。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我第一次错过了这个机会:

    > _bis_SR_register (LPM3_bits + GIE);
    根据数据表(SLASE58C)表5-2、从 LPM3唤醒需要10us、因此您已经输掉了比赛。 考虑使用 LPM0 --这不是很长的时间。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我通过调用 main()中每个通道的单个读数并在函数调用后立即打印该读数,似乎可以正常工作。

    我在读取板载温度传感器时遇到问题、因为我似乎获得的读数变化很大、似乎与其他输入通道电压相关。 我知道我有正确的通道、因为如果我从12切换到13、我会得到一个很好的稳定电压、这将是板载基准电压。 我使用适当的功能启用了板载基准和温度传感器、在启用温度传感器之前、我在通道12上获得了0V。

    此器件的数据表是复制/粘贴灾难。 在某些地方、它表示内部基准电压为1.5V、而在其他地方、它表示内部基准电压为1.2V。 这不能帮助我解决问题。

    www.ti.com/.../msp430fr2311.pdf

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我没有尝试过 FR2311上的温度传感器、但(与大多数 MSP430一样)它需要额外的 S/H 时间。 UG 显示30us、即大约150个 ADCOSC 时钟。 您还必须从 TLV 应用校准[另请参阅示例 msp430fr231x_ADC10_16.c]。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、这就是问题所在。 我刚刚更改了采样保持时钟、它看起来工作正常。

    谢谢