==================================Outline====================================
Interrupt
----------------------------------------------------------------------------
인터럽트 사용에 대해 알아보자. 레지스터 데이터시트 p/196이다.



회색으로 표시된 인터럽트는 시스템 인터럽트이고 흰색으로 표시된 것들은 소프트웨어 인터럽트이다.
종류가 많다는 것을 알 수 있다.
이번 시간에 주로 살펴볼 인터럽트는 ‘EXTI’라는 인터럽트이다. 20개의 edge 감지기를 가지고 있다.
주요 특징을 살펴보자.



firmware 라이브러리 함수를 사용하여 설정해주면 된다.
원하는 인터럽트를 선택해야 한다.
주요 레지스터들을 살펴보자.



인터럽트 레지스터와 이벤트 마스크 레지스터에서 원하는 자리를 set해주면 해당 인터럽트가 작동하게 된다.
상승에지와 하강에지 인터럽트를 설정하는 레지스터

상승에지와 하강에지 인터럽트를 동시에 set하는 것도 가능하다.
‘EXTI_PR'은 인터럽트가 발생하면 ‘1’로 바뀌는 레지스터이다.


변수 생성 시 24가지 종류의 변수 타입을 참고한다.
** 4byte 변수는 int가 아니라 long임을 주의하자.




EXTI설정은 쉬우나 NVIC설정은 까다롭다.
PM0056 프로그래밍 매뉴얼 p/118



원하는 인터럽트 자리에 ‘1’를 입력해주면 해당 인터럽트가 활성화된다.





각 레지스터들의 기능을 참고하여 프로그래밍을 해보자.
firmware 라이브러리를 사용하면 간단하다.
- 전원 ON 시 LED(PA0)가 1초 간격으로 깜빡거리게 만든다.
- 스위치(PA2)를 누르면 깜빡거리는 기능이 멈춘다.
- 스위치(PA2)를 떼면 다시 정상 작동한다.

#include <stm32f10x.h> #include <misc.h>
vu32 vulCnt;
#define Delay(x) for(vulCnt = 0; vulCnt < x; ++vulCnt)
// EXTI2_IRQn void EXTI2_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line2) != RESET) { // 처리할 내용 : while (A가 눌러진 상태) while( 0==(GPIOA->IDR & 0x04) ) { ; } } EXTI_ClearITPendingBit(EXTI_Line2); } void EXTI2_init(void) { /* Enables external lines 2 interrupt generation on falling edge */ EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line = EXTI_Line2; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); }
void NVIC_init(void) { /* Enable and set EXTI2 Interrupt to the lowest priority */ NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }
void PA2_in(void) { /* Configure all the GPIOA in Input Floating mode */ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); }
void PA0_out(void) { /* Configure all the GPIOA in Input Floating mode */ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); }
void Init(void) { EXTI2_init(); NVIC_init(); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE); PA0_out(); PA2_in(); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);
}
int main(void) { Init(); while(1) { GPIO_SetBits(GPIOA, GPIO_Pin_0); Delay(1000000); GPIO_ResetBits(GPIOA, GPIO_Pin_0); Delay(1000000); } return 0; } |