당근보드의 FND를 이용해 시계 만들기(DS1307 이용)

글 내용

당근보드의 디스플레이 보드에는 4개의 FND와 8개의 LED(8개중 동시에 사용가능한 LED는 4개)가 있습니다.
또한 메인보드에는 DS1307과 32.768khz의 크리스탈이 달려 있습니다.
이제 이 소자들을 활용하여 당근보드를 시계로 사용해 보겠습니다.

사용자 삽입 이미지

당근보드 디스플레이부의 모습.

당근보드에는 위와 같은 디스플레이부가 있습니다. 보시다시피 8개의 LED가 있으며 4개의 점퍼 설정으로 시계처럼 LED를 사용할것인지, 아니면 밑에 4개의 LED가 일렬로 있는 부분을 사용할 것인지 정할수 있습니다.
저는 점퍼를 모두 위에 연결하여 시계부분에 있는 녹색1개, 노란색1개, 빨간색2개를 사용하겠습니다.
그리고 당연히 4개의 FND를 사용해야겠지요.

제가 쓰는 당근보드는 보드 색이 녹색입니다.(위 사진은 당근이의AVR갖고놀기 카페에서 가져왔습니다) 그리고 LED를 고휘도 LED로 달아놓았지요.. 볼땐 멋있었는데 시계로 해놓으니 눈아파서 못보겠네요.ㅡㅡ;
아무튼 녹색 LED를 '오전'을 표시하는 LED로, 노란색 LED를 '오후'를 표시하는 LED로 사용하겠습니다.
또한 중간의 빨간색 2개의 LED는 약 0.5초 간격으로 깜빡이는 용도로 사용합니다.

시계IC인 DS1307은 32.768Khz 크리스탈과 함께 사용하며, 년, 월, 일, 요일, 시, 분, 초 를 나타낼 수 있습니다.
통신 방식은 I2C(TWI) 이며, DATASHEET는 아래에서 다운 받을수 있습니다.


I2C는 따로 열심히 공부하셔야 하구요, 저는 대충만 공부하고 소스를 구해다가 입맞에 맞게 고쳐 쓴 것입니다...ㅎ
제가 사용한 소스를 공개합니다. 이 소스는 엄청나게 큰 문제점이 있는데요.
시간 설정이 안된다는 겁니다. 그래서 소스를 넣을때 한번은 시간을 설정한 소스를 한번 넣어주고, 그담에 시간설정 부분이 없는 소스를 넣어줘 사용하면 됩니다. ㅎㅎ 시간 설정하는건 귀찮아서 넣지 않았습니다.ㅡㅡ;

그리고 이상하게 전원을 끊었다가 넣어주면 I2C 통신이 안되는가 봅니다. FND에 이상한 값이 출력됩니다.
이럴땐 백업 배터리 입력핀인 3번핀을 GND에 연결시켜준 후 리셋버튼을 누르면 또 잘 동작 하더군요...;;
왜이런지 아직 원인을 모르겠습니다. 데이터시트엔 백업배터리를 사용하지 않으면 Vbat 를 GND에 연결하라고 돼있길래 그리 해보니 되긴 하는데 전 백업배터리도 있고,, 배터리가 다 닳았나...ㅡㅡ;;;;;

아무튼 소스를 공개합니다~ 자자자잔!

#include <avr/io.h>
#include <stdio.h>
#include <carroty/delay.h>
#include <carroty/fnd.h>

unsigned char number_array[16]= { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, };
unsigned char fnd_sel_array[4]= { 0,0,0,0,};
unsigned char hour, min;
int n1000, n100, n10, n, time;

void rtc_write(unsigned char address, unsigned char byte) {
 delay_us(6);
 TWCR = 0xA4;      // START condition
 while(((TWCR & 0x80) == 0x00) || (TWSR & 0xF8) != 0x08);
 
 TWDR = 0xD0;
 TWCR = 0x84;      // MT_SLA_ACK
 while(((TWCR & 0x80) == 0x00) || (TWSR & 0xF8) != 0x18);
 
 TWDR = address;
 TWCR = 0x84;      // MT_DATA_ACK
 while(((TWCR & 0x80) == 0x00) || (TWSR & 0xF8) != 0x28);
 
 TWDR = byte;
 TWCR = 0x84;      // MT_DATA_ACK
 while(((TWCR & 0x80) == 0x00) || (TWSR & 0xF8) != 0x28);
 
 TWCR = 0x94;      // STOP condition
}

