[임베디드]Board-광센서,온도센서

공부기록·2023년 12월 2일
0
post-thumbnail

🔊 광센서


  • 황화카디늄 센서를 이용하여 빛이 밝아지면 전기저항값이 작아지고 빛이 어두워지면 전기저항값이 커지는 성질을 가지고 있어 빛의 양에 따라 가변저항의 역할을하여 특정 지점의 전압을 변화시킬 수 있다.

  • 광센서
    • A/D 컨버터 (Analog to Digital)
      • 아날로그 신호를 디지털 데이터로 변환하여주는 장치이다.
    • 분해능 (resolution)
    • 변환시간
      • A/D변환을 수행하는데 걸리는 시간
    • 10비트의 분해능 13~260usec 변환시간 (50KHz ~ 1MHz)

🏷️ ADMUX

  • 멀티플렉서 선택 레지스터
  • 아날로그 입력 채널(4,3,2,1,bit - 00000)과 기준 전압(7,6bit - 00 : AREF(+5V))을 선택한다.
  • ADLAR = 0 : ADCH, ADCL(값 저장 레지스터)가 우정렬된다.
  • ADMUX = 0x00

🏷️ ADCSRA (control과 status)

  • ADFR
    • 0 : 단일 변환 모드 (Single Conversion Mode)로 사용자가 시작하면 한번만 변환 실행
  • ADIF
    • 변환 완료되어 Data 레지스터의 값이 업데이트되면 이 비트가 1로 세팅되어 변환이 완료되었음을 알린다.
  • ADPS (ADC Prescaler Select Bit)
    • 10bit 변환을 막기위하여 50에서 200 범위 내에 있어야하므로 128선택(111)

🏷️ ADCH, ADCL

  • 변환결과는 10비트의 양의 정수로 표현되고 기준 전압에 대한 비율 상수를 의미한다.
    • 기준전압을 AVCC(+5V)로 설정했을 경우, CDS신호의 전압레벨이 0V이면 이 값은 0이고, +5이면 1023이 된다.



🖇️ 조도에 따라 LED 변화

#include <avr/io.h>
#define CDS_VALUE 871 //만약 저항이 35K라면 ADC기준값은 200/(35+200)*(1024-1)
void init_adc();
void show_adc(unsigned short value);
int main(){
	unsigned short value;
    DDRA = 0xff;
    init_adc();
    while(1){
    	value = read_adc();
        shoe_adc(value);
    }
}

