STM32的中断NVIC——C里面的所有调用都是久别重逢

我才发现,STM32的中断向量表(interrupt vector table)是不用配置的!!!

这和TI的芯片LM3S系列所用的函数库不一样,Ti的函数库都需要在启动文件startup.s中对中断向量表进行配置。具体操作是把中断服务函数的名字写到对应的汇编代码位置,名字就是中断服务函数的入口地址。一旦发生中断,则跳入到这个地址执行程序。

而STM32的逻辑是把中断向量表里所有的中断服务子函数名字给定,你需要用到哪个中断时,把这个函数名取来用就行。如果需要了解一下STM32的启动过程和中断向量表的作用,可以查看[1]。

ADC单通道采样

现在需要一个ADC采样程序,在中断中读取采样的数据。

    <!-- lang: cpp -->
#include "stm32f2xx.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h> 

extern void Uart2Init(void);
float f1;
uint32_t ADCVal = 0;  
static void ADC_Configuration(void)
{
    ADC_InitTypeDef ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Enable ADC3 clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    /* Configure ADC3 Channel 3 as analog input */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* ADC Common Init */
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div6;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 
    ADC_CommonInit(&ADC_CommonInitStructure); 

    /* ADC3 Configuration ------------------------------------------------------*/
    ADC_StructInit(&ADC_InitStructure);
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; 
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion = 1;
    ADC_Init(ADC3, &ADC_InitStructure);

    /*Interrupt Configuration*/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    NVIC_InitStructure.NVIC_IRQChannel  = ADC_IRQn;         //ADC1,ADC2,ADC3的全局中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//先占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority   = 1;   //从优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    ADC_ITConfig(ADC3, ADC_IT_EOC, ENABLE);

/* ADC3 Regular Channel Config */
    ADC_RegularChannelConfig(ADC3, ADC_Channel_3, 1, ADC_SampleTime_56Cycles);

    /* Enable ADC3 */
    ADC_Cmd(ADC3, ENABLE);

    /* ADC3 regular Software Start Conv */ 
    ADC_SoftwareStartConv(ADC3);
    }

    void AdcDelay(void)
   {
    unsigned int i;
    for(i = 0; i < 6000000; i++);
    }

    void ADC_IRQHandler(void)
   { 
    int Status;
    Status = ADC_GetITStatus(ADC3, ADC_IT_EOC);                 //检查指定的ADC中断是否发生
    if(Status ==SET){             //如果发生中断
    ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); //清除中断标志位
    //进行转换处理
    ADCVal = ADC_GetConversionValue(ADC3);
    /* convert to Voltage,  step = 0.8 mV */
    ADCVal = (uint32_t)(ADCVal * 0.8);  
    /* get digits to display */
    f1 = (float)ADCVal / 1000.0;
    printf("ADC input volage:%.2fV\n",f1);
    }
}


int main(void)
{
    Uart2Init();
    ADC_Configuration();
    printf("\n\rTest ADC..........\n\r");
    while(1)
    {
        AdcDelay();
    }
 }

这个里面的ADC_IRQHandler就是来自startup_stm32fxx.s。

printf重定向

在开发板上肯定无法使用stdio库中printf,这里能够使用是因为它被重定向为UART输出了。具体方法见
[2]。

久别重逢

像这种由STM或者TI官方库带来的向函数式编程的转化,写的程序过一段时间很快就忘记用法了。如果换一个平台又得重新熟悉。但万码虽殊,其理揆一。要知道,C语言的所用调用都是久别重逢。

Reference

[1].http://www.amobbs.com/thread-5462931-1-1.html
[2].http://blog.csdn.net/jiangjingui2011/article/details/7216693
[3].http://blog.csdn.net/lanmanck/article/details/8306045

你可能感兴趣的:(STM32的中断NVIC——C里面的所有调用都是久别重逢)