0

我正在尝试使用 LPCOpen 对LPC824微控制器板([ https://www.switch-science.com/catalog/2265/][1])进行编程。我将它与 LPCLink 2 调试器板一起使用。

我的目标是从带有 ADC 的“压力传感器”中获取一些信息。

执行函数时,我的代码以HardFaultNVIC_EnableIRQ停止(第 92 行)。

如果我不使用“NVIC 中断控制器”,那么我的代码就可以工作,我可以从带有 ADC 的传感器中获取值。

我做错了什么?

这是我的 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");
                }
            }
        }
    }
}
4

1 回答 1

1

硬故障通常意味着您尝试在允许的地址之外执行代码。如果您没有在向量表中注册中断但启用了它,MCU 将跳转到那里写入的任何地址,之后程序崩溃。

如何解决这个问题取决于工具链。假设 LPCXpresso,您有几个选项来设置库(我不具体了解 LPCOpen),因此在哪里可以找到向量表因情况而异。但是,这在大多数 MCU(无论是否为 ARM)上都非常相似。在“crt 启动”文件的某处,您应该有类似以下内容的内容:

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

这是一个函数指针数组,它将是分配在 Cortex M 上地址 0 的内存中的向量表。您必须将函数放置在相关的中断向量中。例如,它可能会说类似

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 文件中实现。

于 2018-12-17T09:03:51.140 回答