我才发现,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