Open changheepark-dev opened 11 months ago
/* * 프로그램 이름 : 11주차 과제 * 프로그램 내용 : LCD 스위치 버저 LED 인터럽트 타이머 UART 통신 * Created: 2023-11-13 오후 6:17:00 * Author : 1922288 박창희 * 마지막 수정일 : 2023-11-18 오후 10:38:00 * 마지막 수정내용 : 키보드 3입력 */ #define F_CPU 16000000UL // 16MHz의 오실레이터를 사용 #include <avr/io.h> //입출력 포트 사용을 위한 헤더 include #include <avr/delay.h> //딜레이 사용을 위한 헤더 inlcude #include <avr/interrupt.h> //인터럽트 사용을 위한 헤더 include #include "lcd.h" //LCD 사용을 위한 헤더 include -> " "외부의 파일을 include #include "uart.h" #include <stdlib.h> // 랜덤 사용 /* 외부 인터럽트 */ int value1 = 0, trial_n = 16, ckd = 0; ISR(INT0_vect) { cli(); if(!(PIND & (1<<PD0)) && value1 != 777 && trial_n !=0) { ckd = 1; } } void INTR_Init() { EICRA = (0b10<<ISC00); //하강엣지 트리거 EIMSK = (1<<INT0); //인터럽트 0 허용 PORTD |= (1<<PD0); //스위치를 PORTD 0번에 연결 sei(); //전역인터럽트 활성화 } /* 외부 인터럽트 끝 */ /* 타이머 */ volatile int count = 0, count_m = 1000, dis = 0; //오버플로우가 발생한 횟수 ISR(TIMER1_COMPA_vect) { count++; if (count > 5) { count_m--; if (dis == 1) { LCDMove(1,11); LCD_nNum1(count_m); } if (count_m <= 0) { TIMER1_Initx(); } count = 0; } } void TIMER1_Init() { TCCR1A = (0<<WGM11) | (1<<WGM10); TCCR1B = (0<<WGM13) | (0<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10); TIMSK |= (1 << OCIE1A); OCR1A = 128; sei(); //전역인터럽트 활성화 } void TIMER1_Initx() { TCCR1A = (0<<WGM11) | (0<<WGM10); TCCR1B = (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10); TIMSK |= (0 << OCIE1A); OCR1A = 128; } /* 타이머 끝 */ /*AD 변환*/ int readAnalog(unsigned char ch) // AD 채널 값을 받아서 AD를 값을 읽어오는 함수. { int res; ADCSRA = 1<<ADEN | 0b111<<ADPS0; // 128 분주율로 AD를 사용 인에이블 설정 ADMUX = 0b01<<REFS0 | ch<<MUX0; // AREF를 기준전압으로 사용, AREF와 GND사이에 콘덴서 접속 ADCSRA |= 1<<ADSC; // A/D 변환 시작 while((ADCSRA & (1<<ADIF))) {} // A/D 변환완료인터럽트플래그비트 ADC 완료 대기 res = ADC; // 결과값을 res 변수에 넣음 return res; } /*숫자 변환*/ int LCD_nNum1(unsigned int NUM) { unsigned char Buff[8] = "0"; Buff[0] = '0'+((NUM %1000)/100); Buff[1] = '0'+((NUM %100)/10); Buff[2] = '.'; Buff[3] = '0'+(NUM %10); Buff[4] = 's'; LCDPuts(Buff); } int LCD_nNum2(unsigned int NUM) { unsigned char Buff[8] = " 0"; Buff[0] = '0'+((NUM %10000)/1000); Buff[1] = '0'+((NUM %1000)/100); Buff[2] = '0'+((NUM %100)/10); Buff[3] = '0'+(NUM %10); for (unsigned char i=0; i<=2; i++) { if (Buff[i] != '0') { break; } Buff[i]=' '; } Buff[4]= '\0'; LCDPuts(Buff); } int LCD_nNum3(unsigned int NUM) { unsigned char Buff[8] = "0"; Buff[0] = '0'+((NUM %100)/10); Buff[1] = '0'+(NUM %10); LCDPuts(Buff); } /*숫자 변환 끝*/ int receivedData = 0; int main(void) { restart: DDRB |= 0xf0; //7~4 LED 3~0 스위치가 연결되어 있다. 상위 니블 7~4까지는 출력을로 설정 하위 니블 3~0 입력으로 설정 DDRG |= (1<<PG3); //PG3번에 buzzer 연결되어있음 UDR0 |= 0x00; dis = 0; INTR_Init(); // 인터럽트 사용을 위한 초기화 MCU_Init(); //LCD 사용을 위한 MCU 설정 UART_INIT(); // UART 통신 초기화 ( 9600 ) TIMER1_Init(); LCDInit(); //LCD 사용을 위한 초기화 설정 static char string1[]="- 2 team : DEA -"; static char string2[]="Start with 3"; static char string3[]="ready 0 "; while (1) { LCDMove(0,0); //표시할 문자의 위치를 선택->HOME 위치 LCDPuts(string1); LCDMove(1,0); //LCD의 두번쨰 줄 LCDPuts(string2); if(0 == (PINB & (1<<PB0)) || (UDR0 != 0x00)) { UDR0 |= 0x00; srand(TCNT1); value1 = rand() % 103; for (unsigned int i=3; i>0; i--) { LCDMove(1,0); //LCD의 두번쨰 줄 string3[6] = '0' + i; LCDPuts(string3); _delay_ms(1000); } LCDInit(); count_m = 1000; TIMER1_Init(); break; } } static char passwd[]="passwd:"; static char trial[]="trial:"; static char down[]="down"; static char up[]="up "; static char hit[]="hit "; int analog = 0; dis = 1; trial_n = 15; while (1) { //receivedData = UART_receive(); analog = readAnalog(6); //가변저항 ADC 6,7번에 연결 LCDMove(0,0); LCDPuts(passwd); LCDMove(0,7); //home 위치 LCD_nNum2(analog); LCDMove(1,0); LCDPuts(trial); LCD_nNum3(trial_n); PORTB = trial_n << 4; if (trial_n == 0) { TIMER1_Initx(); PORTG |= (1<<PG3); //buzzer ON if(0 == (PINB & (1<<PB0)) || (UDR0 != 0x00)) { UDR0 |= 0x00; PORTG &= ~(1<<PG3); //buzzer OFF goto restart; } } // 인터럽트 처리 if (ckd == 1) { trial_n --; int ck = analog / 10; if (value1 == ck) { LCDMove(0,12); LCDPuts(hit); LCDMove(0,0); value1 = 777; PORTB = 0x00; } else if (value1 > ck) { LCDMove(0,12); LCDPuts(up); LCDMove(0,0); } else { LCDMove(0,12); LCDPuts(down); LCDMove(0,0); } _delay_ms(500); ckd = 0; } //재시작 if(0 == (PINB & (1<<PB0)) || (UDR0 != 0x00)) { UDR0 |= 0x00; goto restart; } // 저항 체크 성공 if(value1 == 777) { TIMER1_Initx(); for (int b = 3; b < 7; b++){ PORTG = (b % 2 << PG3); //buzzer ON _delay_ms(100); } while(1){ if(0 == (PINB & (1<<PB0)) || (UDR0 != 0x00)) { UDR0 |= 0x00; PORTG &= ~(1<<PG3); //buzzer OFF goto restart; } } } // 부저 int bz(void){ PORTG |= (1<<PG3); //buzzer ON _delay_ms(10); PORTG &= ~(1<<PG3); //buzzer OFF _delay_ms(10); } switch (count_m) { case 900: case 800: case 700: case 600: bz();break; case 500: bz();bz();bz();break; case 450: case 400: case 350: case 300: bz();break; case 250: bz();bz();bz();break; case 225: case 200: case 175: case 150: bz();break; case 125: bz();bz();bz();break; case 112: case 100: case 88: case 75: bz();break; case 62: bz();bz();bz();break; case 55: case 49: case 43: case 37: bz();break; case 31: bz();bz();bz();break; case 28: case 25: case 22: case 19: case 16: case 13: case 10: case 7: case 4: case 1: bz();break; case 0: while(1) { TIMER1_Initx(); PORTG |= (1<<PG3); //buzzer ON if(0 == (PINB & (1<<PB0)) || (UDR0 != 0x00)) { UDR0 |= 0x00; PORTG &= ~(1<<PG3); //buzzer OFF goto restart; } } } } }