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.

[参考译文] MSP430F5172:MSP430F5172 -使用 DMA 进行 ADC 读取

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1018663/msp430f5172-msp430f5172---using-dma-for-adc-reading

器件型号:MSP430F5172

您好!  

我正在对 MSP430f5172微控制器进行编程。 我的电源转换器中有3个电压传感器和3个电流传感器。 我计划使用 DMA 通道来存储 ADC 读数。 我能够使用我的代码获取读数、但我最初的想法是、如果我声明一个用于存储数据的数组、它的值将对应于每个 ADC 通道、并且在每次检测期间不会改变、但情况并非如此、 这意味着我的传感器读数将会混淆

我不熟悉该微控制器并使用 DMA。 我出了什么问题? 是否无法将信号读数存储在固定阵列位置?

谢谢你

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

    您好、Firehiwot、

    让我为您研究一下这个问题。

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

    是的、目标是使缓冲区字按顺序对应于每个采样通道、但必须适当地配置 DMA。 您能否布置(或附加)如何配置 ADC 和 DMA?

    我在 Resource Explorer 中看到几个 ADC+DMA 示例:

    msp430f51x2_ADC10_10.c:

    https://dev.ti.com/tirex/explore/node?node=ACxR2ViLR-3U9df34vpizQ__IOGqZri__LATEST

    和 msp430f51x2_ADC10_14.c

    https://dev.ti.com/tirex/explore/node?node=AA0J2gkmfVYDIlaMkeFW7A__IOGqZri__LATEST

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

    您好!  

    谢谢你。 以下是我的代码。 我尝试使用示例10、并且还在示例12的 while 环路中使用了配置、但我仍然有相同的问题。  

    #include
    #include
    #include

    //定义函数
    void SetADC ();
    void SetDMA();
    unsigned int adc_result[8];// 10位 ADC 转换结果数组

    void main (void){
    unsigned int i;//声明计数器变量
    volatile unsigned int D_BUCK;// BUCK 占空比
    volatile unsigned int D_BOOST;//升压占空比
    volatile unsigned int bat_state;//电池开关状态

    WDTCTL = WDTPW + WDTHOLD;//停止看门狗计时器

    //配置模拟寄存器
    PMAPPWD = 0x02D52;//启用写入访问以修改端口映射寄存器
    PMAPCTL = PMAPRECFG;//允许在运行时重新配置
    P1MAP0|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A0
    P1MAP1|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A1
    P1MAP2|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A2
    P1MAP3|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A3
    P1OMAP4|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A4
    P1MAP5|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A5
    P3MAP5|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A8
    P3MAP6|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A7
    PMAPPWD = 0;//通过写入不正确的密钥来禁用写入访问以修改端口映射寄存器
    P1SEL|=BIT0+BIT1+BIT2+BIT3+BIT4+BIT5+BIT7+BIT8;//在应用模拟信号时将端口映射寄存器 PxMAPy 与 PxSEL.y=1一起设置为 PM_ANALOG

    SetADC();
    SetDMA();

    while (1)

    for (i=0;i<8;i++)

    __data20_write_long ((uintptr_t)&DMA0DA、(uintptr_t)&ADC_Result[i]);//更新目标数组地址
    while (ADC10CTL1 & BUSY);//如果 ADC10内核处于活动状态则等待
    ADC10CTL0 |= ADC10ENC + ADC10SC;//采样和转换准备就绪
    _bis_SR_register (CPUOFF + GIE);// LPM0、ADC10_ISR 将强制退出

    __DELAY_CYCLES (5000);//序列转换之间的延迟
    __no_operation ();//断点;检查 ADC_Result


    /*


    // DMA ISR
    #if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
    #pragma vector=dma_vector
    _interrupt void DMA0_ISR (void)
    #Elif defined (_GNU_)
    void __attribute__((中断(DMA_vector)) DMA0_ISR (void)
    其他
    错误编译器不受支持!
    #endif

    switch (__evo_in_range (DMAIV、16))

    情况0:中断;//无中断
    案例2:
    //转换序列完成
    ADC10CTL0 &=~ADC10ENC;//禁用 ADC 转换
    _BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出 LPM
    中断;// DMA0IFG
    案例4:中断;// DMA1IFG
    案例6:中断;// DMA2IFG
    案例8:中断;//保留
    案例10:中断;//保留
    案例12:中断;//保留
    案例14:中断;//保留
    案例16:中断;//保留
    默认值:break;


    //配置 ADC 通道
    void SetADC (){
    ADC10CTL0 = ADC10SHT_2 + ADC10MSC + ADC10ON;// 16xADC 时钟周期、多采样转换、ADC10ON
    ADC10CTL1 = ADC10SHP+ ADC10CONSEQ_1;// ADCCLK = MODOSC;采样信号来源于采样定时器、单次序列
    ADC10CTL2 = ADC10RES;// 10位转换结果
    ADC10MCTL0= ADC10INCH_8 + ADC10SREF_1;//选择 ADC 通道;使用 VR+= VREF 和 VR-= AVSS

    //默认情况下、REFMSTR=1 => REFCTL 被用来配置内部基准
    while (REFCTL0 & REFGENBUSY);//如果基准发生器忙,请等待
    REFCTL0 |= REFVSEL_2 + REFON;//选择内部基准= 2.5V
    _DELAY_CYCLS (75);//参考建立延迟(~75us)-ADC10采样和转换=(32+13)*2/SMCLK = 90/SMCLK = 75us

    void SetDMA(){
    //配置 DMA0 (ADC10IFG 触发器)
    DMACTL0 = DMA0TSEL_24;// ADC10IFG 触发器
    __data20_write_long ((uintptr_t)&DMA0SA、(uintptr_t)&ADC10MEM0);//源单地址
    DMA0SZ = 0x08;// 8次转换-字节或字传输的数量
    DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAEN + DMAIE;// Rpt、inc dest、字节访问、在转换序列后启用 int

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

    >__data20_write_long ((uintptr_t)&DMA0DA、(uintptr_t)&ADC_Result[i]);//更新目标数组地址

    当 CONSEQ=1和 MSC=1时、您将为每个循环获得突发(全部8个通道)(ADC10SC=1设置)、因此您希望下一个循环存储在相同的位置。 尝试:

    >__data20_write_long ((uintptr_t)&DMA0DA、(uintptr_t)&ADC_Result [0]);//设置目标数组基址

    由于每次只设置相同的值、因此您只需在 while (1)循环之前执行一次。

    [编辑:我刚刚注意到:

    >ADC10MCTL0= ADC10INCH_8 + ADC10SREF_1;//选择 ADC 通道;使用 VR+= VREF 和 VR-= AVSS

    ADC10从英寸到0进行采样,因此8->0是9个通道。 尝试:

    >ADC10MCTL0= ADC10INCH_7 + ADC10SREF_1;//选择 ADC 通道;使用 VR+= VREF 和 VR-= AVSS

    ]

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

    我曾尝试在 setdma()例程中包含这行代码,但之前 while (1)循环中没有 for 循环,但我仍然有相同的问题。 下面是表达式表中的结果图片。 我还认为这是它应该的工作方式、因为它会自动扫描所有 ADC 通道、并在每次迭代期间将数据传输到 DMA、但我没有获得正确的输出。  

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

    在此测试中、我仅为 ADC 通道0、1和4提供输入、正确的 ADC 值应为~240  

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

    非常感谢、将其更改为 ADC10INCH_7使其在高达输入通道7的情况下工作。 但是、我在发送输入通道8时遇到问题。 由于 MSP430F5172没有 A6通道、 我认为配置它的正确方法是从  ADC10INCH_8开始、但将阵列的大小设为8 (因为未感测到 A6)。

    我尝试将阵列大小设置为9并从 ADC10INCH_8开始、但这不起作用。  

    如果按这种方式配置、我如何感应 A8?

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

    对于 ADC10、没有跳过序列中的通道的机制。 [参考用户指南(SLAU208Q)图27-7]您必须继续进行采样、然后忽略结果。 您甚至可以将跳过的通道用于数字 I/O - ADC 在采样阶段获取的少量电流不会干扰任何内容。

    另一种方法是转换单通道(CONSEQ=0)并在两者之间切换、但这通常比它的价值更麻烦。

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

    我看到、我找到了我的代码的问题。 我还需要 将 DMA 大小转换为9才能读取 A8。 它现在正在工作。 非常感谢。