LPC824 микроконтроллер ADC демо проблема HardFault - PullRequest
0 голосов
/ 17 декабря 2018

Я пытаюсь запрограммировать LPC824 плату микроконтроллера ([https://www.switch -science.com / catalog / 2265 /] [1] ) с LPCOpen .Я использую его с отладочной платой LPCLink 2.

Моя цель - получить некоторую информацию от "датчика давления" с помощью АЦП.

Мой код останавливается при HardFault при выполнении функции NVIC_EnableIRQ (в строке: 92).

Если я не использую «контроллер прерываний NVIC», тогда мой код работает, и я могу получить значение от датчикас АЦП.

Что я делаю не так?

Вот мой код adc.c:

#include "board.h"

static volatile int ticks;
static bool sequenceComplete = false;
static bool thresholdCrossed = false;

#define TICKRATE_HZ (100)     /* 100 ticks per second */

#define BOARD_ADC_CH 2

/**
 * @brief     Handle interrupt from ADC sequencer A
 * @return     Nothing
 */
void ADC_SEQA_IRQHandler(void) {
    uint32_t pending;

    /* Get pending interrupts */
    pending = Chip_ADC_GetFlags(LPC_ADC);

    /* Sequence A completion interrupt */
    if (pending & ADC_FLAGS_SEQA_INT_MASK) {
        sequenceComplete = true;
    }

    /* Threshold crossing interrupt on ADC input channel */
    if (pending & ADC_FLAGS_THCMP_MASK(BOARD_ADC_CH)) {
        thresholdCrossed = true;
    }

    /* Clear any pending interrupts */
    Chip_ADC_ClearFlags(LPC_ADC, pending);
}

/**
 * @brief     Handle interrupt from SysTick timer
 * @return     Nothing
 */
void SysTick_Handler(void) {
    static uint32_t count;

    /* Every 1/2 second */
    if (count++ == TICKRATE_HZ / 2) {
        count = 0;
        Chip_ADC_StartSequencer(LPC_ADC, ADC_SEQA_IDX);
    }
}

/**
 * @brief     main routine for ADC example
 * @return     Function should not exit
 */
int main(void) {
    uint32_t rawSample;
    int j;

    SystemCoreClockUpdate();
    Board_Init();

    /* Setup ADC for 12-bit mode and normal power */
    Chip_ADC_Init(LPC_ADC, 0);
    Chip_ADC_Init(LPC_ADC, ADC_CR_MODE10BIT);

    /* Need to do a calibration after initialization and trim */
    Chip_ADC_StartCalibration(LPC_ADC);
    while (!(Chip_ADC_IsCalibrationDone(LPC_ADC))) {
    }

    /* Setup for maximum ADC clock rate using sycnchronous clocking */
    Chip_ADC_SetClockRate(LPC_ADC, ADC_MAX_SAMPLE_RATE);

    Chip_ADC_SetupSequencer(LPC_ADC, ADC_SEQA_IDX,
            (ADC_SEQ_CTRL_CHANSEL(BOARD_ADC_CH) | ADC_SEQ_CTRL_MODE_EOS));
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SWM);
    Chip_SWM_EnableFixedPin(SWM_FIXED_ADC2);
    Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SWM);

    /* Setup threshold 0 low and high values to about 25% and 75% of max */
    Chip_ADC_SetThrLowValue(LPC_ADC, 0, ((1 * 0xFFF) / 4));
    Chip_ADC_SetThrHighValue(LPC_ADC, 0, ((3 * 0xFFF) / 4));

    Chip_ADC_ClearFlags(LPC_ADC, Chip_ADC_GetFlags(LPC_ADC));
    Chip_ADC_EnableInt(LPC_ADC,
            (ADC_INTEN_SEQA_ENABLE | ADC_INTEN_OVRRUN_ENABLE));
    Chip_ADC_SelectTH0Channels(LPC_ADC, ADC_THRSEL_CHAN_SEL_THR1(BOARD_ADC_CH));
    Chip_ADC_SetThresholdInt(LPC_ADC, BOARD_ADC_CH, ADC_INTEN_THCMP_CROSSING);

    /* Enable ADC NVIC interrupt */
    NVIC_EnableIRQ(ADC_SEQA_IRQn);

    Chip_ADC_EnableSequencer(LPC_ADC, ADC_SEQA_IDX);

    SysTick_Config(SystemCoreClock / TICKRATE_HZ);

    /* Endless loop */
    while (1) {
        /* Sleep until something happens */
        __WFI();

        if (thresholdCrossed) {
            thresholdCrossed = false;
            printf("********ADC threshold event********\r\n");
        }

        /* Is a conversion sequence complete? */
        if (sequenceComplete) {
            sequenceComplete = false;

            /* Get raw sample data for channels 0-11 */
            for (j = 0; j < 12; j++) {
                rawSample = Chip_ADC_GetDataReg(LPC_ADC, j);
                /* Show some ADC data */
                if (rawSample & (ADC_DR_OVERRUN | ADC_SEQ_GDAT_DATAVALID)) {
                    printf("Chan: %d Val: %d\r\n", j, ADC_DR_RESULT(rawSample));
                    printf("Threshold range: 0x%x ",
                            ADC_DR_THCMPRANGE(rawSample));
                    printf("Threshold cross: 0x%x\r\n",
                            ADC_DR_THCMPCROSS(rawSample));
                    printf("Overrun: %s ",
                            (rawSample & ADC_DR_OVERRUN) ? "true" : "false");
                    printf("Data Valid: %s\r\n\r\n",
                            (rawSample & ADC_SEQ_GDAT_DATAVALID) ?
                                    "true" : "false");
                }
            }
        }
    }
}

1 Ответ

0 голосов
/ 17 декабря 2018

Жесткий сбой обычно означает, что вы пытаетесь выполнить код за пределами разрешенных адресов.Если вы не зарегистрировали прерывание в таблице векторов, но включили его, MCU перейдет на любой адрес, который там записан, после чего произойдет сбой программы.

Как исправить это, зависит от цепочки инструментов.Предполагая LPCXpresso, у вас есть несколько опций для настройки библиотек (я не знаю, в частности, о LPCOpen), поэтому, где найти таблицу векторов, отличается от случая к случаю.Тем не менее, это работает довольно похоже на большинство MCU, ARM или нет.Где-то в файле запуска crt у вас должно быть что-то вроде этого:

void (* const g_pfnVectors[])(void) = ...

Это массив указателей на функции, который будет таблицей векторов, размещенной в памяти по адресу 0 в Cortex.М. Вы должны поместить свою функцию в соответствующий вектор прерывания.Например, он может сказать что-то вроде

PIN_INT0_IRQHandler,                     // PIO INT0

Если это прерывание вы должны реализовать, то вы замените эту строку:

#include "my_irq_stuff.h"
...

void (* const g_pfnVectors[])(void) = 
...
my_INT0,                                 // PIO INT0

Предполагая, что my_irq_stuff.h содержит прототип функции my_INT0для обработки прерываний.Фактическая процедура должна быть реализована в соответствующем файле .c.

...