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.

[参考译文] MSP430F5529:确定我在通过计时器 B 使用 ADC12触发器时出错了什么

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1352035/msp430f5529-ok-what-have-i-got-wrong-in-using-adc12-trigger-by-timer-b

器件型号:MSP430F5529

确定快速代码片段。 我预计 ADC12在进入计时器 B0中断时会很忙-但事实并非如此;所以我猜是我漏掉了启用的东西。 那有什么明显的东西吗? 本周末我将仔细阅读相关文档。

int main(void)
{
  // Stop WDT
  HWREGW( WDT_A_BASE | WDTCTL ) = WDTPW|WDTHOLD;

  // stop interupts whilst we configure
  __disable_interrupt();
    // first disable ADC12
  HWREGW( ADC12_A_BASE | ADC12CTL0 )&= ~ADC12ENC;
  HWREGW( ADC12_A_BASE | ADC12CTL0 )&= ~ADC12ON;
  // 4 ticks sample and hold.
  // 0x80 = 1 - sample on SHi signal
  // 0x40 - 2.5V ADC12_A ref gen volt
  // 0x20 - Ref on
  // 0x10 =0 - ADC12_A is off
  // 0x08 =0 - overflow int disable
  // 0x04 =0 - conversion time int disable
  // 0x02 - enable conversion ????
  // 0x01 - Start conversiom
  HWREGW( ADC12_A_BASE | ADC12CTL0 ) =
    ADC12SHT0_0 | ADC12MSC | ADC12REF2_5V | ADC12REFON ;
  // ADC12CSTARTADDx = 0 (write starting at ADC12MEM0)
  // ADC12SHP =0
  // ADC12SHSx = 2 - Timer B0
  // ADC12ISSH = 0 Not inverted
  // ADC12DIVx = 0 (divide by 1)
  // ADC12SSELx = 3 (SMCLK)  
  HWREGW( ADC12_A_BASE | ADC12CTL1 ) =
    ADC12SHS_2 | ADC12SSEL_3 ;
  // ADC12PDIV =0 (predivide 1)
  // ADC12TCOFF =0 (oddly means temp sensor on)
  // ADC12RES=2 (12bit)
  // ADC12DF=0 (unsigned)
  // ADC12SR=0 (200ksps sample rate)
  // ADC12REFOUT=1 = Ref Output on
  // ADC12REFBURST=1 only on during sample and convert
  HWREGW( ADC12_A_BASE | ADC12CTL2 ) =
    ADC12RES_2 | ADC12REFOUT | ADC12REFBURST;
  // ADC12SREF2 = 1 Vref- user the external reference
  // ADC12SFREG01 = 11 or 10 - user Vref+
  HWREGB( ADC12_A_BASE | ADC12MCTL0 ) = ADC12SREF_7 | ADC12INCH_0;
  HWREGB( ADC12_A_BASE | ADC12MCTL1 ) = ADC12SREF_7 | ADC12INCH_10;
  HWREGB( ADC12_A_BASE | ADC12MCTL2 ) = ADC12EOS;
  // enable ADC12
  HWREGW( ADC12_A_BASE | ADC12CTL0 )|= ADC12ON;
  HWREGW( ADC12_A_BASE | ADC12CTL0 )|= ADC12ENC;
    
  __enable_interrupt();


  // now all set for now just loop, with LED flashing
  while(1) {
  }
  

}
// TIMER B CC
__attribute__ ((interrupt(TIMER0_B0_VECTOR)))
void TIMER0_B0_ISR (void)
{

  sprintf(print,"%i\0", HWREGW( ADC12_A_BASE | ADC12CTL1 )&ADC12BUSY);    
}

打印缓冲器由 USCI_A1中断进行处理并发送到 UART。

在 UART 上我只得到"0"输出、这是因为它是 Timer B 断流器例程中的第一条指令、也就是用来触发 ADC12的指令似乎是错误的。

