A/D 컨버터(Analog Digital Converter)

 AT91SAM7S256은 8채널 10비트 또는 8비트 분해능의 축자비교형 A/D 컨버터를 가지고 있다. 각 채널의 입력은 내부의 아날로그 멀티플렉서에 의하여 선택되며, 이들 8채널의 아날로그 입력신호 중에서 AD0~AD3은 병렬 I/O 포트와 겸용으로 사용하고 있고, AD4~AD7은 전용핀을 가지고 있다.

 A/D 컨버터에서 사용하는 클럭의 주파수는 ADC_MR 레지스터의 PRESCAL 필드에 의하여 MCK/2/(PRESCAL+1)로 결정되므로 MCK/2 ~ MCK/128의 범위가 된다. 10비트 분해능을 사용할 때는 A/D 클럭으로 5MHz 이하를 사용해야 하며, 8비트 분해능을 사용할 때는 A/D 클럭으로 8MHz 이하를 사용해야 한다.
 각 채널에서 10비트 또는 8비트 분해능으로 A/D 변환을 수행하는데는 ADC_MR 레지스터에서 SHTIM 필드로 지정한 샘플/홀드에 필요한 클럭 주기와 10주기의 A/D 변환 클럭 사이클이 소요 된다. 샘플/홀드 시간은 최소 600ns 이상이 필요하다.
ex) 10비트 분해능 5MHz 클럭에서 최소 3주기의 샘플/홀드 시간과 10주기의 A/D 변환 시간이 소요  
      : 최대 384kSPS(sampling/sec)
       8비트 분해능 8MHz 클럭에서 최소 5주기의 샘플/홀드 시간과 10주기의 A/D 변환 시간이 소요  
      : 최대 533kSPS(sampling/sec)

 A/D 컨버터에는 외부 단자 ADVREF를 통하여 기준전압이 공급되어야 한다. 이 기준전압은 2.6V ~ VDDIN의 범위를 가져야 하며, 이에 따라 각 채널에서의 아날로그 신호 입력의 범위는 0.0V ~ ADVREF로 결정된다.

 8비트 분해능을 사용할 경우에는 이중에서 하위 8비트만 유효하며 사용하지 않는 상위 2비트는 0으로 읽혀진다.

 A/D 컨버터가 변환을 완료하면 상태 레지스터 ADC_SR 에서 EOCx 비트와 DRDY 비트가 1로 세트된다. 사용자 프로그램으로 ADC_CDRx 레지스터를 읽으면 EOCx 비트는 0으로 클리어되며, ADC_LCDR 레지스터를 읽으면 EOCx 비트와 DRDY 비트가 모두 0으로 클리어 된다.

 새로운 A/D 변환이 왼료될 때까지 ADC_CDRx 레지스터에 저장되어 있는 이전의 A/D 변환 결과를 읽지 않으면 오버런 에러가 되고 ADC_SR 레지스터에서 대응하는 채널의 OVREx 비트가 세트된다. 마찬가지로 ADC_LCDR 레지스터를 읽지 않아 오버런 에러가 발생하면 ADC_SR 레지스터에서 GOVRE 비트가 세트된다. 이들 에러 비트는 ADC_SR 레지스터를 읽으면 자동으로 클리어된다.

 A/D 변환 트리거는 여러 개의 채널을 사용하더라도 오직 1번만을 필요로 한다. 즉 A/D 변환을 시작하도록 트리거하면 동작이 허용된 모든 채널에서 A/D 변환이 시작된다.

 A/D 컨버터를 슬립 모드로 하면 클럭의 공급을 차단하고 동작을 저지시킴으로써 소비전력을 크게 절약할 수 있다. A/D 컨버터가 슬립 모드에 있더라도 A/D 컨버터 내부의 로직 회로는 정상으로 동작하여 모든 I/O 레지스터의 액세스가 가능하다.

 // ADC 예제 소스
#include "MyArm.h"

//--------- Global Variable�

void Delayms(unsigned int ms) //Delay Function..

  volatile unsigned int count, countmax = (MASTERCLOCK / 10000) * ms;

  for(count = 0; count < countmax; count++);
}

void DBGU_write(char *d)
{
  while(0 != *d)
  {
    while(0 == (DBGU_SR & 0x0002));
    DBGU_THR = *d;
    ++d;
  }
}

void intToChar(char *buf, unsigned int num)
{
  int i, j;
  int target;    // 각 자리수
  int value = 1;  // 숫자 크기 확인
  
  while(value <= num)
  {
    value *= 10;
  }  
  
  for(i = 0, j = value/10 ; j >= 10 ; j /= 10)
  {
    target = num / j;
    num = num % j;
    buf[i++] = target + 48;    // buf에 문자값 저장
  }
  buf[i++] = num + 48;
  buf[i] = '\0';
}

int main(void)
{  
  unsigned int data;
  unsigned int tmp;
  char buf[10];
  
  DBGU_CR = (1 << P2) | (1 << P3);  // TX,RX reset & disable
  
  // PMC setting
  PMC_PCER = (1 << PID4);

  // PIO setting
  PIO_PDR = (1 << P10);
  PIO_ASR = (1 << P10);
  
  // DBGU setting
  DBGU_MR = (1 << P11);        // No Parity
  DBGU_BRGR = 313;          // Baud rate = 9600
  DBGU_CR = (1 << P6);        // TX enable
  
  // ADC setting
  ADC_MR = (23 << P8) | (1 << P4) | (1 << P24);  // PRESCAL = 23(1Mhz), 8 bit Low Resolution, SHTIM = 1
  ADC_CHER = (1 << P4);              // Channel 4

  while(1)
  {
    ADC_CR = (1 << P1);            // Start Conversion
    while(0 == (ADC_SR & (1 << P16)));
    data = ADC_LCDR;
    intToChar(buf, data);
    DBGU_write(buf);
    DBGU_write("\r\n");
    Delayms(50);
    tmp = ADC_SR;
  }
  
  return 0;
// End Main...
// 변환 값 입력에 가변저항을 연결하여 저항을 바꿔가면서 입력값에 변화를 준다.
// 이때 입력된 아날로그 신호에 대응하는 변환된 디지털 값들을 시리얼 통신을 이용하여 PC의 터미널에 보여준다.
// ADC_CR 에 START 비트는 변환할 때마다 1로 세트 해주어야 한다.

+ Recent posts