부제목: 25일차
일정: 2023.11.29(수)
수업 내용:
- AD Converter 제어
목표:
- AD Converter 제어
A/D 변환기란 ? 아날로그 신호를 디지털 데이터로 변환
ATmega128의 A/D 변환기 특징
: 10-bit resolution(분해 능)
: 13~260㎲ 변환시간
: 8개의 단극성 입력 채널
(ADC0~ADC7)을 포트 F로 입력 받아 multi-plexer에 의해 A/D 변환기로 연결
: 10배와 20배 증폭을 갖는 2개 차동(differential) 입력 (ADC1,ADC0 그리고 ADC3, ADC2)
Free running mode
: 변환이 완료되면 자동적으로 즉시 새로운 A/D변환이 시작, ADSC 비트는 High상태 유지
ADC 레지스터
ADMUX (ADC Multiplexer Selection Register)
[5]bit – ADLAR (ADC Left Adjust Result)
: A/D 변환 결과값을 ADCH와 ADCL에 저장 형식을 지정하는 비트
: ADLAR=0 → 하위부터 10비트에 A/D 변환 결과 저장
: ADLAR=1 → 상위부터 10비트에 A/D 변환 결과 저장
[4]~[0]bit - MUX4~ MUX0(Analog Channel and Gain Selection Bits)
[7] ADEN (ADC Enable) : A/D 변환기 enable 비트
: ADEN=1 → A/D 변환기 동작 가능
: ADEN=0 → A/D 변환기 동작 정지, 소비 전력이 감소시킬 수 있음
[6] ADSC(ADC Start Conversion) : ADC 변환 시작 비트
: single running 에서 ADSC=1 → A/D 변환이 시작
: free running 모드, ADSC=1 → 첫 번째 A/D 변환 후 자동적으로 A/D 변환이 계속
ADEN=1이 된 후, 첫 번째 A/D 변환에서 clkADC가 25clock 필요하고
다음 변환부터는 13clock 이 소요됨
[5] ADFR (ADC Free Running Select) : A/D 변환을 연속적으로 수행하는 모드
: ADFR=1 → A/D 변환기는 Free Running 모드로 설정
: ADFR=0 → A/D 변환기는 single running 모드로 설정
[4] ADIF(ADC Interrupt Flag) : A/D 변환 완료 인터럽트 flag 비트
: A/D 변환이 완료되면 ADCH, ADCL에 A/D 변환 결과값이 write되고
ADIF=1이 되면서 A/D 변환 완료 인터럽트 발생
: ADIE=1이고 SREG의 I=1이면,
A/D 변환 완료 인터럽트가 처리되고 이 때 ADIF=0으로 clear됨
: ADIF를 강제적으로 clear 시키려면 ADIF=1로 write 시켜야 함
[3] ADIE(ADC Interrupt Enable) : A/D 변환 완료 인터럽트 enable 비트
[2]~[0] ADPS2~ADPS0 (ADC Pre-scaler Select Bits) : A/D 변환기에서 사용되는 시스템 clock의 분주비 선택
8. ADC (Analog to Digital Converter)
: 10비트의 A/D 변환 결과값을 저장
: A/D 변환 결과값을 리드할 때 ADCH를 먼저 read해야 함
A/D 변환 결과는 ADCH와 ADCL에 저장.
Differential (차동) 입력의 A/D 변환 결과 값의 범위
ADC 초기화
① AREF 전압 선택, A/D 변환 결과 저장 형식 선택,
A/D 변환 입력채널 설정 (단극성 입력, 차동입력)
→ 사용 레지스터 : ADMUX
② 사용 모드 설정
A/D 변환 enable, 분주비 설정,
변환모드 설정(단일변환/ 프리러닝), A/D변환 인터럽트 enable,
A/D변환기 입력 클럭 분주비 설정
→ 사용 레지스터 : ADCSRA
③ 전역 인터럽트 enable 레지스터 : SREG(최상위 비트)
<단일변환 모드 A/D 변환 동작>
- ADCSRA 레지스터의 ADSC(ADC Start Conversion) 를 1로 하여 A/D 변환 시작
- ADIF = 1(또는 ADSC=0)이 되어 A/D변환이 완료될 때까지 대기
- A/D 변환 결과 읽기(ADCW 또는 ADCH:ADCL)
<프리러닝 모드 A/D 변환 동작>
- 사용모드 설정하면서 ADCSRA 레지스터의 ADSC 비트를 1로 하여 A/D 변환 시작
- A/D 변환 결과 (ADCW 또는 ADCH : ADCL)를 읽고 싶을 때 읽기 가능
#include <mega128.h>
#include <delay.h>
typedef unsigned char u_char;
flash u_char seg_pat[10]= {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
void AD_disp(int); // A/D 변환값 표시
void main(void)
{
int ad_val;
DDRB = 0xF0;
DDRD = 0xF0;
DDRG = 0x0F;
ADMUX = 0x06; // ADC6 단극성 입력 선택
ADCSRA = 0x87; // ADEN=1, 16MHz 256분주 -> 125kHz
delay_ms(5);
while(1){
ADCSRA = 0xC7; // ADEN=1, ADSC = 1 변환 시작
while((ADCSRA & 0x10) == 0); // ADIF=1이 될 때까지
ad_val = (int)ADCL + ((int)ADCH << 8); // A/D 변환값 읽기
AD_disp(ad_val); // A/D 변환값 표시
}
}
void AD_disp(int val) {
float fval;
int ival, buf;
u_char N100, N10, N1;
fval = (float)val * 5.0 / 1024.0; // 전압 값으로 변환
ival = (int)(fval * 100.0 + 0.5); // 반올림 후 정수화, (소수 둘째자리까지)
N100 = ival / 100; // 정수부 추출
buf = ival % 100;
N10 = buf / 10; // 소수 첫째 자리 추출
N1 = buf % 10; // 소수 둘째 자리 추출
PORTG = 0b00001000; // PG3=1, 소수 둘째 자리
PORTD = ((seg_pat[N1] & 0x0F) << 4) | (PORTD & 0x0F);
PORTB = (seg_pat[N1] & 0x70 ) | (PORTB & 0x0F);
delay_ms(1);
PORTG = 0b00000100; // PG2=1, 소수 첫째 자리
PORTD = ((seg_pat[N10] & 0x0F) << 4) | (PORTD & 0x0F);
PORTB = (seg_pat[N10] & 0x70 ) | (PORTB & 0x0F);
delay_ms(1);
PORTG = 0b00000010; // PG1=1, 정수부
PORTD = ((seg_pat[N100] & 0x0F) << 4) | (PORTD & 0x0F);
PORTB = (seg_pat[N100] & 0x70 ) | (PORTB & 0x0F);
PORTB = PORTB | 0x80; // DP on(소수점)
delay_ms(1);
}
[예제 8-2] Free running, ADC6 입력 전압 7-Segment 표시
ADC6 (PF6)에는 가변저항(VR2) 10KΩ이 연결되어 있으며
이 단자를 통해 입력되는 전압(단극성 입력)을
3개의 7-Segment에 소수 두 자리까지 전압 값으로 표시하는 프로그램을 작성
Free running mode.
#include <mega128.h>
#include <delay.h>
typedef unsigned char u_char;
const u_char seg_pat[10]= {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
void AD_disp(int); // A/D 변환값 표시
void main(void)
{
int ad_val;
DDRB = 0xF0; // 포트 B 상위 4비트 출력 설정
DDRD = 0xF0; // 포트 D 상위 4비트 출력 설정
DDRG = 0x0F; // 포트 G 하위 4비트 출력 설정
ADMUX = 0x06; // ADC6 단극성 입력 선택
ADCSRA = 0xE7; // ADEN=1, ADSC=1, ADFR=1, 16MHz, 256분주 -> 125kHz
delay_ms(5);
while(1)
{
ad_val = (int)ADCL + ((int)ADCH << 8); // A/D값 읽기
AD_disp(ad_val); // A/D값 표시
delay_ms(2);
}
}
void AD_disp(int val) {
float fval;
int ival, buf;
u_char N100, N10, N1;
fval = (float)val * 5.0 / 1023.0; // 전압값으로 변환
ival = (int)(fval * 100.0 + 0.5); // 반올림 후 정수화
N100 = ival / 100; // 정수부 추출
buf = ival % 100;
N10 = buf / 10; // 소수 첫째 자리 추출
N1 = buf % 10; // 소수 둘째 자리 추출
PORTG = 0b00001000; // PG3=1, 소수 둘째 자리
PORTD = ((seg_pat[N1] & 0x0F) << 4) | (PORTD & 0x0F);
PORTB = (seg_pat[N1] & 0x70 ) | (PORTB & 0x0F);
delay_ms(1);
PORTG = 0b00000100; // PG2=1, 소수 첫째 자리
PORTD = ((seg_pat[N10] & 0x0F) << 4) | (PORTD & 0x0F);
PORTB = (seg_pat[N10] & 0x70 ) | (PORTB & 0x0F);
delay_ms(1);
PORTG = 0b00000010; // PG1=1, 정수부
PORTD = ((seg_pat[N100] & 0x0F) << 4) | (PORTD & 0x0F);
PORTB = (seg_pat[N100] & 0x70 ) | (PORTB & 0x0F);
PORTB = PORTB | 0x80; // DP on(소수점)
delay_ms(1);
}
'[Intel] 엣지 AI SW 아카데미 > 펌웨어 프로그래밍 75hour' 카테고리의 다른 글
[Intel] 엣지 AI SW 아카데미 28일차 (부산상공회의소 인력개발원) (0) | 2023.12.17 |
---|---|
[Intel] 엣지 AI SW 아카데미 27일차 (부산상공회의소 인력개발원) (1) | 2023.12.17 |
[Intel] 엣지 AI SW 아카데미 24일차 (부산상공회의소 인력개발원) (1) | 2023.12.17 |
[Intel] 엣지 AI SW 아카데미 23일차 (부산상공회의소 인력개발원) (1) | 2023.12.17 |
[Intel] 엣지 AI SW 아카데미 22일차 (부산상공회의소 인력개발원) (1) | 2023.12.17 |