저번에는 LED를 깜빡거리는 동작만 구현했었지만 이번에는 User switch를 이용하여 스위치를 누르면 LED가 깜빡거리는 속도가 빨라지는 동작을 수행해보자
먼저 회로도를 확인해서 User switch가 어떤 포트랑 연결되어있는지 확인해보자
회로도를 보면 User switch 는 PC13에 연결되어있는것을 확인할 수 있다.
그럼 ioc를 통해 핀 설정을 변경해보자
연결되어 있는 pc13번을 gpio input으로 설정해준다.
좌측 system core에서 gpio를 클릭하면 다양한 설정 값들을 바꿀 수 있다.
user switch는 회로적으로 pull up으로 연결돼있기에 일단 no pull up and no pull down으로 설정한다.
설정이 끝나고 저장을 하면 해당 설정값이 반영된 코드를 생성해준다.
.
gpio 초기값을 설정하는 함수를 확인해보면 Pin13번이 정상적으로 input으로 변경된 것을 확인할 수 있다.
그럼 main함수에서 기존에 쓰던 코드를 조금 수정해서 동작을 확인해보자.
위의 코드는 만약 PC13번 핀에 논리 0의 전압이 입력되면 LED가 0.2초마다 깜빡거리고 0이 아닌 값이 입력되면 LED가 깜빡거리는 동작을 수행하는 코드이다.
동작을 동영상으로 확인해보면
이러한 동작을 확인하는 것을 확인할 수 있다.
코드 리뷰를 해보면
먼저 HAL_GPIO_ReadPin 함수에 대해 간략하게 정리해보자
먼저 매개변수로 GPIO값과 Pin 번호에 대한 값을 받게 되고 만약 입력한 GPIO_Pin 값과 IDR 레지스터에 입력되어있는 값을 AND연산한 값이 0이 아니라면 bitstatus 값이 1이 되어 bitstatus 값이 return 되는 것을 확인할 수 있다.
그러면 IDR 레지스터에 대해 알아보면
풀네임은 GPIO port input data register이며 읽기 전용 레지스터인것을 확인할 수 있다. 해당 레지스터는 각 pin에 입력된 값을 읽어올 수 있는 레지스터이며 위에 코드에서 설정한 GPIO_PIN_13은 0x20000000인것을 확인할 수 있고
IDR에 저장된 값이 User switch가 On인 상태면 0x2000000가 된다(pull up으로 연결되어 있어 스위치를 안누르면 13번 bit가 on이 됨)
최종적으로 User switch를 안누르면 HAL_GPIO_ReadPin 함수는 1 값이 return되어 if문에 걸리지 않게 된다. 하지만 User switch를 누르게되면 HAL_GPIO_ReadPin 함수에 0 값이 return 되어 if문 안의 코드를 동작하게 된다.
이런 구조로 작성한 코드를 polling 방식이라 한다 polling방식의 단점은 반복해서 조건을 검증하기 때문에 cpu에 무리가 간다는 단점이 있다. 이러한 문제점을 interrupt 방식을 통해 개선할 수 있다.
인터럽트 방식이란
-> 인터럽트 신호가 발생하면 실행하고 있던 동작을 멈춰두고 ISR(Interrupt Service Routin)을 실행하고 ISR이 끝나면 다시 원래 동작하고 있던 코드를 실행하는 방식이다 해당 방식은 CPU의 리소스를 polling방식보다 적게 소모하는 장점이 있다.
그러면 User switch를 통해 interrupt를 실행하는 코드를 작성해보자
먼저 ioc를 통해 User switch가 연결되어있는 PC13 핀을 EXIT(External Interrupt)로 설정해준다.
그리고 system core에 GPIO를 클릭, 안에서 GPIO를 클릭하여 EXIT 를 설정할 수 있다 지금은 스위치가 처음 눌려지고 Rising Edge일 때 인터럽트를 수행하도록 설정한다.(해당 창에서 Rising, falling, 아님 둘 다 설정할 수 있음)
그리고 NVIC을 선택하여 EXTI line[15:10]의 Enabled를 체크해주고 저장을한다.
main.c 코드에서 Gpio 초기화 함수를 확인해보면 정상적으로 PC13 핀이 interrupt 호출 핀으로 세팅된것을 확인할 수 있다.
그럼 인터럽트가 호출되면 변수 값이 증가하면서 변수 값을 비교하여 LED 속도를 변경하는 코드를 작성해보자
먼저 인터럽트 관련 코드는 stm32f4xx_it.c 를 열어보면 확인할 수 있다.
EXTI15_10_IRQHandler 함수가 생성되어 있는것을 확인할 수 있고
HAL_GPIO_EXIT_IRQHandler 함수 안에 __weak void HAL_GPIO_EXTI_Callback 함수가 있는것을 확인할 수 있다.
이 Callback함수는 인터럽트가 호출될 때 마다 실행되는 함수이다. 우리는 이 함수를 사용하여 코드를 작성할 것이다.
__weak 부분을 제외하고 나머지 부분을 복사해서 main.c에 추가한다.
아래 코드는 인터럽트 신호가 발생하고 만약 핀 13번에 의해 호출된 인터럽트라면 변수 i 를 1 추가하라라는 코드이다.
그리고 전역 정적 변수로 i를 선언해주고
while문 안에 위에서 선언한 변수 값이 변할 때 마다 LED 깜빡임 시간이 변경되는 코드이다.
동작을 동영상으로 확인해보면
User switch를 누를 때 마다 속도가 달라지는 것을 확인할 수 있다.
'[Harman] 임베디드 시스템을 위한 sw 구조설계' 카테고리의 다른 글
[부산 인력개발원 Harman 과정]임베디드 시스템을 위한 sw 구조설계 6 (0) | 2023.05.03 |
---|---|
[부산 인력개발원 Harman 과정]임베디드 시스템을 위한 sw 구조설계 5 (0) | 2023.05.01 |
[부산 인력개발원 Harman 과정]임베디드 시스템을 위한 sw 구조설계 4 (0) | 2023.04.30 |
[부산 인력개발원 Harman 과정]임베디드 시스템을 위한 sw 구조설계 3 (0) | 2023.04.30 |
[부산 인력개발원 Harman 과정]임베디드 시스템을 위한 sw 구조설계 1 (0) | 2023.04.30 |