Embedded LPC824微控制器ADC演示硬件故障问题

Embedded LPC824微控制器ADC演示硬件故障问题,embedded,clang,adc,nxp-microcontroller,Embedded,Clang,Adc,Nxp Microcontroller,我正在尝试用LPCOpen对LPC824微控制器板进行编程。 我在LPCLink 2调试板上使用它 我的目标是通过ADC从压力传感器获取一些信息 在第92行执行NVIC_EnableIRQ函数时,我的代码因硬故障而停止 若我不使用NVIC中断控制器,那个么我的代码可以工作,我可以通过ADC从传感器获取值 我做错了什么 这是我的adc.c代码: #include "board.h" static volatile int ticks; static bool sequenceComplete =

我正在尝试用LPCOpen对LPC824微控制器板进行编程。 我在LPCLink 2调试板上使用它

我的目标是通过ADC从压力传感器获取一些信息

在第92行执行NVIC_EnableIRQ函数时,我的代码因硬故障而停止

若我不使用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");
                }
            }
        }
    }
}

硬故障通常意味着您试图在允许的地址之外执行代码。如果您没有在向量表中注册中断,但启用了它,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文件中实现。

中断向量是否设置为调用ADC_seka_IRQHandler?关于该硬故障的任何细节,寄存器值?谢谢你的回答。我太新手了,我的知识还不清楚刚刚够了。现在我正在学习像这样的基础知识。谢谢你的指导:。