Skip to content

예제 adc_temperature

irmusy edited this page Oct 1, 2013 · 1 revision

개요

adc_temperature는 ADC를 이용하여 MCU 내장 온도 센서의 출력을 읽어 MCU 코어 온도를 UART로 출력하는 예제입니다. MCU 코어는 높은 클럭 속도로 동작할 때 열이 발생하므로 내장 온도 센서로 읽은 온도 값은 대기 온도와 무관하게 나오는 점 감안하시기 바랍니다.

관련 Peripheral

  • SysCtl
  • ADC
  • UART(llio)

소스 살펴보기

모든 예제들에 공통적으로 있는 내용들은 건너띄고 핵심 부분만 설명하도록 하겠습니다. 다른 부분이 궁금하시면 [timer](에제 timer), [printf_scanf](예제 printf_scanf) 등을 참고하시기 바랍니다.

56 line:

    //
    // Set the clocking to run directly from the crystal.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_8MHZ);

이번 예제에서는 외장 8MHz 크리스털을 그대로 사용하는 구성입니다. PLL을 사용하지 않기 때문에 MCU 코어 클럭 역시 8MHz로 동작합니다.

PLL을 사용해 50MHz 클럭으로 동작시킬 경우 MCU 코어 온도가 더 높아집니다. 이는 소비전력이 늘어나기 때문이며, 소스 코드를 수정해서 직접 확인해 보실 수 있습니다.

69 line:

    //
    // Configure ADC
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC);
    SysCtlADCSpeedSet(SYSCTL_ADCSPEED_500KSPS);

    ADCSequenceDisable(ADC_BASE, 0);
    ADCSequenceConfigure(ADC_BASE, 0, ADC_TRIGGER_TIMER, 0);

    ADCSequenceStepConfigure(ADC_BASE, 0, 0, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END);

    ADCSequenceEnable(ADC_BASE, 0);

ADC 장치를 초기화하고 설정하는 부분입니다. 우선 **SysCtlPeripheralEnable()**함수를 이용해 ADC 장치를 enable 시켜줍니다. 다음으로 ADC의 동작 속도를 설정합니다. 이 예제에서는 500KSPS(kilo sampling per sec)로 설정하였습니다.

ADC 장치를 enable 시킨 다음에는 ADC 시퀀스를 설정해야 합니다. ADC 시퀀스는 한번의 AD 변환을 수행 할 채널의 개수와 순서를 정의하는 것입니다. 본 예제에서는 온도 센서 하나만 사용할 것이므로 채널 개수는 1개 입니다.

시퀀스를 설정하려면 우선 **ADCSequenceDisable()**를 이용해 시퀀스를 disable시킨 후에 설정을 변경해야 합니다. **ADCSequenceConfigure()**함수에서는 시퀀스 번호와 트리거 방법, 우선도를 지정합니다. **ADCSequenceStepConfigure()**함수는 시퀀스 내의 채널 순서와 인터럽트 발생 방식을 정의합니다. 이 예제에서는 ADC_CTL_TS 채널 1개만 사용하고, 이 채널의 ADC가 끝난 다음에 ADC 인터럽트가 발생하면서 시퀀스가 끝나는 형태로 설정하고 있습니다.

마지막으로 **ADCSequenceEnable()**을 통해 ADC 시퀀스를 enable 시켜주면 됩니다.

한가지 확인하고 넘어갈 부분은 ADC 인터럽트 발생 조건은 지정했지만 ADC 인터럽트를 enable 시키지는 않았다는 점입니다. 이렇게 설정해 두면 하드웨어적인 인터럽트가 발생하지는 않습니다. 다만 인터럽트 관련 flag들은 인터럽트가 발생할 시점에 정상적으로 setting됩니다. 이를 이용해 소프트웨어적으로 처리하고자 할 때 이처럼 인터럽트 설정만 하고 enable 시키지는 않는 형태로 사용할 수 있다. 자세한 내용은 뒤에서 계속 이어집니다.

82 line:

    //
    // Configure Timer to trigger ADC
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    TimerConfigure( TIMER0_BASE, TIMER_CFG_32_BIT_PER );
    TimerControlTrigger(TIMER0_BASE, TIMER_A, true);
    TimerLoadSet( TIMER0_BASE, TIMER_A, SysCtlClockGet() / 2 );     // 2Hz trigger
    TimerEnable( TIMER0_BASE, TIMER_A );

앞에서 ADC 시퀀스 설정을 할 때 트리거 이벤트로 타이머를 지정하였습니다. 즉 타이머를 원하는 주기로 설정해 두면 그 주기에 맞춰 자동으로 ADC가 수행되는 것입니다. 본 예제에서는 2Hz로 타이머를 설정했습니다. [timer 예제](예제 timer)에서와 동일한 방법으로 타이머를 설정합니다. 한가지 차이점이 있다면 새 번째 줄의 **TimerControlTrigger()**함수 입니다. 이 함수를 통해 이 타이머는 ADC 트리거용으로 사용되는 것임을 알려주게 됩니다. 이렇게 설정해 두면 타이머 이벤트가 발생할 때 마다 별다른 조작 필요 없이 자동으로 ADC가 시작되고, ADC가 다 끝나면 ADC 인터럽트가 발생하게 됩니다.

99 line:

        while(!ADCIntStatus(ADC_BASE, 0, false));
        ADCIntClear(ADC_BASE, 0);
        cnt = ADCSequenceDataGet(ADC_BASE, 0, adc_result);      // Read ADC result
        if (cnt == 1)
        {
            // Calculate temperature
            temperature = (2.7 - (float)adc_result[0] * 3.0 / 1024.) * 75. - 55.;

            printf("%d, %.1f[degC]\r\n", adc_result[0], temperature);
        }

99 line의 while 루프는 ADC가 완료될 때 까지 기다리기 위함 입니다. ADC 인터럽트를 enable 시키지 않았지만 ADC가 완료되었을 때 인터럽트 flag는 정상적으로 setting됩니다.

ADC가 완료되면 **ADCSequenceDataGet()**함수를 이용해 결과를 받아옵니다. 받아온 결과는 LM3S8962의 데이터시트를 참조하여 섭씨 온도로 계산한 다음 이를 printf()를 사용해 출력합니다.

타이머를 2Hz 주기로 설정했으므로 0.5초 간격으로 ADC 결과 메시지가 출력되게 됩니다.

실행 방법 안내

  1. 펌웨어를 빌드하여 보드에 다운로드 한 다음 리셋 버튼을 1회 누릅니다.
  2. PC에서 ComPortMaster로 시리얼 포트를 open합니다. 이때 baudrate는 115200bps 입니다.
  3. ComPortMaster의 수신창에 0.5초 마다 새로운 메시지가 출력되는 것을 확인합니다. 측정된 온도는 MCU 코어 온도이므로 3~40도 정도의 높은 온도가 표시되는 것이 정상입니다.
  4. 측정 도중 보드의 MCU 칩을 엄지손가락으로 지긋이 눌러주면 상대적으로 온도가 낮은 손가락 피부에 의해 코어가 냉각되면서 출력되는 온도 역시 낮아지는 것을 확인할 수 있습니다.