关于ADC我自己的一些疑问处理

1.ADC代码到底是按照什么顺序在跑

拿这段代码举例:

void ADC0Sequence0Handler(void)
{

    uint16_t i;
    //
    // Clear the ADC interrupt flag.
    //
    ADCIntClear(ADC0_BASE, 0);
    //
    // Read ADC Value.
    //
    ADCSequenceDataGet(ADC0_BASE, 0, pui32ADC0Value);

    for(i = 0;i < 8;i ++)
    {
        sum= sum+(pui32ADC0Value[i]*3300/4096);
    }

    flag=1;

}

//*****************************************************************************
//
// The main application.
//
//*****************************************************************************
int
main(void)
{
    //
    // Set the system clock to run at 200/5=40MHz using the PLL.  When
    // using the ADC, you must either use the PLL or supply a 16 MHz clock
    // source.
    SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_16MHZ);

    // LCD Initial
    PortFunctionInit();

    lcd_init();

    //
    // enable processer interrupt
    //
    IntMasterEnable();

    //
    // The ADC0 peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    //
    // example ADC0 is used with AIN2 on port E1.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    //
    // Select the analog ADC function for these pins.
    //
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);

    ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);

    ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 6, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 7, ADC_CTL_CH2 | ADC_CTL_IE | ADC_CTL_END);

    // Interrupt Register for ADC0SS0
    ADCIntRegister(ADC0_BASE,0, ADC0Sequence0Handler);
    //
    // enable ADC0 sequence 0 interrupt
    //
    ADCIntEnable(ADC0_BASE, 0);
    IntEnable(INT_ADC0SS0);

    //
    // Since sample sequence 0 is now configured, it must be enabled.
    //
    ADCSequenceEnable(ADC0_BASE, 0);

    //
    // Clear the interrupt status flag.  This is done to make sure the
    // interrupt flag is cleared before we sample.
    //
    ADCIntClear(ADC0_BASE, 0);

    char str[20];
    lcd_clear();

    //
    // Sample the temperature sensor forever.  Display the value on the
    // console.
    //
    while(1)
    {
        //
        // Trigger the ADC conversion.
        //
        ADCProcessorTrigger(ADC0_BASE, 0);

        // Wait until the sample sequence has completed.
        if(flag==1)
        {
            value=sum/8;
            sprintf(str, "%d mV", value);
            lcd_printf(2,1,str);
            SysCtlDelay(SysCtlClockGet() / 3);
            flag=0;
            sum=0;
        }
        lcd_clear();
    }

}
  • 主函数(main)先运行:

    • 程序从 main() 开始,先配置系统时钟、LCD以及其他外围设备(例如GPIO、ADC)。

    • 然后配置ADC采样序列(Sequence 0),为通道2(AIN2)设置8个采样步骤,并将最后一个步骤配置为触发中断(使用ADC_CTL_IE | ADC_CTL_END)。

    • 接着通过 ADCIntRegisterIntEnable 注册并使能了ADC的中断服务程序 ADC0Sequence0Handler

    • 最后启用ADC采样序列,并进入一个无限循环,在循环中不断触发ADC转换。

  • 中断触发时机:

    • 在主循环中,每次调用 ADCProcessorTrigger(ADC0_BASE, 0) 后,ADC开始按照配置的8个步骤进行转换。

    • 当8个采样步骤全部完成后,ADC硬件自动将中断标志置位,从而触发中断服务程序 ADC0Sequence0Handler

所以就是按照main里的顺序,然后触发ADC,ADC就开始八步采样,然后自动进入中断。

2.为什么要在中断里清除标志位

  • 第一行代码 ADCIntClear(ADC0_BASE, 0); 用于清除ADC的中断标志。
    原因:

    • 清除中断标志是为了通知硬件,“本次中断已被处理”,这样硬件才能检测到下一次ADC转换完成后的中断请求。

    • 如果不清除,中断标志仍然保持在“已置位”状态,可能导致后续转换的中断无法触发或者造成重复中断。

所以,单片机程序不仅要符合C的代码逻辑,还与硬件有一定衔接,所以有时候可能看起来无头无尾,但是其实符合单片机内部的逻辑。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值