CPU/STM32F103

STM32 ADC2 Interrupt Mode 사용

멋진 고파 2013. 2. 8. 00:27

이번엔 ADC2를 사용하여 인터럽트 모드로 동작 시켜 보겠습니다.

전반적인 내용은 이전 내용과 비슷하지만 adc의 설정이 약간 다르고, 인터럽트 관련 설정이 추가 되었습니다.


0. 환경설정

환경설정은 stm32f10x_conf.h에서 

#define _ADC2

을 설정합니다.



1. 인터럽트 설정

1.1 인터럽트 등록

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;


..................


  /* Configure and enable ADC interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

ADC1_2_IRQChannel인터럽트를 활성화 합니다.


1.2 인터럽트 서비스 루틴 추가

stm32f10x_it.c 에 인터럽트 처리함수를 추가합니다.

vu16 ADC2ConvertedValue


/*******************************************************************************

* Function Name  : ADC1_2_IRQHandler

* Description    : This function handles ADC1 and ADC2 global interrupts requests.

* Input          : None

* Output         : None

* Return         : None

*******************************************************************************/

void ADC1_2_IRQHandler(void)

{

  /* Get injected channel13 converted value */

  ADC2ConvertedValue = ADC_GetConversionValue(ADC2);

}


인터럽트 서비스 루틴에서 EOC마다 변수에 저장합니다.


2. ADC관련 설정

2.1 CLOCK관련

/* Enable ADC1, ADC2, ADC3 and GPIOC clocks */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2 | RCC_APB2Periph_GPIOC, ENABLE);

해당 ADC2와 포트 GPIOC에 클럭을 설정합니다.


2.2 GPIO설정

void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;


  /* Configure PC.0 (ADC Channel10,  as analog inputs */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

}

해당 ADC핀을 아나로그 입력으로 설정합니다.

2.3 ADC설정

/* ADC2 configuration ------------------------------------------------------*/

  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

  ADC_InitStructure.ADC_ScanConvMode = DISABLE;

  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfChannel = 1;

  ADC_Init(ADC2, &ADC_InitStructure);

  /* ADC2 regular channels configuration */ 

  ADC_RegularChannelConfig(ADC2, ADC_Channel_10, 1, ADC_SampleTime_28Cycles5);

 

 /* Enable ADC2 EOC interupt */

  ADC_ITConfig(ADC2, ADC_IT_EOC, ENABLE);


/* Enable ADC2 */

  ADC_Cmd(ADC2, ENABLE);


  /* Enable ADC2 reset calibaration register */   

  ADC_ResetCalibration(ADC2);

  /* Check the end of ADC2 reset calibration register */

  while(ADC_GetResetCalibrationStatus(ADC2));


  /* Start ADC2 calibaration */

  ADC_StartCalibration(ADC2);

  /* Check the end of ADC2 calibration */

  while(ADC_GetCalibrationStatus(ADC2));


/* Start ADC2 Software Conversion */ 

  ADC_SoftwareStartConvCmd(ADC2, ENABLE);

위의 설정에서 ADC_ScanConvMode 가 DISABLE되고, 

ADC_ITConfig(ADC2, ADC_IT_EOC, ENABLE);와 같이 인터럽트를 ENABLE시킴니다. 그럼 NVIC에서 등록된것은 인터럽트 MASK정도 될듯하네요.


그럼 준비 완료되고.


3. 확인

메인루프에서 다음과 같이 찍었습니다.

printf("==== %d ====\r\n",ADC2ConvertedValue*3300/4096);

잘 나오네요.


인제 대충감이 잡히네요.

1> stm32f10x_conf.h에서 기능선택

2> 클럭관련 모듈설정

3> 해당 모듈의 인아웃 핀 섲정

3> 해당 기능 설정

4> 사용.


더블어 인터럽트는

1> NVIC_Configuration에 인터럽트 enable

2> 해당 모듈의 인터럽트 enable

3> 인터럽트 서비스 루틴 구현


주의 점은 인터럽트에서 합수 호출시 멈추는 경우가 있네요.

예로.

void ADC1_2_IRQHandler(void)

{

  /* Get injected channel13 converted value */

  ADC2ConvertedValue = ADC_GetConversionValue(ADC2);

  

  /*if (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_13) == 0x00)

      GPIO_SetBits(GPIOE, GPIO_Pin_13);

    else

      GPIO_ResetBits(GPIOE, GPIO_Pin_13);*/

    

}

주석처리 된 부분이 그러네요..

요건 다시 분석 해보아야 겠네요.


그럼 오늘은 여기서 이만.