390 likes | 709 Views
KT-M128 Peripheral Device. ADC 2010. 8. 10 조 승훈. Reference: AVR ATmega128 정복 , ohm 사 Atmega128 Datasheet, Atmel 사. INDEX. Overview 관련 레지스터 Clock 의 선택 Timing A/D 변환 결과 및 오차 잡음 제거 방법 Source Code. Overview. 실생활에서 연속적으로 측정되는 신호를 (Analog) 프로세서가 읽을 수 있도록 디지털 신호로 변환해주는 장치. V. V.
E N D
KT-M128 Peripheral Device ADC 2010. 8. 10 조 승훈 Reference: AVR ATmega128 정복, ohm사 Atmega128 Datasheet, Atmel사
INDEX • Overview • 관련 레지스터 • Clock의 선택 • Timing • A/D 변환 결과 및 오차 • 잡음 제거 방법 • Source Code
Overview • 실생활에서 연속적으로 측정되는 신호를 (Analog) 프로세서가 읽을 수 있도록 디지털 신호로 변환해주는 장치 V V 변환 Digital signal Analog signal t 연속적인 전압신호 이산적인 전압신호 t 0 0
Overview • ADC의 종류 • 적분 방식 : 저속으로 변환 • 전압 시간 변환형 • 이중 적분형 • 전압 주파수 변환형 • 비교 방식 : 적분 방식에 비해 고속으로 변환 • 축차 비교형 (연속 근사형) • 추종 비교형 • 병렬 비교형
Overview • 적분 방식 ADC • 전압 시간 변환형 • 기준 신호를 적분한 것과 샘플링 된 입력 전압을 비교 • 입력전압의 크기에 비례하는 계수 시간을 결정 • 그 시간 동안 기준 펄스의 수를 계수하여 변환 • 비교적 간단 • 빠른 속도와 높은 정확도를 기대하기 힘듦 • 이중 적분형 • 샘플링 된 +의 입력 전압을 미리 설정 된 일정한 시간동안 적분 • 적분 된 값을 초기값으로 –의 기준 신호를 적분한 값이 0에 도달 할 때까지 기준 펄스의 수를 계수하여 변환 • 전압 시간 변환형보다는 안정되어 있음 • 디지털 전압계 등에 많이 활용 됨
Overview • 비교 방식 ADC • 축차 비교형 (연속 근사형) : Successive Approximation ADC • 샘플링 회로, D/C 변환기, 연속근사 레지스터, 비교기로 구성 • MSB를 1로 설정 • 입력 신호와 비교하여 MSB를 경정하기 시작 • 계속해서 다음 상위 bit를 결정 • nbit의 경우 n번의 비교로 변환 완료 • 변환 시간이 100us 이하 • 일반적인 응용에 널리 사용 • 내셔날 세미 컨덕터사의 ADC08 시리즈가 8bit 축자형 ADC의 대표적 임 축차 비교형 ADC Block Diagram SAR Logic Flow
Overview • A/D 변환 과정 • 전처리: 아날로그 신호에 포함 된 잡음 제거, 신호의 대역폭을 제한하여 Aliasing을 감소 시킴 • 표본화: 신호에 포함 된 최고 주파수 성분 주기의 ½보다 작은 주기로신호 값을 취하여 저장 • 양자화: 표본화 된 값을 소구간으로 분할하여 유한한 단계의 유한한 자리수를 갖는 불연속적인 대표값에 할당 • 표본화 된 아날로그 신호는 연속적인 양이기 때문에 이진화하면 무한한 자리수를 요구 할 수 있음 • 양자화 단계의 개수가 많으면 실제 값과 대표 값의 차인 양자화 오차 감소하지만디지털 출력의 비트 수 중가, 이를 처리하기 위한 시간 및 장치를 요구 • 부호화: 양자화 된 값에 2진 디지털 코드를 부여
Overview • Sampling [표본화] • 아날로그 신호를 일정주기로 추출하는 과정 연속 시간 -> 이산 시간 V 40 38 37 34 28 26 20 15 t V 4 5 6 7 8 1 2 3 0 t 0 V 40 38 38 37 37 35 34 34 30 30 Sampling 을 많이할수록 더욱 정확한 디지탈변환값을 얻을 수 있다. 29 24 24 22 18 18 15 15 t 14 1 1.5 2 2.5 3 3.5 4 4.5 5 5.5 6 6.5 7 7.5 8 8.5 9 0.5 0
Overview • Quantizing [양자화] • 표본화된 각각의 신호를 대표 값으로 변환하는 과정 연속적인 신호의 크기 -> 이산적인 신호의 크기 분해능이 클수록 표현할 수 있는 크기가 세밀해진다.
Overview • Atmega128의 ADC • 8 채널 • 10bit 분해능 • 축자비교형 • 내부 아날로그 멀티플렉서 탑재 • 샘플 / 홀드 회로 탑재 • A/D 동작 중 전압 고정화 • 단극성 아날로그 입력 / 차동 입력 선택 가능 • 차동입력에서 10배~200배의 증폭 A/D 가능 • PortF는 아날로그 비교기 기능으로 사용 가능 • 0~VREF범위의 전압 입력 (VREF는 VCC를 초과 할 수 없음) • 변환 시간 (13us ~ 260us – 50kHz ~ 200kHz)
Overview PORT F PORT A PORT E PORT C PORT B PORT D
아날로그 전원 단자 PRESCALER의 출력 주파수의 반을 넘어서는 안됨 (나이퀴스트의 정리) 내부 기준 전압 외부 기준 전압 8채널 10bit, 아날로그 입력 단자, Portf의 특수기능
Overview • ADC의 동작 순서 • ADC 활성화(ADEN=1) • ADC 클럭설정(ADPS 2~0) • ADC 기준전압설정(REF 1~0) • ADC 입력채널설정(MUX 4~0) • ADC 동작모드설정(ADFR) • ADC 변환 완료 인터럽트 활성화(ADIE) A/D 컨버터 초기화 설정 A/D 변환 완료 인터럽트 요청 A/D 컨버터 스타트 (ADC 시작신호:ADSC) ADC 상태플래그 셋 (AIDF = 1) A/D 변환 ADC 다음 동작 결정 (단일/연속동작) A/D 변환 완료 (변환값을 ADCH/L에 저장)
Overview • 신호 입력 방법 • 단극성 아날로그 입력 (Single ended) • GND와 입력 신호 간의 차이를 변환 • VREF : 2.0V ~ AVCC • 아날로그 입력 전압의 범위 : GND ~ VREF • 차동 아날로그 입력 (Differential) • -입력 신호부터 +입력 신호 간의 차이를 변환 • 이 때, ADC 단자 중 두 개를 이용하여 한 쪽은 -, 한 쪽은 +신호를 입력 • VREF : 2.0V ~ AVCC – 0.5 • 아날로그 입력 전압의 범위 : GND ~ VCC
관련 레지스터 • ADCSRA (ADC Control & Status Register A) • Bit 7 (ADEN, ADC Enable) • 1 : ADC의 모든 동작 Enable • 0 : ADC의 모든 동작 Disable • Bit 6 (ADSC, ADC Start Conversion) • 1 : ADC 변환 시작, Free-Running Mode에서는 자동으로 반복 • Bit 5 (ADFR, ADC Free-Running Select) • 1 : ADC를 Free-Running Mode로 설정 (임의의 시간에 Data Read 가능)
관련 레지스터 • ADCSRA (ADC Control & Status Register A) • Bit 4 (ADIF, ADC Interrupt Flag) • A/D 변환이 완료되어 ADCH/ADCL 레지스터 값이 갱신되면 1로 Set • 이후, 변환완료 인터럽트 요청 • Bit 3(ADIE)과 SREG의 Bit 8이 1로 Set되어 있어야 함 • Bit 3 (ADIE, ADC Interrupt Enable) • A/D 변환완료 인터럽트를 개별적으로 허용 • Bit 2-0 (ADPS2-0, ADC Prescaler Select Bit) • ADC에 인가되는 Clock의 분주비를 선택 • 우측 표 참고
관련 레지스터 • ADMUX (ADC Multiplexer Selection Register) • Bit 7-6 (REFS1-0, Reference Selection Bit) • ADC에서 사용하는 기준전압 선택 • 우측 표 참고 • Bit 5 (ADLAR, ADC Left Adjust Result) • 1 : ADCH / ADCL 레지스터의 데이터가 좌측 정렬 • 0 : ADCH / ADCL 레지스터의 데이터가 우측 정렬 • Bit 4-0 (MUX4-0, Analog Channel & Gain Selection Bit) • ADC의 아날로그 입력 채널 선택 (8가지의 단극성 입력, 22가지의 차동입력) • 차동입력은 다시 4가지로 나뉨 • ADC1 – ADC0 단자 사이의 차동 입력 (Gain 10 or 200) • ADC3 – ADC2 단자 사이의 차동 입력 (Gain 10 or 200) • ADC1 단자를 기준으로 한 8가지의 차동 입력 • ADC2 단자를 기준으로 한 6사지의 차동 입력
관련 레지스터 • ADCH / ADCL (ADC Data Register) • A/D 변환의 결과를 저장 • 단극성 입력 : 10bit 양의 정수로 표시 (0 ~ 1023) • 차동 입력 : 10bit 2의 보수로 표현 (-512 ~ +511) • 좌측 정렬은 하위 2bit를 잘라내고 8bit로 사용하고 싶을 때 유리
Clock의 선택 • System Clock을 Prescalar로 분주하여 공급 • ADCSRA 레지스터의 ADPS2-0Bit를 이용하여 분주비 선택 가능 • Prescalar는 ADCSRA 레지스터의 ADEN bit를 1로 Set해야만 동작 • 단극성 입력 • 50kHz ~ 1000kHz 범위의 클록 사용 • 차동 입력 • 50kHz ~ 200kHz 범위의 클록 사용
A/D 변환 결과 • 단극성 입력 채널 • 10bit 양의 정수 표현법 사용 • 0(0x0000) ~ 1023(0x03FF) 범위의 값을 가짐 • 0x0000 = 아날로그 입력전압이 접지(0V)와 같음을 나타냄 • 0x03FF = 아날로그 입력전압이 VREF보다 1LSB 낮은 값임을 나타냄 멀티플렉서로 선택 된 단극성 아놀로그 입력 전압 ADC 결과 레지스터 (ADCH : ADCL) 선택 된 기준 전압
A/D 변환 결과 • 차동 입력 채널 • 10bit 2의 보수 표현법 사용 • -512 (0x0200) ~ +511(0x01FF) 범위의 값을 가짐 • GAIN이 1인 경우, 0x0000 = 차동 입력 전압이 0V임을 나타냄 • 0x01FF = 차동 입력 전압이 VREF보다 1LSB 낮음 • 0x0200 = 차동 입력 전압이 –VREF와 같음 멀티플렉서로 선택된 차동 아날로그 입력의 양극성 단자 전압 멀티플렉서로 선택된 차동 아날로그 입력의 음극성 단자 전압 아날로그 전압의 이득 1, 10, 200 중 하나 ADC 결과 레지스터 (ADCH : ADCL) 선택 된 기준 전압
A/D 변환 오차 • 양자화 오차 (Quantization Error) • 아날로그 값을 디지털 값으로 변환하면서 생기는 변환의 한계 • 대처 방안 : 분해능이 높은 ADC 사용으로 극복 • 오프셋 오차 (Offset Error) • 변환 결과가 이상적인 디지털 값에서 일정한 양만큼 벗어난 상태 • 대처 방안 : 변환된 디지털 값에 일정한 값을 더하거나 빼서 교정 • 이득 오차 (Gain Error) • 변환 결과가 이상적인 디지털 값에서 일정한 양만큼 벗어난 상태 • 대처 방안 : 변환된 디지털 값에 일정치 값을 곱하거나 나누어서 교정
A/D 변환 오차 • 비선형 오차 (Integral non-linearity Error) • 변환 결과가 교정 될 수 없는 상태 • 대처 방안 : 없음 • 차동 비선형 오차 (Differential non-linearity Error) • 변환 결과가 교정 될 수 없는 상태 • 대처 방안 : 없음
잡음 제거 방법 • ADC의 아날로그 입력은 최소한으로 짧게 함 • 아날로그 전원 단자 AVCC에는 디지털 전원 VCC를 LC 필터로 안정화시켜 인가하는 것이 좋음 • ADC 근처에서는 접지 단자 GND와 디지털 전원 VCC 사이에도 충분한 바이패스 콘덴서를 달아 줌 • A/D 변환이 수행되는 동안에는 병렬 I/O Port의 논리 상태를 스위칭하지 않는 것이 좋음 • 잡음에 대해 극도로 안정적인 A/D 변환이 필요한 경우에는 Idle Mode 또는 ADC Noise Reduction Mode에서 A/D 변환을 수행하는 것도 권장 됨 • A/D 변환 결과가 잡음 등에 의하여 흔들리는 경우, 디지털 필터를 사용하거나 여러 번 A/D 변환 결과를 읽어 들인 것을 평균처리 하는 것이 좋음
잡음 제거 방법 • VCC를 LC 필터로 안정화시켜, AVCC에인가하는 회로 • L = 10uH, C = 0.1uF 정도가 무난
아날로그 전원 단자 = 내부 전압 = 기준 전압 = 5V Sampling 10bit Resolution = 최대 15Ksps의 Sampling Rate 15000 / 4 = 3750 sampling/sec
ADC Source Code #define F_CPU 16000000 //Clock Frequency : to use util/delay.h #define EX_SS_DATA (*(volatile unsigned char *)0x8002) //7seg data #define EX_SS_SEL (*(volatile unsigned char *)0x8003) //7seg digit #define EX_SS_SW (*(volatile unsigned char *)0x0036) //Switch #define led_out (*(volatile unsigned char *)0x8008) //LED #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> const char segment_data[10] = {63, 6,91,79,102,109,125,39,127,103}; // 0 to 9 unsigned char display_num[4]={0,0,0,0}; //7segment digit unsigned char digit_num=0; void port_init(void) { PORTA = 0x00; DDRA = 0xFF; //1출력 0입력 to 7segment PORTB = 0x00; DDRB = 0x00; //Input from Switch PORTC = 0x00; DDRC = 0x0F; //Low 8bit output to 7segment PORTD = 0x00; DDRD = 0x0F; //Output to LED PORTE = 0x00; DDRE = 0x00; PORTF = 0x00; DDRF = 0x00; //Input from ADC PORTG = 0x00; DDRG = 0x00; } // TIMER0 initialize : prescale:64 // WGM: Normal Mode // desired Clock : 1KHz // actual value : 1ms void timer0_init(void) { ASSR = 0x00; //set async mode TCNT0 = 0x06; //set count for 6 to 255 OCR0 = 0x00; //ignore TCCR0 = 0x04; //prescale 64 } //call this routine to initialize all peripherals void init_devices(void) { //stop errant interrupts until set up asm("cli"); //disable all interrupts port_init(); adc_init(); timer0_init(); MCUCR = 0x80; //enable interrupt TIMSK = 0x01; //timer interrupt sources (MASK) T/C0 Ovf flag asm("sei"); //re-enable interrupts //all peripherals are now initialized }
ADC Source Code /********************************************************************* // ADCSRA // Bit 7 : ADEN - ADc ENable // Bit 6 : ADSC - ADc Start Conversion // Bit 5 : ADFR - ADc Free-Running selection // Bit 4 : ADIF - ADc Interrupt Flag // Bit 3 : ADIE - ADc Interrupt Enable // Bit 2 : ADPS - ADc Prescaler Select // Bit 0 : 2 to 0 // ADMUX // Bit 7 : REFS - Reference Selection (01 - Ext. AVCC) // Bit 6 : 7 to 6 // Bit 5 : ADLAR - ADc Left Adjust Result // Bit 4 : MUX - Analog Channel and Gain Selection (default 00xxx) // Bit 0 : 4 to 0 **********************************************************************/ void adc_init(void) { ADCSRA = 0x00; //disable adc ADMUX = 0x00; //select adc input 0 ACSR = 0x80; //set Analog Comparator disable ADCSRA = 0xC6; //set 1100_0110 } void startConvertion(unsigned char ch) { // 011_000xx ADMUX = 0x60 | ch; //Channel Selection ( 0 to 3) ADCSRA = ADCSRA | 0xc0; //Enable ADC & Start ADC } unsigned char readConvertData(void) { volatile unsigned char temp = 0; while((ADCSRA & 0x10)==0); //wait ADC Complete INT temp = ADCL; //ignore Lower 2-bit temp = ADCH; //get Upper 8-bit ADCSRA = ADCSRA | 0x10; //INT clear return temp; } // Timer0 Overflow Interrupt Service Routine for 7Segment Digit Display ISR(TIMER0_OVF_vect) { TCNT0 = 0x06; //reload counter value digit_num++; digit_num = digit_num % 4; //get Digit Selection Number EX_SS_DATA = segment_data[display_num[digit_num]]; //get segment data EX_SS_SEL = ~(0x01 << digit_num); //Digit Selection } 16000000 / 64 = 250kHz
ADC Source Code int main() { volatile unsigned char adc_value; //ADC Result Value volatile unsigned char sw; //Switch Value init_devices(); EX_SS_SW = 0; //sw 0 : Variable Register //sw 1 : IR Sensor //sw 2 : Temp Sensor //sw 3 : CDS Sensor while(1) { if(EX_SS_SW & 0xF) { //Check SW Button switch(EX_SS_SW) //Convert SW to ADC { case 1: sw = 0; break; case 2: sw = 1; break; case 4: sw = 2; break; case 8: sw = 3; break; } led_out = EX_SS_SW; //Display to LED } //while(EX_SS_SW & 0xFF); //Post Channeling startConvertion(sw); //sw is ADC input Channel adc_value = readConvertData(); display_num[0] = (adc_value % 10000) / 1000; display_num[1] = (adc_value % 1000) / 100; display_num[2] = (adc_value % 100) / 10; display_num[3] = (adc_value % 10); _delay_ms(1000); } return 0; } 0 1 2 3