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.

TM4C123 系列ADC配置

硬件为TM4C launchpad

主函数程序如下。

int main(void)
{

SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|
SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);

PWM1_init();
ADC0_init();
Timer_init();

。。。

然后

void ADC0_init(void)
{
// Enable GPIO for ADC
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);// Enable pin PE3 for ADC AIN0
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);// Enable pin PE2 for ADC AIN1
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);// Enable pin PE1 for ADC AIN2
GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_3);// Enable pin PD3 for ADC AIN4

SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
ADCSequenceDisable(ADC0_BASE, 1);
ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 0);
ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH2);
ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH4| ADC_CTL_IE |ADC_CTL_END);
//ADC0_CC_R=0x00;
ADCSequenceEnable(ADC0_BASE, 1);

ADCIntClear(ADC0_BASE, 1);
ADCIntRegister(ADC0_BASE,1,&ADC0_ISR);
ADCIntEnable(ADC0_BASE,1);
}

问题是出在如果单步运行调试。程序可以正常工作。但是如果全速运行程序就不正常。(ADC无法采样,我再ADC中断里放了个翻转IO的语句来查看。)

继续查看是发现在 ADC0_init这个函数的ADCSequenceDisable(ADC0_BASE, 1)语句的时候跳入了FaultISR(void)中断里。如果我单步调试或者把系统时钟调慢(SYSCTL_SYSDIV_20)就不会发生这个问题。我印象是ADC的时钟信号可以来自于PLL的25分频或者PIOSC。我试过了ADC0_CC_R=0x00或者等于0x01都没有改变。

