[AVR] DP Blink/Stopwatch,Clock 구분 LED표시 시간 표시 기능

2021. 11. 9. 22:14코딩/AVR

main.c

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "global.h"      // 현재 내 디렉토리 밑에 있는 화일을 include할때는 ""
#include "fnd.h"
#include "button.h"
#include "time_clock.h"
//button : watch <--> stopwatch
//button2: stopwatch start <--> stop
//button3: stopwatch reset
#define WATCH 0
#define STOPWATCH 1
unsigned char mode_state=WATCH;
//for stopwatch
#define STOP 0
#define RUN 1
#define RESET 2
unsigned char stop_watch_state=STOP;
void inc_stop_watch_clock();
void stop_watch_stop_state();
void stop_watch_run_state();
void stop_watch_reset_state();
//0.001sec => 1ms마다 이곳으로 들어온다.
ISR(TIMER0_OVF_vect)
{
	static uint16_t sec_count=0;
	
	if (++sec_count >= 1000)
	{
		sec_count=0;
		inc_time_sec();
		
	}
	
	if (stop_watch_state == RUN)
	{
		inc_stop_watch_clock();
		
	}
	
	fnd_display();
	timeTick++;
}
uint16_t stop_watch_clock=0; //전역변수
void inc_stop_watch_clock()
{
	static uint8_t count =0;
	
	if (++count >= 100)
	{ 
		count =0;
		stop_watch_clock++;
		
	}
}
int main(void)
{
	TIME myTime;
	
	button_Init();
	fnd_init();
	//분주비를 64로 설정 16MHZ / 64 => 250KHZ 이렇게 설정시 TIM0 OV 256/250000
	//0.001sec => 1ms마다 타이머 int가 발생된다.
	
	TCCR0 |= (1 << CS02) | (0 << CS01) | (0 << CS00);
	TIMSK |= (1 << TOIE0); //	timer overflow int 설정 TCNT0의 register 값이256이 되는순간 발생
	sei();		//모든 인터럽트가 실행이 되도록 대문을 연다
	myTime.hour=00;
	myTime.min=00;
	myTime.sec=00;
	
	set_time_clock(myTime);
	
	// botton의 동작 상황을 체크하면서 상태 전이를 할수 있도록한다.
    while (1) 
    {
		switch (mode_state)
		{   
			case WATCH:
			
			get_time_clock(&myTime);
			
			set_fnd_data(myTime.min*100 + myTime.sec);
			if (getButton1State())	//버튼 1이 눌려졌다
			{	PORTA = 0x01;
				mode_state = STOPWATCH;
				
			} 
			
			break;
			
			case STOPWATCH:
		
		
			switch (stop_watch_state)
			{	
				case STOP:
				stop_watch_stop_state();
				break;
				
				case RUN:
				stop_watch_run_state();
				break;
				
				case RESET:
				stop_watch_reset_state();
				break;
			}
			if (getButton1State())	//버튼 1이 눌려졌다
			{	PORTA = 0x02;
				mode_state = WATCH;
				
			}
		}
		
	 }
}
void stop_watch_stop_state()
{
	set_fnd_data(stop_watch_clock);
	
	if (getButton2State())	//버튼1을 누르면 
	{
		stop_watch_state=RUN; //run상태로 상태처리
	}
	if (getButton3State())	//버튼 2를 누름 reset버튼
	{
		stop_watch_state=RESET;	//
	}
}
// 현제 스톱워ㅣ가 돌고있는 상태에서 버튼 1 누르면 스탑상태
void stop_watch_run_state()
{
	set_fnd_data(stop_watch_clock);
	
	if (getButton2State())	//버튼1을 누르면
	{
		stop_watch_state=STOP; //STOP상태로 상태처리
	}
}
//현제 스톱워치가 리셋상태에서 STOP모드로 복귀
void stop_watch_reset_state()
{
	stop_watch_clock=0;
	set_fnd_data(stop_watch_clock);
	stop_watch_state=STOP;	//stop상태로 전이
}

 

fnd.c

#include "fnd.h"
#include "extern.h"

uint16_t fnd_data;

void set_fnd_data(uint16_t data)
{
	fnd_data = data;
}
uint16_t get_fnd_data()
{
	return fnd_data;
}

void set_sec(uint32_t sec)
{
	sec_data = sec;  // 초를 받아서 save
}
void fnd_display(void)
{
	#if 1   // common 애노우드
	uint8_t fnd_font[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xd8,0x80, 0x98}; // common +가 공통애노우드
	#else
	uint8_t fnd_font[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x27,0x7f, 0x67}; // common -가 캐소우드
	#endif
	
	uint16_t data = get_fnd_data();   // 현재의 초를 가져 온다. 
	
	uint8_t dot[]={0x7f,0xff}; // 01111111  11111111 을 의미 dp만 빛이들어오거나 안들어오거나 신호를줌
	
	FndPositionState++;
	FndPositionState %=4;   // FndPositionState = FndPositionState % 4;와 동일
	
	switch(FndPositionState)
	{
		case 0:   // digit1 선택  1000의 자리
		FND_DIGIT_PORT = 0b10000000;  // D1만ON 시키고 나머지는 OFF FND_DIGIT_PORT = 0b01111111;
		FND_DATA_PORT=fnd_font[data/1000%10];  // 60분이 되기 전까지의 값을 출력 0~59분
		// and문을 사용하여 양쪽이 다 신호가 들어갈때 만 신호가 출력됨 에노드 문이기 때문에  0일때 출력이 들어간다
		//0x7f일때 출력이 들어가서 dp에 신호가 나오고 0xff일때 0과1의 and가 되어서 출력이 나오지 않는다
		
		break;
		
		case 1:   // digit2 선택  100의 자리
		FND_DIGIT_PORT = 0b01000000;  // D2만ON 시키고 나머지는 OFF FND_DIGIT_PORT = 0b01111111;
		FND_DATA_PORT= (fnd_font[data/100%10] & dot[data%2]);  // 10분이 되기 전까지의 값을 출력 0~9분
		break;
		 //dot[data/10%2]
		case 2:   // digit3 선택  10의 자리
		FND_DIGIT_PORT = 0b00100000;  // D3만ON 시키고 나머지는 OFF FND_DIGIT_PORT = 0b01111111;
		FND_DATA_PORT= fnd_font[data/10%10];  // 1분이 되기 전까지의 값을 출력 0~59초 출력
		break;
		
		case 3:   // digit4 선택  1의 자리
		FND_DIGIT_PORT = 0b00010000;  // D4만ON 시키고 나머지는 OFF FND_DIGIT_PORT = 0b01111111;
		FND_DATA_PORT= fnd_font[data%10];  // 10가 되기 전의 값을 출력 (0~9)
		
		break;
	}
}

void fnd_init(void)
{
	FND_DATA_DDR=0xff;
	FND_DIGIT_DDR=0xff;
	FND_DIGIT_PORT=0x00;
	FND_LED_PORT=0x00;
	FND_LED_DDR=0xff;
}

동작 동영상

상단의 붉은 LED 2개를 각각 모드에 따라 빛나게 하였습니다.

'코딩 > AVR' 카테고리의 다른 글

[AVR]출입 통제 시스템  (3) 2021.11.09
[AVR] 계산기  (0) 2021.11.09
[AVR]전자레인지 동작 동영상  (0) 2021.11.09
[AVR] 모터 속도제어 (선풍기)  (0) 2021.11.09
[AVR] UltraSonic 활용  (0) 2021.11.09