질문게시판 > avr Atmega 소스코드 잘못된부분 수정바랍니다.

인기검색어 > 아두이노 센서 ATMEGA128

최신글 질문게시판 동영상강좌 가입하기

▼ BASIC4MCU 후원업체 신제품 정보 ▼

▲ BASIC4MCU 후원업체 신제품 정보 ▲

BASIC4MCU > 질문게시판

avr Atmega 소스코드 잘못된부분 수정바랍니다.

페이지 정보

작성자 전자초짜 작성일18-06-01 17:11 조회6,339회 댓글1건

본문

#include <stdio.h> // sprintf()를 위해 #include

#include <avr/io.h>

#include <avr/interrupt.h>

void Delay_us(unsigned int time_us)

{

register unsigned int 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 = 12 cycle = 0.9216 MHz

} // for 11.0592 MHz

// =1.085 us

}

void Delay_ms(unsigned int time_ms)

{

register unsigned int j;

for(j=0; j<time_ms; j++)

{

Delay_us(1000);

}

} //1.085 ms

 

// ADC

 

void adc_init(void) // AD 컨버터 초기화

{

ADMUX = 0x40;

//AVCC단자전압을 기준전압으로 이용

 

ADCSRA = 0xA5;

//ADC enable, free running mode, 프리스케일러 32분주

ADCSRA |= 0x40;

// A/D변환 시작

 

}

 

// AD 컨버팅을 한다.

// 오차를 줄이기 위해 16ADC를 하여 평균한다.

uint16_t get_adc(uint8_t channel) // 1024분주로 AD 컨버팅을 한다.

{

uint16_t result = 0;

uint8_t i = 0;

 

ADMUX = 0x40 | channel;

//MUX를 조작하여 ADC 채널을 선택한다.

Delay_us(150); //MUX 변환 시간 동안 대기

 

ADCSRA |= (1 << ADSC); // 변환 시작

 

for(i = 0; i < 16; i++)

{

ADCSRA |= (1 << ADIF); //ADC재시작

while( !((ADCSRA >> ADIF) & 1) );

//ADC 완료될 때 까지 대기

result += ADC; //1024분주 값으로 데이터를 받아온다.

}

 

ADCSRA &= (~(1 << ADSC)); //변환을 멈춤

 

return (result >> 4);//쉬프트

}

 

//LCD

 

#define LCD_DCTRL (DDRG)

#define LCD_DDATA (DDRA)

#define LCD_CTRL (PORTG)

#define LCD_DATA (PORTA)

 

#define LCD_RS (PG0)

#define LCD_RW (PG1)

#define LCD_E (PG2)

 

 

 

void lcd_control(uint8_t data)

{

LCD_CTRL = LCD_CTRL & ~_BV(LCD_RW);

// #define _BV(bit) (1 << (bit)) // RW=0

LCD_CTRL = LCD_CTRL & ~_BV(LCD_RS);

// RS=0 IR(인스트럭션 레지스터) 쓰기 동작을 실행한다.

LCD_DATA = data;

LCD_CTRL = LCD_CTRL | _BV(LCD_E);// EN = 1

Delay_ms(1);

LCD_CTRL = LCD_CTRL & ~_BV(LCD_E);//EN = 0

}

 

void lcd_init(void)

{

LCD_DDATA = 0xFF; // A포트를 출력으로 사용

LCD_DCTRL = 0x07;

// G포트의 0,1,2번 핀인 LCD_RS,LCD_RW,LCD_EN 핀을 출력으로 사용

LCD_DATA = 0; // A포트의 데이터 출력 값을 0으로 한다.

LCD_CTRL = 0; // RS,RW,EN 의 데이터 출력 값을 0으로 한다.

 

lcd_control(0x38); // Function Set (8bit, 2line, 5 x 7 dot)

lcd_control(0x0C); // Display ON, Cursor OFF

lcd_control(0x06); // Entry Mode Set (어드레스 +1 커서를 우로 이동, not shift)

lcd_control(0x01); // Clear Display

}

void lcd_write_char(uint8_t data)

