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.

TIVA在ADC数字比较器中断中能否直接读取采样值?



        我在使用TM4C123G launchpad的时候,想使用ADC内部的数字比较器的功能,我设置比较器为中值带模式,现在实验结果是能正常的触发比较器中断,但是我想在这个中断中读取ADC的采样值,但是ROM_ADCSequenceDataGet函数返回的一直是0,是不是TIVA数字比较器不能这样操作,只能进行比较判断。

        

        看这副ADC的结构图,数据同时传进了比较器与FIFO,所以我自己猜测应该是可以取到这个值的,有没有做过的高手指点一下,实在不行的话我只能再把ADC切回采样模式,重新采一次值这样来回切换了。

  • 在中断中直接看ADC结果寄存器中的值,看看可不可以取到。手册上好像真没说这个东东

  •         按照您所说的,发现使用不同的电压值触发中断寄存器值始终没变,一直为100000100000,我设置了断点自动刷新,发现每次中断都只有图2中所示的3个寄存器值有变化,这三个基本都是中断标志位,与采样结果没有关系。。。

  • 看来,这个结果是不会放在中断寄存器中的,自动比较了。

  •         这两天又重新折腾了一下这个东西,我重新下载了芯片的英文手册,发现了这么一段话:

    ADC conversions can either be stored in the ADC Sample Sequence FIFOs or compared using the
    digital comparator resources

            这个词表明这两条路径只能二选一了,我一直参照的是另一款TM4C123的中文手册,中文翻译没有体现出这个,原文如下:

    “取决于 ADC 采样序列 n 操作 (ADCCSOPn) 寄存器中的 SnDCOP 位的设置,ADC 转换结果可以保
    存到 ADC 采样序列 FIFO 中,也可以供给数字比较器进行比较。”

            也字换成“或者”应该就意思明确了,然后我继续实验,使用下面的代码对同一个通道多次采样:

    ROM_ADCSequenceStepConfigure(ADC0_BASE, key_sequence, 0, ADC_CTL_CH0);

    ROM_ADCSequenceStepConfigure(ADC0_BASE, key_sequence, 0, ADC_CTL_CH0 | ADC_CTL_CMP0);

    ROM_ADCSequenceStepConfigure(ADC0_BASE, key_sequence, 0, ADC_CTL_CH0 | ADC_CTL_END);

           这个的结果是在进入中断后成功采样到了触发中断的电压值,但是惊讶的发现,采样结果有一个周期的延迟,比如我分别用1V,1.5V,3V,2V,1V这样的序列触发,中断里采到的是RANDOM,1V,1.5V,3V,2V,我是想用ADC的这个特性做一个按键电压判断,这样一来本次触发得到的都是上一个按键的值,这导致按键功能完全没法实现,翻阅手册暂时没有看到这方面的描述,但是偶然中我发现驱动库函数手册ADCComparatorReset()函数介绍里面是这样写的:

    “Because the digital comparator uses current and previous ADC values, this function allows the comparator to be reset to its initial value to prevent stale data from being used when a sequence is enabled.”

            使用了前一次和本次的采样值?是怎样使用的?是否这就是产生延迟的原因?

            感觉追踪到这已经超出手册所能提供的支持范围了,不知道有没有对这个具体细节了解的大大,希望看到了能不吝指教,虽然用曲线救国的方法在ADC比较中断后马上切回普通采样模式也能在按键没松开的时间段内采到按键值,但是我很看好这个功能,要是能直接采到就完美了。希望有共同关注这个问题的朋友<_>

  • 不知道楼主验证的咋样了,由于手头没有板子了,也无法验证。在涉及到细微功能的时候,还是以英文的手册为准,因为那个一般是最新版本的,而中文的翻译版是很早的版本。

  •         现在我是确实没办法直接得到,然后采用的是折中的办法,先用比较器检测到后切回软件触发重新采样然后再切换到比较器模式,由于速度比较快,这样并看不出来切换,实际用起来也是不错的。大致的代码如下,可以一起看看^_^

    /****************************adc mode switch***********************************/
    void keyADCModeSet(uint8_t adcMode) {
    	switch (adcMode) {
    	case mode_init:
    //		ROM_ADCSequenceDisable(ADC0_BASE, key_sequence);			//暂时禁止ADC采样序列
    		//复位比较器
    		ROM_ADCComparatorReset(ADC0_BASE, 0, true, true);
    		//绑定比较器
    		ROM_ADCSequenceStepConfigure(ADC0_BASE, key_sequence, 0,
    		ADC_CTL_CH4 | ADC_CTL_CMP0 | ADC_CTL_END);
    //		ROM_ADCIntEnable(ADC0_BASE, key_sequence);
    //		ROM_ADCIntClear(ADC0_BASE, key_sequence);						//清零中断标志
    		//设置触发
    		ROM_ADCSequenceConfigure(ADC0_BASE, key_sequence, ADC_TRIGGER_ALWAYS,
    				0);		//配置AD采样序列,持续触发采样
    		ROM_ADCSequenceEnable(ADC0_BASE, key_sequence);		//使能ADC_IN使用的采样序列
    		ROM_ADCComparatorIntEnable(ADC0_BASE, key_sequence);
    		ROM_IntEnable(INT_ADC0SS0);
    		break;
    	case mode_samp:
    		//重新配置AD采样序列,处理器触发采样
    		ROM_ADCSequenceDisable(ADC0_BASE, key_sequence);		//暂时禁止ADC采样序列
    		ROM_ADCSequenceConfigure(ADC0_BASE, key_sequence, ADC_TRIGGER_PROCESSOR,
    				0);
    		ROM_ADCSequenceStepConfigure(ADC0_BASE, key_sequence, 0,
    		ADC_CTL_CH4 | ADC_CTL_IE | ADC_CTL_END);			//接收产生中断信号
    		ROM_ADCSequenceEnable(ADC0_BASE, key_sequence);			//重新开启采样序列
    		break;
    	case mode_comp:
    		ROM_ADCSequenceDisable(ADC0_BASE, key_sequence);		//暂时禁止ADC采样序列
    		//重新绑定比较器
    		ROM_ADCSequenceStepConfigure(ADC0_BASE, key_sequence, 0,
    		ADC_CTL_CH4 | ADC_CTL_CMP0 | ADC_CTL_END);
    		//设置触发
    		ROM_ADCSequenceConfigure(ADC0_BASE, key_sequence, ADC_TRIGGER_ALWAYS,
    				0);		//配置AD采样序列,持续触发采样
    		ROM_ADCSequenceEnable(ADC0_BASE, key_sequence);		//使能ADC_IN使用的采样序列
    		break;
    	default:
    		break;
    	}
    }
    
    //init the hardware of key such as adc & gpio
    void initKeypad(void) {
    //	初始化设置ADC以及比较器模块
    	ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64);	//64位的硬件平均值滤波
    	ROM_ADCComparatorConfigure(ADC0_BASE, 0,
    	ADC_COMP_TRIG_NONE | ADC_COMP_INT_MID_ONCE);	//比较器中值带工作
    	//设置比较器门限
    	ROM_ADCComparatorRegionSet(ADC0_BASE, 0, 150, 3950);
    //	默认初始化模式
    	keyADCModeSet(mode_init);
    //	使能全局中断
    	ROM_IntMasterEnable();
    }
    
    /**
     * get the raw value of key adc
     */
    void keypadGet(uint32_t *keypad_value) {
    	ROM_ADCProcessorTrigger(ADC0_BASE, key_sequence);				//处理器触发采样
    
    	while (!ROM_ADCIntStatus(ADC0_BASE, key_sequence, false))		//等待采样结束
    	{
    	}
    
    	ROM_ADCIntClear(ADC0_BASE, key_sequence);						//清除中断标志
    
    	ROM_ADCSequenceDataGet(ADC0_BASE, key_sequence, keypad_value);	//获取采样值
    }
    
    /********************************按键中断处理函数****************************/
    void keyIntHandler() {
    //	led_1_on;
    	//比较器中断处理
    	ROM_ADCIntClear(ADC0_BASE, key_sequence);						//清除ADC中断标志
    	uint32_t DCStatus = ROM_ADCComparatorIntStatus( ADC0_BASE);
    	ROM_ADCComparatorIntClear( ADC0_BASE, DCStatus);				//清除比较器中断标志
    
    	//切换为采样模式
    	keyADCModeSet(mode_samp);
    
    	//软件触发采样,等待返回
    	keypadGet(&keypad_value);
    
    	//重新配置回比较器模式
    	keyADCModeSet(mode_comp);
    
    	//键值处理
    	getKeyCode();
    //	led_1_off;
    }