BASIC4MCU | 질문게시판 | 아트메가 128 DHT22온도센서
페이지 정보
작성자 tmet 작성일2023-06-08 05:21 조회1,811회 댓글1건본문
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
// 온습도 센서 관련 상수
#define DHT_DATA_PIN PD2
// 경고 온습도 임계값
#define TEMP_THRESHOLD 3 // 일정 온도 임계값 (예: 25도)
#define HUMIDITY_THRESHOLD 70 // 일정 습도 임계값 (예: 70%)
// LCD관련 상수
#define LCD_DATA PORTA //LCD데이터 포트 정의
#define LCD_INST PORTA
#define LCD_CTRL PORTC //LCD제어 포트 정의
#define RS 0x01
#define EN 0x00
// 변수
volatile uint16_t temperature = 0;
volatile uint16_t humidity = 0;
// 함수 선언
void delay_us(unsigned char time_us);
void delay_ms(unsigned int time_ms);
char flip_bits(char ch);
void LCD_data(char ch);
void LCD_comm(char ch);
void LCD_CHAR(char c); // 한문자 출력 함수
void LCD_STR(char *str);
void LCD_pos(char col, char row);
void LCD_clear(void);
void LCD_init(void);
void read_dht_data();
void display_temperature_humidity();
int main()
{
while (1) {
display_temperature_humidity();
check_threshold();
_delay_ms(2000); // 1초 딜레이
}
return 0;
}
void display_temperature_humidity()
{
DDRA = 0xF0;
DDRC |= (1 << RS) | (1 << EN); // PC0~1까지 출력으로 사용
LCD_init(); // LCD 초기화
LCD_pos(0, 0);
LCD_STR("Temperature:"); // 온도 출력
LCD_pos(0, 1);
LCD_STR("Humidity:"); // 습도 출력
read_dht_data(); // 온습도 센서에서 데이터 읽기
LCD_pos(12, 0);
LCD_CHAR(' '); // 이전 온도 값 삭제
LCD_pos(12, 1);
LCD_CHAR(' '); // 이전 습도 값 삭제
LCD_pos(12, 0);
LCD_CHAR(temperature / 10 + '0'); // 십의 자리 숫자 출력
LCD_pos(13, 0);
LCD_CHAR(temperature % 10 + '0'); // 일의 자리 숫자 출력
LCD_pos(12, 1);
LCD_CHAR(humidity / 10 + '0'); // 십의 자리 숫자 출력
LCD_pos(13, 1);
LCD_CHAR(humidity % 10 + '0'); // 일의 자리 숫자 출력
}
// 온습도 센서에서 데이터 받아서 저장하기
void read_dht_data()
{
uint8_t data[5];
uint8_t i, j;
// 시작 신호 전송
DDRD |= (1 << DHT_DATA_PIN); // OUTPUT 모드
PORTD |= (1 << DHT_DATA_PIN); // OUTPUT 모드
_delay_ms(2); // 20ms 대기
PORTD &= ~(1 << DHT_DATA_PIN); // 0으로 설정
_delay_us(5); // 40us 대기
PORTD |= (1 << DHT_DATA_PIN); // 1로 설정
DDRD &= ~(1 << DHT_DATA_PIN); // INPUT 모드
// 응답 확인
_delay_us(80);
if (!(PIND & (1 << DHT_DATA_PIN))) {
return;
}
_delay_us(80);
// 데이터 수신
if (!(PIND & (1 << DHT_DATA_PIN))) {
_delay_us(80);
for (j = 0; j < 5; j++) {
uint8_t result = 0;
for (i = 0; i < 8; i++) {
while (!(PIND & (1 << DHT_DATA_PIN)));
_delay_us(30);
if (PIND & (1 << DHT_DATA_PIN)) {
result |= (1 << (7 - i));
}
while ((PIND & (1 << DHT_DATA_PIN)));
}
data[j] = result;
}
if ((uint8_t)(data[0] + data[1] + data[2] + data[3]) == data[4]) {
// 온도와 습도 값 저장
temperature = data[2] << 8 | data[3];
humidity = data[0] << 8 | data[1];
}
}
}
//LCD
void delay_us(unsigned char time_us)
{
register unsigned char i;
for(i=0;i<time_us;i++) //4 cycle
{
asm volatile("PUSH R0"); //2 cycle
asm volatile("POP R0"); //2 cycle
asm volatile("PUSH R0"); //2 cycle
asm volatile("POP R0"); //2 cycle
asm volatile("PUSH R0"); //2 cycle
asm volatile("POP R0"); //2 cycle
// Sum = 16 cycle=1 us for 16MHz
}
}
void delay_ms(unsigned int time_ms)
{
register unsigned int i;
for(i=0;i<time_ms;i++) //4 cycle
{
delay_us(250);
delay_us(250);
delay_us(250);
delay_us(250);
}
}
char flip_bits(char ch)
{
char return_ch=0;
return_ch=(ch>>3) & 0x10;
return_ch=return_ch | ((ch>>1) & 0x20);
return_ch=return_ch | ((ch<<1) & 0x40);
return_ch=return_ch | ((ch<<3) & 0x80);
return return_ch;
}
void LCD_data(char ch)
{
LCD_DATA=flip_bits(ch); //upper nibble 데이터 출력
LCD_CTRL |= (1<<RS);
LCD_CTRL |= 1<<EN;
delay_us(1);
LCD_CTRL &= ~(1<<EN);
delay_us(20);
LCD_DATA=flip_bits(ch<<4); //lower nibble 데이터 출력
LCD_CTRL |= (1<<RS);
LCD_CTRL |= 1<<EN;
delay_us(1);
LCD_CTRL &= ~(1<<EN);
delay_us(50);
}
void LCD_comm(char ch)
{
LCD_INST=flip_bits(ch); //upper nibble 명령어 쓰기
LCD_CTRL &= ~(1<<RS);
LCD_CTRL |= 1<<EN;
delay_us(1);
LCD_CTRL &= ~(1<<EN);
delay_us(5);
LCD_INST=flip_bits(ch<<4); //lower nibble 명령어 쓰기
LCD_CTRL &= ~(1<<RS);
LCD_CTRL |= 1<<EN;
delay_us(1);
LCD_CTRL &= ~(1<<EN);
delay_ms(5);
}
void LCD_CHAR(char c) // 한문자 출력 함수
{
delay_ms(1);
LCD_data(c); // DDRAM으로 데이터 전달
}
void LCD_STR(char *str) // 위의 문자열을 한문자씩 출력함수로 전달 ,출력해줄 문자열을 받음
{
while(*str)
LCD_CHAR(*str++);
}
void LCD_pos(char col, char row) // LCD 포지션 설정
{
LCD_comm(0x80|(col+row*0x40)); //문자 처음 출력해줄 위치 설정
}
void LCD_clear(void) // 화면 클리어
{
LCD_comm(1);
}
void LCD_init(void) // LCD 초기화
{
LCD_comm(0x20); //4bit 초기화
delay_ms(5);
LCD_comm(0x28); //데이터 4비트 사용, 5X7도트 , LCD2열로 사용(6) 0010 1000
delay_ms(5);
LCD_comm(0x0C); //Display ON/OFF
delay_ms(5);
LCD_comm(0x06); //주소 +1 , 커서를 우측으로 이동 (3)
delay_ms(5);
LCD_clear();
}
온도와 습도를 담아서 변수에 저장한 뒤, LCD에 보여주고 싶은데 변수에 0이 담겨요 아마 읽는 함수가 아에 잘못된 것 같아요.. 도와주세요 제발...
댓글 1
조회수 1,811master님의 댓글
master 작성일
https://cafe.naver.com/circuitsmanual/106735
오실로스코프를 사용해서 파형을 측정하고 코드를 만들었습니다.
AM2302는 DHT22로 알고 있습니다.