{

LCD_CTRL = LCD_CTRL & ~_BV(LCD_RW); //RW=0

LCD_CTRL = LCD_CTRL | _BV(LCD_RS); //RS=1

LCD_DATA = data;

//DR(데이터 레지스터)쓰기 동작,D.D.RAM 에 데이터값을 쓴다.

 

LCD_CTRL = LCD_CTRL | _BV(LCD_E);

Delay_ms(1);

LCD_CTRL = LCD_CTRL & ~_BV(LCD_E);

 

}

 

 

void lcd_position(uint8_t x, uint8_t y)

{

uint8_t location=0;

if(y>0x01)

y=0x01;

if(x>0x0f)

x=0x0f;

 

if(y == 0)

location = x + 0x80; //1행에 표시

else

location = x + 0xC0; //2행에 표시

 

lcd_control(location);

}

// D.D.RAM adressx 로 설정한다. 1행의 주소는 0x00~0x27까지 2행의 주소는 0x40 ~ 0x67 까지

 

void lcd_display_string(uint8_t x, uint8_t y, char *string)

{

lcd_position(x,y); // 글자를 출력할 위치를 정해준다.

 

while(*string != '\0')

//포인터의 마지막인 null 문자가 될 때까지 포인터 주소 값을 증가시키며 DR어드레스에 쓴다.

{

lcd_write_char(*string);

string++;

}

}

 

//시간 컨트롤

 

 

char sec='0',sec10='0',min='0',min10='0',hour='0',hour10='0',mid='A';

//시간을 표현하기 위한 변수들을 char 타입으로 숫자와 문자를 저장한다.

 

char time[17]; //LCD에 시간을 표시하기 위한 배열을 설정한다.

 

void Time_Control()

{

if(hour10=='0' && hour=='0' && min10=='0' && min=='0' && sec10=='0' && sec=='0')

{

if(mid == 'A')

{mid='P';}

else

{mid='A';}

}

//00:00:00 이 되는 순간 APPA로 바꾼다.

 

else if(hour10 == '1' && hour > '1' )

{

hour10='0';

hour='0';

}

//시간이 12으로 증가하면 00시로 변경시킨다.

 

else if(hour > '9')

{

hour='0';

hour10++;

 

}

// hour10 이면 hour = '0' 이되고 hour10 1증가시킨다.

else if(min10 > '5')

{

min10='0';

hour++;

 

}

//min106 이되면 min10 0 이 되고 hour1증가시킨다.

else if(min > '9')

{

min='0';

min10++;

 

}

//10분이 되면 min= '0' 이 되고 min10 1을 증가시킨다.

else if(sec10 > '5')

{

sec10='0';

sec='0';

min++;

 

}

//sec106이되면 sec100으로 바꾸고 min1증가시킨다.

else if(sec > '9')

{

sec='0';

sec10++;

 

}

//sec10이 되면 sec0 으로 바꾸고 sec101증가시킨다.

}

double humi=0;

 

ISR(TIMER0_OVF_vect) //TIMER0 오버플로우 인터럽트 발생 시 실행

{

TCNT0 = 156;

humi++;

if (humi==104) // 0.9956초를 카운트

{

lcd_display_string(0, 0,time);

humi = 0;

sec++;

 

}

}

//1초를 카운트 하기 위해 오버플로우가 될때까지의 값을 100으로 설정하고 104번의 루프를 돌려 약 1초를 만들었다.

//1초마다 LCD에 시간을 표시하도록 하였다.

//LCD를 표시하는 딜레이시간을 고려하여 104번의 루프를 돌리면 오차가 최소화 된다.

// 외부 인터럽트

 

 

ISR(INT4_vect) //INT4 interrupt service routine

{

Delay_ms(10);

if(TCCR0 &= 0x07)

{TCCR0 &= 0x00;}

else

{TCCR0 |= 0x07;}

}

//TCCR0 레지스터의 마지막 3비트를 비교하여 프리스케일러가 1024분주이면 인터럽트 발생 시

//TCCR0의 마지막 3비트가 0이 되어 카운터를 멈춘다.

