AVR 임베디드 학습/개인 프로젝트 공부

ATmega128 디지털 시계 만들기 (3탄)

9bexel9 2024. 10. 3. 15:54

ATmega128을 활용한 디지털시계 구현 3탄이다. 1탄에서는 대략적인 설명, 2탄부터 코딩 구현 관련 글을 작성하고 있다! 3탄에서는 2탄 다음으로 코드 작성 관련해서 글 작성해 보겠다.

 

timer.c



타이머 0번으로 오버플로 인터럽트로 100us 마다 인터럽트가 발생하게 만들었다. 그리고 PORTA, PORTD에 값을 reset 하여 초기화를 진행했다. 그리고 switch case 문을 활용하여 4 fnd, 2 fnd에 숫자 표현을 했는데 case0~6번까지 번호를 지정하여 각 case마다 fnd부분을 담당하게 만들었다.

변수 중 time_stop, flag 가 있는 이는 앞서 1탄에서 설명했듯이 디지털시계에 시간을 변경해야 할 상황이 발생했을 때 시간 변경 모드로 진입을 위한 time_stop, flag 변수를 지정한 것이다. 즉 기본상태에서는 time_stop이 0이므로 else문에 빠져 switch 문이 정상 동작하고 시간 변경 모드에서 time_stop 값에 0 이외에 값이 들어가게 되면서 진입하게 된다.

개발 프로젝트에서 사용하는 fnd는 4 fnd, 2 fnd로 총 6개의 fnd를 사용하고 있다. 위에 있는 switch 문에서 if~elseif문이 총 4개가 있는 것은 time_stop = 1,2,3일 때 각각 해당 fnd에 시간 변경 모드에 들어갔을 때 blink 효과를 주어 깜빡이게 만들고 싶어서이다. 즉 time_stop = 1 일 때는 빨간 네모에 있는 fnd가 blink 되면서 시간 변경모드에 들어갈 수 있다!라는 의미이다.

그렇게 진행되어 case는 0~5까지 fnd숫자에 맞춰 6개가 될 수 있다. 다음으로 fnd [n] 배열은 각 자리마다 step 값에 따라 지정된 자리에 초, 분, 시를 넣어주기 위해 변숫값을 지정했다. 관련된 time_sec 변수는 타이머 2번에 지정했는데 100ms마다 인터럽트를 발생시켜 1씩 time_sec가 증가할 수 있게 했다. 따라서 fnd [0] 같은 경우 초단위를 나타내는 변수이니 %10을 통해 0~9까지에 숫자를 표현할 수 있게 하였다. 


다음으로 timer2 오버플로 인터럽트로 1ms 마다 인터럽트가 발생하게 만들었다. timer2번 같은 경우는 스위치 모듈 제어용으로 만들었다.

Tact switch

 

다음은 내가 사용한 tact 스위치이다. 간략한 이론을 정리하자면 tact 스위치는 Push 스위치로 눌렸을 때 사용자가 원하는 동작을 하게 하는 스위치라고 한다. 즉 눌렀을 때나 눌렀다가 땠을때 스위치의 접점이 쇼트되어 pull-up 저항의 경우 1 -> 0 pull-down 저항의 경우 0 -> 1 인 상태로 변환된다(나의 경우 풀다운 저항으로 기본상태가 low인 상태이다). 이러한 이점을 활용하여 상승에지, 하강에지, 롱키 등 다양하게 스위치를 활용할 수 있다!!

다시 코드로 돌아와서 내가 사용한 방식은 우선 sw를 항상 값을 받는 것이 아니라 50ms 마다 스위치 체크를 하도록 만들어 채터링, 디바운싱을 어느 정도 방지? 했다. 스위치가 눌렸을 때 high, low가 여러 차례 나타나는 현상이 발생할 수 있는데 이를 방지하려고 했다. 

state 1 0
pre_state 0 1

또한 if(pre_state!= state)와 pre_state = state로 작성되어 있는 코드를 볼 수 있을 것이다. 이는 스위치가 눌렸을 때나 눌렸다가 땠을 때만 동작하도록 설계했다는 의미이다.( 여기서 state는 현재 스위치 상태를 의미하고 pre_state는 이전 스위치 상태를 의미한다.)

  1. state = 0, pre_state = 1
  2. state = 1, pre_state = 0

마지막으로 time_stop = 0일 때는 1s 마다 time_sec가 1씩 증가할 수 있도록 했고 time_stop이 다른 값일 경우 blink를 만들어 fnd가 깜빡일 수 있도록 만들었다.