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.

[参考译文] MSP430FR5989:DMA 与 ADC12搭配使用

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/950812/msp430fr5989-dma-use-with-adc12

器件型号:MSP430FR5989

我正在尝试在 MSP430FR5989上将 ADC12与 DMA 配合使用。 我传递我要读取和存储的秒数。 该函数用于初始化 ADC 以进行从 ACLK 运行的重复单通道采集。 DMA 配置为从 ADC12触发并递增目的地址。 DMA 中断被启用、因此在设定的数据量被存储后、它将关闭 ADC12和 DMA。

有一个次级功能、在通道序列配置中使用 ADC12对电池电压进行8次连续测量。 然后对8个采样进行平均值计算、以获得平均电压测量值。

这两个函数不会同时运行。  我运行一个(可能重复)然后运行另一个、因此不会发生资源冲突。

有三个相关函数:record_AMPLE()、stop_asense_capture ()和 diagnostics_batter()。 下面提供了这些功能。

如果我在启动后立即调用 record_AMPLEA()函数,RECODE_AMPLE()和 STOP_ASENS_CAPTURE ()函数将按预期工作。 此外,我还可以反复调用 record_AMPLEA()函数,并且每次目标地址中的数据被适当更新并且 DMA 中断发生时调用 stop_asense_capture ()函数,该函数会停止 ADC12和 DMA。

如果我调用 diagnostics_battery()函数,那么当我调用 record_AMPLEA()函数时,ADC12开始连续测量,但没有 DMA 传输。 如果我暂停调试器中的程序并设置 DMALEVEL=1然后运行,那么数据将被传输,随后对 RECODE_AMPL()的调用将正常工作。 但是如果我再次调用 diagnostics_battery(),则问题再次出现–调用 record_AMPLEA()启动 ADC12,但不传输任何数据。

我试过的:

1)    1)停止调试器中的固件并检查所有寄存器是否均已正确设置–它们是正确的。

2) 2)    在调用 record_limer()之前清除 ADC12MCTLx 寄存器–未更正。

3) 3)    在 RECODE_AMPLAD()函数中设置 ADC12MCTL0中的 ADC12EOS 位。 –未更正。

4)    4)设置 DMA0CTL 中的 DMALEVEL 位–这可以“修复”问题,但我不认为这是带有 ADC12的 DMA 的首选配置。

在正确配置寄存器、ADC 正在运行并采集数据但不会生成传输之前、您是否曾遇到过此问题?

您是否有任何解决问题的建议。

 

//初始化 ADC12的函数、以及用于持续读取和存储 P9.6端口的 DMA。

void record_放大 器(uint8_t seconds_TO_RECORD)

  uint16_t 采样;

  // ASens->P9.6->模拟通道6.

  P9SEL0 |=(1 << 6);    //选择 A14

  P9SEL1 |=(1 << 6);    //选择 A14

  P9DIR &=~(1 << 6);  //这是无关的、无关紧要

  

  //关闭 ADC。

  ADC12CTL0 &=~ADC12ENC;

  ADC12CTL0 = 0;//确保 ADC 关闭、如果它打开、则 REFGENBUSY 将始终置1。

  // REFCTL0寄存器中的大多数位只能在时修改

  // REFGENBUSY 位为0。 因此、请确保它是。

  while (REFCTL0和 REFGENBUSY);

  

  //在1.2V 基准上进行选择。 关闭温度传感器以节省功耗。

  REFCTL0 = REFTCOFF | REFVSEL_0;

  

  //打开 Vref (1.2V)

  REFCTL0 = REFON;

  

  //我们希望重复采样>250毫秒,因此请使用 ACLCK

  //时钟分频器=1,SHT=96,和15个时钟脉冲,用于转换=>111个时钟脉冲,3.387毫秒,295Hz。

  //启用 ADC 和多采样模式

  ADC12CTL0 = ADC12MSC | ADC12ON | ADC12SHT00 | ADC12SHT02;

  

  //使用采样定时器、ACLK 和重复单通道模式

  ADC12CTL1 = ADC12SHP | ADC12SSEL0 | ADC12CONSEQ1;

  

  // 12位转换结果,低功耗模式?检查 LPM 是否正常

  ADC12CTL2 = ADC12RES_2 | ADC12PWRMD_L;

  

  ADC12MCTL0 = ADC12INCH_14 | ADC12VRSEL_1;

  ADC12IFGR0 = 0;//复位任何挂起的中断

  

  //源块地址

  __data16_write_addr ((unsigned short)&DMA0SA、(unsigned long) ADC12MEM0_);

  //目标地址

  __data16_write_addr ((unsigned short)&DMA0DA、(unsigned long) 0x20010);

  if (秒_至_记录>25)

  {

    seconds_TO_RECORD = 25;//将其限制在25秒以防止溢出

  }

  采样=(uint16_t)(seconds_TO_RECORD)*295;//秒数*采样率

  DMA0SZ =样片;

  DMACTL0 = DMA0TSEL_26;//ADC12转换结束触发 DMA0

  //重复单次传输,递增目的,启用中断

  DMA0CTL = DMADT_4 | DMADSTINCR_3 | DMAEN | DMAIE;   

  

  //等待基准电压表明其已准备就绪。

  while (!(REFCTL0 & REFGENRDY));

  

  //启用采样并开始转换。

  ADC12CTL0 |= ADC12ENC | ADC12SC;

 

