ADC comparator 问题



你好!!

我们使能了开发板上的GPIO作为ADC的digital comparator来使用

我们选择了 hysteris always mode,high band operation, 上限60mV ,下限40mV(避免掉我们输入讯号造成 false trigger 的问题)

当输入讯号超过60mV就让他中断并设计一计数器让它记录中断的次数

问题在于如何在code中加入这一个中断和计数器?

下面是我们的CODE (ulLowRef, ulHighRef 是上下限电压值我们还在调整)

//=====================================================

SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
        
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
     
GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_6);
        
ADCSequenceConfigure(ADC1_BASE, 1, ADC_TRIGGER_COM1, 0);
        
ADCComparatorConfigure(ADC1_BASE, 1, ADC_COMP_TRIG_HIGH_HALWAYS);
        
ADCComparatorRegionSet(ADC1_BASE, 1,  ulLowRef, ulHighRef);

ADCSequenceStepConfigure(ADC1_BASE, 1, 0, ADC_CTL_CH5| ADC_CTL_IE | ADC_CTL_END);

ADCSequenceEnable(ADC1_BASE, 1);

ADCIntClear(ADC1_BASE, 1);

while(1) {

     ADCProcessorTrigger(ADC1_BASE, 1);
     while(!ADCIntStatus(ADC1_BASE,1, false));
     ADCSequenceDataGet(ADC1_BASE,1, ulADC1_Value);  }

