Skip to content
irmusy edited this page Oct 1, 2013 · 2 revisions

개요

adc_2ch는 ADC를 이용하여 아날로그 입력 1 채널과 MCU 내장 온도 센서의 출력 1 채널을 읽어 그 결과를 UART로 출력하는 예제입니다. [adc_temperature 예제](예제 adc_temperature)와 다른 점은 2개 채널로 구성된 시퀀스를 사용한다는 점과 ADC 인터럽트를 사용하는 점이 있습니다.

본 예제는 ADC0 핀의 아날로그 입력을 읽어 출력합니다. 실험을 위해서는 ADC0 핀에 외부에서 0~3V 범위의 전압을 인가하거나 가변저항을 이용해 전압을 만들어 넣어야 합니다. [myMCU-EXP rev.B 보드](myMCU-EXP rev.B)가 있다면 내장된 가변저항이 ADC0 핀에 바로 연결되어 있어 간단하게 실험하실 수 있습니다.

관련 Peripheral

  • SysCtl
  • ADC
  • UART(llio)

소스 살펴보기

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

57 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 코어 온도가 더 높아집니다. 이는 소비전력이 늘어나기 때문이며, 소스 코드를 수정해서 직접 확인해 보실 수 있습니다.

76 line:

    // ADC sequence #0 - setup with 2 conversions
    ADCSequenceDisable(ADC_BASE, 0);
    ADCSequenceConfigure(ADC_BASE, 0, ADC_TRIGGER_TIMER, 0);
    ADCIntRegister(ADC_BASE, 0, ADCIntHandler);
    ADCIntEnable(ADC_BASE, 0);

    // sequence step 0 - channel 0
    ADCSequenceStepConfigure(ADC_BASE, 0, 0, ADC_CTL_CH0);
    // sequence step 1 - internal temperature sensor. Generate Interrupt & End of Sequence
    ADCSequenceStepConfigure(ADC_BASE, 0, 1, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END);

    ADCSequenceEnable(ADC_BASE, 0);

ADC 시퀀스를 설정하고 있습니다. 0번 시퀀스에 ADC_CTL_CH0와 ADC_CTL_TS을 각각 0번, 1번 채널로 지정하였습니다. ADC_CTL_TS 직후에는 인터럽트를 발생시키고 시퀀스가 종료되게끔 하였습니다.

[adc_temperature 예제](예제 adc_temperature)와 달리 ADC 인터럽트 핸들러를 등록하고 ADC 인터럽트를 enable 하는 코드도 포함되어 있습니다.

106 line:

        cnt = ADCSequenceDataGet(ADC_BASE, 0, adc_result);
        if (cnt == 2)
        {
            // Calculate temperature
            temperature = (2.7 - (float)adc_result[1] * 3.0 / 1024.) * 75. - 55.;

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

**SysCtlSleep()**함수는 sleep 모드로 전환하는 함수입니다. 이 함수를 만나면 더이상 진행하지 않고 그 지점에서 sleep하게 됩니다. 이때 인터럽트가 발생하면 다시 sleep에서 깨어나게 됩니다.

Sleep에서 깨어났다는 것은 인터럽트가 발생했다는 의미이므로 그때 **ADCSequenceDataGet()**을 사용해 ADC 결과를 읽어옵니다. 만일 ADC 인터럽트가 아닌 다른 인터럽트에 의해 sleep에서 깨어난 것일 수도 있습니다. 그런 경우에는 ADCSequenceDataGe() 리턴 값이 시퀀스 내 채널 개수인 2가 아닌 다른 값을 가지고 있을 것입니다.

118 line:

static void ADCIntHandler(void)
{
    ADCIntClear(ADC_BASE, 0);
}

ADC 인터럽트 핸들러입니다. 이 인터럽트 핸들러에서는 ADC 인터럽트 flag만 clear 해줄 뿐 다른 일을 하지 않습니다. ADC 결과를 읽어 계산하고 출력하는 일은 main()함수의 while 루프 내에서 처리하고 있습니다.

실행 방법 안내

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