개요.
- nRF52840 의 GPIO 제어 코드를 nRF5 SDK 없이 레지스터 직접 접근하여 코딩하는 예 정리.
- SDK 없이 레지스터 직접 제어 코드 작성해봐야 하는 이유 . 실활용목적에서는 SDK 기반하여 작성하겠지만 초보자인 경우 기본골격 파악도 못한 상태에서 SDK 기반한 코딩해봤자 실력 늘지 않음.
사전 준비
1. SES 혹은 KEIL 기본프로젝트 만든상태 의 main.c 에 아래 코드들 추가.
2. nRF52840 GPIO 기본개념숙지 : https://igotit.tistory.com/2031
nRF52. GPIO (General Purpose Input Output)
nRF52840 GPIO Features • Up to 32 GPIO pins per GPIO port • Configurable output drive strength • Internal pull-up and pull-down resistors • Wake-up from high or low level triggers on all pins •..
igotit.tistory.com
코드1 - 핀 P0.13 out 설정 예.
주요 include 파일 : 레지스터 주소 정의된 nrf52840.h , bitfields 정의파일인 nrf52840_bitfields.h
#include "nrf52840.h"
#include "nrf52840_bitfields.h"
int main()
{
// gpio config for P0.13 . board PCA10056 LED1,2,3,4 = P0.13, P0.14, P0.15, P0.16.
uint32_t pin_number=13; // P0.13
NRF_GPIO_Type * reg = ((NRF_GPIO_Type*)NRF_P0_BASE);
reg->PIN_CNF[pin_number] = ((uint32_t)GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos)
|((uint32_t)GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
|((uint32_t)GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
|((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
|((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
while(1)
{
// toggling the pin
uint32_t pins_state = reg->OUT;
reg->OUTSET = (~pins_state & (1UL << pin_number));
reg->OUTCLR = (pins_state & (1UL << pin_number));
}
}
while 문 내의 처리는 해당핀을 토글링 하는 처리이다. 즉 현재상태의 반대 값을 핀에 출력 하는 식. 1->0->1,...
위 코드를 타겟보드 PCA10056 에 기록하여 실행시키면 토글링 사이에 지연없는 상태이므로 LED1 이 계속 켜져있는것으로 보인다.
코드2. 4개 핀 output 설정 예
아래코드는 위 코드1 에서의 설정을 함수 2개에 분리 구현하고, 4개의 핀 P0.13, P0.14, P0.15, P0.16 을 out 설정하고 토글링 하는 예. PCA10056 에 기록하여 실행시키면 4개 LED모두 켜지는 것 확인가능.
#include "nrf52840.h" | |
#include "nrf52840_bitfields.h" | |
void init_gpio_p0_output(uint32_t pin_num) | |
{ | |
NRF_GPIO_Type * reg = ((NRF_GPIO_Type*)NRF_P0_BASE); | |
reg->PIN_CNF[pin_num] = ((uint32_t)GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | |
|((uint32_t)GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | |
|((uint32_t)GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | |
|((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | |
|((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); | |
} | |
void toggle_gpio_p0(uint32_t pin_num) | |
{ | |
NRF_GPIO_Type * reg = ((NRF_GPIO_Type*)NRF_P0_BASE); | |
uint32_t pins_state = reg->OUT; | |
reg->OUTSET = (~pins_state & (1UL << pin_num)); | |
reg->OUTCLR = (pins_state & (1UL << pin_num)); | |
} | |
int main() | |
{ | |
// gpio config for board PCA10056 LED1,2,3,4 = P0.13, P0.14, P0.15, P0.16. | |
init_gpio_p0_output(13); // LED1 on PCA10056 | |
init_gpio_p0_output(14); // LED2 on PCA10056 | |
init_gpio_p0_output(15); // LED3 on PCA10056 | |
init_gpio_p0_output(16); // LED4 on PCA10056 | |
while(1) | |
{ | |
// toggling the pin | |
toggle_gpio_p0(13); | |
toggle_gpio_p0(14); | |
toggle_gpio_p0(15); | |
toggle_gpio_p0(16); | |
} | |
} |
코드3. 핀 Input 설정예.
특정 핀을 입력으로 설정하는 함수 와 핀 상태값 읽는 함수 정의.
void init_gpio_p0_input(uint32_t pin_num)
{
NRF_GPIO_Type * reg = ((NRF_GPIO_Type*)NRF_P0_BASE);
reg->PIN_CNF[pin_num] = ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos)
|((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
|((uint32_t)GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
|((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
|((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
}
uint32_t read_gpio_p0(uint32_t pin_num)
{
NRF_GPIO_Type * reg = ((NRF_GPIO_Type*)NRF_P0_BASE);
return (((reg->IN)>>pin_num) & 1UL);
}
위 함수를 이용하여 while 문 내에서 PCA10056 의 Button1,2,3,4 의 상태값을 읽으면서 상태값이 1이면 동일번호의 LED 켜기, 0이면 끄기.
전체코드.
#include "nrf52840.h" | |
#include "nrf52840_bitfields.h" | |
void init_gpio_p0_output(uint32_t pin_num) | |
{ | |
NRF_GPIO_Type * reg = ((NRF_GPIO_Type*)NRF_P0_BASE); | |
reg->PIN_CNF[pin_num] = ((uint32_t)GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | |
|((uint32_t)GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | |
|((uint32_t)GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | |
|((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | |
|((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); | |
} | |
void toggle_gpio_p0(uint32_t pin_num) | |
{ | |
NRF_GPIO_Type * reg = ((NRF_GPIO_Type*)NRF_P0_BASE); | |
uint32_t pins_state = reg->OUT; | |
reg->OUTSET = (~pins_state & (1UL << pin_num)); | |
reg->OUTCLR = (pins_state & (1UL << pin_num)); | |
} | |
void out_gpio_p0(uint32_t pin_num, int pin_logic) | |
{ | |
NRF_GPIO_Type * reg = ((NRF_GPIO_Type*)NRF_P0_BASE); | |
uint32_t pins_state = reg->OUT; | |
if(pin_logic == 1) // pin out high | |
reg->OUTSET = (1UL << pin_num); //other pins no effect, because write 0 no effect | |
else // pin out low. | |
reg->OUTCLR = (1UL << pin_num); //other pins no effect, because write 0 no effect | |
} | |
void init_gpio_p0_input(uint32_t pin_num) | |
{ | |
NRF_GPIO_Type * reg = ((NRF_GPIO_Type*)NRF_P0_BASE); | |
reg->PIN_CNF[pin_num] = ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | |
|((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | |
|((uint32_t)GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | |
|((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | |
|((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); | |
} | |
uint32_t read_gpio_p0(uint32_t pin_num) | |
{ | |
NRF_GPIO_Type * reg = ((NRF_GPIO_Type*)NRF_P0_BASE); | |
return (((reg->IN)>>pin_num) & 1UL); | |
} | |
int main() | |
{ | |
// gpio out config for board PCA10056 LED1,2,3,4 = P0.13, P0.14, P0.15, P0.16. | |
init_gpio_p0_output(13); // LED1 , PCA10056 | |
init_gpio_p0_output(14); // LED2 , PCA10056 | |
init_gpio_p0_output(15); // LED3 , PCA10056 | |
init_gpio_p0_output(16); // LED4 , PCA10056 | |
out_gpio_p0(13, 1); // LED1 Off | |
out_gpio_p0(14, 1); // LED1 Off | |
out_gpio_p0(15, 1); // LED1 Off | |
out_gpio_p0(16, 1); // LED1 Off | |
// gpio in config for board button1,2,3,4 | |
init_gpio_p0_input(11); // Button1 , PCA10056 | |
init_gpio_p0_input(12); // Button2 , PCA10056 | |
init_gpio_p0_input(24); // Button3 , PCA10056 | |
init_gpio_p0_input(25); // Button4 , PCA10056 | |
while(1) | |
{ | |
if(read_gpio_p0(11) == 0) // Button1 pressed | |
out_gpio_p0(13, 0); // LED1 On. | |
else | |
out_gpio_p0(13, 1); // LED1 Off | |
if(read_gpio_p0(12) == 0) // Button2 pressed | |
out_gpio_p0(14, 0); // LED2 On. | |
else | |
out_gpio_p0(14, 1); // LED2 Off | |
if(read_gpio_p0(24) == 0) // Button3 pressed | |
out_gpio_p0(15, 0); // LED3 On. | |
else | |
out_gpio_p0(15, 1); // LED3 Off | |
if(read_gpio_p0(25) == 0) // Button4 pressed | |
out_gpio_p0(16, 0); // LED4 On. | |
else | |
out_gpio_p0(16, 1); // LED4 Off | |
} | |
} |
위 코드 PCA10056 에서 실 작동 확인..
- 버튼 누른것에 해당하는 LED 가 켜짐 확인.
본 글 포함된 상위 정리글
https://igotit.tistory.com/244 의 nRF52
STM32. nRF52. ESP32. EFM8. EFM32. PSoC 활용 정리.
STM32. nRF52. ESP32. EFM8. EFM32. PSoC 총정리 제조사 칩 주요특징 실리콘랩 8bit MCU EFM8 시리즈 32bit EFM32 시리즈 EFM8 싸다. STM STM32 . 최고 항상 만족. Cypress pSoC pSoC6 은 기대해볼만. NORDIC nRF5..
igotit.tistory.com
첫등록 : 2019년 10월 4일
최종수정 : 2019년 10월 5일
본 글 단축주소 : https://igotit.tistory.com/2314
'임베디드.일렉트로닉스 > nRF52' 카테고리의 다른 글
nRF52840. SDK기반 코딩. step by step 1. 시간지연함수 (0) | 2019.10.05 |
---|---|
nRF52. GPIOTE. GPIO tasks and events. (0) | 2019.10.05 |
nRF52840 USB동글의 J-link 커넥터 연결하기 (0) | 2019.10.05 |
nRF52840 USB 동글. PCA10059 (0) | 2019.10.04 |
nRF52840 DK (Development Kit) . PCA10056 (0) | 2019.10.04 |
댓글