#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
TWCR에서 START signal을 출력한 후 TWSR로 상태를 체크한 후 TWDR로 데이터를 입력하고 TWCR로 데이터를 전송하고 TWSR로 ACK 확인후 TWCR로 STOP signal을 출력하는 일련의 과정을 반복한다.
START 후 상태체크 : TWSR & 0xF8 = 0x08
Address 전송 후 ACK 체크 : TWSR & 0xF8 = 0x18
데이터 전송 후 ACK 체크 : TWSR & 0xF8 = 0x28
START 후 상태체크 : TWSR & 0xF8 = 0x08
Address 전송 후 ACK 체크 : TWSR & 0xF8 = 0x04
데이터 전송 후 ACK 체크 : TWSR & 0xFC = 0x50
TWCR의 STOP 전송 : TWINT = 1, TWSTA = 0, TWSTO = 1, TWEN = 1
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 리턴
}