//다시 한번 인터럽트를 걸면 1024분주로 카운터가 시작된다.

 

ISR(INT5_vect)//INT5 interrupt service routine

{

Delay_ms(25);

if(mid == 'A')

{

mid='P';

lcd_display_string(0, 0,time);

}

else if(mid == 'P')

{

mid='A';

lcd_display_string(0, 0,time);

}

}

// 인터럽트 발생 시 문자 AP로 바꾸고 PA로 바꾸어 오전 오후를 표시한다.

//메인

 

#define FORWARD 0XFF // 모터 정방향 인에이블(2번핀)

#define DISABLE 0X00 // 모터 정지

int main(void)

{

int i=0;

char string[16]; // LCD에 나타낼 온도 부분의 문자열을 저장할 임시 변수

uint16_t result; // A/D 컨버팅 결과를 받아올 임시 변수

unsigned char Setup_hour,Setup_min,Setup_sec,Hold_Humi;

//스위치 사용을 위하여 변수 설정

 

 

char *Introduce1=" 2008 TermProject";

char *Introduce2=" 200412459";

char *Introduce3=" Hwang se jun";

char *Introduce4=" 200511405";

char *Introduce5=" Seo dong hwan";

char *Introduce6=" 200711490";

char *Introduce7=" Kim se mi";

// 처음에 켜면 나오는 학번 및 이름을 저장한 포인터 변수 설정

 

 

Delay_ms(20);

// LCDMCU 등은 전원이 들어온 후 약간의 시간이 지나야 정상 동작하므로 초기 지연시간을 준다.

 

DDRE = 0x00;

//INT4INT5를 사용하기위해 E포트를 입력으로 사용함을 선언.

 

DDRC = 0x00;

//스위치를 사용하기 위해 C포트를 입력으로 사용함을 선언.

 

DDRF = 0x00; // ADC를 입력으로 한다.

DDRD = 0xfC; //LED를 모두 출력으로 사용함을 선언.

PORTE = 0x0C;

//E포트의 INT4,INT5 의 데이터 값에 1을 주어 인터럽트를 사용하도록 한다.

 

DDRB= 0xff; //포트B를 모터 출력으로 사용 지정

int rx;

rx=getchar(); // 문자에 대한 표준입력함수

 

EICRA = 0x00;

//INT3~0low level일 때 trigger로 설정. 위에서 포트의 입력을 모두 1로 설정하므로 off와 동일.

EICRB = 0x0A; //INT4,INT5falling edge일 때trigger

EIMSK = 0x30; //INT4,INT5 on

EIFR = 0x30; // INT4,INT5가 트리거 되었음을 표시

 

sei(); //Global interrupt enable

 

adc_init(); // AC 컨버터 초기화

lcd_init() ; // LCD 초기화

 

 

Delay_ms(10);

 

for(i=0;i<17;i++)

{

lcd_display_string(0, 0,Introduce1++);

Delay_ms(25);

}

Delay_ms(100);

lcd_control(0x01);

 

for(i=0;i<10;i++)

{

lcd_display_string(0, 0,Introduce2++);

Delay_ms(25);

}

 

for(i=0;i<13;i++)

{

lcd_display_string(0, 1,Introduce3++);

Delay_ms(25);

}

Delay_ms(100);

lcd_control(0x01);

 

for(i=0;i<10;i++)

{

lcd_display_string(0, 0,Introduce4++);

Delay_ms(25);

}

for(i=0;i<14;i++)

{

lcd_display_string(0, 1,Introduce5++);

Delay_ms(25);

}

Delay_ms(100);

lcd_control(0x01);

 

for(i=0;i<10;i++)

{

lcd_display_string(0, 0,Introduce6++);

Delay_ms(25);

}

 

for(i=0;i<10;i++)

{

lcd_display_string(0, 1,Introduce7++);

Delay_ms(25);

}

Delay_ms(50);

lcd_control(0x01);

Delay_ms(50);

// 학번 이름 등 소개하는 글을 LCD에 차례대로 띄운다.

 

 

TCCR0 = _BV(CS02)|_BV(CS01)|_BV(CS00); // Prescaling : clk/1024

TIMSK = 0x01; //Enable overflow

UBRR0L = 71; // USART BAUD RATE REG.송수신속도 조절 (11059200/16/9600)-1=71

UCSR0B = 0x18; // USART CONTROL&STATUS REG. 송수신부 enable

 

while(1) // 무한 루프 - 프로그램은 종료되지 않는다.

{

time[0]=mid;

time[1]='m';

time[2]=' ';

time[3]=hour10;

time[4]=hour;

time[5]=':';

time[6]= min10;

time[7]=min;

time[8]=':';

time[9]=sec10;

time[10]=sec;

time[11]=' ';

time[12]='*';

time[13]='^';

time[14]='^';

time[15]='*';

 

//time[17]배열의 요소를 한개씩 지정해 준다.

 

Hold_Humi=(PINC & 0x08);

Setup_hour = (PINC & 0x01);

Setup_min =(PINC & 0x02);

Setup_sec = (PINC & 0x04);

Time_Control();

// 스위치5번이 연결되어있는 PC0 핀의 값을 Setup_hour에 입력

// 스위치6번이 연결되어있는 PC1 핀의 값을 Setup_min에 입력

//스위치7번이 연결되어있는 PC2 핀의 값을 Setup_sec에 입력

//스위치를 누르면 PINC에 각각 걸리는 값이 0이 된다.

if(Setup_hour == 0x00)

{

Delay_ms(50);

hour++;

}

//SW5를 누르면 시간이 1씩 증가한다.

 

if(Setup_min == 0x00)

{

Delay_ms(50);

min++;

 

}

//SW6을 누르면 분이 1씩 증가한다.

 

if(Setup_sec == 0x00)

{

Delay_ms(50);

sec++;

}

//SW7을 누르면 초가 1씩 증가한다.

 

lcd_display_string(0, 0,time); //시간을 LCD의 첫줄에 표시한다.

 

if(Hold_Humi == 0x00 )

{

sprintf(string, "Humidity:%2d.%d RH", result/10, result%10);

// 결과를 포맷에 맞게 문자열로 생성한다.

 

lcd_display_string(0, 1, string);

 

}

//SW8을 누르면 현재 온도가 그대로 LCD에 고정되어 표시된다.

else

{

result = (uint16_t) get_adc(2);

// 1024 분해능으로 ADC2 결과를 받아온다.

result=((result*5/10.24)-80)*10/3.1;

 

}

//SW8을 누르고 있지 안은 경우에는 계속해서 ADC의 결과를 받아서 result값에 저장한다.

 

if(result < 250)

{

PORTD=0x04;

}

else if(result < 300 && result > 250)

{

PORTD=0x0C;

}

else if(result < 350 && result > 300)

{

PORTD=0x1C;

}

else if(result < 400 && result > 350)

{

PORTD=0x3C;

}

else if(result < 450 && result > 400)

{

PORTD=0x7C;

}

else if( result > 450)

{

PORTD=0xFC;

}

 

//습도가 45% 이하일때는 LED불빛이 한개만 켜지고 5% 증가할 때마다 LED의 불이 하나씩 더 켜진다.

 

if(result > 450)

{

PORTD=0xFC;

PORTB = FORWARD;

 

 

 

lcd_control(0x01);

sprintf(time, "Sooo Humid *-_-*");//string

lcd_display_string(0, 0, time);

 

sprintf(string, "Humidity:%2d.%d RH", result/10, result%10);

lcd_display_string(0, 1,string);

 

Delay_ms(1);

 

 

while(1)

{ Hold_Humi=(PINC & 0x08);

Setup_hour = (PINC & 0x01);

Setup_min =(PINC & 0x02);

Setup_sec = (PINC & 0x04);

Time_Control(0x01);

 

 

while((UCSR0A & 0x80) == 0x00);// CPU가 수신 문자를 읽어서

 

{ // 수신 버퍼가 비어있는 상태라면 (RXC=0)

 

rx=UDR0; // 받은 데이터를 임시 변수에 저장

 

while((UCSR0A & 0x20) == 0x00); // 송신이 가능한 동안 (UDRE0=0)

 

{

UDR0=rx;// 데이터를 보낸다.(임시변수에 저장된

// 데이터를 UDR0에 저장한다.)

 

}

}

 

{ Delay_ms(1); //딜레이}

 

if ((rx=='S')||(rx=='s')) //s값을 받으면 정지시킨다.

{ PORTB=DISABLE;

PORTD=0XFF;

Delay_ms(1);

}

else if((rx=='e')||(rx=='E'))

{

break;

}

else

{

PORTB=FORWARD; //s값이 아니면 led가 켜진다.

PORTD=0XFF;

Delay_ms(1);

 

}

 

 

}

 

PORTD = 0x00;

 

}

 

//현재의 습도가 45%가 넘어가면 글씨가 LCD에 표시가 되고 부저가 울리며 LED의 모든 불이 켜진다.

//45% 이하로 내려오면 정상작동을 한다.

}

else

{

PORTB=0x00;

sprintf(string, "Humidity:%2d.%d RH", result/10, result%10);

lcd_display_string(0, 1, string);

}

Delay_ms(1); //LCD가 동작하기 위한 시간지연

}

return 0;

}