unsigned char rtc_read(unsigned char address) {
 delay_us(6);
 unsigned char byte;
 
 TWCR = 0xA4;      // START condition
 while(((TWCR & 0x80) == 0x00) || (TWSR & 0xF8) != 0x08);
 
 TWDR = 0xD0;
 TWCR = 0x84;      // MT_SLA_ACK
 while(((TWCR & 0x80) == 0x00) || (TWSR & 0xF8) != 0x18);
 
 TWDR = address;
 TWCR = 0x84;      // MT_DATA_ACK
 while(((TWCR & 0x80) == 0x00) || (TWSR & 0xF8) != 0x28);
 
 TWCR = 0xA4;      // RESTART condition
 while(((TWCR & 0x80) == 0x00) || (TWSR & 0xF8) != 0x10);
 
 TWDR = 0xD1;
 TWCR = 0x84;      // MR_SLA_ACK
 while(((TWCR & 0x80) == 0x00) || (TWSR & 0xF8) != 0x40);
 
 TWCR = 0x84;      // MR_DATA_NOACK
 while(((TWCR & 0x80) == 0x00) || (TWSR & 0xF8) != 0x58);
 byte = TWDR;
 
 TWCR = 0x94;      // STOP condition
 return byte;
}

void display_fnd(unsigned char number, unsigned char fnd_select) {
 PORTB= number;
 PORTC= fnd_select;
}

void time_print(unsigned int value) {
 
 n1000=value/1000;
 n100=(value-(value/1000*1000))/100;
 n10=(value-(value/100*100))/10;
 n=value-(value/10*10);
 int g;
 for(g=0;g<10;g++){
  display_fnd(number_array[n1000], fnd_sel_array[0]); delay_ms(3);
  display_fnd(number_array[n100], fnd_sel_array[1]);  delay_ms(3);
  display_fnd(number_array[n10], fnd_sel_array[2]); delay_ms(3);
  display_fnd(number_array[n], fnd_sel_array[3]);  delay_ms(3);
 }
}

void led_init(void) {
 DDRB= 0xFF;
 DDRC= 0xF0;
 DDRA= 0xF0;
}

int main(void) {
 TWBR= 72;  
 TWSR= 0x00;
 TWCR= 0x04;      
 number_array[0]=  NUMBER_0;
 number_array[1]=  NUMBER_1;
 number_array[2]=  NUMBER_2;
 number_array[3]=  NUMBER_3;
 number_array[4]=  NUMBER_4;
 number_array[5]=  NUMBER_5;
 number_array[6]=  NUMBER_6;
 number_array[7]=  NUMBER_7;
 number_array[8]=  NUMBER_8;
 number_array[9]=  NUMBER_9;
 
 fnd_sel_array[0]= FND_SEL_1;
 fnd_sel_array[1]= FND_SEL_2;
 fnd_sel_array[2]= FND_SEL_3;
 fnd_sel_array[3]= FND_SEL_4;
 led_init();  

 /*  시간 설정 부분.
 rtc_write(0x06,0x09);
 rtc_write(0x05,0x09);
 rtc_write(0x04,0x25);
 rtc_write(0x03,0x05); 
 rtc_write(0x02,0x02);
 rtc_write(0x01,0x17);  
 rtc_write(0x00,0x00);   */
 
 PORTA=0xF0;
 int h=0;
 while(1) {
 
  hour=   rtc_read(0x02);
  hour=   ((hour >>4) & 0x07)*10 + (hour & 0x0f);
 
  min=    rtc_read(0x01);
  min=    ((min >>4) & 0x07)*10 + (min & 0x0f);
 
  if(hour>12){
   //hour=hour-12;
   PORTA=PORTA&0b11011111;
   PORTA=PORTA|0b00010000;
  }
  else {
   PORTA=PORTA&0b11101111;
   PORTA=PORTA|0b00100000;
  }
 
  time=hour*100+min;
  time_print(time);
  h++;
  if(h>4) {
   h=0;
   PORTA^=0xC0;
  }
 }
}



ㅎㅎㅎ 코딩실력이 부족해 소스가 난잡합니다.ㅡㅡ; 이해하시길;;;ㅎㅎ
그럼 동작 하는 모습을 보시죠~

현재 새벽이므로 오전이라는 표시인 노란색 LED가 들어와있습니다.
그리고 빨간색 LED 2개가 깜빡이는데 0.5초마다 깜빡이는건 아니고 그냥 대충 깜빡이는것입니다...;;
하지만 시계는 정확하지요.ㅎㅎㅎ


  1. user picture
    비밀댓글입니다
    • user picture
      위 시계는 '당근이의 AVR갖구놀기' 라는 네이버 카페에서 공동구매를 통해 판매하는 일종의 AVR 실습 KIT 입니다. 제가 만든게 아니구 구입한 것이지요...

      회로도와 재료등은 모두 위 카페에 가시면 있습니다^^
  2. user picture
    당근보드
    RTC 시계 및 설정 완성 소스 있나요??

    보드를 제대로 갖고 놀지도 못하고 있어요 ㅠㅠ
    • user picture
      시계 소스는 위에 포스팅에 올려놨구요..ㅎㅎ 설정하는 부분은 따로 구현하지 않았습니다..
      공부하시는겸 해서 한번 작성해 보시는것도 도움이 될것같습니다^^
      인터럽트를 이용하면 쉽게 가능할것도 같네요..ㅎㅎ;;;

티스토리 툴바