我正在尝试在 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;
}