#include <avr/io.h>
#include <avr/interrupt.h>
#define ir_ready 0
#define ir_lead 1
#define ir_data 2
unsigned char ir_rx_data[4];
//voliate
unsigned char ir_state;
unsigned char ir_timer_cnt;
unsigned char ir_bit_cnt;
unsigned char ir_rx_flag=0;
unsigned char ir_rx_temp;
void clock_data_m_change();
void clock_data_p_change();
void alarm_data_m_change();
void alarm_data_p_change();
void ir_car_run();
char moter_data;
void delay_us(unsigned int us)
{
unsigned int i;
for(i=0;i<us;i++){
asm(“PUSH R0″);
asm(“POP R0″);
asm(“PUSH R0″);
asm(“POP R0″);
asm(“PUSH R0″);
asm(“POP R0″);
}
}
void delay_ms(unsigned int ms)
{
unsigned int i;
for(i=0;i<ms;i++){
delay_us(1000);
}
}
#define CUR11 0×02 /* 커서 홈에 위치시키는 명령어 값 */
#define CUR21 0xC0 /* 커서 2라인 1열에 위치시키는 명령어 값 */
#define LCDON 0x0C /* LCD ON 명령어 값 */
#define LCDOFF 0×08 /* LCD OFF 명령어 값 */
#define MODE4 0×20 /* 4비트 인터페이스 설정 */
#define FSET 0×28 /* 기능설정, 4비트 인터페이스, NF=10 : 2행 5×7 폰트 */
#define LCDCLR 0×01 /* LCD 클리어 */
#define MODENT 0×06 /* 엔트리모드 설정, 표시는 이동 않고, AC 증가, 커서 우측 이동 */
typedef unsigned char byte;
void lcd_cmd(unsigned char ch){ /LCD에 명령어값 1바이트 쓰는 서브루틴, ch는 명령어 값 /
unsigned char temp0, temp1;
delay_ms(1); / 약 15msec delay /
DDRA = 0xff; // 포트C를 출력으로
temp0 = ch & 0xf0; / 상위4비트 마스크 /
temp1 = temp0 | 0×04; / 하위 4비트에 0100b(RS=R/W=0, E=1) 써넣기 /
PORTA = temp1; / LCD에 명령어값의 상위 4비트 써넣기 /
temp1 = temp0 & 0xf0; / 하위 4비트에 0000b(RS=R/W=0, E=0) 써넣기 /
PORTA = temp1; / LCD에 입력 불허 /
delay_us(10); / 약 0.01 msec 시간지연 /
temp0 = (ch << 4) & 0xf0 ; / 하위4비트를 상위로 옮기고 마스크 /
temp1 = temp0 | 0×04 ; / 하위 4비트에 0100b(RS=R/W=0, E=1) 써넣기 /
PORTA = temp1; / LCD에 명령어값의 하위 4비트 써넣기 /
temp1 = temp0 & 0xf0; / 하위 4비트에 0000b(RS=R/W=0, E=0) 써넣기 /
PORTA = temp1; / LCD에 입력 불허 /
}
void lcd_ln11(void){ /* LCD의 1행1열에 커서를 위치시키는 서브루틴 */
lcd_cmd(CUR11);
}
void lcd_dat(unsigned char ch){ /* LCD에 1글자 쓰는 서브루틴, ch는 글자의 아스키 코드 값 */
unsigned char temp0, temp1;
delay_ms(1); /* 약 15msec delay */
DDRA = 0xff; // 포트C를 출력으로
temp0 = ch & 0xf0; /* 상위4비트 마스크 */
temp1 = temp0 | 0×05; /* 하위 4비트에 0101b(RS=1, R/W=0, E=1) 써넣기 */
PORTA = temp1; /* LCD에 DATA값의 상위 4비트 써넣기 */
temp1 = temp0 | 0×01; /* 하위 4비트에 0001b(RS=1, R/W=0, E=0) 써넣기 */
PORTA = temp1; /* LCD에 입력 불허 */
delay_us(10); /* 약 0.01 msec 시간지연 */
temp0 = (ch << 4) & 0xf0 ; /* 하위4비트를 상위로 옮기고 마스크 */
temp1 = temp0 | 0×05; /* 하위 4비트에 0101b(RS=1, R/W=0, E=1) 써넣기 */
PORTA = temp1; /* LCD에 DATA값의 하위 4비트 써넣기 */
temp1 = temp0 | 0×01; /* 하위 4비트에 0001b(RS=1, R/W=0, E=0) 써넣기 */
PORTA = temp1; /* LCD에 입력 불허 */
}
void lcd_init(void){ /* LCD 초기화 서브루틴 */
delay_ms(15); /* 약 15msec delay */
delay_ms(5);
lcd_cmd(MODE4);
delay_ms(5);
delay_ms(5); /* 약 5msec delay */
lcd_cmd(MODE4); delay_us(100);
delay_ms(5);
lcd_cmd(MODE4);
delay_ms(5);
lcd_cmd(FSET); /* 기능설정, 4비트 인터페이스, NF=10 : 2행 5×7 폰트 */
delay_ms(5);
lcd_cmd(LCDON); /* LCD ON 명령어 값 */
delay_ms(5);
lcd_cmd(LCDCLR); /* LCD Clear 명령어 값 */
delay_ms(5);
lcd_cmd(MODENT); /* 엔트리모드 설정, 표시는 이동 않고, AC 증가, 커서 우측 이동 */
delay_ms(5);
}
void lcd_str(char *str){ /* LCD에 flash에 저장된 문자열을 출력하는 함수 */
unsigned int i=0;
for(i=0;str[i] != 0; i++)
lcd_dat(str[i]);
}
//시간 관련 소스
char s,m,h;
char as,am,ah;
char a_on;//알람
//키관련 소스
char key;
char key_on;
char key_mode;
char key_count;
char key_buffer;
//1s
int us100;
char count_on;
//시간 변경 함수
void clock_count(){
if(key_mode==1){
}else if(key_mode==11){
}else{
if(count_on==1){
s++;
if(s==60){
m++;
s=0;
}
if(m==60){
h++;
m=0;
}
if(h==60){
h=0;
}
count_on=0;
}
}
}
void key_data(){
if(key_on==1){
//일반 모드
if(key_mode==0){
if(key==4){
key_mode=1;//시간 변경 모드
}else if(key==5){
key_mode=2;//알람 시간 변경 모드
}else if(key==6){
key_mode=3;//알람 설정 모드
}else if(key==7){
key_mode=0;
key_count=0;
}
//시간 시분초 결정
}else if(key_mode==1){
if(key==4){
key_count=(key_count+1)%6;//시분초
}else if(key==5){
key_count=(key_count+5)%6;//시분초
}else if(key==6){//시분초 변경 결정
key_mode=11;
key_buffer=key_count;
}else if(key==7){
key_mode=0;
key_count=0;
}
//시간 시분초 변경
}else if(key_mode==11){
if(key==4){
clock_data_p_change();
}else if(key==5){
clock_data_m_change();
}else if(key==6){
key_mode=1;
}else if(key==7){
key_mode=0;
key_count=0;
}
}else if(key_mode==2){
if(key==4){
key_count=(key_count+1)%6;//시분초
}else if(key==5){
key_count=(key_count+5)%6;//시분초
}else if(key==6){//시분초 변경 결정
key_mode=21;
}else if(key==7){
key_count=0;
key_mode=0;
}
//시간 시분초 변경
}else if(key_mode==21){
if(key==4){
alarm_data_p_change();
}else if(key==5){
alarm_data_m_change();
}else if(key==6){
key_mode=2;
}else if(key==7){
key_mode=0;
key_count=0;
}
}else if(key_mode==3){
if(key==4){
a_on=1;
}else if(key==5){
a_on=0;
}else if(key==6){
key_mode=0;
key_count=0;
}else if(key==7){
key_mode=0;
key_count=0;
}
}
key_on=0;
}
}
//시간 시분초 변경
void clock_data_p_change(){
if(key_count==0){
if((s%10)==9){
s=s-9;
}else{
s=s+1;
}
}else if(key_count==1){
if((s/10)==5){
s=s-50;
}else{
s=s+10;
}
}else if(key_count==2){
if((m%10)==9){
m=m-9;
}else{
m=m+1;
}
}else if(key_count==3){
if((m/10)==5){
m=m-50;
}else{
m=m+10;
}
}else if(key_count==4){
if((h/10)==2){
if((h%10)==3){
h=h-3;
}else{
h=h+1;
}
}else{
if((h%10)==9){
h=h-9;
}else{
h=h+1;
}
}
}else if(key_count==5){
if((h%10)<4){
if((h/10)==2){
h=h-20;
}else{
h=h+10;
}
}else{
if((h/10)==1){
h=h-10;
}else{
h=h+10;
}
}
}
}
//시간 시분초 변경
void clock_data_m_change(){
if(key_count==0){
if((s%10)==0){
s=s+9;
}else{
s=s-1;
}
}else if(key_count==1){
if((s/10)==0){
s=s+50;
}else{
s=s-10;
}
}else if(key_count==2){
if((m%10)==0){
m=m+9;
}else{
m=m-1;
}
}else if(key_count==3){
if((m/10)==0){
m=m+50;
}else{
m=m-10;
}
}else if(key_count==4){
if((h/10)==2){
if((h%10)==0){
h=h+3;
}else{
h=h-1;
}
}else{
if((h%10)==0){
h=h+9;
}else{
h=h-1;
}
}
}else if(key_count==5){
if((h%10)<4){
if((h/10)==0){
h=h+20;
}else{
h=h-10;
}
}else{
if((h/10)==0){
h=h+10;
}else{
h=h-10;
}
}
}
}
//시간 시분초 변경
void alarm_data_p_change(){
if(key_count==0){
if((as%10)==9){
as=as-9;
}else{
as=as+1;
}
}else if(key_count==1){
if((as/10)==5){
as=as-50;
}else{
as=as+10;
}
}else if(key_count==2){
if((am%10)==9){
am=am-9;
}else{
am=am+1;
}
}else if(key_count==3){
if((am/10)==5){
am=am-50;
}else{
am=am+10;
}
}else if(key_count==4){
if((ah/10)==2){
if((ah%10)==3){
ah=ah-3;
}else{
ah=ah+1;
}
}else{
if((ah%10)==9){
ah=ah-9;
}else{
ah=ah+1;
}
}
}else if(key_count==5){
if((ah%10)<4){
if((ah/10)==2){
ah=ah-20;
}else{
ah=ah+10;
}
}else{
if((ah/10)==1){
ah=ah-10;
}else{
ah=ah+10;
}
}
}
}
//시간 시분초 변경
void alarm_data_m_change(){
if(key_count==0){
if((as%10)==0){
as=as+9;
}else{
as=as-1;
}
}else if(key_count==1){
if((as/10)==0){
as=as+50;
}else{
as=as-10;
}
}else if(key_count==2){
if((am%10)==0){
am=am+9;
}else{
am=am-1;
}
}else if(key_count==3){
if((am/10)==0){
am=am+50;
}else{
am=am-10;
}
}else if(key_count==4){
if((ah/10)==2){
if((ah%10)==0){
ah=ah+3;
}else{
ah=ah-1;
}
}else{
if((ah%10)==0){
ah=ah+9;
}else{
ah=ah-1;
}
}
}else if(key_count==5){
if((ah%10)<4){
if((ah/10)==0){
ah=ah+20;
}else{
ah=ah-10;
}
}else{
if((ah/10)==0){
ah=ah+10;
}else{
ah=ah-10;
}
}
}
}
void lcd_display(){
if(key_mode==0){
lcd_cmd(0×80);
if(a_on==1){
lcd_str(“a_on s]”);
}else{
lcd_str(“a_off s]”);
}
lcd_dat(ah/10+0×30);
lcd_dat(ah%10+0×30);
lcd_dat(‘:’);
lcd_dat(am/10+0×30);
lcd_dat(am%10+0×30);
lcd_dat(‘:’);
lcd_dat(as/10+0×30);
lcd_dat(as%10+0×30);
PORTC=0X00;
lcd_cmd(0xc0);
lcd_str(“time] “);
lcd_dat(h/10+0×30);
lcd_dat(h%10+0×30);
lcd_dat(‘:’);
lcd_dat(m/10+0×30);
lcd_dat(m%10+0×30);
lcd_dat(‘:’);
lcd_dat(s/10+0×30);
lcd_dat(s%10+0×30);
}else if(key_mode==1){
lcd_cmd(0×80);
lcd_str(“time setting “);
PORTC=0X00;
lcd_cmd(0xc0);
lcd_dat(h/10+0×30);
lcd_dat(h%10+0×30);
lcd_dat(‘:’);
lcd_dat(m/10+0×30);
lcd_dat(m%10+0×30);
lcd_dat(‘:’);
lcd_dat(s/10+0×30);
lcd_dat(s%10+0×30);
lcd_dat(‘ ‘);
if(key_count==0){
lcd_str(“1s “);
}else if(key_count==1){
lcd_str(“10s “);
}else if(key_count==2){
lcd_str(“1m “);
}else if(key_count==3){
lcd_str(“10m “);
}else if(key_count==4){
lcd_str(“1h “);
}else if(key_count==5){
lcd_str(“10h “);
}
}else if(key_mode==11){
lcd_cmd(0×80);
if(key_count==0){
lcd_str(“time(1s) change “);
}else if(key_count==1){
lcd_str(“time(10s) change “);
}else if(key_count==2){
lcd_str(“time(1m) change “);
}else if(key_count==3){
lcd_str(“time(10m) change “);
}else if(key_count==4){
lcd_str(“time(1h) change “);
}else if(key_count==5){
lcd_str(“time(10h) change “);
}
PORTC=0X00;
lcd_cmd(0xc0);
lcd_dat(h/10+0×30);
lcd_dat(h%10+0×30);
lcd_dat(‘:’);
lcd_dat(m/10+0×30);
lcd_dat(m%10+0×30);
lcd_dat(‘:’);
lcd_dat(s/10+0×30);
lcd_dat(s%10+0×30);
lcd_str(” “);
}else if(key_mode==2){
lcd_cmd(0×80);
lcd_str(“alarm setting “);
PORTC=0X00;
lcd_cmd(0xc0);
lcd_dat(ah/10+0×30);
lcd_dat(ah%10+0×30);
lcd_dat(‘:’);
lcd_dat(am/10+0×30);
lcd_dat(am%10+0×30);
lcd_dat(‘:’);
lcd_dat(as/10+0×30);
lcd_dat(as%10+0×30);
lcd_dat(‘ ‘);
if(key_count==0){
lcd_str(“1s “);
}else if(key_count==1){
lcd_str(“10s “);
}else if(key_count==2){
lcd_str(“1m “);
}else if(key_count==3){
lcd_str(“10m “);
}else if(key_count==4){
lcd_str(“1h “);
}else if(key_count==5){
lcd_str(“10h “);
}
}else if(key_mode==21){
lcd_cmd(0×80);
if(key_count==0){
lcd_str(“alarm(1s) change “);
}else if(key_count==1){
lcd_str(“alarm(10s) change “);
}else if(key_count==2){
lcd_str(“alarm(1m) change “);
}else if(key_count==3){
lcd_str(“alarm(10m) change “);
}else if(key_count==4){
lcd_str(“alarm(1h) change “);
}else if(key_count==5){
lcd_str(“alarm(10h) change “);
}
PORTC=0X00;
lcd_cmd(0xc0);
lcd_dat(ah/10+0×30);
lcd_dat(ah%10+0×30);
lcd_dat(‘:’);
lcd_dat(am/10+0×30);
lcd_dat(am%10+0×30);
lcd_dat(‘:’);
lcd_dat(as/10+0×30);
lcd_dat(as%10+0×30);
lcd_str(” “);
}else if(key_mode==3){
lcd_cmd(0×80);
lcd_str(“alarm setting “);
PORTC=0X00;
lcd_cmd(0xc0);
if(a_on==0){
lcd_str(“alarm off “);
}else if(a_on==1){
lcd_str(“alarm on “);
}
}
}
char buzzer=0;
char ir_go=0;
void alarm_oper(void){
if(a_on==1){
if(h==ah){
if(m==am){
if(s==as){
buzzer=1;
ir_go=1;
}
}
}
}
if(buzzer==1){
PORTD|=0X02;
}else{
PORTD&=0Xfd;
}
delay_ms(1);
if(ir_go==1){
ir_car_run();
}
}
char sr,sl,sf,sb;
char ad_data;
void senser(){
ADMUX=0X60; //어느핀 변화시킬건지
ADCSRA=0XC7; //ad 변환 시작
while((ADCSRA&0×10)==0); //변수=AD값 걸림
ad_data=ADCH; //변수값에 저장
if(ad_data<100){
sf=1;
}else{
sf=0;
}
delay_ms(1);
ADMUX=0X61; //어느핀 변화시킬건지
ADCSRA=0XC7; //ad 변환 시작
while((ADCSRA&0×10)==0); //변수=AD값 걸림
ad_data=ADCH; //변수값에 저장
if(ad_data<100){
sb=1;
}else{
sb=0;
}
delay_ms(1);
ADMUX=0X62; //어느핀 변화시킬건지
ADCSRA=0XC7; //ad 변환 시작
while((ADCSRA&0×10)==0); //변수=AD값 걸림
ad_data=ADCH; //변수값에 저장
if(ad_data<100){
sr=1;
}else{
sr=0;
}
delay_ms(1);
ADMUX=0X63; //어느핀 변화시킬건지
ADCSRA=0XC7; //ad 변환 시작
while((ADCSRA&0×10)==0); //변수=AD값 걸림
ad_data=ADCH; //변수값에 저장
if(ad_data<100){
sl=1;
}else{
sl=0;
}
delay_ms(1);
}
void ir_car_run(){
senser();
//전방 물체 감지
if(sf==0){
//전후방 물체 감지
if(sb==0){
//오른쪽 물체 감지
if(sr==0){
//오른쪽으로 회전 7
PORTC=0X9C;
}else{
//왼쪽으로 회전 6 5 4
PORTC=0X6C;
}
}else{
//후방으로 전진 3 0
PORTC=0X5C;
}
}else{
//후방 물체 감지
if(sb==0){
//전방으로 전진 2 0
PORTC=0XAC;
}else{
//오른쪽 물체 감지
if(sr==0){
//전방으로 전진 1
PORTC=0XAC;
}else{
//왼쪽 물체 감지
if(sl==0){
//전방으로 전진 1
PORTC=0XAC;
}else{
//정지 0
PORTC=0X00;
}
}
}
}
}
void putch(unsigned char ch){ /* 한개의 문자를 pc로 송신한다. */
while((UCSR0A & 0×20) == 0);
UDR0 = ch;
UCSR0A |= 0×20; // 문자 송신준비완료
}
char ir_oper;
void ir_remote(){
//RC카
if(ir_rx_flag == 1){//데이터 전송
ir_rx_flag =0;
putch(ir_rx_data[0]);
putch(ir_rx_data[1]);
putch(ir_rx_data[2]);
putch(ir_rx_data[3]);
ir_oper=1;
//rc_data=ir_rx_data[2];
}
if(ir_oper==1){
if(ir_rx_data[2]==0×05){
//전방
PORTC=0XAC;
}else if(ir_rx_data[2]==0×08){
//왼쪽
PORTC=0X9C;
}else if(ir_rx_data[2]==0x0a){
//오른쪽
PORTC=0X6C;
}else if(ir_rx_data[2]==0x0d){
//뒤로
PORTC=0X5C;
}else if(ir_rx_data[2]==0×04){
ir_go=1;
}else{
PORTC=0X00; }
ir_oper=0;
}
}
int main(void){
DDRA = 0Xff; //LCD
DDRC = 0Xff; //모터 구동
DDRD = 0×02; //리모컨 소자
DDRE = 0X0f; //스위치
DDRF = 0X00; //거리 측정 센서
//외무 인터럽트
EICRB = 0XFF;//상승 에지
EICRA = 0XFF;//상승 에지
EIMSK = 0Xf1;//0-초음파,1-리모컨
UBRR0H = 0;
UBRR0L = 103; // baud rate 9600
UCSR0A = 0;
UCSR0B = 0×98;
UCSR0C = 0×06;
//타이머 카운트 100us
TIMSK = 0X02;
TCCR0 = 0X0A;
OCR0 = 200;
SREG = 0X80;
putch(0×03);
lcd_init();
//lcd_ln11();
//lcd_str(“COME ON”);
delay_ms(10);
while(1){
//물체 회피 및 부저
alarm_oper();
//리모컨 컨트롤
ir_remote();
//키스위치
key_data();
//LCD
lcd_display();
//시간 카운터
clock_count();
delay_ms(10);
}
}
SIGNAL(INT4_vect){
// lcd_cmd(0×80);
// lcd_str(“adfag”);
// delay_ms(3000);
key_on=1;
key=4;
buzzer=0;
ir_go=0;
PORTC=0X00;
}
SIGNAL(INT5_vect){
key_on=1;
key=5;
buzzer=0;
ir_go=0;
PORTC=0X00;
}
SIGNAL(INT6_vect){
key_on=1;
key=6;
buzzer=0;
ir_go=0;
PORTC=0X00;
}
SIGNAL(INT7_vect){
key_on=1;
key=7;
buzzer=0;
ir_go=0;
PORTC=0X00;
}
SIGNAL(TIMER0_COMP_vect){
ir_timer_cnt++;
us100=us100+1;
if(us100==10000){
us100=0;
count_on=1;
}
}
SIGNAL(INT0_vect){
switch(ir_state){
case ir_ready : //오류 데이터
ir_state = ir_lead;
break;
case ir_lead ://시작 관련 데이터
//리드 펄스 데이터가 오면 4.5ms과 0.5ms의 합의 구간인 5ms
//0×30=48, 0×35=53이다
if((ir_timer_cnt>=0×30) && (ir_timer_cnt<0×35)){
ir_state = ir_data;
}else{
ir_state = ir_state;
}
ir_bit_cnt = 0;
ir_rx_temp = 0;
break;
case ir_data ://진짜 데이터 3번 데이터 활용
if((ir_timer_cnt>=8) && (ir_timer_cnt<15)){ //0데이터
}else if((ir_timer_cnt>=19) && (ir_timer_cnt<30)){//1데이터
ir_rx_temp = ir_rx_temp|0×80;
}else { //에러 데이터
ir_state = ir_lead;
break;
}
ir_bit_cnt++;
////8개의 비트가 다 들어 올 경우 데이터화 시킴
if((ir_bit_cnt%8)==0){
ir_rx_data[(ir_bit_cnt/8)-1] = ir_rx_temp;
ir_rx_temp = 0;
if(ir_bit_cnt >= 32){//모든 데이터 다 들어 올 경우
ir_state = ir_ready;
ir_bit_cnt = 0;
ir_rx_flag = 1;//새로운 데이터 인식 변수
}
}
ir_rx_temp = ir_rx_temp>>1;//데이터화 하는 과정
break;
default: break;
}
ir_timer_cnt = 0;
}