BASIC4MCU | 질문게시판 | Atmega128 온도센서 활용 재질문입니다.
페이지 정보
작성자 donggle 작성일2022-11-26 16:24 조회893회 댓글3건첨부파일
본문
독학하는 입장에서, 답변 달아주시고 도움주셔서 항상 감사히 생각하고 있습니다.
앞서 질문한 내용에서 "포인터 지정 2바이트 read"로 구현했다는 것은
첨부파일에 올린 사이클에 맞춰서 구현을 했다는 의미입니다.
int read_twi_2byte_nopreset(char reg) 함수를 사용하여 코드로 구현했구요.
제가 원하는것은 앞서 구현한 코드에서 "포인터 지정" 과 "포인터 미지정 2바이트 read" 2단계로 나누어서 구현하는 것인데
첨부파일에 올린 사이클로 구현하는것을 목표로 하고있습니다.
어떤식으로 구현해야할지 저 또한 감이 안잡혀서 도움을 청하고자 글을 썼습니다.
#define F_CPU 16000000UL // CPU 클록 값=16 MHz
#define F_SCK 40000UL // SCK 클록 값=40 KHz
#include
#include
#include
//
#define LM75A_ADDR 0x98 // 0b10011000,7비트를 1비트 left shift
#define LM75A_CONFIG_REG 1
#define LM75A_TEMP_REG 0
#define STOP 0 // 체온계 모드
#define GO 1 // 온도계 모드
//
unsigned char digit[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67};
volatile int temperature=0; // 전역변수(Global Variable)
volatile int stop_temp=0; // 정지 시 온도
volatile int state=GO;
int sw=0;
//
void init_twi_port(){
DDRC=0xff; DDRG=0xff; // FND 출력 세팅
TWSR=TWSR&0xfc; // Prescaler 값=00(1배)
TWBR=(F_CPU/F_SCK-16)/2; // 공식 참조,bit rate 설정
}
//
int read_twi_2byte_nopreset(char reg){
char high_byte,low_byte;
TWCR=(1<)|(1<
// START 상태 검사,이후 ACK 및 상태 검사
TWDR=LM75A_ADDR|0; // SLA+W 준비,W=0
TWCR=(1<)|(1<
TWDR=reg; // LM75A Reg 값 준비
TWCR=(1<)|(1<
TWCR=(1<)|(1<
//RESTART 상태 검사,이후 ACK,NO_ACK 상태 검사
TWDR=LM75A_ADDR|1; // SLA+R 준비,R=1
TWCR=(1<)|(1<
TWCR=(1<)|(1<
high_byte=TWDR; // 1st DATA 수신
TWCR=(1<)|(1<
low_byte=TWDR; // 2nd DATA 수신
TWCR=(1<)|(1<
return((high_byte<<8)| low_byte); // 수신 DATA 리턴
}
//
void display_FND(int value){
char digit[12]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67,0x00,0x40 }; //‘0’~‘9’,‘ ’,‘-’
char fnd_sel[4]={0x01,0x02,0x04,0x08};
int value_int,value_deci,num[4],i;
if((value&0x8000)!=0x8000)num[3]=10; // Sign 비트 체크 // 양수인 경우는 디스플레이 없음
else{
num[3]=11; // 음수인 경우는 ‘-’ 디스플레이
value=(~value)+1; // 2’s Complement 값을 취함
}
value_int=(char)((value&0x7f00)>>8); // High Byte bit6~0 값(정수 값)
value_deci=(char)(value&0x0080); // Low Byte bit7 값(소수 첫째자리값)
num[2]=(value_int/10)%10;
num[1]=value_int%10;
num[0]=(value_deci==0x80)?5:0; // 소수 첫째자리가 1이면 0.5에 해당하므로
// 5를 디스플레이
for(i=0;i<4;i++){
PORTC=digit[num[i]]; PORTG=fnd_sel[i];
if(i==1)PORTC|=0x80; // 왼쪽에서 3번째 FND에는 소수점(.)을 찍음
if(i%2)_delay_ms(2); // 2번은 2ms 지연
else _delay_ms(3); // 2번은 3ms 지연,총 10ms 지연
}
}
//
ISR(INT4_vect){
_delay_ms(100); // 스위치 바운스 시간 동안 기다림
EIFR|=1<<4; // 바운스에 의해 생긴 인터럽트는 무효화 - 디바운싱
if((PINE&0x10)!=0x00)return; // SW1이 눌려진 것이 아니면
if(state==STOP)state=GO; // STOP 상태라면 GO 상태로 변경
else{
state=STOP; // GO 상태라면 STOP 상태로 변경
stop_temp=read_twi_2byte_nopreset(LM75A_TEMP_REG); // 그리고,‘현재 온도’를 읽어서 저장
}
}
//
int main(void){
int i;
DDRC=0xff; // C 포트는 FND 데이터 출력 신호
DDRG=0x0f; // G 포트는 FND 선택 출력 신호
DDRE=0xef; // 0b11101111,PE4(SW1)는 입력
EICRB=0x02; // INT4 트리거 모드는 하강 에지(falling edge)
EIMSK=0x10; // INT4 인터럽트 인애이블
SREG|=0x80; // SREG의 I(Interrupt Enalbe)비트(bit7)‘1’로 세트
init_twi_port(); // TWI 및 포트 초기화
while(1){ // 온도값 읽어 FND 디스플레이
for(i=0;i<60;i++){ // 0.6초 동안 처리
if(state==GO){ // 온도계 모드인 경우
if((i==0)||(i==30))temperature=read_twi_2byte_nopreset(LM75A_TEMP_REG); // 억세스시간(300ms)동안 기다리기 // 위하여 30번에 1번 꼴로 실제 억세스
display_FND(temperature); // 한 번 디스플레이에 약 10ms 소요
}
else{ // 체온계 모드인 경우
if(i<30){ temperature=stop_temp; display_FND(temperature); } // 0.3초는 디스플레이
else { PORTG=0x00; _delay_ms(10); } // 0.3초는 디스플레이 끔
}
}
}
}
댓글 3
조회수 893master님의 댓글
master 작성일
아직도
포인터 지정/포인터 미지정/ 이 무슨 뜻인지 모르겠습니다.
다른 사람들은 관심사항이 아니므로 타인에게 설명 할 때는 이해가 가능하도록 상세한 설명이 필요합니다.
donggle님의 댓글
donggle
게시글에 사진이 안올라가진것을 확인하고, 첨부파일에 사진을 올렸습니다. 혹시 확인해주실수 있는지요
donggle님의 댓글
donggle
첨언을 하자면 아래 주소에 있는 데이터 시트에서
http://www.ti.com/lit/ds/symlink/lm75a.pdf
7.6.1 pointer register 부분
이걸 이용해서 온도센서 레지스터를 지정해서 읽는다는것을 의미합니다.
칩은 ponter register로 지정하지 않아도 온도레지스터가 선택된 상태이지만
i2c 쓰기를 통해서 온도레지스터를 선택하는 과정을 구현하길 원한다고 말씀드리고 싶습니다