nRF52840 TWI(I2C) Slave 드라이버 활용하기
nRF52840은 블루투스 5.0과 멀티프로토콜을 지원하는 고성능 SoC(System on Chip)로, 다양한 통신 인터페이스를 제공하며, 그중 TWI(Two-Wire Interface)는 I2C(Inter-Integrated Circuit)와 유사한 프로토콜로 두 개의 선(SCL, SDA)을 통해 데이터를 주고받는 통신 방식입니다. TWI Slave 장치는 TWI Master의 명령에 따라 데이터를 수신하거나 전송하는 역할을 수행합니다.
이 글에서는 nRF52840에서 TWI Slave 드라이버를 설정하고 구현하는 방법에 대해 설명합니다. 이를 통해 TWI Master와 안정적으로 통신할 수 있는 소프트웨어를 개발할 수 있습니다.
1. TWI Slave 드라이버 설정
TWI Slave 드라이버를 설정하기 위해 nrf_drv_twis_config_t 구조체를 사용하여 Slave Address, SDA 핀, SCL 핀을 설정합니다. 이후, nrf_drv_twis_init() 함수를 호출하여 TWI Slave 드라이버를 초기화하고, nrf_drv_twis_enable() 함수를 호출하여 드라이버를 활성화합니다.
TWI Master 드라이버와의 차이점은 통신 속도가 아닌 Slave Address를 설정한다는 것입니다. Slave Address는 Master 장치가 통신할 Slave 장치를 식별하는 데 사용됩니다.
static const nrf_drv_twis_t g_twi_s = NRF_DRV_TWIS_INSTANCE(1);
#define TWI_S_SDA_PIN NRF_GPIO_PIN_MAP(0, 30)
#define TWI_S_SCL_PIN NRF_GPIO_PIN_MAP(0, 31)
#define TWI_S_SLAVE_ADDR 0x50
uint8_t g_twi_s_rx_buf[5] = {0x00, };
uint8_t g_twi_s_tx_buf[5] = {0x00, };
/**
* Initialize twi devices and add to device list.
*
**/
static void twis_event_handler(nrf_drv_twis_evt_t const * const p_event)
{
switch (p_event->type)
{
case TWIS_EVT_READ_REQ:
{
if(p_event->data.buf_req)
(void)nrf_drv_twis_tx_prepare(&g_twi_s, g_twi_s_tx_buf, 4);
break;
}
case TWIS_EVT_READ_DONE:
break;
case TWIS_EVT_WRITE_REQ:
{
if(p_event->data.buf_req)
{
(void)nrf_drv_twis_rx_prepare(&g_twi_s, g_twi_s_rx_buf, sizeof(g_twi_s_rx_buf));
if((0xAD == g_twi_s_rx_buf[0]) && (0xED == g_twi_s_rx_buf[1]))
NRF_LOG_INFO("RX 0x%02x, 0x%02x", g_twi_s_rx_buf[0], g_twi_s_rx_buf[1]);
}
break;
}
case TWIS_EVT_WRITE_DONE:
break;
case TWIS_EVT_READ_ERROR:
case TWIS_EVT_WRITE_ERROR:
case TWIS_EVT_GENERAL_ERROR:
break;
default:
break;
}
}
int aika_twi_slave_init(void)
{
ret_code_t ret;
const nrf_drv_twis_config_t slave_config = {
.addr = {TWI_S_SLAVE_ADDR, 0}, // Slave Address
.scl = TWI_S_SCL_PIN, // SCL Pin
.scl_pull = NRF_GPIO_PIN_PULLUP, // SCL Pin 초기 상태
.sda = TWI_S_SDA_PIN, // SDA Pin
.sda_pull = NRF_GPIO_PIN_PULLUP, // SDA Pin 초기 상태
.interrupt_priority = APP_IRQ_PRIORITY_HIGH // Interrupt 우선순위
};
/* Init TWIS */
do
{
ret = nrf_drv_twis_init(&g_twi_s, &slave_config, twis_event_handler);
if(NRF_SUCCESS != ret)
{
NRF_LOG_INFO("TWI Slave init failed");
break;
}
nrf_drv_twis_enable(&g_twi_s);
}while (0);
if(NRF_SUCCESS == ret)
NRF_LOG_INFO("TWI Slave init Done");
return 0;
}
주요 설정 사항
- Slave Address: TWI Master가 통신할 Slave를 식별하기 위해 사용하는 주소입니다. 7비트 또는 10비트로 설정할 수 있습니다.
- SDA 핀 및 SCL 핀: 각각의 핀을 사용해 데이터를 주고받습니다.
- Interrupt Priority: 인터럽트 우선순위는 응용 프로그램의 요구 사항에 따라 적절히 설정해야 합니다.
2. TWI Slave Event Handler 설명
- TWIS_EVT_READ_REQ : Master가 Slave로부터 데이터를 요청할 때 발생합니다. 이 이벤트에서 Slave는 Master에게 전송할 데이터를 준비합니다.
- TWIS_EVT_WRITE_REQ : Master가 Slave에게 데이터를 전송하려고 할 때 발생합니다. 이 이벤트에서 Slave는 수신 버퍼를 준비하고, 수신된 데이터를 검증하고 처리할 수 있습니다.
- TWIS_EVT_READ_DONE : Master가 데이터를 성공적으로 읽었을 때 발생합니다.
- TWIS_EVT_WRITE_DONE : Master가 데이터를 성공적으로 전송했을 때 발생합니다.
- TWIS_EVT_READ_ERROR, TWIS_EVT_WRITE_ERROR, TWIS_EVT_GENERAL_ERROR : 통신 중 에러가 발생했을 때 이를 처리합니다.
- 중요 고려사항*
- 통신 버퍼 관리: tx_prepare와 rx_prepare 함수 호출 시, 적절한 버퍼와 그 크기를 전달해야 합니다. 잘못된 버퍼 크기나 초기화되지 않은 버퍼를 사용하면 예기치 않은 동작이 발생할 수 있습니다.
- 에러 핸들링: 통신 중 발생할 수 있는 다양한 오류를 고려하여 에러 핸들링을 철저히 구현해야 합니다.
3. 결론
이 글에서는 nRF52840에서 TWI Slave 드라이버를 설정하고 사용하는 방법에 대해 다루었습니다. TWI Slave 드라이버의 핵심 기능은 Slave Address 설정, SDA 및 SCL 핀 설정, 그리고 이벤트 핸들러를 통한 통신 처리입니다. 이러한 설정을 통해 TWI Master와의 통신을 원활하게 구현할 수 있습니다.
nRF52840에서 TWI Slave 드라이버를 효과적으로 구현하려면, 각종 이벤트와 오류 처리에 신경 써야 합니다. 이를 통해 TWI 프로토콜을 활용한 안정적인 데이터 통신을 구현할 수 있습니다. TWI 통신의 안정성을 높이기 위해선 통신 핸들러와 버퍼 관리가 중요하다는 점을 유념해야 합니다.
'nRF52' 카테고리의 다른 글
nRF52840 QSPI 드라이버 활용 (0) | 2024.09.04 |
---|---|
nRF52840 SPI 드라이버 활용하기 (0) | 2024.09.03 |
nRF52840 TWI(I2C) Master 드라이버 활용하기 (0) | 2024.09.01 |
nRF52840 TWI I2C 설정 가이드 (0) | 2024.08.31 |
nRF52840 UART 통신 가이드 (0) | 2024.08.30 |