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.

[参考译文] MSP430FR5969:采用 DMA 后的 LPM

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/802723/msp430fr5969-lpm-after-employing-dma

器件型号:MSP430FR5969

尊敬的同事:

我正在使用嵌入在 LPM3中以低频运行的 MSP430FR5969中的 ADC。

然后、我将尝试通过 DMA 将转换结果传输到给定的存储器位置。

但是、我在使用 DMA 后产生的 LPM 有问题。

我认为 MCU 会在传输数据后返回到 LPM3、但它会保持在 LPM0中。

这是我们应该期望的结果、还是我在配置中做了一些错误的事情?

非常感谢您的参与、

Ferran

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

    请给我一些时间来进一步了解这一点、但与此同时、您能否提供一个隔离 ADC、DMA 和 LPM 功能的项目精简版本、以便我可以尝试在测试设置中重新创建您的问题?

    此致、

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

    尊敬的 Matt:

    感谢您的回答!!

    接下来、您可以找到我用于设置 ADC、计时器和 DMA 的代码。

    您的任何反馈、肯定会有所帮助!!

     LF 下的 ADC 的//配置
     ADC12CTL0 = 0x0010;// S&H:4 clk
                         // ADC 打开
     ADC12CTL1 = 0x060C;   // 32kHz
                            //重复单通道
                            // Clk 源:ACLK
                            // SAMPCON 信号来源于采样定时器
                           //它由计时器触发
     ADC12CTL2=0x0011;//转换10位
                        //启用 ADC 的低功耗模式

                         //与 ADC12MEM0相关的寄存器:
     ADC12MCTL0 = 0x0082;   // A2 ADC 输入选择
                            //电压基准为 Vcc

     ADC12CTL0 |= ADC12ENC; //启用 ADC

     //配置 Timer0_A3以定期触发 ADC12
     TA0CCR0 = 32768;               //为了使周期为1s。计时器每秒激活 ADC 而不中断 CPU
     TA0CCTL1 = OUTMOD_3;           // TACCR1设置/复位
     TA0CCR1 = 32767;
     TA0CTL = tassel_ACLK | MC__UP;// ACLK、UP 模式

     DMA 的//配置
     DMACTL0 = DMA0TSEL_26;  // DMA 通道0由 ADC 转换结束触发

     DMA0CTL = 0x0010;         // DMA 使能
                             //源和目的是一个字,而不是一个字节
                             //源地址不变
                             //目标地址递增;现在禁用
                             //为了获得增量,我们应该具有0x4C10
                             //重复单次传输
      DMA0SZ = 1;           //传输1字节/字

     __data16_write_addr ((unsigned short)&DMA0SA、(unsigned long)&ADC12MEM0);   //DMA0SA:具有源地址(ADC12MEM0)的寄存器

     __data16_write_addr ((unsigned short)&DMA0DA、(unsigned long)&DMA_dst); //DMA0DA:具有目标地址的寄存器(DMA_dst 在开头定义)


     //进入睡眠模式
     _bis_SR_register (LPM3_bits);      //进入 LPM3、不启用中断

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

    Ferran、

    我汇总了一个代码示例、该示例可实现您在帖子中所述的内容。 我将 ACLK 初始化为在低频晶振上运行、然后将 ADC 捕获配置为触发 DMA 传输、而不会唤醒器件或进入中断。 您可以找到电流消耗屏幕截图和粘贴在下面的代码。 根据我所能知、一旦启动代码执行并启动 ADC、我们就会从此处对器件进行采样、并保持在 LPM3电流消耗水平(~1uA)、除非对 ADC 进行采样并使用 DMA 进行数据传输(在电流曲线中显示为尖峰)。

    #include 
    #include 
    
    int main (void)
    {
    WDTCTL = WDTPW | WDTHOLD; //停止 WDT
    
    //将 GPIO 配置为其最低功耗状态
    P1OUT = 0; //所有 P1.x 复位
    P1DIR = 0xFF; //所有 P1.x 输出
    P2OUT = 0; //所有 P2.x 复位
    P2DIR = 0xFF; //所有 P2.x 输出
    P3OUT = BIT0; //所有 P3.x 复位
    P3DIR = 0xFF; //所有 P3.x 输出
    P4OUT = 0; //所有 P4.x 复位
    P4DIR = 0xFF; //所有 P4.x 输出
    PJOUT = 0; //所有 PJ.x 复位
    PJDIR = 0xFFFF; //所有 PJ.x 输出
    
    //设置 XT1
    PJSEL0 = BIT4 | BIT5; //对于 XT1
    
    P1SEL0 |= BIT2; //为 ADC 函数
    P1SEL1配置 P1.2/A2 |= BIT2; //
    
    //禁用 GPIO 上电默认高阻抗模式以激活
    //先前配置的端口设置
    PM5CTL0 &=~LOCKLPM5;
    
    //时钟系统设置
    CSCTL0_H = CSKEY >> 8; //解锁 CS 寄存器
    CSCTL1 = DCOFSEL_0; //将 DCO 设置为1MHz
    CSCTL2 = SELA_LFXTCLK | SELESS__DCOCLK | SELM_DCOCLK;
    CSCTL3 = DIVA__1 | DIVM_1; //设置所有分频
    器 CSCTL4 &=~LFXTOFF;
    
    执行
    {
    CSCTL5 &=~LFXTOFFG; //清除 XT1故障标志
    SFRIFG1 &=~OFIFG;
    }while (SFRIFG1 & OFIFG); //测试振荡器故障标志
    
    //配置 DMA 通道0
    __data20_write_long ((uintptr_t)&DMA0SA,(uintptr_t)&ADC12MEM0);//从 ADC12MEM0写入
    //源块地址
    __data20_write_long ((uintptr_t)&DMA0DA,(uintptr_t) 0x1C40); //目标地址
    //目标单地址
    DMACTL0 |= DMA0TSEL_26; //由 ADC12触发的 DMA 转换结束
    DMA0SZ = 1; //传输一个字节/字
    DMA0CTL = DMADD_4 | DMAIE;// Rpt 单次传输,如果 GIE 被置位
    DMA0CTL,则启用中断|= DMAEN; //启用 DMA0
    
    ADC12CTL0 = ADC12SHT0_0 | ADC12ON; //采样时间、S&H=4、ADC12打开
    //使用 TA0.1触发和重复单通道
    ADC12CTL1 = ADC12SHP | ADC12SH_1 | ADC12CONSEQ_2;
    // A2 ADC 输入选择;VREF+= VREF
    ADC12MCTL0 = ADC12INCH_1 | ADC12CONSEQ2;// ADC12IE0 | ADC12EOS
    
    //启用 ADC 中断
    ADC12CTL0 |= ADC12ENC | ADC12SC; //开始采样/转换
    
    //配置 Timer0_A3以定期触发 ADC12
    TA0CCR0 = 2048-1; // PWM 周期
    TA0CCTL1 = OUTMOD_3; // TACCR1设置/复位
    TA0CCR1 = 2047; // TACCR1 PWM 占空比
    TA0CTL = tassel__ACLK | MC__UP; // ACLK、向上计数模式
    //_ bis_SR_register (LPM3_bits | GIE); //输入 LPM3、启用中断
    __bis_SR_register (LPM3_bits); //lpm 永远
    
    返回0;
    } 

    此致、

    Matt

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

    尊敬的 Matt:

    非常感谢您的回答!

    我已经测试了您的代码、它可以正常工作、但我的代码不能正常工作。

    我想看看原因是什么、因为代码非常相似。

    您是否认为原因可能是...

    a)外设的配置顺序?

    b)使用_data20_write_long?

    最棒的,感谢您的观看!

    Ferran

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

    只要外设配置正确、并且捕获和存储器写入序列仅在配置完成后启动、那么首先初始化哪个外设就无关紧要。

    此外、由于您不是写入20位地址空间、"数据写入16"应该没有问题。

    我从单独的 ADC 和 DMA 代码示例开始、并将它们从那里合并、以获得我在上面共享的示例。 在您的情况下、如果我在上面分享的示例在您的硬件上按预期工作、则您应该能够利用该示例继续开发您的项目。

    我不知道我们的项目之间有何差异、但您最好在两个项目都点击"_bis_SR_register (LPM3_bits)"行之前映射所有寄存器初始化、并查看两者之间的差异。

    此致、

    Matt