77주차주차AVRAVR의의 A/DA/D변환기변환기 제어제어 레지스터레지스터 및및 관련관련 실습실습
Next-Generation Networks Lab.
3. 관련 레지스터
레지스터 설명
표 9-4
레지스터 설명
ADMUXADC Multiplexer Selection Register
ADMUXADC 의 입력채널 선택 및 기준전압 선택 외
ADCSRAADC Control and Status Register A
ADCSRAADC의 동작을 설정하거나 동작상태를 표시함
ADC Data Register – High ByteADCH
g g y
ADC의 변환 결과를 저장하는 레지스터 중 상위 레지스터
ADC Data Register – Low ByteADCL
ADC Data Register – Low Byte
ADC의 변환 결과를 저장하는 레지스터 중 하위 레지스터
58
ADMUX (ADC Multiplexer Selection Register)
REFS1~REFS0 (Reference Selection) : 기준전압 선택 REFS1~REFS0 (Reference Selection) : 기준전압 선택
ADLAR (ADC Left Adjust Result) : 데이터를 왼쪽 정렬로 저장
MUX4 0은( l MUX l ti ) A/D 변환할 채널 선택과 단극성 또 MUX4~0은(analog MUX selection) A/D 변환할 채널 선택과 단극성 또
는 차동 입력 방식을 선택. 그림 9-16
- Default 설정의 의미- 기준전압은 AREF 전압으로 설정
59
기준전압은 전압 설정- 데이터는 오른쪽 정렬로 저장
표 9-5
60
61
그림 9-18
ADCH
ADCL
ADCL
ADCH
저해상도로 사용할 때 유리함
62
8비트로 사용하면 ADCH만 읽음
ADCSRA (ADC Control and Status Register A)
ADEN (ADC Enable) : ADC 동작
그림 9-17 ADEN (ADC Enable) : ADC 동작
ADSC (ADC Start Conversion) : ADC 변환 시작. 변환 완료 후에 ‘0’로 됨
ADFR (ADC F R i ) F i d 로 설정 ADFR (ADC Free Running) : Free-running mode로 설정
ADIF (ADC Interrupt Flag) : ADC가 완료되면 ‘1’로 세트되면서 인터럽트
를 요청. 인터럽트가 서비스되면 하드웨어적으로 ‘0’으로 설정됨
ADIE (ADC Interrupt Enable) : ADC 인터럽트 서비스를 개별적으로 허용
ADPS2~0 (ADC Prescaler Select) : ADC 변환클럭을 위한 분주비 설정
63
ADCH / ADCL (ADC Data Register – High byte, Low byte)
• ADC 결과 값인 10비트를 저장하는 2개의 8비트 레지스터ADC 결과 값인 10비트를 저장하는 2개의 8비트 레지스터
• 항상 ADCL을 먼저 읽고 후에 ADCH를 읽을 것!
ADC 데이터 변환 결과
• 단극성 입력 채널을 사용하는 경우의 변환 결과• 단극성 입력 채널을 사용하는 경우의 변환 결과
• 차동입력 채널을 사용하는 경우의 변환 결과차동입력 채널을 사용하는 경우의 변환 결과
64
ADC 설정사항 ADMUX 레지스터
기준전압: 입력 신호의 최고 전압
신호 입력 채널
변환된 데이터의 정렬: 처리방식(8비트, 10비트)
ADCSRA 레지스터 ADCSRA 레지스터 Free-running 여부
변환 클럭속도: Prescaler 설정변환 클럭속 설정
인터럽트 활용 여부
65
ADC ADC 초기화초기화 함수함수
void adc_init (INT8 channel) {asm("CLI"); // cli( );asm( CLI ); // cli( );
ADMUX= (0<<REFS1) | (0<<REFS0); // 기준전압ADMUX |= (0<<ADLAR); // 10비트 해상도ADMUX | channel;ADMUX |= channel;
ADCSRA= (1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (1<<ADIE)| (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // 기준 클럭 : 1MHz / 8| (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // 기준 클럭 : 1MHz / 8
asm("SEI"); // sei( ); //SREG |= 0x80;}
비트 설정 동작 비트 설정 동작
REF1:0 00 AREF input ADSC 1 변환 시작REF1:0 00 AREF input ADSC 1 변환 시작
ADLAR 0 우측정렬 ADFR 1 Free-running
MUX4:0 channel 입력선택 ADIE 1 Interrupt 허용
ADEN 1 Enable ADPS2:0 011 Prescaler 8분주
66
예제예제 9.1 9.1 온도센서온도센서
TMP35 온도센서를 활용하여 현재 온도를 측정한다.
TMP35의 출력전압을 ADC의 채널 #0을 통해 A/D 변환한다.
A/D 변환된 10비트 값으로부터 TMP35 출력 전압과 온도를 계산한다.
CPU 클럭주파수: 1MHz 내부 발진기
기준 전압: 외부 AREF 입력 전압
입력 채널: ch #0
해상도: 10비트
온도를 PORTA의 7-segment에 출력한다. 예를 들어, 현재 온도가 28도이면, 2
개의 7-segment에 ‘28’을 출력한다.
67
Port A
CPU Board7-segment(Decoder)
온도센서Port F0
온도센서(TMP35)
68
온도센서온도센서(TMP35) (TMP35) 및및 구동구동 회로도회로도
회로도
1 3
회로도
12
1
2
3
2
3
69
FeaturesFeatures
Calibrated directly in Celsius (Centigrade)
Linear +10 0 mV/C scale factor Linear +10.0 mV/C scale factor
0.5C accuracy guaranteeable (at +25 C)
Rated for full 55 to +150C range Rated for full -55 to +150C range
Suitable for remote applications
L t d t f l l t i i Low cost due to wafer-level trimming
Operates from 4 to 30 volts
70
Temperature vs. Output VoltageTemperature vs. Output Voltage
71
예제예제 99--1 1 ADC (ADC (온도센서온도센서 TMP35) TMP35)
typedef unsigned char INT8;typedef unsigned int INT16;
ISR(ADC_vect) // ADC interrupt function{
read_adc = ADCL;#define F_CPU 1000000UL
#include <avr/io.h>#i l d til/d l h
read_adc += (ADCH<<8);adc_flag = 1;
}#include <util/delay.h>#include <avr/interrupt.h>
#define ADC CH 0 // 입력 채널
void adc_init(INT8 channel) {asm("CLI"); // cli( );
#define ADC_CH 0 // 입력 채널#define TMP35 100 // TMP35 환산//#define REF_VOLTAGE 2.56 // 기준전압//#define REF VOLTAGE 3 3 // 기준전압
ADMUX= (0<<REFS1)|(0<<REFS0); // 기준전압ADMUX |= (0<<ADLAR); // 10비트 해상도ADMUX |= channel;
//#define REF_VOLTAGE 3.3 // 기준전압#define REF_VOLTAGE 5.0 // 기준전압//#define RESOLUTION 256.0 // 8비트#define RESOLUTION 1024 0 // 10비트
// ADMUX = 0b0000000;ADCSRA = (1<<ADEN)|(1<<ADSC)
|(1<<ADFR)|(1<<ADIE)| | 1 |#define RESOLUTION 1024.0 // 10비트
volatile INT16 read_adc = 0;volatile INT8 adc flag = 0;
|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);// 기준 클럭 : 1MHz / 8
// ADCSRA = 0b11101011;("SEI") // i( ) //SREG | 0 80volatile INT8 adc_flag 0; asm("SEI"); // sei( ); //SREG |= 0x80;
}
72
예제예제 99--1 1 ADC (ADC (온도센서온도센서 TMP35) TMP35)
int main (void){
INT8 count=0;
if(adc_flag == 1){
PORTG = count++;;INT8 Value_10, Value_01;volatile float temp_volt = 0.0;volatile float Temperature = 0.0;
;
// adc_flag를 clear adc_flag = 0;// 10비트 ADC 값으로부터 전압 계산
p
DDRG = 0xFF; DDRA = 0xFF;
adc init(ADC CH); // Ch # of ADC
// 10비트 ADC 값으로부터 전압 계산temp_volt = read_adc *
(REF_VOLTAGE/RESOLUTION); // 계산된 전압에서 온도 계산adc_init(ADC_CH); // Ch # of ADC
_delay_ms(10);
PORTA = 0x99;
// 계산된 전압에서 온도 계산Temperature = temp_volt * (float)TMP35;
// 온도값을 7-segment에 표현_delay_ms(500);
while(1){
Value_10 = Temperature / 10;Value_01 = (INT8) Temperature % 10;PORTA = (Value_10<<4) | Value_01; d l (200){
// 우측 프로그램 추가}return 0;
_delay_ms(200);}
;}
73
예제예제 99--2 ADC (2 ADC (온도센서온도센서 TMP35 TMP35 –– 입력채널입력채널, , 기준전압기준전압 설정설정 변경변경) )
TMP35 온도센서를 활용하여 현재 온도를 측정한다.
TMP35의 출력전압을 ADC의 채널 #2를 통해 A/D 변환한다.
A/D 변환된 10비트 값으로부터 TMP35 출력 전압과 온도를 계산한다.
CPU 클럭주파수: 1MHz 내부 발진기
기준 전압: 내부 2.56V
입력 채널: ch #2
해상도: 10비트
온도를 PORTA의 7-segment에 출력한다. 예를 들어, 현재 온도가 28도이면, 2
개의 7-segment에 ‘28’을 출력한다.
74
예제예제 99--22
typedef unsigned char INT8;typedef unsigned int INT16;
ISR(ADC_vect) // ADC interrupt function{
read adc = ADCL;#define F_CPU 1000000UL
#include <avr/io.h>
read_adc ADCL;read_adc += (ADCH<<8);adc_flag = 1;
}/#include <util/delay.h>#include <avr/interrupt.h>
}
void adc_init(INT8 channel) {asm("CLI"); // cli( );
#define ADC_CH 2 // 입력 채널#define TMP35 100 // TMP35 환산#define REF_VOLTAGE 2.56 // 기준전압
asm( CLI ); // cli( );
ADMUX= (1<<REFS1)|(1<<REFS0); // 기준전압ADMUX |= (0<<ADLAR); // 10비트 해상도ADMUX |= channel;//#define REF_VOLTAGE 3.3 // 기준전압
//#define REF_VOLTAGE 5.0 // 기준전압//#define RESOLUTION 256.0 // 8비트#d fi RESOLUTION 1024 0 비
ADMUX |= channel;
ADCSRA= (1<<ADEN)|(1<<ADSC)|(1<<ADFR)|(1<<ADIE)
#define RESOLUTION 1024.0 // 10비트
volatile INT16 read_adc = 0;volatile INT8 adc flag 0;
|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);// 기준 클럭 : 1MHz / 8
asm("SEI"); // sei( ); //SREG |= 0x80;volatile INT8 adc_flag = 0; ( ); // ( ); // | ;}
75
예제예제 99--22
int main (void){
INT8 count=0;
if(adc_flag == 1){
PORTG = count++;;INT8 Value_10, Value_01;volatile float temp_volt = 0.0;volatile float Temperature = 0.0;
;
// adc_flag를 clear adc_flag = 0;// 10비트 ADC 값으로부터 전압 계산
p
DDRG = 0xFF; DDRA = 0xFF;
adc init(ADC CH); // Ch # of ADC
// 10비트 ADC 값으로부터 전압 계산temp_volt = read_adc *
(REF_VOLTAGE/RESOLUTION); // 계산된 전압에서 온도 계산adc_init(ADC_CH); // Ch # of ADC
_delay_ms(10);
PORTA = 0x99;
// 계산된 전압에서 온도 계산Temperature = temp_volt * (float)TMP35;
// 온도값을 7-segment에 표현_delay_ms(500);
while(1){
Value_10 = Temperature / 10;Value_01 = (INT8) Temperature % 10;PORTA = (Value_10<<4) | Value_01; d l (200){
// 우측 프로그램 추가}return 0;
_delay_ms(200);}
;}
76
예제예제 99--3 ADC (3 ADC (온도센서온도센서 TMP35 TMP35 –– 클럭속도클럭속도 설정설정 변경변경) )
TMP35 온도센서를 활용하여 현재 온도를 측정한다.
TMP35의 출력전압을 ADC의 채널 #2를 통해 A/D 변환한다.
A/D 변환된 10비트 값으로부터 TMP35 출력 전압과 온도를 계산한다.
CPU 클럭주파수: 4MHz 내부 발진기
기준 전압: 외부 AREF 입력 전압
입력 채널: ch #2
해상도: 10비트
Prescaler 설정을 000에서 111까지 변화하면서 결과 확인
온도를 PORTA의 7-segment에 출력한다. 예를 들어, 현재 온도가 28도이면, 2
개의 7-segment에 ‘28’을 출력한다.
77
예제예제 99--33
typedef unsigned char INT8;typedef unsigned int INT16;
ISR(ADC_vect) // ADC interrupt function{
read adc = ADCL;#define F_CPU 4000000UL
#include <avr/io.h>
read_adc ADCL;read_adc += (ADCH<<8);adc_flag = 1;
}/#include <util/delay.h>#include <avr/interrupt.h>
}
void adc_init(INT8 channel) {asm("CLI"); // cli( );
#define ADC_CH 2 // 입력 채널#define TMP35 100 // TMP35 환산//#define REF_VOLTAGE 2.56 // 기준전압
asm( CLI ); // cli( );
ADMUX= (0<<REFS1)|(0<<REFS0); // 기준전압ADMUX |= (0<<ADLAR); // 10비트 해상도ADMUX |= channel;//#define REF_VOLTAGE 3.3 // 기준전압
#define REF_VOLTAGE 5.0 // 기준전압//#define RESOLUTION 256.0 // 8비트#d fi RESOLUTION 1024 0 비
ADMUX |= channel;
ADCSRA= (1<<ADEN)|(1<<ADSC)|(1<<ADFR)|(1<<ADIE)
#define RESOLUTION 1024.0 // 10비트
volatile INT16 read_adc = 0;volatile INT8 adc flag 0;
|(0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);// 기준 클럭 : 1MHz / 8
asm("SEI"); // sei( ); //SREG |= 0x80;volatile INT8 adc_flag = 0; ( ); // ( ); // | ;}
78
예제예제 99--33
int main (void){
INT8 count=0;
if(adc_flag == 1){
PORTG = count++;;INT8 Value_10, Value_01;volatile float temp_volt = 0.0;volatile float Temperature = 0.0;
;
// adc_flag를 clear adc_flag = 0;// 10비트 ADC 값으로부터 전압 계산
p
DDRG = 0xFF; DDRA = 0xFF;
adc init(ADC CH); // Ch # of ADC
// 10비트 ADC 값으로부터 전압 계산temp_volt = read_adc *
(REF_VOLTAGE/RESOLUTION); // 계산된 전압에서 온도 계산adc_init(ADC_CH); // Ch # of ADC
_delay_ms(10);
PORTA = 0x99;
// 계산된 전압에서 온도 계산Temperature = temp_volt * (float)TMP35;
// 온도값을 7-segment에 표현_delay_ms(500);
while(1){
Value_10 = Temperature / 10;Value_01 = (INT8) Temperature % 10;PORTA = (Value_10<<4) | Value_01; d l (200){
// 우측 프로그램 추가}return 0;
_delay_ms(200);}
;}
79
예제예제 99--4 ADC (4 ADC (온도센서온도센서 TMP35 TMP35 –– FreeFree--running running 해제해제) )
TMP35 온도센서를 활용하여 현재 온도를 측정한다.
TMP35의 출력전압을 ADC의 채널 #2를 통해 A/D 변환한다.
A/D 변환된 10비트 값으로부터 TMP35 출력 전압과 온도를 계산한다.
CPU 클럭주파수: 1MHz 내부 발진기
기준 전압: 외부 AREF 입력 전압
입력 채널: ch #2
해상도: 10비트
Free-running을 해제하고 결과 확인 주기적으로 A/D 변환을 하기 위한 명령
은 ??
온도를 PORTA의 7-segment에 출력한다. 예를 들어, 현재 온도가 28도이면, 2
개의 7-segment에 ‘28’을 출력한다.
80
예제예제 99--44
typedef unsigned char INT8;typedef unsigned int INT16;
ISR(ADC_vect) // ADC interrupt function{
read adc = ADCL;#define F_CPU 1000000UL
#include <avr/io.h>
read_adc ADCL;read_adc += (ADCH<<8);adc_flag = 1;
}/#include <util/delay.h>#include <avr/interrupt.h>
}
void adc_init(INT8 channel) {asm("CLI"); // cli( );
#define ADC_CH 2 // 입력 채널#define TMP35 100 // TMP35 환산//#define REF_VOLTAGE 2.56 // 기준전압
asm( CLI ); // cli( );
ADMUX= (0<<REFS1)|(0<<REFS0); // 기준전압ADMUX |= (0<<ADLAR); // 10비트 해상도ADMUX |= channel;//#define REF_VOLTAGE 3.3 // 기준전압
#define REF_VOLTAGE 5.0 // 기준전압//#define RESOLUTION 256.0 // 8비트#d fi RESOLUTION 1024 0 비
ADMUX |= channel;
ADCSRA= (1<<ADEN)|(1<<ADSC)|(0<<ADFR)|(1<<ADIE)
#define RESOLUTION 1024.0 // 10비트
volatile INT16 read_adc = 0;volatile INT8 adc flag 0;
|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);// 기준 클럭 : 1MHz / 8
asm("SEI"); // sei( ); //SREG |= 0x80;volatile INT8 adc_flag = 0; ( ); // ( ); // | ;}
81
예제예제 99--44
int main (void){
INT8 count=0;
if(adc_flag == 1){
PORTG = count++;;INT8 Value_10, Value_01;volatile float temp_volt = 0.0;volatile float Temperature = 0.0;
;
// adc_flag를 clear adc_flag = 0;// 10비트 ADC 값으로부터 전압 계산
p
DDRG = 0xFF; DDRA = 0xFF;
adc init(ADC CH); // Ch # of ADC
// 10비트 ADC 값으로부터 전압 계산temp_volt = read_adc *
(REF_VOLTAGE/RESOLUTION); // 계산된 전압에서 온도 계산adc_init(ADC_CH); // Ch # of ADC
_delay_ms(10);
PORTA = 0x99;
// 계산된 전압에서 온도 계산Temperature = temp_volt * (float)TMP35;
// 온도값을 7-segment에 표현_delay_ms(500);
while(1){
Value_10 = Temperature / 10;Value_01 = (INT8) Temperature % 10;PORTA = (Value_10<<4) | Value_01; d l (200){
// 우측 프로그램 추가}return 0;
_delay_ms(200);ADCSRA |= (1<<ADSC); // ADCSRA |= 0x40;
};}
}
82