AT91SAM7S256은 8채널 10비트 또는 8비트 분해능(정밀한 높이측정)의 축차비교형(변환이 끝남) A/D 컨터버를 가지고 있다.
8bit와 10bit 비교
|
8bit |
10bit |
번지수 |
(0~255) |
(0~1023) |
장 점 |
256까지 세니까 빠르다 |
1024까지 있어 세밀하다 |
전 압 |
3.3/256 = 0.01289.. => 12.89 |
3.3/1024 = 0.00322.. => 3.22 |
이들 8채널의 아날로그 입력신호 중 AD0~AD3은 병렬 I/O포트와 겸용으로 사용하고, AD4~AD7은 전용이다.
A/D 변환이 가능한 아날로그 입력전압의 범위는 0~ADVREF(AD:아날로그디지털, V:전압, REF:기준전압)이며, 변환은 10비트모드 또는 8비트모드를 사용할 수 있다.
A/D 변환된 디지털 데이터는 각 채널에 내장된 전용의 데이터 레지스터 ADC_CDRx(x->0~7번까지)에 저장되며 모든채널에 공통인 데이터 레지스터 ADC_LCDR(1개)에도 저장된다.
A/D 컨버터에서 사용하는 클록의 주파수는 ADC_MR 레지스터의 PRESCAL 필드에 의하여 MCK/2/(PRESCAL+1)로 결정되므로 MCK/2~MCK/128의 범위가 된다.
10비트 분해능을 사용할 때는 A/D 클록으로 5MHz(10bit최대) 이하를 사용해야 하며, 8비트 분해능을 사용할 때는 A/D 클록으로 8MHz(8bit최대) 이하를 사용해야 한다.
ADC클록 주파수 = MCK/(PRESCAL+1)*2
예) 10비트일때 ADC클록은 5이하여야 하니
5 = 48/(x+1)*2 x = 5이면 ADC클록이 4가 되므로 만족한다.
그래서 ADC_MR = (5<<PRESCAL) 이렇게 나타낸다.
빛센서를 이용해 결과를 알아보기
ADC클록 주파수 = MCK/(PRESCAL+1)*2
예) 10비트일때 ADC클록은 5이하여야 하니
5 = 48/(x+1)*2 x = 5이면 ADC클록이 4가 되므로 만족한다.
그래서 ADC_MR = (5<<PRESCAL) 이렇게 나타낸다.
빛센서를 이용해 결과를 알아보기
ADC.h
#ifndef __ADC_H__
#define __ADC_H__
//#include "pio.h"
#include "pmc.h"
#include "lcd.h"
#define ADC_CR (*((volatile unsigned int *)0xFFFD8000))
//제어 레지스터
#define ADC_MR (*((volatile unsigned int *)0xFFFD8004))
//모드 레지스터
#define ADC_SR (*((volatile unsigned int *)0xFFFD801C))
//상태 레지스터
#define ADC_CHER (*((volatile unsigned int *)0xFFFD8010))
//채널허용 레지스터
#define ADC_LCDR (*((volatile unsigned int *)0xFFFD8020))
//모든채널 공통 데이터 레지스터
#define ADC_CDR (((volatile unsigned int *)0xFFFD8030))
//전용의 데이터 레지스터의 주소, 배열로 해당채널을 정할 거라 *를 빼버림
#define ADC 4 //PID4
#define START 1 //A/D 변환시작
#define SWRST 0 //리셋
#define ADC_CDR7 7 //7번핀
#define PRESCAL 8 //8번핀
#define TRGEN 0 //트리거 활성핀
#define TRGSEL 1 //트리거 선택
#define LOWRES 4 //분해능 설정(0 = 10비트,1 = 8비트)
#define SLEEP 5 //슬립모드(0 = 정상모드,1 = 슬립모드)
#define EOC7 7
void ADC_init(void);
unsigned char * ADC_run7();
#endif //__ADC_H__
#ifndef __ADC_H__
#define __ADC_H__
//#include "pio.h"
#include "pmc.h"
#include "lcd.h"
#define ADC_CR (*((volatile unsigned int *)0xFFFD8000))
//제어 레지스터
#define ADC_MR (*((volatile unsigned int *)0xFFFD8004))
//모드 레지스터
#define ADC_SR (*((volatile unsigned int *)0xFFFD801C))
//상태 레지스터
#define ADC_CHER (*((volatile unsigned int *)0xFFFD8010))
//채널허용 레지스터
#define ADC_LCDR (*((volatile unsigned int *)0xFFFD8020))
//모든채널 공통 데이터 레지스터
#define ADC_CDR (((volatile unsigned int *)0xFFFD8030))
//전용의 데이터 레지스터의 주소, 배열로 해당채널을 정할 거라 *를 빼버림
#define ADC 4 //PID4
#define START 1 //A/D 변환시작
#define SWRST 0 //리셋
#define ADC_CDR7 7 //7번핀
#define PRESCAL 8 //8번핀
#define TRGEN 0 //트리거 활성핀
#define TRGSEL 1 //트리거 선택
#define LOWRES 4 //분해능 설정(0 = 10비트,1 = 8비트)
#define SLEEP 5 //슬립모드(0 = 정상모드,1 = 슬립모드)
#define EOC7 7
void ADC_init(void);
unsigned char * ADC_run7();
#endif //__ADC_H__
ADC.c
#include "adc.h"
void ADC_init(void)
{
PMC_PCER = 1<<ADC; //주변장치 클록 허용 레지스터(1<<4);,ADC => PID4
ADC_CR = 1<<SWRST; //제어 레지스터에 리셋
ADC_CHER = 1<<ADC_CDR7; //7번핀을 활성화
ADC_MR = (5<<PRESCAL) |(0<<LOWRES);
//MCK가 5MHz이하 (4로 게산 ) 4 = 48(5+1)*2 그래서 5를 넣음
return;
}
unsigned char * ADC_run7()
{
static unsigned int uiResult;
static unsigned char ucBuf[] = "0000\n\r"; //0~1023
ADC_CR = 1<<START; //제어 레지스터에 스타트(전압이 들어왔다는 가정하에)
// 컨버팅완료까지 대기코드가 들어가야 한다. (0이면 7번채널 금지거나 A/D변환이 미완료)
while(0==(ADC_SR&(1<<EOC7))); //폴링 (A/D변환 중...)
uiResult = ADC_CDR[7]; //ADC_CDR 주소를 배열로 (7번채널에 새로운 A/D변환이 된 데이타 레지스터에 값을 결과로 저장)
ucBuf[0] = '0'+(uiResult%10000)/1000; //1000단위
ucBuf[1] = '0'+(uiResult%1000)/100; //100단위
ucBuf[2] = '0'+(uiResult%100)/10; //10단위
ucBuf[3] = '0'+(uiResult%10); // 1단위
LCD_Inst(LCD_CD); //lcd화면 클리어
LCD_Data('0'+(uiResult%10000)/1000);
LCD_Data('0'+(uiResult%1000)/100);
LCD_Data('0'+(uiResult%100)/10);
LCD_Data('0'+(uiResult%10));
return ucBuf;
}
#include "adc.h"
void ADC_init(void)
{
PMC_PCER = 1<<ADC; //주변장치 클록 허용 레지스터(1<<4);,ADC => PID4
ADC_CR = 1<<SWRST; //제어 레지스터에 리셋
ADC_CHER = 1<<ADC_CDR7; //7번핀을 활성화
ADC_MR = (5<<PRESCAL) |(0<<LOWRES);
//MCK가 5MHz이하 (4로 게산 ) 4 = 48(5+1)*2 그래서 5를 넣음
return;
}
unsigned char * ADC_run7()
{
static unsigned int uiResult;
static unsigned char ucBuf[] = "0000\n\r"; //0~1023
ADC_CR = 1<<START; //제어 레지스터에 스타트(전압이 들어왔다는 가정하에)
// 컨버팅완료까지 대기코드가 들어가야 한다. (0이면 7번채널 금지거나 A/D변환이 미완료)
while(0==(ADC_SR&(1<<EOC7))); //폴링 (A/D변환 중...)
uiResult = ADC_CDR[7]; //ADC_CDR 주소를 배열로 (7번채널에 새로운 A/D변환이 된 데이타 레지스터에 값을 결과로 저장)
ucBuf[0] = '0'+(uiResult%10000)/1000; //1000단위
ucBuf[1] = '0'+(uiResult%1000)/100; //100단위
ucBuf[2] = '0'+(uiResult%100)/10; //10단위
ucBuf[3] = '0'+(uiResult%10); // 1단위
LCD_Inst(LCD_CD); //lcd화면 클리어
LCD_Data('0'+(uiResult%10000)/1000);
LCD_Data('0'+(uiResult%1000)/100);
LCD_Data('0'+(uiResult%100)/10);
LCD_Data('0'+(uiResult%10));
return ucBuf;
}
빛센서에 휴대폰에 있는 카메라 불빛으로 환하게 비춰보니 1023이란 숫자가 찍혔다.
'디지털회로 > AT91SAM7S256' 카테고리의 다른 글
SPI - 직렬통신 포트 (0) | 2011.09.26 |
---|---|
PWM 제어기 (0) | 2011.09.22 |
초음파 SRF-05 실행시키기 (0) | 2011.09.16 |
오늘 바꾼 TIMER / main 외 ULTRA (0) | 2011.09.09 |
타이머카운터 (0) | 2011.09.08 |