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

nRF52 BLE 개발하기 - temperature

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

시작하기

이번에는 nRF52832 내부에 있는 온도센서의 값을 읽어오는 temperature 예제에 대해서 알아보자.

\examples\peripheral\temperature\pca10040\blank\ses 폴더에서 프로젝트를 실행시킨다.

예제는 500ms 마다 온도를 측정해서 문자열로 출력해주는 간단한 구성이다.

저번 글에서 다뤘던 NRF_LOG_INFO 출력 설정을 해주고 main 함수를 살펴보도록 하자.

int main(void)
{
    // This function contains workaround for PAN_028 rev2.0A anomalies 28, 29,30 and 31.
    int32_t volatile temp;

    nrf_temp_init();

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    NRF_LOG_INFO("Temperature example started.");

    while (true)
    {
        NRF_TEMP->TASKS_START = 1; /** Start the temperature measurement. */

        /* Busy wait while temperature measurement is not finished, you can skip waiting if you enable interrupt for DATARDY event and read the result in the interrupt. */
        /*lint -e{845} // A zero has been given as right argument to operator '|'" */
        while (NRF_TEMP->EVENTS_DATARDY == 0)
        {
            // Do nothing.
        }
        NRF_TEMP->EVENTS_DATARDY = 0;

        /**@note Workaround for PAN_028 rev2.0A anomaly 29 - TEMP: Stop task clears the TEMP register. */
        temp = (nrf_temp_read() / 4);

        /**@note Workaround for PAN_028 rev2.0A anomaly 30 - TEMP: Temp module analog front end does not power down when DATARDY event occurs. */
        NRF_TEMP->TASKS_STOP = 1; /** Stop the temperature measurement. */

        NRF_LOG_INFO("Actual temperature: %d", (int)temp);
        nrf_delay_ms(500);

        NRF_LOG_FLUSH();
    }
}

nrf_temp_init 함수를 호출해 내부 온도센서를 읽기 전용으로 설정해준다.

/**
 * @brief Function for preparing the TEMP module for temperature measurement.
 *
 * This function initializes the TEMP module and writes to the hidden configuration register.
 */
static __INLINE void nrf_temp_init(void)
{
    /**@note Workaround for PAN_028 rev2.0A anomaly 31 - TEMP: Temperature offset value has to be manually loaded to the TEMP module */
    *(uint32_t *) 0x4000C504 = 0;
}

/**
  * @brief Temperature Sensor (TEMP)
  */

