프로그래밍/STM32

[STM32] CPU 온도 측정하기

Beginner:) 2023. 9. 30.
320x100

먼저 나의 환경은 Ubuntu 20.04, NUCLEO-F411RE 사용 중이다.

 

1. 설명

STM32는 내부에서 CPU의 온도를 측정할 수 있다. 계산방법은 모르겠어서 코드만 GPT 것을 가져왔다.

 

Polling, Interrupt, DMA 3가지 방법이 있는데, 온도는 1초에 한 번 체크해도 무방하다 생각하기에 Interrupt 방식을 택할 것이다.

설명은 아래와 같이 있지만 구현은 Interrupt 방식만 해볼 것이다.

(Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c 주석 중)

(#) ADC 드라이버는 폴링(Polling), 인터럽트(interruption), 세 가지 모드 중에서 사용할 수 있습니다,
      DMA에 의한 양도.    

     *** 폴링모드 IO동작 ***
     =================================
     [..]    
       (+) HAL_ADC_Start()를 사용하여 ADC 주변기기를 시동합니다 
       (+) HAL_ADC_PollForConversion()을 사용하여 변환 종료 대기(), 이 단계에서
           사용자는 자신의 최종 응용 프로그램에 따라 시간 초과 값을 지정할 수 있습니다      
       (+) ADC 변환값을 읽으려면 HAL_ADC_GetValue() 기능을 사용합니다.
       (+) HAL_ADC_Stop()을 사용하여 ADC 주변 장치를 중지합니다
       
     *** 인터럽트 모드 IO 작업 ***    
     ===================================
     [..]    
       (+) HAL_ADC_Start_IT()를 사용하여 ADC 주변기기를 시동합니다 
       (+) ADC_IRQHandler() Interrupt 서브루틴에서 호출된 HAL_ADC_IRQHandler()를 사용합니다
       (+) ADC 변환 종료 시 HAL_ADC_ConvCpltCallback() 기능이 실행되어 사용자는 다음과 같이 할 수 있습니다 
           함수 포인터 HAL_ADC_ConvCpltCallback을 사용자 지정하여 자신의 코드를 추가합니다 
       (+) ADC Error의 경우 HAL_ADC_ErrorCallback() 기능이 실행되어 사용자는 
           함수 포인터 HAL_ADC_ErrorCallback을 사용자 정의하여 자신의 코드를 추가합니다
       (+) HAL_ADC_Stop_IT()를 사용하여 ADC 주변기기를 정지합니다     

     *** DMA 모드 IO 작동 ***    
     ==============================
     [..]    
       (+) HAL_ADC_Start_DMA()를 사용하여 ADC 주변 장치를 시작합니다. 이 단계에서 사용자가 길이를 지정합니다 
           변환이 끝날 때마다 전송할 데이터의 
       (+) HAL_ADC_ConvCpltCallback() 기능에 의한 데이터 전송 종료 시 실행되며 사용자는 다음을 수행할 수 있습니다 
           함수 포인터 HAL_ADC_ConvCpltCallback을 사용자 지정하여 자신의 코드를 추가합니다 
       (+) 전송오류의 경우 HAL_ADC_ErrorCallback() 기능이 실행되어 사용자는 
           함수 포인터 HAL_ADC_ErrorCallback을 사용자 정의하여 자신의 코드를 추가합니다
       (+) HAL_ADC_Stop_DMA()를 사용하여 ADC 주변기기를 정지합니다
                    

 

2. 설정

[Analog] - [ADC1]-[Mode]에서 스크롤을 아래로 내리면 "Temperature Sensor Channel"이 존재하는데, 체크하고 [Parameter Settings]에서 "Continuous Conversion Mode"를 Enable로 변경한다.

"ADC1 global interrupt"도 Enable 체크해준다.

 

3. 코드

getCPUTemp()에서 HAL_ADC_Start_IT함수를 수행하면 인터럽트가 수행되어 HAL_ADC_ConvCpltCallback함수가 실행되는 방식이다.

#include "adc.h"
#include "stm32f4xx_hal_adc.h"

static float cpu_temp = 0.0f;

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
    uint16_t rawValue = HAL_ADC_GetValue(&hadc1);
    float temperature = ((float)rawValue / 4095) * 3300; // ADC 값을 전압으로 변환
    cpu_temp = ((temperature - 760.0) / 2.5) + 25.0; // 온도로 변환
}

float getCPUTemp(){
    HAL_ADC_Start_IT(&hadc1);

    return cpu_temp;
}

 

main.c의 while문에서는 1초에 한 번씩 인터럽트를 발생시켜 print로 출력한다.

while (1)
  {
    printf("TEMP: %.2f\n", getCPUTemp());
    HAL_Delay(1000);
  }

 

실행을 시켜보면 같은 숫자가 반복되어 좀 수상하긴 한데, 선풍기를 틀면 온도가 내려가는 것을 보아 정상작동으로 보인다.

 

 


+) 아래는 ChatGPT에서 알려준 방식인데 Polling 방식이며 global interrupt 체크 해제해야 한다.

while (1) {
    // ADC 변환 시작
    HAL_ADC_Start(&hadc1);

    // ADC 변환 완료 대기
    HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);

    // 변환된 값 읽기 (CPU 온도 센서 채널 사용)
    uint16_t rawValue = HAL_ADC_GetValue(&hadc1);

    // CPU 온도 계산 (참고: STM32 데이터 시트)
    float temperature = ((float)rawValue / 4095) * 3300; // ADC 값을 전압으로 변환
    temperature = ((temperature - 760.0) / 2.5) + 25.0; // 온도로 변환

    // CPU 온도 출력 (예를 들어 시리얼 포트를 통해)
    printf("CPU 온도: %.2f°C\n", temperature);

    // 일정한 시간 동안 대기
    HAL_Delay(1000);
  }
}
반응형

댓글