for(i=0;i<17;i++)

{

lcd_display_string(0, 0,Introduce1++);

Delay_ms(25);

}

Delay_ms(100);

lcd_control(0x01);

Hold_Humi=(PINC & 0x08);

Setup_hour = (PINC & 0x01);

Setup_min =(PINC & 0x02);

Setup_sec = (PINC & 0x04);

Time_Control();

// 스위치5번이 연결되어있는 PC0 핀의 값을 Setup_hour에 입력

// 스위치6번이 연결되어있는 PC1 핀의 값을 Setup_min에 입력

//스위치7번이 연결되어있는 PC2 핀의 값을 Setup_sec에 입력

//스위치를 누르면 PINC에 각각 걸리는 값이 0이 된다.

if(result < 250)

{

PORTD=0x04;

}

else if(result < 300 && result > 250)

{

PORTD=0x0C;

}

else if(result < 350 && result > 300)

{

PORTD=0x1C;

}

else if(result < 400 && result > 350)

{

PORTD=0x3C;

}

else if(result < 450 && result > 400)

{

PORTD=0x7C;

}

else if( result > 450)

{

PORTD=0xFC;

}

 

//습도가 45% 이하일때는 LED불빛이 한개만 켜지고 5% 증가할 때마다 LED의 불이 하나씩 더 켜진다.

