BASIC4MCU | 질문게시판 | atmega 화재감지 소스코드 해석 부탁드립니다ㅜ
페이지 정보
작성자 adonis 작성일2019-06-11 12:22 조회3,544회 댓글0건본문
밑의 소스코드로 발표를 하려하는데 atmel에 관해선 하나도 모르겠더라구요ㅠㅠ
공부는 하고있는데 제 시간에는 못맞출것같아서 글을 써봅니다..
되도록이면 상세하게 부탁드립니다ㅜㅜ
#include <mega128.h>
#include <delay.h>
// typedef 설정
typedef unsigned char U8;
typedef signed char S8;
typedef unsigned int U16;
typedef signed int S16;
typedef unsigned long U32;
typedef signed long S32;
unsigned char data;
// define 설정
#define BUAD_9600_RATE 103
#define sbi(PORT,BIT) PORT |= (1<<BIT)
#define cbi(PORT,BIT) PORT &= (~(1<<BIT))
#define tog(PORT,BIT) PORT ^= (1<<BIT)
#define LM35 1
#define gas 3
#define LCD_IW 0 // instruction write
#define LCD_IR 1 // instruction read
#define LCD_DW 2 // data write
#define LCD_DR 3 // data read
#define LCD_RS 0
#define LCD_RW 1
#define LCD_E 2
#define LCD_DATA_DIR_PORT DDRD
#define LCD_DATA_PORT PORTD
#define LCD_CON_DIR_PORT DDRB
#define LCD_CON_PORT PORTB
#define INT0_RISING_EDGE() cbi(MCUCR,0); sbi(MCUCR,1);
#define Key_1() ((PINE & 0x08) == 0)
#define Key_2() ((PINE & 0x04) == 0)
#define Relay_On() sbi(PORTF, 5)
#define Relay_Off() cbi(PORTF, 5)
#define Led_2_On() sbi(PORTF ,4)
#define Led_2_Off() cbi(PORTF ,4)
// MCU Init Part(사용자 함수)
void main_init(void);
void key_data(void);
void Port_Init(void);
void ADC_Init(void);
U16 Read_ADC(char ADC_Channel);
unsigned int Read_SMOG(char ADC_Channel);
// LCD Part(사용자 함수)
void Init_Lcd(void); // 상위 4비트를 사용한다.
void Init_Lcd_Port(void);
void Lcd_4BitPutData(U8 Sel_IW_Or_DW,U8 PutData);
void Lcd_PutData(U8 Sel_IW_Or_DW,U8 PutData);
void Lcd_Clear(void);
void Lcd_Enable(void);
void Lcd_Disable(void);
void Lcd_Putch(U8 LcdPutData);
void Cursor_Pos(U8 row, U8 col);
void Lcd_print_data(U8 row, U8 col, U8 *str);
void Lcd_U8Bit_PutNum(U8 row, U8 col, U8 NumData );
// Led Part
void Led_1_On(void);
void Led_1_Off(void);
// Buzzer Part
void Buzzer_On(void);
void Buzzer_Off(void);
// Lcd Part
void lcd_on(void);
void lcd_off(void);
// Servo Part
void servo_center(void);
void servo_left(void);
double Current_temp; // 현재의 온도가 저장
U8 Ref_temp = 27; // 원하는 온도
unsigned int smog = 0;
// Lcd 표시 문장
U8 Letter[2][11] = {{"Cur:"}, {"Ref:"}};
U8 Letter1[2][11] = {{"Temp"},{"Caution"}};
U8 Letter2[2][11] = {{" "},{" "}};
// Servo Motor Control (0~90)
void servo_center(void)
{
int i;
for(i=0;i<20;i++)
{
PORTE.7 = 1;
delay_ms(1); //최고로 왼쪽
delay_us(200);
delay_us(260);
PORTE.7 = 0;
delay_ms(19);
}
}
void servo_left(void)
{
int j;
for(j=0; j<20; j++)
{
PORTE.7 = 1;
delay_ms(2); //최고로 오른쪽
delay_us(200);
delay_us(190);
PORTE.7 = 0;
delay_ms(17);
}
}
// 통신 설정
void Usart0_Init(unsigned char buad)
{
UCSR0A = 0x00;
UCSR0B = 0x18;
UCSR0C = 0x06;
UBRR0H = 0x00;
UBRR0L = buad;
}
// 시리얼 포트로부터 한문자를 송신한다.
void putch(unsigned char data)
{
if(!(UCSR0A & 0x20));
UDR0 = data;
//UCSR0A |= 0x20;
}
// 주요 Main Part
int main(void)
{
main_init();
Usart0_Init(BUAD_9600_RATE);
// BPort bit 3~7 출력 설정
DDRB.3=1;
DDRB.4=1;
DDRB.5=1;
DDRB.6=1;
DDRB.7=1;
while(1)
{
key_data(); // 스위치 눌렸나 확인
Current_temp = Read_ADC(LM35); // ADC 결과를 변수 Current_temp에 저장
Current_temp *= 0.106; // ADC_result *(5/(1024*4*0.01)) = ADC_result * 0.122
// (실제 온도계와 값을맞추기위해서 조금 설정 조절)
smog = Read_SMOG(gas);
// LCD에 온도의 현재, 원하는 온도 표시
Lcd_print_data(0,0, Letter[0]);
Lcd_U8Bit_PutNum(0,4,(U16)Current_temp);
Lcd_print_data(1,0, Letter[1]);
Lcd_U8Bit_PutNum(1,4,Ref_temp);
// 현재 온도가 설정온도보다 높으면 실행
if(Ref_temp < (U16)Current_temp || smog < 900)
{
Lcd_print_data(0,9, Letter1[0]);
Lcd_print_data(1,9, Letter1[1]);
data='a';
putch(data);
lcd_on();
servo_left();
Relay_On(); // 원하는 온도보다 현재 온도가 높으면 선풍기 ON
Led_1_On();
Buzzer_On();
Led_2_Off();
}
// 현재 온도가 설정온도보다 낮으면 실행
else
{
Lcd_print_data(0,9, Letter2[0]);
Lcd_print_data(1,9, Letter2[1]);
data='b';
putch(data);
lcd_off();
servo_center();
Relay_Off(); // 원하는 온도보다 현재 온도가 높으면 선풍기 OFF
Led_2_On();
Buzzer_Off();
Led_1_Off();
}
}
return 0;
}
// Lcd BackLight Control
void lcd_on(void)
{
do
{
sbi(PORTF, 6);
delay_ms(150);
cbi(PORTF, 6);
delay_ms(50);
}while(PORTD.6==1);
}
// Lcd BackLight Control
void lcd_off(void)
{
cbi(PORTF, 6);
}
// Red Led Control
void Led_1_On(void)
{
do
{
sbi(PORTE, 4);
delay_ms(100);
cbi(PORTE, 4);
delay_ms(30);
sbi(PORTE, 5);
delay_ms(100);
cbi(PORTE, 5);
delay_ms(30);
sbi(PORTE, 6);
delay_ms(100);
cbi(PORTE, 6);
delay_ms(30);
sbi(PORTB, 3);
delay_ms(100);
cbi(PORTB, 3);
delay_ms(30);
sbi(PORTB, 4);
delay_ms(100);
cbi(PORTB, 4);
delay_ms(30);
sbi(PORTB, 5);
delay_ms(100);
cbi(PORTB, 5);
delay_ms(30);
sbi(PORTB, 6);
delay_ms(100);
cbi(PORTB, 6);
delay_ms(30);
sbi(PORTB, 7);
delay_ms(100);
cbi(PORTB, 7);
delay_ms(30);
}while(PORTD.6==1);
}
// Red Led Control
void Led_1_Off(void)
{
cbi(PORTF, 0);
}
// Buzzer Control
void Buzzer_On(void)
{
do
{
sbi(PORTF, 7);
delay_ms(300);
cbi(PORTF, 7);
delay_ms(10);
}while(PORTD.6==1);
}
// Buzzer Control
void Buzzer_Off(void)
{
cbi(PORTF, 7);
}
// Key Control
void key_data(void){
if(Key_2()) Ref_temp++;
else if(Key_1()) Ref_temp--;
else;
}
// 주요 설정 부분
void main_init(void){
#asm("cli");
Init_Lcd();
ADC_Init();
Port_Init();
Relay_Off();
#asm("sei");
}
// Port 설정
void Port_Init(void)
{
DDRF = 0b11110101;
DDRD = 0b11111111;
DDRE = (0 << 0)|(1 << 1)|(0 << 2)|(0 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7);
}
// ADC 설정 부분
void ADC_Init(void)
{
ADCSRA = 0x87; // (1000 0111) ADEN, 분주를 128로.
SFIOR &= 0xEF; // (1110 1111)
// ADATE가 클리어라면 노이펙트라서.. 노이팩트
}
U16 Read_ADC(char ADC_Channel){ // 기준 전압은 AREF를 사용..
ADCL = 0;
ADMUX = ADC_Channel; // 채널 선택... 끝에 3개의 비트가 채널 선택 비트(0번 채널은 0을 입력하면 된다.)
sbi(ADCSRA,6); // ADCSC 으로 ADC 변환을 시작하라는 레지..
while((ADCSRA & 0x10) == 0); // ADIF로 ADC변환이 완료가 되면 0으로 클리어.
ADCSRA |= 0x10; // ADIF를 1로 셋팅..sbi(ADCSRA,4)와 같은 명령어
return ADCW; // adc결과를 리턴한다. 이건 0x04번째 메모리 리드
// sfrw이므로 16비트 따라서 (ADCH + ADCL)
}
unsigned int Read_SMOG(char ADC_Channel){ // 기준 전압은 AREF를 사용..
ADCL = 0;
ADMUX = ADC_Channel; // 채널 선택... 끝에 3개의 비트가 채널 선택 비트(0번 채널은 0을 입력하면 된다.)
sbi(ADCSRA,6); // ADCSC 으로 ADC 변환을 시작하라는 레지..
while((ADCSRA & 0x10) == 0); // ADIF로 ADC변환이 완료가 되면 0으로 클리어.
ADCSRA |= 0x10; // ADIF를 1로 셋팅..sbi(ADCSRA,4)와 같은 명령어
return ADCW; // adc결과를 리턴한다. 이건 0x04번째 메모리 리드
// sfrw이므로 16비트 따라서 (ADCH + ADCL)
}
//////////////////////////////////////// LCD 정의 부분 //////////////////////////////////////////////////
void Init_Lcd(void) // 상위 4비트를 사용한다.
{
// Rs = 0 , Rw = 0 : 제어 명령 쓰기
// Rs = 0 , Rw = 1 : busy flag 와 adress counter 읽기
// Rs = 1 , Rw = 0 : DD/CG RAM 에 쓰기
// Rs = 1 , Rw = 1 : DD/CG RAM 에서 읽기
// 4 bit U8erface : D4 ~ D7 사용
// 8 bit U8erface : D0 ~ D7 사용
Init_Lcd_Port();
delay_ms(35);
Lcd_PutData(LCD_IW,0x28); // Function Set --> 4 bit U8erface
delay_ms(10);
delay_us(40);
Lcd_PutData(LCD_IW,0x28); // Function Set --> 4 bit U8erface
delay_ms(10);
delay_us(40);
Lcd_PutData(LCD_IW,0x28); // Function Set --> 4 bit U8erface
delay_ms(10);
Lcd_PutData(LCD_IW,0x28); // Function Set --> 4 bit U8erface
delay_ms(10);
Lcd_Clear(); // LCD Clear
Lcd_Clear();
Lcd_Clear();
Lcd_PutData(LCD_IW,0x06); // Entry Mode Set
Lcd_PutData(LCD_IW,0x0c); // Display ON, Cursor OFF, Blink OFF
}
void Init_Lcd_Port(void)
{
sbi(LCD_CON_DIR_PORT,LCD_RS);
sbi(LCD_CON_DIR_PORT,LCD_RW);
sbi(LCD_CON_DIR_PORT,LCD_E);
LCD_DATA_DIR_PORT |= 0xff;
LCD_DATA_PORT &= 0xf0;
}
void Lcd_4BitPutData(U8 Sel_IW_Or_DW,U8 PutData)
{
if(Sel_IW_Or_DW == LCD_IW){
Lcd_Disable();
cbi(LCD_CON_PORT,LCD_RW);
cbi(LCD_CON_PORT,LCD_RS);
}
else if(Sel_IW_Or_DW == LCD_DW){
Lcd_Disable();
cbi(LCD_CON_PORT,LCD_RW);
sbi(LCD_CON_PORT,LCD_RS);
}
LCD_DATA_PORT = PutData;
Lcd_Enable();
Lcd_Disable();
sbi(LCD_CON_PORT,LCD_RW);
}
void Lcd_PutData(U8 Sel_IW_Or_DW,U8 PutData)
{
U8 Lcd_tmp = 0;
Lcd_tmp = (PutData >> 4) & 0x0f;
Lcd_4BitPutData(Sel_IW_Or_DW,Lcd_tmp);
Lcd_tmp = PutData & 0x0f;
Lcd_4BitPutData(Sel_IW_Or_DW,Lcd_tmp);
if(Sel_IW_Or_DW == LCD_IW) delay_ms(10);
else delay_ms(1);
}
void Lcd_Clear(void)
{
Lcd_PutData(LCD_IW,0x01);
}
void Lcd_Enable(void)
{
sbi(LCD_CON_PORT,LCD_E);
}
void Lcd_Disable(void)
{
cbi(LCD_CON_PORT,LCD_E);
}
void Lcd_Putch(U8 LcdPutData)
{
Lcd_PutData(LCD_DW,LcdPutData);
}
void Cursor_Pos(U8 row, U8 col)
{
if( row == 0) Lcd_PutData(LCD_IW,0x80+col);
// 커서를 옮긴다.
else Lcd_PutData(LCD_IW,0xc0+col);
// 커서를 옮긴다.
}
void Lcd_print_data(U8 row, U8 col, U8 *str)
{
Cursor_Pos(row,col);
while(*str != '\0') Lcd_Putch(*str++);
}
void Lcd_U8Bit_PutNum(U8 row, U8 col, U8 NumData )
{
U16 TempData;
Cursor_Pos(row,col);
TempData = (NumData%1000)/100;
Lcd_Putch(TempData+48);
TempData = (NumData%100)/10;
Lcd_Putch(TempData+48);
TempData = NumData%10;
Lcd_Putch(TempData+48);
// 1자리는 값이 0이라도 그냥 찍는다.
}
댓글 0
조회수 3,544등록된 댓글이 없습니다.