임베디드 시스템을 위한 SW 구조설계 2

2023. 4. 8. 20:31[Harman] 세미콘(semiconductor) 아카데미-반도체설계/임베디드 시스템을 위한 SW 구조설계

728x90

STM32F411RE보드를 이용하여 내부 소스코드 확인 및 GPIO_Read, GPIO_Write, GPIO_Toggle 함수를 이용하여 소스코드 작성 후 LD2 LED를 점등 및 소등 하였다.


저번 시간에 GPIO PORT를 확인하며 본 레지스터는 데이터를 저장하는 기억장치로 RAM에 저장된다.

 

  • 레지스터

레지스터는 각종 상태, 전송 속도, DATA길이 등의 상태들을 저장하는 데이터이다. 이 레지스터를 확인하려면 해당 소스코드의 헤더파일을 찾아 해당 함수를 호출하여 리턴값을 확인하면 된다. (16비트 레지스터는 16가지의 데이터를 저장하는 것이라 보면 된다.)

 

  • GPIO

Ststem Core - GPIO

GPIO의 16개 핀을 묶어 놓은 것을 GPIO 포트라 한다. 그러면 GPIO PORTA는 해당 포트안에 16개의 GPIO핀이 존재한다 보면 된다. 우리가 사용하는 포트(NUCLEO-F411RE)는 PORT가 A, B, C로 3개 존재한다. 

 

현재 System Core - GPIO에서 볼 수 있는 PA5는 PORTA의 5번 레지스터를 의미한다.

 

우리가 사용하는 GPIO의 레지스터는 5개가 존재한다. (Signal on pin, GPIO output level, GPIO mode, GPIO Pull-up/pull down, Maximum output speed)

현재 PA5에 GPIO output level에 Low가 들어가 있으므로 output level 레지스터의 5번 자리에 Low가 들어가 있게 된다.

 

GPIO PORT에는 각각의 기능들이 나눠져 있다. 

MODER 한 개당 2비트를 의미 / MODER register / speed register

각각의 레지스터에는 자신이 설정한 기능들이 2비트로 입력되어 있다.

해당 핀들의 기능들 / 2비트로 기능을 표현한다.

GPIO포트들 중에는 pull up / pull down 레지스터가 존재하는데 11비트의 Reserved는 없는 기능이라 보면 된다.

GPIO port pull-up/pull-down register는 기능이 3가지있다 보면 된다.

 

그외에도 데이터를 입력받는 input data register와 output data register 또한 존재하는데 해당 기능의 레지스터를 살펴보면 비트가 아닌 r, rw등의 알파벳이 적혀있는 것을 확인할 수 있다.

해당 레지스터의 뜻은 레퍼런스 메뉴얼의 1.1 List of abbreviations for registers에서 알 수 있다.

레지스터 약어를 나타내주는 목록들로 위의 입력 레지스터의 r은 읽기만 가능한 레지스터 / rw는 읽고 쓸 수 있는 레지스터로 각각의 레지스터들 마다 값에 따라 기능이 나눠져 있는 것을 확인할 수 있다.  (r이 있는 레지스터에는 데이터를 쓰는 것이 불가)

rw 읽고 쓸 수 있는 레지스터
r 읽기만 가능한 레지스터
w 쓰기만 가능한 레지스터

인터럽트 레지스터에 레지스터 약어가 많이 존재한다.

Peding regiset는 인터럽트 실행 후 변경된 인터럽트 데이터의 설정을 클리어 해주는 기능(RESET 시켜주는 인터럽트)이라 보면 된다. (인터럽트는 Peripheral을 통해 설정한다 / main문의 무한루프를 잠시 세워두는 것으로 사용)

 

 GPIO alternate function register 또한 존재한다.

해당 레지스터는 한 덩어리당 포트 핀 1개를 의미한다.(low register = 8개의 핀) 그러나 우리가 사용하는 포트는 16개의 핀으로 구성되어 있는데 low register만 사용하면 8개의 핀만 나타낼 수 있으니 high regiser로 추가 레지스터를 설정한다.

더보기

MODER(Configure) 레지스터 = 해당 포트가 어떤 기능을 할 지 설정하는 레지스터

INPUT, OUTPUT, bit set/reset 레지스터 = 해당 포트들의 상태를 설명하는 레지스터

 


보드 업데이트 / 디버그 업데이트

STM32보드를 사용하기에 앞서 CubeIDE를 이용하여 보드와 디버깅을 최신버전으로 업데이트 해주는 것이 좋다.

 

Run - Debug 시 Edit Configuration에서 에뮬레이터, 결선상태(swd / jtag)등을 설정할 수 있다.

 

디버거는 자신에게 맞는 디버거를 다운로드 받아 사용할 수 있는데 이 디버거를 설정하는 방법이 있다

디버거를 설정할 프로젝트 선택 - Properties - Run/Debug Setting에서 설정가능하다.

 


 

High 시 LD2 점등 / Low 시 LD2 소등

System Core - GPIO에서 각 레지스터들의 설정을 변경할 수 있다.

 

System Core이외에도 헤더파일에서의 함수를 불러와 main문에 추가하여 설정을 변경할 수도 있다.

GPIO의 Pin,Mode등이 구조체형식으로 정의되어 있다.

먼저 우리가 사용하는 푸쉬버튼 핀은 전처리기로 0x2000이란 값이 GPIO_PIN_13이라는 상수에 저장되어 있는것을 확인할 수 있다.