请问能帮忙解决下这个问题吗。?

  • SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);这句话放在Enable GPIO前面。

    ADCSequenceDisable(ADC0_BASE, 1);这句话去掉,默认就是关闭的。

  • 非常感谢。这下调对了。昨天还被中断的问题卡了好一顿。跟430有些不同。他读取ADC的值的时候不会自动清除中端标志位。

    ulADC0_Value1[ulADC0_point1++] = HWREG(ADC0_SSFIFO1_R);

    另外这个语句好像不能读取当前FIFO的数据值。读出来是个乱码。确认是ADC0的SS1.

  • 用库函数ADCSequenceDataGet(ADC1_BASE, 0, pui32ADC0Value);来读。

    pui32ADC0Value是个数组,会吧SS1里面的所有数据全读到这里。

  • 非常感谢回答。

    我是系统负载可能比较大就想用这个来写。ADCSequenceDataGet打开来看函数选型也是从FIFO的地址里不断读取数据。我直接写这样一个语句就可以省点时间。ulADC0_Value1[ulADC0_point1++] = HWREG(ADC0_SSFIFO1_R);就只要一个语句就能读了这个转换值了。

  • 把这个代码贴出来吧:

    int32_t
    ADCSequenceDataGet(uint32_t ui32Base, uint32_t ui32SequenceNum,
    uint32_t *pui32Buffer)
    {
    uint32_t ui32Count;

    //
    // Check the arguments.
    //
    ASSERT((ui32Base == ADC0_BASE) || (ui32Base == ADC1_BASE));
    ASSERT(ui32SequenceNum < 4);

    //
    // Get the offset of the sequence to be read.
    //
    ui32Base += ADC_SEQ + (ADC_SEQ_STEP * ui32SequenceNum);

    //
    // Read samples from the FIFO until it is empty.
    //
    ui32Count = 0;
    while(!(HWREG(ui32Base + ADC_SSFSTAT) & ADC_SSFSTAT0_EMPTY) &&
    (ui32Count < 8))
    {
    //
    // Read the FIFO and copy it to the destination.
    //
    *pui32Buffer++ = HWREG(ui32Base + ADC_SSFIFO);

    //
    // Increment the count of samples read.
    //
    ui32Count++;
    }

    //
    // Return the number of samples read.
    //
    return(ui32Count);

    }

    由于FIFO中可能会有不止一个数据,因此需要进行判断,读完后数据会存在数组中,函数返回的是读取到多少个数据。

    你上面写得一句话是不能实现这个功能。

    实际上库函数写得效率也挺高的了。系统开销大,也不差这一点,哈哈。

  • void ADC0_ISR(){
     //static int i=0;
     ADCIntClear(ADC0_BASE, 1);
     //i++;
     //if (i%2) GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5,0xff);
     //else GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5,0);

     ulADC0_Value1[ulADC0_point1++] = HWREG(ADC0_SSFIFO1_R);
     ulADC0_Value2[ulADC0_point2++] = HWREG(ADC0_SSFIFO1_R);
     ulADC0_Value3[ulADC0_point3++] = HWREG(ADC0_SSFIFO1_R);
     ulADC0_Value4[ulADC0_point4++] = HWREG(ADC0_SSFIFO1_R);
     if (ulADC0_point1==128)
     {
            flag=1;
     }
     if (ulADC0_point1==256)
     {
            flag=2;
            ulADC0_point1=ulADC0_point2=ulADC0_point3=ulADC0_point4=0;
     }

    }

    我知道这个问题。我SS1配置的是4个通道。然后我就这么配置我的ADC中断函数。然后对应的四个数组里面读出来的都是乱码。

    非常感谢您的支持。

  • 乱码是啥概念?

    其实可以这样,先用库函数,验证ADC工作正常,采回来的数据都对,然后按照库函数的写法,按照自己的想法去写,应该就能对上了。

  • [86] unsigned int 248315904 0x200003C4

    [89] unsigned int 3372220430 0x200003D0

    [44] unsigned int 969984 0x2000031C

    复制了几个代表出来。

    我现在先用库函数读取FIFO,然后再转到我自己的变量里就是对的。按照我的发上来的代码里那样直接读取FIFO出来的就是这样的数据。没有点逻辑。

  • 楼主读出来的数据分别放到4个数组里然后去处理的?

    建议是这样,先不做数据处理,只是单纯的读FIFO数据,对比看是否一样。我感觉不是读FIFO数据出的问题,而是后面的数据处理逻辑需要看一下。

  • 是这样子的。把四个SS1的四个数据分别放到四个数组里,然后在主函数里处理。

    void ADC0_ISR(){
    //static int i=0;
    ADCIntClear(ADC0_BASE, 1);
    //i++;
    //if (i%2) GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5,0xff);
    //else GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5,0);
    unsigned int adc0_value[4];
    //ADCSequenceDataGet(ADC0_BASE, 1, adc0_value);//读取采样结果

    ulADC0_Value1[ulADC0_point1++] = HWREG(ADC0_SSFIFO1_R);//adc0_value[0];//
    ulADC0_Value2[ulADC0_point2++] = HWREG(ADC0_SSFIFO1_R);//adc0_value[1];//
    ulADC0_Value3[ulADC0_point3++] = HWREG(ADC0_SSFIFO1_R);//adc0_value[2];//
    ulADC0_Value4[ulADC0_point4++] = HWREG(ADC0_SSFIFO1_R);//adc0_value[3];//
    if (ulADC0_point1==128)
    {
    flag=1;
    }
    if (ulADC0_point1==256)
    {
    flag=2;
    ulADC0_point1=ulADC0_point2=ulADC0_point3=ulADC0_point4=0;
    }

    }

    这个是自己写的。

    void ADC0_ISR(){
    //static int i=0;
    ADCIntClear(ADC0_BASE, 1);
    //i++;
    //if (i%2) GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5,0xff);
    //else GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5,0);
    unsigned int adc0_value[4];
    ADCSequenceDataGet(ADC0_BASE, 1, adc0_value);//读取采样结果

    ulADC0_Value1[ulADC0_point1++] = adc0_value[0];//HWREG(ADC0_SSFIFO1_R);//
    ulADC0_Value2[ulADC0_point2++] = adc0_value[1];//HWREG(ADC0_SSFIFO1_R);//
    ulADC0_Value3[ulADC0_point3++] = adc0_value[2];//HWREG(ADC0_SSFIFO1_R);//
    ulADC0_Value4[ulADC0_point4++] = adc0_value[3];//HWREG(ADC0_SSFIFO1_R);//
    if (ulADC0_point1==128)
    {
    flag=1;
    }
    if (ulADC0_point1==256)
    {
    flag=2;
    ulADC0_point1=ulADC0_point2=ulADC0_point3=ulADC0_point4=0;
    }

    }

    而这个是调用固件库的。

    同样在加黑的代码出添加端点,应该是采集完128个数据。(还未处理)这时候固件库的就能看到数组里有正常的数据。而另一个是乱码。

    非常感谢您的帮助!

  • 其实还是程序写法的问题。

    您再看一下adc.c的源码:

    #define ADC_SSFIFO              (ADC_O_SSFIFO0 - ADC_O_SSMUX0)

    //
        // Read samples from the FIFO until it is empty.
        //
        ui32Count = 0;
        while(!(HWREG(ui32Base + ADC_SSFSTAT) & ADC_SSFSTAT0_EMPTY) &&
              (ui32Count < 8))
        {
            //
            // Read the FIFO and copy it to the destination.
            //
            *pui32Buffer++ = HWREG(ui32Base + ADC_SSFIFO);

            //
            // Increment the count of samples read.
            //
            ui32Count++;
        }

     

  • 您好!我重新注意了adc.c的文件。使用了如下的语句。

    ulADC0_Value1[ulADC0_point1++] = HWREG(ADC0_BASE+ADC_O_SSFIFO0 - ADC_O_SSMUX0+ADC_O_SSMUX1);

    可以正常读取数据。

    但是如果用ulADC0_Value1[ulADC0_point1++] = HWREG(ADC0_SSFIFO1_R);就不可以。

    我现在的疑惑是ADC0_BASE+ADC_O_SSFIFO0 - ADC_O_SSMUX0+ADC_O_SSMUX1和ADC0_SSFIFO1_R的值都是0x40038068.都是FIFO的地址为什么后者不行。其他的代码都是没有改变的。