//停止 ADC12和 DMA 的函数

void stop_asense_capture (void)

  DMA0CTL = 0;  //关闭 DMA

  //关闭 ADC。

  ADC12CTL0 &=~ADC12ENC;

  ADC12CTL0 = 0;

  

  //关闭基准。

  REFCTL0 &=~REFON;

  

  P9SEL0 &=~(1 << 6);     

  P9SEL1 &=~(1 << 6);     

 

//功能来测量 P1.2上的调节电池电压

#define NSAMPLES 8.

int diagnostics_battery (void)

  uint16_t * adc_mem_reg;

  uint16_t * adc_mctl_reg;

  uint16_t i;

  uint16_t ADC_SUM;

  uint32_t bol_threshold;

              uint32_t 快照;

 

  // VMonitor->P1.2->模拟通道2

  P1SEL0 |=(1 << 2);    //选择 A2

  P1SEL1 |=(1 << 2);    //选择 A2

  P1DIR &=~(1 << 2);  //这是无关的、无关紧要

 

  // REFCTL0寄存器中的大多数位只能在时修改

  // REFGENBUSY 位为0。 因此、请确保它是。

  while (REFCTL0和 REFGENBUSY);

 

  //在1.2V 基准上进行选择。 关闭温度传感器以节省功耗。

  REFCTL0 = REFTCOFF | REFVSEL_0;

 

  //打开 Vref (1.2V)

  REFCTL0 = REFON;

 

  //启用 ADC 和多采样模式

  ADC12CTL0 = ADC12MSC | ADC12ON | ADC12SHT02;

 

  //使用采样定时器、ACLK 和通道序列模式

  ADC12CTL1 = ADC12SHP | 0x08 | ADC12CONSEQ0;

 

  // 12位转换结果

  ADC12CTL2 = ADC12RES_2;

 

  //选择输入通道 A2 (Vmonitor)和缓冲 Vref /VSS 作为的参考

  //所有样本。

  adc_mctl_reg =(uint16_t *)&ADC12MCTL0;

  对于(I = 0;I < NSAMPLES;I++)

  {

     //通道号= Vmonitor

      // VR+= VREF 缓冲、VR-= AVSS

      // ADC12EOS = 0 (非最后一个采样)

      adc_mctl_reg[i]= ADC12INCH_2 | ADC12VRSEL_1;

  }

 

  // ADC12EOS = 1 (最后一个采样)

  adc_mctl_reg[NSAMPLES - 1]|= ADC12EOS;

 

  //等待基准电压表明其已准备就绪。

  while (!(REFCTL0 & REFGENRDY));

 

  //启用采样并开始转换。

  ADC12CTL0 |= ADC12ENC | ADC12SC;

 

  //等待转换完成。

  while (ADC12CTL1和 ADC12BUSY);

 

  //关闭 ADC。

  ADC12CTL0 = 0;

 

  //关闭基准。

  REFCTL0 &=~REFON;

 

  //对样本求平均值。

  adc_mem_reg =(uint16_t *)&ADC12MEM0;

  ADC_SUM = 0;

  对于(I = 0;I < NSAMPLES;I++)

  {

      adc_sum += adc_mem_reg[i];

  }

 

  返回0;