//=====================================================

  • 你好,首先你的比较器配置和比较器阈值设置你都做好了。接着需要使能比较器中断;

    不知道楼主使用什么开发编译环境,如果是keil的话需要自己编写中断服务函数,并把该函数写到启动代码文件startup.s中断向量表的相应位置,如果是CCS环境的话就写到startup_ccs.c的中断向量表的相应位置;在中断服务程序中,需要读取比较器中断状态,并清除中断标志,你需要的计数器变量就可以在中断服务程序里面加1.

  • 我使用keil来编译,附上完整的程式码

    我不太了解说当比较器中断时的程式码应该要放在哪个位置

    像我现在放在最后面是正确的吗?因为都找不到M4系列关于ADC Digital比较器的模板来参考

    现在这个程式码在板子上无法正确的跑出比较器的结果

    每当输入电压超过我设定的范围时,计数器就要加1,并显示次数在屏幕上,但是他没有,不知道问题是出在哪

    谢谢您的回覆!!!

    下面是我把程式码贴上来,彩色比较容易看,怕网站有问题我也上传了.C档

    http://chopapp.com/#sdla397g

     

  • 你好,我看了一下你的程序,但是因为时间关系,不能很快的在你的程序上改,所以我写了一个程序,将ADC1的采样序列2,将序列的第四个采样的值送到数字比较器0。由于我想较容易的产生比较器中断,所以比较器设置成了LOW_ALWAYS模式。下面是初始化ADC1的函数代码:

    void ADCInit(void)

    {

    //The ADC1 must be enable for use

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);

       ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_ADC1);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);//PE3 as a input AIN0

    ROM_GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_3);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);//PE2 as a input AIN1

    ROM_GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_2);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);//PE1 as a input AIN2

    ROM_GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_1);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);//PE0 as a input AIN3

    ROM_GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_0);

       ROM_ADCSequenceConfigure(ADC1_BASE,2,ADC_TRIGGER_PROCESSOR,0);//use the sequence2 which including 4 FIFO,processor trigger

    ROM_ADCSequenceStepConfigure(ADC1_BASE,2,0,ADC_CTL_CH0);

    ROM_ADCSequenceStepConfigure(ADC1_BASE,2,1,ADC_CTL_CH1);

    ROM_ADCSequenceStepConfigure(ADC1_BASE,2,2,ADC_CTL_CH2);

    ROM_ADCSequenceStepConfigure(ADC1_BASE,2,3,ADC_CTL_CH3|ADC_CTL_END|ADC_CTL_CMP0);

    // ADCComparatorConfigure(ADC1_BASE, 2, ADC_COMP_TRIG_HIGH_HALWAYS);//your configure is not right

    ADCComparatorConfigure(ADC1_BASE, 0, ADC_COMP_INT_LOW_ALWAYS);

    ADCComparatorRegionSet(ADC1_BASE, 0, 200, 300);

    ADCComparatorReset(ADC1_BASE, 0, 1, 1);

    ADCComparatorIntEnable(ADC1_BASE,2);

    ROM_ADCReferenceSet(ADC1_BASE,ADC_REF_INT);//chose the internal reference 3V

    ROM_ADCSequenceEnable(ADC1_BASE,2);//Enable sequence2

    // ROM_ADCIntEnable(ADC1_BASE,2);//Enable ADC1 sequence2 interrupt

    ROM_IntEnable(INT_ADC1SS2);

    }

  • 太长了,继续贴,这是中断服务程序:

    void ADCIntHandler(void)

    {

    unsigned long ulMode,ulStatus;

    ulStatus= ADCComparatorIntStatus(ADC1_BASE);

    ADCComparatorIntClear(ADC1_BASE,ulStatus);

    ROM_ADCIntClear(ADC1_BASE,2);//clearing the int in sequence2,it seems this sentence is useless

    ROM_ADCProcessorTrigger(ADC1_BASE,2);//trigger a sequence2///////////////////////////////////////////

    }

    你需要在main函数里面调用ADC的初始化函数,再调用ROM_ADCProcessorTrigger(ADC1_BASE,2);先触发一次ADC采样,这样比较器0应该就可以运行起来了,当然前提是你已经在中断向量表里面登记了中断服务程序。

    调试的时候你可以监控寄存器ADCRIS,如果第16bit为1表示比较器中断产生了。

    至于楼主希望记录中断次数,我没有加进去,这个应该不是难点。

    临时写的一个程序,不是很规范,只是让比较器跑起来了,希望对楼主有用。

  • 您好

    我不太习惯使用ROM的语法所以我看了您的建议之后把我自己的程式码改写了

    问题在于我之前加入了错误的中断服务程序进向量表里

    改写之后比较器能正常运作了,附上我改写好的

    //==============================================================

    #include "inc/lm4f232h5qd.h"
    #include "utils/ustdlib.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ADC.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/adc.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/gpio.h"
    #include "grlib/grlib.h"
    #include "drivers/cfal96x64x16.h"

    //*****************************************************************************
    //
    // Global variable to count the number of digital comparator interrupts.  This
    // variable is not needed for the proper operation of the ADC or digital
    // comparators.
    //
    //*****************************************************************************
    unsigned long g_ulNumOfInt;

    //*****************************************************************************
    //
    // Global variable to count the number of digital omparator interrupts that
    // have been triggered.  This variable is not needed for the proper operation
    // of the ADC or digital comparators.
    //
    //*****************************************************************************
    unsigned long g_ulDCIntStatus;

    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, unsigned long ulLine)
    {
    }
    #endif


    //*****************************************************************************


    #define SEQUENCER 1
            tContext sContext;
        char cText[8];

    //*****************************************************************************

    void
    ADC1Seq0IntHandler(void)
    {
        //
        // Read the digital comparator interrupt status register.  This global
        // variable will keep track of which digital comparator triggered the
        // interrupt.
        //
        g_ulDCIntStatus = ADCComparatorIntStatus(ADC1_BASE);

        //
        // Clear all of the digital comparator interrupt bits.  We do this because
        // more than one digital comparator interrupt may have been triggered this
        // interrupt.
        //
        ADCComparatorIntClear(ADC1_BASE, 0x0F);

        //
        // Increment the variable that keeps track of how many interrupts have
        // been triggered.
        //
        switch (g_ulDCIntStatus)
            {
                    case 0x01:
                            g_ulNumOfInt++;
                            break;
                    default:
                            break;
            }
    }


    //*****************************************************************************


    int main(void)
    {
        volatile unsigned long ulLoop;
            
        unsigned long ulADC1_Value[4];
        
        //
        // Enable ADC
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
            

          //
          // Enable GPIO Port .
          //
          SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);

        //
        // Configure GPIO pins as ADC input channels.
        //
        GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_5);

        //
        // Enable processor interrupts.
        //
        IntMasterEnable();

        //
        // Enable the ADC sample sequence 0 interrupt on the processor (NVIC).
        //
        IntEnable(INT_ADC1SS0);
            
        //
        // Configure sequencer for trigger.
        //
        ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_ALWAYS, 0);

        //
        // Configure ADC 0 to use Hardware Over Sampling Ciruit.
        //
        ADCHardwareOversampleConfigure(ADC0_BASE, 64);

        //  
        // Sample ADC channels in single ended mode & configure an interrupt flag
        // when sample is done. Configure the last step to cause an interrupt when
        // it is complete
            
        ADCSequenceStepConfigure(ADC1_BASE, 0, 0, ADC_CTL_CH22 | ADC_CTL_CMP0);
        ADCSequenceStepConfigure(ADC1_BASE, 0, 1, ADC_CTL_CH22 | ADC_CTL_END);
            
        //
        // Enable sample sequence.
        //
        ADCSequenceEnable(ADC1_BASE, 0);
            
        //
        // Configure ADC Comparator 0
        //
        ADCComparatorConfigure(ADC1_BASE, 0, ADC_COMP_INT_LOW_HONCE);
        ADCComparatorRegionSet(ADC1_BASE, 0, 300, 400);
            
            g_ulNumOfInt = 0;
            
            ADCComparatorReset(ADC1_BASE, 0, true, true);
            ADCComparatorIntEnable(ADC1_BASE,0);
            
            //==============================================================   

        while(1)
        {
                
                //
                // Read ADC Value.
                //
                ADCSequenceDataGet(ADC1_BASE,0, ulADC1_Value);
                    
                //
                // Display how many times it interrupted on screen .
                //
                usprintf(cText, " %d    ", g_ulNumOfInt);
                GrStringDraw(&sContext, cText, -1, 45, 55, 1);
                    
            //
            // This function provides a means of generating a constant length
            // delay.  The function delay (in cycles) = 3 * parameter.  Delay
            // 250ms arbitrarily.
            //
            SysCtlDelay(SysCtlClockGet() / 20);

            //
            // Flush any cached drawing operations.
            //
            GrFlush(&sContext);
        }
    }

  • 能够正常跑了吗?那恭喜楼主了~~~