/*
0번핀 500ms 토글
1번 200ms 토글
2번핀입력일경우 나머지 6개 LED 로테이트 200ms
3번 모두 오프
4번 모두 온
5번 3개 온 3개 오프
6번 2개씩 led 프래쉬
7번 징검다리 온오프 온오프
*/
#include<stdio.h>
#include<avr/interrupt.h>
#include<avr/signal.h>
#define CPU_CLOCK 16000000
#define TICKS_PER_SEC 1000
#define Prescaler 64
#define OVERFLOW 256
volatile unsigned int cnt;
volatile unsigned int tic_time;
volatile unsigned int tic_time2;
volatile unsigned int oc1cnt;
volatile unsigned int oc3cnt;
volatile unsigned int FUN_MODE;
volatile unsigned char KEY_STATE;
volatile unsigned char CURRENT_KEY_STATE;
volatile unsigned char LAST_KEY_STATE;
void init_port(void);
void init_timer(void);
void init_timer0(void);
void init_timer1(void);
void init_timer3(void);
void fun_run(void);
int main(void){
CURRENT_KEY_STATE=0xFF;
LAST_KEY_STATE=0xFF;
init_port();
init_timer();
init_timer0();
init_timer1();
init_timer3();
sei();
while(1){
if(FUN_MODE!=0)
if(tic_time2>=200){ tic_time2=0; fun_run(); }
CURRENT_KEY_STATE=PINF; // SW에 값을 CURRENT_KEY_STATE에 넣어줌
if(CURRENT_KEY_STATE!=0xFF){
// CURRENT_KEY_STATE가 0xFF가 아닌 경우(어느 키라도 눌렸을경우)
if(CURRENT_KEY_STATE!=LAST_KEY_STATE){
// 지금 누른키와 눌린키가 아닐 경우 (키가 변경된 경우)
tic_time=0;
KEY_STATE=0;
}
if(tic_time>=50){
// 키를 누르고 50ms가 지났으면 (계속 눌려잇는 경우)
if(KEY_STATE==0){
KEY_STATE=1;
if(CURRENT_KEY_STATE==0xFE) sbi(DDRB,5); // oc1a를 출력으로 설정
if(CURRENT_KEY_STATE==0xFD) sbi(DDRE,3); // oc3a를 출력으로 설정
if(CURRENT_KEY_STATE==0xFB) FUN_MODE=1;
if(CURRENT_KEY_STATE==0xF7) FUN_MODE=2;
if(CURRENT_KEY_STATE==0xEF) FUN_MODE=3;
if(CURRENT_KEY_STATE==0xDF) FUN_MODE=4;
if(CURRENT_KEY_STATE==0xBF) FUN_MODE=5;
if(CURRENT_KEY_STATE==0x7F) FUN_MODE=6;
}
}
}
else KEY_STATE=0; // PINA가 0xFF인경우는 KEY_STATE를 0으로 초기화 시켜준다.
LAST_KEY_STATE=CURRENT_KEY_STATE; // 현재 눌린키를 눌려진 키로 넣어줌
if(tic_time>=1000){
// 키를 누르지 않을 경우에 생기는 문제점을 해결하기 위해서
// tic_time은 int형 변수이기에 넘어가게 되면 오버 플로우가 발생될가능성도 있다.
// 그것뿐만 아니라 예를 들어 키보드 방향키 위를 생각해보면
// 위를 한번 꾸우우우욱 누른경우랑
// 위를 한번 꾹 누른 경우랑 같게 된다는것이다.
tic_time=0;
LAST_KEY_STATE=0xFF;
}
}
return 0;
}
void init_port(void){
DDRF=0x00;
DDRC=0xFF;
PORTC=0xFF;
}
void init_timer(void){
// 타이머에 관한 전반적인 공통사항을 기술
TIFR=0x00;
}
void init_timer0(void){
// 타이머0에 대한 설정
TCCR0=0x04;
TCNT0=OVERFLOW - (CPU_CLOCK / TICKS_PER_SEC / Prescaler);
TIMSK=0x01;
}
void init_timer1(void){
// 타이머1에 대한 설정
TCNT1H=0x00;
TCNT1L=0x00;
TCCR1A=0x40;
TCCR1B=0x0C;
TCCR1C=0x00;
OCR1AH=0x7A;
OCR1AL=0x12;
TIMSK=TIMSK|(1<OCIE1A);
}
void init_timer3(void){
// 타이머3에 대한 설정
TCNT3H=0x00;
TCNT3L=0x00;
TCCR3A=0x40;
TCCR3B=0x0C;
TCCR3C=0x00;
OCR3AH=0x18;
OCR3AL=0x6A;
TIMSK=ETIMSK|(1<OCIE3A);
}
SIGNAL(SIG_OVERFLOW0){
// 오버 플로우 인터럽트 발생시 (timer0에서 발생되는..)
tic_time++;
tic_time2++;
TCNT0 = OVERFLOW - (CPU_CLOCK / TICKS_PER_SEC / Prescaler);
}
SIGNAL(SIG_OUTPUT_COMPARE1A){
}
SIGNAL(SIG_OUTPUT_COMPARE3A){
}
void fun_run(void){
switch(FUN_MODE){
case 1:
break; // 6개 로테이트
case 2: PORTC=0x3F; break; // 6개 OFF 해결
case 3: PORTC=0x00; break; // 6개 on 해결
case 4: PORTC=0x38; break; // 6개 3on 3off 해결
case 5: PORTC=0xFF<<cnt);
break; // 2개씩 반복
case 6: PORTC=0xAA; break; // onoffonoff 해결
}
}
Posted by rCan