if(result > 450)

{

PORTD=0xFC;

PORTB = FORWARD;

 

 

 

lcd_control(0x01);

sprintf(time, "Sooo Humid *-_-*");//string

lcd_display_string(0, 0, time);

 

sprintf(string, "Humidity:%2d.%d RH", result/10, result%10);

lcd_display_string(0, 1,string);

 

Delay_ms(1);

 

 

while(1)

{ Hold_Humi=(PINC & 0x08);

Setup_hour = (PINC & 0x01);

Setup_min =(PINC & 0x02);

Setup_sec = (PINC & 0x04);

Time_Control(0x01);

 

 

while((UCSR0A & 0x80) == 0x00);// CPU가 수신 문자를 읽어서

 

{

// 수신 버퍼가 비어있는 상태라면 (RXC=0)

 

rx=UDR0; // 받은 데이터를 임시 변수에 저장

 

while((UCSR0A & 0x20) == 0x00); // 송신이 가능한 동안 (UDRE0=0)

 

{

 

UDR0=rx;// 데이터를 보낸다.(임시변수에 저장된

// 데이터를 UDR0에 저장한다.)

 

}

}

 

{ Delay_ms(1); //딜레이}

 

if ((rx=='S')||(rx=='s')) //s값을 받으면 정지시킨다.

{ PORTB=DISABLE;

PORTD=0XFF;

Delay_ms(1);

}

else if((rx=='e')||(rx=='E'))

{

break;

}

else

{

PORTB=FORWARD; //s값이 아니면 led가 켜진다.

PORTD=0XFF;

Delay_ms(1);

}

 

 

}

 

PORTD = 0x00;

 

}

 

//현재의 습도가 45%가 넘어가면 글씨가 LCD에 표시가 되고 부저가 울리며 LED의 모든 불이 켜진다.

//45% 이하로 내려오면 정상작동을 한다.

}

