본문 바로가기
Embedded/nRF52 BLE 개발 안내서

nRF52 BLE 개발하기 - timer

by 큐찡 2021. 1. 12.
728x90
반응형

시작하기

\examples\peripheral\timer\pca10040\blank\ses 폴더에서 바로 타이머 예제 프로젝트를 실행시켜보자.

그리고 노르딕 인포센터 링크에 접속하여 예제에 대한 내용을 확인하자.

blinky 예제에서 시간 지연으로 사용했던 nrf_delay_ms 함수보다 더 정확한 하드웨어 기반 시간 지연이라고 한다.

500ms마다 LED 상태가 순차적으로 변경되는 매우 간단한 예제이다.

const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(0);

/**
 * @brief Handler for timer events.
 */
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
{
    static uint32_t i;
    uint32_t led_to_invert = ((i++) % LEDS_NUMBER);

    switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE0:
            bsp_board_led_invert(led_to_invert);
            break;

        default:
            //Do nothing.
            break;
    }
}


/**
 * @brief Function for main application entry.
 */
int main(void)
{
    uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events.
    uint32_t time_ticks;
    uint32_t err_code = NRF_SUCCESS;

    //Configure all leds on board.
    bsp_board_init(BSP_INIT_LEDS);

    //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    err_code = nrf_drv_timer_init(&TIMER_LED, &timer_cfg, timer_led_event_handler);
    APP_ERROR_CHECK(err_code);

    time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);

    nrf_drv_timer_extended_compare(
         &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

    nrf_drv_timer_enable(&TIMER_LED);

    while (1)
    {
        __WFI();
    }
}

main 함수를 살펴보면 크게 LED 출력을 위한 GPIO 설정과 타이머 설정으로 나눌 수 있다.

blinky 예제에서 다뤘던 bsp_board_init 함수에 대해선 생략하고 바로 타이머 설정에 대해서 알아보자.

nrf_drv_timer_init 함수에 사용할 타이머(Timer 0)와 설정값(NRF_DRV_TIMER_DEFAULT_CONFIG), 이벤트 핸들러(timer_led_event_handler)를 전달 인자로 넘겨 설정한다.

NRF_DRV_TIMER_DEFAULT_CONFIG는 NRF_TIMER_FREQ_16MHz, NRF_TIMER_MODE_TIMER, NRF_TIMER_BIT_WIDTH_32, 인터럽트 우선순위 6의 값을 가지고 있다.

nrf_drv_timer_ms_to_ticks 함수를 통해 Timer 0가 500ms에 대한 time_ticks값을 반환받는다.

nrf_drv_timer_extended_compare 함수에 Timer 0, Timer CC channel 0, time_ticks, Shortcut register에 COMPARE0_CLEAR_MASK를 전달 인자로 넘겨 설정한다.

마지막으로 nrf_drv_timer_enable 함수로 Timer 0를 활성화한다.

이렇게 500ms마다 timer_led_event_handler 함수가 호출되는 타이머가 실행된다.

타이머 설정에 관한 자세한 내용은 데이터시트 234페이지부터 나와있다.

위 소스코드를 응용하여 타이머를 4개 사용하여 4개의 LED를 각각 다른 시간 지연을 가지며 반짝이게 해 보도록 하자.

먼저 Timer 0, 1, 2, 3을 사용하기 위해 sdk_config.h 파일에서 다음과 같이 설정을 변경해야 사용할 수 있다.

/* sdk_config.h */

// <q> TIMER0_ENABLED  - Enable TIMER0 instance
 

#ifndef TIMER0_ENABLED
#define TIMER0_ENABLED 1
#endif

// <q> TIMER1_ENABLED  - Enable TIMER1 instance
 

#ifndef TIMER1_ENABLED
#define TIMER1_ENABLED 1
#endif

// <q> TIMER2_ENABLED  - Enable TIMER2 instance
 

#ifndef TIMER2_ENABLED
#define TIMER2_ENABLED 1
#endif

// <q> TIMER3_ENABLED  - Enable TIMER3 instance
 

#ifndef TIMER3_ENABLED
#define TIMER3_ENABLED 1
#endif

// <q> TIMER4_ENABLED  - Enable TIMER4 instance
 

#ifndef TIMER4_ENABLED
#define TIMER4_ENABLED 0
#endif
const nrf_drv_timer_t TIMER_LED1 = NRF_DRV_TIMER_INSTANCE(0);
const nrf_drv_timer_t TIMER_LED2 = NRF_DRV_TIMER_INSTANCE(1);
const nrf_drv_timer_t TIMER_LED3 = NRF_DRV_TIMER_INSTANCE(2);
const nrf_drv_timer_t TIMER_LED4 = NRF_DRV_TIMER_INSTANCE(3);

/**
 * @brief Handler for timer events.
 */
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
{
    switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE0:
            bsp_board_led_invert(0);
            break;

        case NRF_TIMER_EVENT_COMPARE1:
            bsp_board_led_invert(1);
            break;
        
        case NRF_TIMER_EVENT_COMPARE2:
            bsp_board_led_invert(2);
            break;
        
        case NRF_TIMER_EVENT_COMPARE3:
            bsp_board_led_invert(3);
            break;

        default:
            //Do nothing.
            break;
    }
}


/**
 * @brief Function for main application entry.
 */
int main(void)
{
    uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events.
    uint32_t time_ticks1, time_ticks2, time_ticks3, time_ticks4;
    uint32_t err_code = NRF_SUCCESS;

    //Configure all leds on board.
    bsp_board_init(BSP_INIT_LEDS);

    //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    err_code = nrf_drv_timer_init(&TIMER_LED1, &timer_cfg, timer_led_event_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_timer_init(&TIMER_LED2, &timer_cfg, timer_led_event_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_timer_init(&TIMER_LED3, &timer_cfg, timer_led_event_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_timer_init(&TIMER_LED4, &timer_cfg, timer_led_event_handler);
    APP_ERROR_CHECK(err_code);

    time_ticks1 = nrf_drv_timer_ms_to_ticks(&TIMER_LED1, 1000);
    time_ticks2 = nrf_drv_timer_ms_to_ticks(&TIMER_LED2, 500);
    time_ticks3 = nrf_drv_timer_ms_to_ticks(&TIMER_LED3, 250);
    time_ticks4 = nrf_drv_timer_ms_to_ticks(&TIMER_LED4, 100);

    nrf_drv_timer_extended_compare(
         &TIMER_LED1, NRF_TIMER_CC_CHANNEL0, time_ticks1, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

    nrf_drv_timer_extended_compare(
         &TIMER_LED2, NRF_TIMER_CC_CHANNEL1, time_ticks2, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);
    
    nrf_drv_timer_extended_compare(
         &TIMER_LED3, NRF_TIMER_CC_CHANNEL2, time_ticks3, NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK, true);

    nrf_drv_timer_extended_compare(
         &TIMER_LED4, NRF_TIMER_CC_CHANNEL3, time_ticks4, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK, true);

    nrf_drv_timer_enable(&TIMER_LED1);
    nrf_drv_timer_enable(&TIMER_LED2);
    nrf_drv_timer_enable(&TIMER_LED3);
    nrf_drv_timer_enable(&TIMER_LED4);

    while (1)
    {
        __WFI();
    }
}

앞으로

지금까지 nRF52의 대표적인 타이머를 이용하여 LED를 제어해보는 예제를 알아보았다.

다음에는 simple_timer 예제를 살펴보도록 하자.

 

728x90
반응형

댓글