0x2000 -> 0b 0010 0000 0000 0000 -> 13번핀

더보기

(전처리기) # define A B = A의 상수를 B로 정의한다. (전처리기로 정의된 상수는 ROM에 저장된다.)

ex)

define c 100 = c100인 상수로 정의

define a c+100 = ac+100(200)인 상수로 정의

더보기

C언어나 다른 언어를 할 때 주소값

0x00으로 주소 지정 = 16진수

0O00으로 주소 지정 = 8진수

0b00으로 주소 지정 = 2진수

숫자 = 10진수

해당 코드는 B1_PinGPIO_PIN_13이란 값을 넣는다 -> GPIO_PIN_13에 0x2000이라는 주소값을 넣는다 -> B1_Pin만 사용해도 0x2000이 입력된다.

 

현재 초록 불이 들어오는 LD2의 주소값은 0x0020이란 것을 확인할 수 있다.

 

이제 헤더파일의 함수를 들고와 소스코드를 작성하여 LD2를 점등하고 소등해 보도록 하자.

GPIO와 관련된 헤더파일은 위의 경로를 통해 볼 수 있다.

 

  • LD2 점등 1

먼저 HAL_GPIO_WritePin 함수를 통해 LD2를 점등시켜 보도록 한다.

우리가 사용하는 포트는 PA5로 GPIOA를 입력하면 된다. 각 함수의 매개변수는 해당 매개변수 설명에 맞게 입력해주면 된다.

LD2를 점등시키기 위해서는 Core - Src - main.c의 main문에서 while안에 코드를 작성하도록 한다.

더보기

GPIO_PIN_SET = HIGH값 

GPIO_PIN_RESET = 0 (LOW값)

해당 코드를 작성 후 RUN 시켰을 시 정상적으로 LD2가 점등되는 것을 확인할 수 있다.

 

  • LD2 점등 2

이번엔 HAL_GPIO_ReadPin함수를 이용하여 푸쉬버튼의 입력을 받으면 LD2 점등, 푸쉬버튼을 때면 소등하는 코드를 작성해 보도록 한다.

GPIO 핀 상태를 리턴값으로 주는 함수
좌, 우 동일한 결과 출력 (매개변수가 같기 때문이다.)

해당 코드 작성 후 RUN 시켰을 시 버튼 누르면 LED 점등, 땠을 시 소등되는 것을 확인할 수 있다.

 

  • LD2 점등 3

이번엔 HAL_GPIO_TogglePin함수를 이용하여 핀을 토글시켜 LD2를 점등, 소등 시켜보도록 한다.

 

main문 시작 시 MX_GPIO_Init() 함수를 먼저 실행하므로 LD2핀이 LOW인 상태이다. 이때 HAL_GPIO_TogglePin함수를 이용하여 토글 시 LOW -> HIGH값으로 변하므로 LD2가 점등되는 것을 확인할 수 있다. 

 

  • 토글을 이용하여 푸쉬버튼을 누를 시 1초 점등, 1초 소등을 3번 반복하는 코드를 작성

HAL_GPIO_ReadPin함수를 조건문으로 걸어 HLA_TogglePin함수를 이용하여 점등, 소등 시켰다.

 


  • 코드 해석

해당 코드를 해석해보면 

먼저 HAL_GPIO_ReadPin함수를 조건문으로 받는다.  

푸쉬버튼 OFF 시 OPEN 상태로 PC13에 VDD가 입력된다 / 푸쉬버튼 ON 시 GND로 전류가 이동하여 PC13에 입력이 안들어온다.

현재 푸쉬버튼이 OFF된 상태로 가정해 보면 PC13에 HIGH값이 들어가는 것을 알 수 있다.

HAL_GPIO_ReadPin 함수를 살펴보면 (GPIOx->IDR & GPIO_Pin) 이 true일 시 bitstatus에 GPIO_PIN_SET값이 / false일 시 GPIO_PIN_RESET값이 리턴값으로 반환되는 것을 볼 수 있다.

조건문의 GPIOx->IDR의 IDR은 포트 입력 데이터 레지스터이므로 현재 푸쉬버튼이 OFF상태라 PC13에 VDD가 입력되고 있으므로 해당 부분에만 1이 들어가게 된다. 또한 GPIO_PIN은 0x2000으로 13번 레지스터가 같은 HIGH값이 된다.

그러므로 GPIO_PIN_SET을 리턴값으로 반환한다.

 

if문이 true로 해당 부분을 실행하게 된다.  조건문에서 PinsState가 GPIO_PIN_RESET와 같이 않으면 true이다. 현재 PinState가 GPIO_PIN_RESET을 입력받은 상태로 해당코드를 수행하게 된다.

BSRR은 포트의 bit set/reset regiset를 나타내는데 현재 매개변수로 받은 GPIO_Pin을 시프트 레지스터로 16U 왼쪽 이동시키면 모든 레지스터가 0의 값을 가지게 된다.

BSRR의 13 레지스터에 0을 입력하게 되므로 bit set/reset regiset는 0일 시 아무런 동작을 시키지 않으므로 LD2가 소등된다.

 

만약 푸쉬버튼을 누르게 되면 PC13에 VDD가 입력되지 않아 처음 if문에 false를 받게 되어 

GPIOx->BSRR에 GPIO_Pin(0x2000)을 입력받아 LD2가 점등하게 된다.