void init_adc(){
	ADMUX = 0x00;
    ADCSRA = 0x87;
}
unsigned short read_adc(){
	unsigned char adc_low, adc_high;
    unsigned short value;
    ADCSRA |= 0X40; //ADC 변환 시작 
    while((ADCSRA & 0X10) != 0x10)); //ADC 변환완료 Flag 확인 1이면 변환완료
    //변환 완료 확인 후
    adc_low = ADCL;
    adc_high = ADCH;
    value = (adc_high << 8) | adc_low;
    return value;
}
void show_adc(unsigned short value){
	if(value < CDS_VALUE) PORTA = 0xff;
    else PORTA = 0x00;



🔊 온도센서

SCL(clock)과 SDA(data) 두가지의 신호만 사용한다.
slave address는 7bit를 할당한다.

SCL은 클락으로 주기적으로 0과 1을 반복한다. SCL이 HIGH인 상태에서 SDA가 하강하면 START Signal을 발생하고 SCL이 LOW한 상태에서 SDA가 상승하면 STOP Signal이 발생한다. 또한 SDA가 변하지않은 상태에서 클락이 한 번 상승과 하강을 하면 1비트의 데이터가 전송된다.

🔈 데이터 송수신 포맷

Master가 하나의 버스를 관리하며 slave에 data를 write하기도 하고, read하기도 한다. 아래 그림에서 노랗게 칠해진 부분이 Master에서 Slave에게 전달되는 데이터이다.

일단 공통적으로 Master는 START signal과 STOP signal을 발생하고 어떤 Slave와 연결할지와 그 연결이 read인지 write인지 보내야한다. 후에 Slave로부터 ACK이 온다면 데이터의 전송이 가능해진다.
Address Cycle + Data Cycle
Slave Address = 1001100

  • write : Slave에게 데이터를 write하고 8비트(1byte)의 전송마다 Slave로부터오는 ACK(1bit)을 확인한다.
  • read : Slave로부터 데이터를 read하고 8비트(1byte)의 전송마다 Slave에게 ACK(1bit)을 전송한다.

🔔 TWI 제어 레지스터

  • TWCR(제어), TWSR(상태), TWDR(데이터)

🔈 TWCR

  • TWINT
    • 현재의 동작이 완료됐음을 알리는 플래그로 완료시 1로 세팅이 필요하다. 자동적으로 CLEAR 되지않으므로 1인 동안은 SCL이 0인 상태를 유지하므로 CLEAR가 필요하다.
  • TWEA
    • 1 바이트의 데이터 수신시 ACK 신호를 보내기 위하여 1로 설정
  • TWSTA
    • START 조건 출력, CLEAR 필요
  • TWSTO
    • STOP 조건 출력
  • TWEN
    • TWI 버스를 활성화시킴
  • TWIE
    • TWI 인터럽트가 발생하도록 허용하며 1로 세팅시 TWINT 생성마다 인터럽트가 발생한다.

🔈 TWSR

  • TWS [7:3] - 5bit
    • 진행상태 표시값을 확인하는 레지스터
    • 각 단계마다 상이하므로 예시를 보며 이해가 필요하다.
  • TWPS
    • Prescaler 값 세팅으로 주로 00(1분주)쓴다.

🔈TWDR

  • 송신모드에서는 송신할 Slave Address 또는 데이터를 저장
  • 수신모드에서는 수신된 데이터를 저장

TWCR에서 START signal을 출력한 후 TWSR로 상태를 체크한 후 TWDR로 데이터를 입력하고 TWCR로 데이터를 전송하고 TWSR로 ACK 확인후 TWCR로 STOP signal을 출력하는 일련의 과정을 반복한다.


🏷️ WRITE

START 후 상태체크 : TWSR & 0xF8 = 0x08
Address 전송 후 ACK 체크 : TWSR & 0xF8 = 0x18
데이터 전송 후 ACK 체크 : TWSR & 0xF8 = 0x28


🏷️ READ

START 후 상태체크 : TWSR & 0xF8 = 0x08
Address 전송 후 ACK 체크 : TWSR & 0xF8 = 0x04
데이터 전송 후 ACK 체크 : TWSR & 0xFC = 0x50
TWCR의 STOP 전송 : TWINT = 1, TWSTA = 0, TWSTO = 1, TWEN = 1



Command Register

  • 내부의 다른 register를 지정, indirection
  • Temperature Register 00
  • Configuration Register 01

Temperature Register

  • 2바이트로 온도값 표시

Configuration Register

  • 온도값 유효 비트설정 : 9bit (소수점 첫째자리까지만)



온도센서

  • 디지털 온도계
    • Configuration Register를 적합한 값으로 설정한다. 지금은 9bit & normal모드로 세팅한다.
    • Command Register가 Temperature Register를 포인팅하도록 세팅한 후 2바이트의 온도값을 읽는다.
    • FND[3]은 High Byte의 MSB값을 확인 후 0이면 아무것도 표시하지 않고 1이면 '-'를 표시한다.
    • FND[0]는 Low Byte의 MSB값 확인 후 0이면 '0'을 1이면 '5'를 표시한다.
int main(){
	unsigned short temperature;
    volatile int i;
    init_twi_port();
    write_twi_1byte_nopreset(ATS75_CONFIG_REG, 0x00); //9비트
    write_twi_0byte_nopreset(ATS75_TEMP_REG);
    while(1){
   		temperature = read_twi_2byte_preset(); //2byte 온도값 읽기
    	for(i = 0; i < 50; i++) display_FND(temperature);
    } //FND display
}

void write_twi_1byte_nopreset(char reg, char data){
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //START 전송
    while(((TWCR & (1<<TWINT))==0x00 || (TWSR&0xF8) != 0x08);
    TWDR = ATS75_ADDR | 0;
    TWCR = (1<<TWINT) | (1<<TWEN);
    while(((TWCR & (1<<TWINT)) == 0x00) || (TWSR & 0xF8) != 0X18);
    TWDR = reg;
    TWCR = (1<<TWINT) | (1<<TWEN);
    while(((TWCR & (1<<TWINT)) == 0x00) || (TWSR & 0xF8) != 0x28);
    TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
}
 
void write_twi_0byte_nopreset(UCHAR reg){
    TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // START 전송
    while(((TWCR & (1 << TWINT)) == 0x00) || ((TWSR & 0xf8) != 0x08 && (TWSR
    & 0xf8) != 0x10)); // ACK를 기다림
    TWDR = ATS75_ADDR | 0; // SLA+W 준비, W=0
    TWCR = (1 << TWINT) | (1 << TWEN); // SLA+W 전송
    while(((TWCR & (1 << TWINT)) == 0x00) || (TWSR & 0xf8) != 0x18);
    TWDR = reg; // aTS75 Reg 값 준비
    TWCR = (1 << TWINT) | (1 << TWEN); // aTS75 Reg 값 전송
    while(((TWCR & (1 << TWINT)) == 0x00) || (TWSR & 0xF8) != 0x28);
    TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); // STOP 전송
}

USHORT read_twi_2byte_preset(){
	CHAR high_byte, low_byte;
    TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // START 전송
    while(((TWCR & (1 << TWINT)) == 0x00) || ((TWSR & 0xf8) != 0x08 &&
    (TWSR & 0xf8) != 0x10)); // ACK를 기다림
    TWDR = ATS75_ADDR | 1; // SLA+R 준비, R=1
    TWCR = (1 << TWINT) | (1 << TWEN); // SLA+R 전송
    while(((TWCR & (1 << TWINT)) == 0x00) || (TWSR & 0xf8) != 0x40);
    TWCR = (1 << TWINT) | (1 << TWEN | 1 << TWEA);// 1st DATA 준비
    while(((TWCR & (1 << TWINT)) == 0x00) || (TWSR & 0xf8) != 0x50);
    high_byte = TWDR; // 1 byte DATA 수신
    TWCR = (1 << TWINT) | (1 << TWEN | 1 << TWEA);// 2nd DATA 준비
    while(((TWCR & (1 << TWINT)) == 0x00) || (TWSR & 0xf8) != 0x50);
    low_byte = TWDR; // 1 byte DATA 수신
    
    return ((high_byte<<8) | low_byte); // 수신 DATA 리턴
}

0개의 댓글

관련 채용 정보