typedef struct {                                /*!< (@ 0x4000C000) TEMP Structure                                             */
  __OM  uint32_t  TASKS_START;                  /*!< (@ 0x00000000) Start temperature measurement                              */
  __OM  uint32_t  TASKS_STOP;                   /*!< (@ 0x00000004) Stop temperature measurement                               */
  __IM  uint32_t  RESERVED[62];
  __IOM uint32_t  EVENTS_DATARDY;               /*!< (@ 0x00000100) Temperature measurement complete, data ready               */
  __IM  uint32_t  RESERVED1[128];
  __IOM uint32_t  INTENSET;                     /*!< (@ 0x00000304) Enable interrupt                                           */
  __IOM uint32_t  INTENCLR;                     /*!< (@ 0x00000308) Disable interrupt                                          */
  __IM  uint32_t  RESERVED2[127];
  __IM  int32_t   TEMP;                         /*!< (@ 0x00000508) Temperature in degC (0.25deg steps)                        */
  __IM  uint32_t  RESERVED3[5];
  __IOM uint32_t  A0;                           /*!< (@ 0x00000520) Slope of 1st piece wise linear function                    */
  __IOM uint32_t  A1;                           /*!< (@ 0x00000524) Slope of 2nd piece wise linear function                    */
  __IOM uint32_t  A2;                           /*!< (@ 0x00000528) Slope of 3rd piece wise linear function                    */
  __IOM uint32_t  A3;                           /*!< (@ 0x0000052C) Slope of 4th piece wise linear function                    */
  __IOM uint32_t  A4;                           /*!< (@ 0x00000530) Slope of 5th piece wise linear function                    */
  __IOM uint32_t  A5;                           /*!< (@ 0x00000534) Slope of 6th piece wise linear function                    */
  __IM  uint32_t  RESERVED4[2];
  __IOM uint32_t  B0;                           /*!< (@ 0x00000540) y-intercept of 1st piece wise linear function              */
  __IOM uint32_t  B1;                           /*!< (@ 0x00000544) y-intercept of 2nd piece wise linear function              */
  __IOM uint32_t  B2;                           /*!< (@ 0x00000548) y-intercept of 3rd piece wise linear function              */
  __IOM uint32_t  B3;                           /*!< (@ 0x0000054C) y-intercept of 4th piece wise linear function              */
  __IOM uint32_t  B4;                           /*!< (@ 0x00000550) y-intercept of 5th piece wise linear function              */
  __IOM uint32_t  B5;                           /*!< (@ 0x00000554) y-intercept of 6th piece wise linear function              */
  __IM  uint32_t  RESERVED5[2];
  __IOM uint32_t  T0;                           /*!< (@ 0x00000560) End point of 1st piece wise linear function                */
  __IOM uint32_t  T1;                           /*!< (@ 0x00000564) End point of 2nd piece wise linear function                */
  __IOM uint32_t  T2;                           /*!< (@ 0x00000568) End point of 3rd piece wise linear function                */
  __IOM uint32_t  T3;                           /*!< (@ 0x0000056C) End point of 4th piece wise linear function                */
  __IOM uint32_t  T4;                           /*!< (@ 0x00000570) End point of 5th piece wise linear function                */
} NRF_TEMP_Type;                                /*!< Size = 1396 (0x574)

내부 온도센서 기본 레지스터 주소는 0x4000C000이며 온도 센서를 읽기 위해 NRF_TEMP->TASKS_START 값을 1로 설정해준다.

NRF_TEMP->EVENTS_DATARDY 레지스터로 온도 측정이 완료되었는지 확인한다.

내부 온도센서의 온도가 측정되었다면 해당 레지스터는 값이 1로 설정되어 있다.

nrf_temp_read 함수를 호출해 내부 온도센서의 값을 읽는다.

NRF_TEMP->TEMP 값에 MASK_SIGN(0x200)을 AND 연산하는데 읽어온 값이 양수라면 연산 결과는 0이 돼서 그대로 값을 전달해준다.

만약 음수일 경우 읽어온 값에 MASK_SIGN_EXTENSION을 OR 연산한 후 값을 전달해준다.

전달받은 값에 4를 나누어 주면 내부 온도센서에서 읽은 온도 값으로 변환된다.

마지막으로 NRF_TEMP->TASKS_STOP 값을 1로 설정해줌으로써 내부 온도센서 동작을 중지한다.

/**
 * @brief Function for reading temperature measurement.
 *
 * The function reads the 10-bit 2's complement value and transforms it to a 32-bit 2's complement value.
 */
static __INLINE int32_t nrf_temp_read(void)
{
    /**@note Workaround for PAN_028 rev2.0A anomaly 28 - TEMP: Negative measured values are not represented correctly */
    return ((NRF_TEMP->TEMP & MASK_SIGN) != 0) ?
                (int32_t)(NRF_TEMP->TEMP | MASK_SIGN_EXTENSION) : (NRF_TEMP->TEMP);
}

내부 온도센서는 0.25℃의 해상도를 가지고 있는데 예제에서는 소수점은 빼고 출력하고 있어 이 부분만 수정하면 다음과 같다.

int main(void)
{
    // This function contains workaround for PAN_028 rev2.0A anomalies 28, 29,30 and 31.
    float volatile temp;

    nrf_temp_init();

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    NRF_LOG_INFO("Temperature example started.");

    while (true)
    {
        NRF_TEMP->TASKS_START = 1; /** Start the temperature measurement. */

        /* Busy wait while temperature measurement is not finished, you can skip waiting if you enable interrupt for DATARDY event and read the result in the interrupt. */
        /*lint -e{845} // A zero has been given as right argument to operator '|'" */
        while (NRF_TEMP->EVENTS_DATARDY == 0)
        {
            // Do nothing.
        }
        NRF_TEMP->EVENTS_DATARDY = 0;

        /**@note Workaround for PAN_028 rev2.0A anomaly 29 - TEMP: Stop task clears the TEMP register. */
        temp = (nrf_temp_read() / 4.0);

        /**@note Workaround for PAN_028 rev2.0A anomaly 30 - TEMP: Temp module analog front end does not power down when DATARDY event occurs. */
        NRF_TEMP->TASKS_STOP = 1; /** Stop the temperature measurement. */

        NRF_LOG_INFO("Actual temperature: "NRF_LOG_FLOAT_MARKER"", NRF_LOG_FLOAT(temp));
        nrf_delay_ms(500);

        NRF_LOG_FLUSH();
    }
}

앞으로

nRF52832 내부 온도센서를 읽어오는 예제를 통해 온도 값을 확인해보았다.

지금부터는 nRF52832 DK에 주변기기를 연결하여 센서와의 통신을 하는 예제에 대해서 알아보자.

728x90
반응형

댓글