有人有什么想法吗? 我会继续挖掘。

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

    您是否配置了计时器的输出模块? 触发信号为 TB0.0输出。

    不需要启用引脚、但输出模块会启用。

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

    1) 1)我看不出您是在何处设置计时器。 SHS 背后的理念是你让定时器(在本例中为 CCR0)生成一个信号,在上升沿触发 ADC --你有效地生成用户指南(SLAU208Q)中看到的 SHI 信号图28-5。 对于 CCR0、您可以使用 OUTMOD=4 (速度为两倍、即 CCR0值的一半)。  

    2)  

    > HWREGW ( ADC12_A_BASE | ADC12CTL1 )= ADC12SHS_2 | ADC12SSEL_3 ;

    您要配置2个通道(MCTL0/1)和 MSC=1、但设置(省略) CONSEQ=0、因此只能获得一个通道。 可能需要 CONSEQ=1。 您可能还需要 SHP=1:

    > HWREGW (ADC12_A_base | ADC12CTL1)= ADC12SHS_2 | ADC12SSEL_3 | ADC12SHP | ADC12CONSEQ_1;

    3)当 CONSEQ=1时,您需要在每个批处理后切换 ADC12ENC (=0然后=1 )[参考 UG 章节28.2.7.2]。 这通常在 ADC ISR 内部完成(计时器 ISR 几乎肯定过早)。

    4)  

    > HWREGW ( ADC12_A_BASE | ADC12CTL0 )|= ADC12ENC;

    ADC12CTL0是绝对地址、而不是偏移量。 这种形式是偶然的、因为 ADC12_A_BASE 是256的倍数(0xX00)。 首选形式如下所示:

    > ADC12CTL0 |= ADC12ENC;

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

      // Now set up Timer B
      // first disable before programming
      HWREGW( TIMER_B0_BASE | TBxCTL )&=0xffcf;
      // all Timer B latch updates not tied together (But 
      // 16 bit
      // SMCLK is the clock
      // divide by 1
      // keep disabled
      // Time clear - here we clear just be sure, but will do again when start
      // TBIFG interrupt disabled (we just do CC0)
      // - this done when we emable at the bottom 
      //  HWREGW( TIMER_B0_BASE | TBxCTL )=0x30;
      // and set TBIDEX to divide by 1 as well
      HWREGW( TIMER_B0_BASE | TBxEX0 )= TAIDEX_0;
      // write CCR0 to CL0 immediatly
      HWREGW( TIMER_B0_BASE | TBxCCTL0 ) &= ~(CLLD1|CLLD0);  
      // CCR0 sets period
      // and CCR0 is the interupt
      HWREGW( TIMER_B0_BASE | TBxCCTL0 )= CCIE;
      //  HWREGW( TIMER_B0_BASE | TBxCCR0 )= Period-1;
      HWREGW( TIMER_B0_BASE | TBxCCR0 )= 12000-1; // harmonic 1-8 + bridge
      // now CC5-6 the PWM compare states
      // latch when TB0R counts to zero
      // (implicit) Compare mode
      // Reset/Set on PWM
      HWREGW( TIMER_B0_BASE | TBxCCTL5 )= CLLD_1 | OUTMOD_7 ;
      HWREGW( TIMER_B0_BASE | TBxCCR5 )= 0;
      // Set/Reset - quick hack of push/pull - needs more though and a gap
      HWREGW( TIMER_B0_BASE | TBxCCTL6 )= CLLD_1 | OUTMOD_3 ;
      HWREGW( TIMER_B0_BASE | TBxCCR6 )= 0;
      // and enable output pins TB0.5 - TB0.6 - 5 and 6 used as on ext pins
      HWREGB( P3_BASE + PxDIR ) |= BIT5 ;
      HWREGB( P3_BASE + PxDIR ) |= BIT6 ;
      // and switch to PWM usage
      HWREGB( P3_BASE + PxSEL ) |= BIT5 ;
      HWREGB( P3_BASE + PxSEL ) |= BIT6 ;
      // Now all set enable and clear
      HWREGW( TIMER_B0_BASE | TBxCTL )=
        TBCLGRP_0 | CNTL__16 | TBSSEL__SMCLK | MC__UP | TBCLR ;
    
    谢谢 Bruce 和 David -现在还没有时间检查您的想法、但听起来不错。

    可以快速发布我的计时器 B 配置。 这已经过测试、可以正常工作。

    HWREGW 宏将一个 unint16_t 写入存储器地址、我通常会在.h 文件中设置偏移。 我更喜欢这种方法、因为压缩 c、已经执行或运算并获得内存地址-并且为代码提供将长度正确的变量写入内存。 我从不喜欢 Texas Instruments 方法、此方法在连接器中解析符号...

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我的 HWREGW 宏向内存地址写入 unint16_t,我通常在.h 文件中设置偏移。 我更喜欢这种方法、因为压缩 c、已经执行或运算并获得内存地址-并且为代码提供将长度正确的变量写入内存。 我从不喜欢 Texas Instruments 方法、此方法在链接器中解析符号...

    "我要去厕所了。"

    今天早上检查了我的代码-我还没有重新定义 ADC12*变量、如 ADC12CTL0 -所以它在使用链接器中的值!

    今天早上、将变量名称更改为 ADC12ACTL0等;如果在标头中找不到、则会出错。

    再次刷新-和宾果,我现在得到忙旗!

    导致这个问题的编码风格也是如此。 多么愚蠢。 必须查看我是否可以不使用链接文件、以便找到我不想解析的名称。

    感谢两个你的帮助,将仔细地通过评论。

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

    TI 提供的接头具有偏移量。 例如、msp430f5xx_6xxgeneric.h 中的 OFS_ADC12CTL0

    大多数情况下、在链接阶段之前、仅仅为了解析地址而进行操作仍然是一种愚蠢的方法。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    3)当 CONSEQ=1时、每批处理后需要切换 ADC12ENC (=0则=1)[Ref UG Sec 28.2.7.2]。 这通常在 ADC ISR 内部完成(计时器 ISR 几乎肯定太早)。

    您认为您是指  

      HWREGW( ADC12_A_BASE | OFS_ADC12CTL0 ) |= ADC12SC;
      HWREGW( ADC12_A_BASE | OFS_ADC12CTL0 ) &= ~ADC12SC;
    

    至少这会让 BUSY 标志按照我的预期工作-现在读取这些值!

    哦、是的、我改变了在 ADC12SC 上操作触发器-而不是 timerB CCR0 -设置 CCR0会混乱我的其他代码、而且我还需要发生每个计时器 B 中断、而不是每隔一个中断!

    啊、我现在看到了-做计时器 B 触发您可以切换 ADC12ENC、但使用 ADC12SC 触发器、您可以切换 ADC12SC。

    我也希望不需要 ADC12 ISR。

    TI 文档的优点在于、我认为*所有内容*都已在用户手册中进行了说明、几乎没有遗漏。 不好的是,使一个1000页的文档,这是*非常*密集,与魔鬼在细节!

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

    现在唯一的问题是温度参考 ADCINCH_10始终提供最大的读数-我已经将 ADC12TCOFF 设置为0、假设我已经启用了参考电压-从图18-1看来、参考电压就是热敏电阻驱动电压 Ref_x 的来源。

      HWREGW( ADC12_A_BASE | OFS_ADC12CTL0 ) =
        ADC12SHT1_0 | ADC12SHT0_0 | ADC12MSC | ADC12REF2_5V | ADC12REFON ;
      HWREGW( ADC12_A_BASE | OFS_ADC12CTL1 ) =
        ADC12CSTARTADD_0 | ADC12SHS_0 | ADC12SHP | ADC12DIV_0 | ADC12SSEL_3 | ADC12CONSEQ_1 ;
      HWREGW( ADC12_A_BASE | OFS_ADC12CTL2 ) =
        ADC12RES_2 | ADC12REFOUT | ADC12REFBURST;
      HWREGB( ADC12_A_BASE | OFS_ADC12MCTL0 ) = ADC12SREF_7 | ADC12INCH_0;
      HWREGB( ADC12_A_BASE | OFS_ADC12MCTL1 ) = ADC12SREF_7 | ADC12INCH_10;
      HWREGB( ADC12_A_BASE | OFS_ADC12MCTL2 ) = ADC12EOS;
      HWREGW( ADC12_A_BASE | OFS_ADC12CTL0 )|= ADC12ON;
      HWREGW( ADC12_A_BASE | OFS_ADC12CTL0 )|= ADC12ENC;
    

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

    ADC12SREF_7为 ADC 选择一个外部基准(+和-)。 这真的是你想要的吗?

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

    是的、认为这就是问题所在、改为 ADS12SREF_1、我在 ADC 上得到了"随机数"-现在增加采样、看看它是如何改变稳定性的。

    最关键的例子是 slau208q 的图28-1、图28-1更清楚地显示了将位 ADC12SREF0/1设置改为01、通过基准选择从 AVCC 的路径-在任何地方都找不到文本中描述的路径!

    感谢两位-帮助我找到 UG 的路线。

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

    表28-8明确显示了 ADC12SREF 的影响。 假设您已经了解 VREF 和 VeREF 之间的差异。

    当使用内部温度传感器时、您希望使用内部基准。 这使您可以使用 TLV 校准数据来校正结果。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    假定您无论如何都了解 VREF 和 VeREF 之间的区别。

    是的、这是我的问题、只看到了图18-1中的区别;是的、还进行了更改、以通过 REFCTL0对基准进行编程。