реклама на сайте
подробности

 
 
> LPC2368, ADC и ...., ...полтергейст
Kitsok
сообщение Mar 10 2010, 15:35
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136



Добрый день!

FreeRTOS завел, даже думал написать краткий мануал, а потом понял, что мануал давно написан и называется FreeRTOS Porting Guide,
zltigo хоть и суров, но прав на 100% wink.gif

Теперь взялся за ADC.
Последовательность такая: прочитал User Manual, посмотрел исходники для gcc, посмотрел библиотеку NXP (LPC CDL), подключил ее.
Причина использования библиотеки - любовь к функциям типа PINSEL_Set, оставшаяся от писания под SAM7S.

Итого получилось так:
Код
void xSetupADC(void)
{
// Select pin that used as ADC function

    PINSEL_Set (PORT_0, 23, FUNC_1);
    PINSEL_Set (PORT_0, 24, FUNC_1);
    PINSEL_Set (PORT_0, 25, FUNC_1);
    PINSEL_Set (PORT_0, 26, FUNC_1);
    PINSEL_Set (PORT_1, 30, FUNC_3);
    PINSEL_Set (PORT_1, 31, FUNC_3);  

PINSEL_SetResistorMode(PORT_0,23,PINMODE_TRISTATE);
PINSEL_SetResistorMode(PORT_0,24,PINMODE_TRISTATE);
PINSEL_SetResistorMode(PORT_0,25,PINMODE_TRISTATE);
PINSEL_SetResistorMode(PORT_0,26,PINMODE_TRISTATE);
PINSEL_SetResistorMode(PORT_1,30,PINMODE_TRISTATE);
PINSEL_SetResistorMode(PORT_1,31,PINMODE_TRISTATE);

/* Init ADC device */
if ((adcdev = ADC_Init()) == 0)
     {
         while(1);
     }
    
        // Install ADC interrupt handler
    if ((VIC_InstallIRQ (ADC0_INT, (void *) ADC_ISR, 0x0F)) == _ERROR)
     {
         while(1);
     }

    // Set call back function for ADC
    //ADC_SetCBS (adcdev, (void *)usr_adc_cbs);
    
    // Configure ADC with 1MHz of freq, 10-bit of resolution
    ADC_Config (adcdev, 500000, 10);
    
    // Enable all channels
    ADC_EnableCH (adcdev, 0);
    ADC_EnableCH (adcdev, 1);
    ADC_EnableCH (adcdev, 2);
    ADC_EnableCH (adcdev, 3);
    ADC_EnableCH (adcdev, 4);
    ADC_EnableCH (adcdev, 5);
    
    // Enable interrupt for ADC0 channel 5
    ADC_EnableInt (adcdev, 5);
        //ADC_EnableGlobalInt(adcdev);
    
    // Enable ADC interrupt source
    VIC_EnableInt (ADC0_INT);

        // Start ADC conversion
    ADC_Start (adcdev, ADC_START_CONTINUOUS, 0);
}


ADC_Config пришлось подправить, ибо частоту я выставляю не через библиотечные функции:
Код
S32 ADC_Config (S32 ADCdev, U32 freq, U32 resolution)
{
    ADC_CFG_T *pADCdev = (ADC_CFG_T *) ADCdev;
    U32 tmp;
    
    if (pADCdev->init == FALSE)
    {
        return _ERROR;
    }
    
    if ((resolution > 10) || (resolution < 3))
    {
        return _ERROR;
    }
    
    if (freq > 4500000)
    {
        return _ERROR;
    }
    
    tmp = SCB_GetPCLK (PCLK_ADC);
    
    //tmp = (tmp / freq) - 1;
        tmp = (30000000 / freq) -1;
    pADCdev->regptr->CR &= ~(ADC_CR_CLKDIV(0xFF));
    pADCdev->regptr->CR |= ADC_CR_CLKDIV(tmp);
    
    pADCdev->regptr->CR &= ~(ADC_CR_BITS(3));
    pADCdev->regptr->CR |= ADC_CR_BITS(resolution);
    
    return _NO_ERROR;
}


Обработчик прерывания:
Код
__irq __arm void ADC_ISR (void)
{
        //FIXME For debug
    U32 regval;//= adccfg.regptr->STAT;
        //FIXME For debug
        volatile U32 ulStatus = AD0STAT;
    volatile U32 dummy;
    U8 i;
    
        regval = ulStatus;
    if (regval & 0x0000FF00)    /* check OVERRUN error first */
    {
        regval = ADC_STAT_CH_OVERRUN_FLAG(regval);
               //regval = AD0STAT;

                // BUGBUG There are 6 channels, not 8        
        for (i = 0; i < 6; i++)
        {
            if (regval & 0x01)
            {
                /* if overrun, just read ADDR to clear */
                dummy = adccfg.regptr->DR[i];
            }
            regval = regval >> 1;
        }
    }
    // Check DONE bit
    else if (regval & ADC_STAT_INT_FLAG)
    {
        regval = ADC_STAT_CH_DONE_FLAG(regval);
        
                // BUGBUG There are 6 channels, not 8
        for (i = 0; i < 6; i++)
        {
            if (regval & 0x01)
            {
                /* if overrun, just read ADDR to clear */
                adccfg.ADCBuff[i] = adccfg.regptr->DR[i];
            }
            regval = regval >> 1;
        }
    }
    
    // call callback function if it is already installed
    if (adccfg.cbs != NULL)
    {
        adccfg.cbs();
    }
    
if ((ulStatus & 0x3f) != 0x3f)
  ulStatus=0;

// Acknowledge interrupt
VIC_Ack();
}


Чего хотел добиться:
1. Чтобы работали все 6 каналов.
2. Чтобы работало в Free run в Burst-режиме
3. Чтобы возникало одно прерывание при отработке всех 6 каналов.
4. Прерывание поставлено на 5 канал, потому что он должен отработаться последним:
The first conversion after the start corresponds to the least-significant 1 in the SEL field, then
higher numbered 1 bits (pins) if applicable.

В общем, ставлю я два брейка - один на VIC_Ack(), другой - на ulStatus=0, запускаю.

Дальше что-то, что я не понимаю.
Если стоит два брейка, то остановка происходит только на VIC_Ack(), и статусный регистр содержит 0x00013F3F, что более или менее соответствует ожиданиям. Не соответствует Overrun, происхождение которого я не понимаю.

Но стоит снять брейк с VIC_Ack(), начинает срабатывать брейк на ulStatus=0, при этом ulStatus == 0x00013C3C, т.е. каналы 0 и 1 не отработали.

Частоту АЦМ пробовал менять, история повторяется от 4.5МГц до 30кГц.

Вопрос традиционный: что я делаю не так?
Заранее спасибо!
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 15:50
Рейтинг@Mail.ru


Страница сгенерированна за 0.01358 секунд с 7
ELECTRONIX ©2004-2016