else

{

PORTB=0x00;

sprintf(string, "Humidity:%2d.%d RH", result/10, result%10);

lcd_display_string(0, 1, string);

}

 

 

  • BASIC4MCU 작성글 SNS에 공유하기
  • 페이스북으로 보내기
  • 트위터로 보내기
  • 구글플러스로 보내기
  • 카카오톡으로 보내기

댓글 : 1

조회수 : 6,339

master님의 댓글

master 작성일

뭐가 안되는지 상세히 작성해주세요

게시물 검색

BASIC4MCU > 질문게시판 목록

제목 날짜
공지 MCU, AVR, 아두이노 등 전자공학에 관련된 질문은… 스태프  19-01-15
공지 사이트 이용 안내 댓글[25] master  17-10-29
질문 라즈베리파이4 신형 선택문제 maximum 새글 22-06-26
질문 음전압 ADC 412904 새글 22-06-26
질문 아두이노 센서값 출력 질문입니다! 댓글[1] 아궁2  22-06-24
질문 ATmega128, ATmega28 RS232통신 첨부파일Moon4201  22-06-24
답변 답변 : ATmega128, ATmega28 RS232… 댓글[1] master 새글 22-06-25
질문 서보모터, 온습도센서 코드 질문 댓글[2] 첨부파일kshdlfaldfh  22-06-22
답변 답변 : 서보모터, 온습도센서 코드 질문 댓글[15] master  22-06-22
질문 steppermulti5 질문 응애  22-06-21
답변 답변 : steppermulti5 질문 댓글[1] master  22-06-22
질문 atmega128 avr usart 질문 snoflak  22-06-21
답변 답변 : atmega128 avr usart 질문 댓글[5] master  22-06-21
질문 사용자 정의 함수 변환 하는 방법 댓글[2] 첨부파일da0800  22-06-21
질문 atmega128 댓글[1] 양의노래  22-06-20
질문 아두이노 동시동작 재질문 댓글[9] 첨부파일죠르디  22-06-20
질문 초음파센서로 dc모터 제어하기 댓글[1] 첨부파일난쟁2  22-06-20
질문 아두이노 동시동작 댓글[7] 죠르디  22-06-19
질문 ATMEGA128 UART,FND 연동 질문 JMOD  22-06-19
답변 답변 : ATMEGA128 UART,FND 연동 질문 댓글[1] master  22-06-20
질문 atmeg128 질문이요 댓글[1] 첨부파일공대생er  22-06-18
질문 atmega128 초음파 센서로 신호등 시간초 늘리기 서동씨  22-06-18
답변 답변 : atmega128 초음파 센서로 신호등 시간초… 댓글[1] master  22-06-18
질문 atmega128 댓글[2] 망경이  22-06-18
질문 앱인벤터 이용해서 수동 자동 할라고하는데 ..잘안됩니다… 댓글[1] 따랑해영  22-06-18
답변 질문 : 앱인벤터 이용해서 수동 자동 할라고하는데 ..… 댓글[1] 첨부파일따랑해영  22-06-19
답변 질문 : 앱인벤터 이용해서 수동 자동 할라고하는데 .… 첨부파일따랑해영  22-06-19
질문 서보모터와 초음파센서 댓글[1] 브링미히어  22-06-17
질문 LCD 도와주세요 ㅜㅠㅠㅠ 댓글[2] 첨부파일dentist22  22-06-17
질문 안녕하세요 atmega128 질문드리고 싶습니다. (자… 댓글[3] dlcldl  22-06-17
게시물 검색


Privacy Policy
MCU BASIC ⓒ 2017
PC버전