1탄에서는 출력만 했는데
이번 2탄에서는 셋업, 출력 두가지를 모두 했습니다. ^^;;
#define F_CPU 16000000 //Clock frequency
#define F_SCL 100000 //100kHz
#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <util/twi.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define DS1307_R 0xD1
#define DS1307_W 0xD0
#define DS1307_YEAR 0x06
#define DS1307_MONTH 0x05
#define DS1307_DATE 0x04
#define DS1307_DAY 0x03
#define DS1307_HOUR 0x02
#define DS1307_MIN 0x01
#define DS1307_SEC 0x00
struct Read_DT{
unsigned char yr, mh, date, dday, hours, minutes, seconds;
};
void i2c_init(void) {
TWSR = 0;
TWBR = ((F_CPU / F_SCL) - 16) / 2; //100kHz
TWCR = 0x04; //TWI Enable
}
int i2c_start(void) {
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // Send Start Condition
while((TWCR & (1<<TWINT))==0); // Wait for TWINT Flag set
return 0;
}
int i2c_write(unsigned char data) {
TWDR = data; // Load "data" into TWDR Register.
TWCR = (1<<TWINT)|(1<<TWEN); // Clear TWINT bit in TWCR to start transmission of address
while((TWCR & (1<<TWINT)) == 0); // Wait for TWINT Flag set
return 0;
}
unsigned char i2c_read() {
TWCR = (1<<TWINT)|(1<<TWEN);
while((TWCR & (1<<TWINT)) == 0);
return TWDR;
}
int i2c_stop(void) {
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // Transmit STOP Condition
return 0;
}
unsigned char i2c_getc(unsigned char cmd) {
i2c_start();
i2c_write(DS1307_W);
i2c_write(cmd);
i2c_start();
i2c_write(DS1307_R);
unsigned char data = i2c_read();
i2c_stop();
_delay_us(5);
return data;
}
void Tx_Char(char Tdata) {
while(!(UCSR0A & (1<<UDRE0)));
UDR0 = Tdata;
}
void Tx_String(char *str) {
while(*str) {
Tx_Char(*str++);
}
}
Read_DT DS1307_now() {
Read_DT i;
i.yr = i2c_getc(DS1307_YEAR);
i.yr = ((i.yr>>4) & 0x0F)*10 + (i.yr & 0x0F);
i.mh = i2c_getc(DS1307_MONTH);
i.mh = ((i.mh>>4) & 0x01)*10 + (i.mh & 0x0F);
i.date = i2c_getc(DS1307_DATE);
i.date = ((i.date>>4) & 0x03)*10 + (i.date & 0x0F);
i.dday = i2c_getc(DS1307_DAY);
i.dday = (i.dday & 0x07);
i.hours = i2c_getc(DS1307_HOUR);
i.hours = ((i.hours>>4) & 0x07)*10 + (i.hours & 0x0F);
i.minutes = i2c_getc(DS1307_MIN);
i.minutes = ((i.minutes>>4) & 0x07)*10 + (i.minutes & 0x0F);
i.seconds = i2c_getc(DS1307_SEC);
i.seconds = ((i.seconds>>4) & 0x07)*10 + (i.seconds & 0x0F);
return i;
}
void DS1307_set(byte ss, byte mm, byte hr, byte wd, byte md, byte mh, byte yr) {
i2c_start();
i2c_write(DS1307_W);
i2c_write(0x00);
i2c_write(DecToBcd(ss)); //seconds
i2c_write(DecToBcd(mm)); //min
i2c_write(DecToBcd(hr)); //hour
i2c_write(DecToBcd(wd)); //weekday
i2c_write(DecToBcd(md)); //day
i2c_write(DecToBcd(mh)); //month
i2c_write(DecToBcd(yr)); //year
i2c_write(0x00);
i2c_stop();
_delay_us(5);
}
byte DecToBcd(byte val) {
return ((val/10*16) + (val%10));
}
int main(void) {
char str[30];
UCSR0A = 0;
UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0); //RX INT EN, RX & TX Enable
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); //8bit no parity
UBRR0H = 0; UBRR0L = 8;
i2c_init();
// DS1307_set(50, 2, 17, 3, 17, 7, 18);
while(1) {
char *dday;
Read_DT dt;
dt = DS1307_now();
switch(dt.dday) {
case 0:
dday = "SUN";
break;
case 1:
dday = "MON";
break;
case 2:
dday = "TUE";
break;
case 3:
dday = "WED";
break;
case 4:
dday = "TUR";
break;
case 5:
dday = "FRI";
break;
case 6:
dday = "SAT";
break;
}
sprintf(str, "%02d-%02d-%02d %02d:%02d:%02d %s\r\n", dt.yr+2000, dt.mh, dt.date, dt.hours, dt.minutes, dt.seconds, dday);
Tx_String(str);
_delay_ms(500);
}
}
조금 비교를 하자면
구조체를 이용해서 RTC 데이터를 묶어서 이해하기 편하게 했습니다.
그리고 DS1307_now(), DS1307_set(byte..) 함수를 만들었습니다.
DS1307_now함수는 현재시간을 알려주는 함수이고 set함수는 RTC를 셋업하는 함수입니다.
동작을 한번 시켜보면 금방 알수 있을 듯 합니다. ^^
알람시계는 이제 금방 만들수 있지 않을까요?? ㅎㅎ
반응형
'b. 임베디드 > AVR' 카테고리의 다른 글
[ATtiny2313A] Blink 예제 (0) | 2018.11.16 |
---|---|
[ATmega328] Nokia 5110 LCD (GLCD) bmp파일 출력하기 (0) | 2018.08.18 |
[ATmega328] Nokia 5110 LCD (GLCD) 문자 출력하기 (0) | 2018.08.04 |
[ATmega328] 알람시계 만들기 (DS1307RTC, 부저) 1탄 (0) | 2018.08.04 |
[ATmega328] 아두이노 Uno 핀맵 (0) | 2018.08.04 |
[ATmega328] DS1307 RTC I2C(TWI)통신 1탄 (0) | 2018.08.04 |
[ATmega328] UART통신 송수신 예제 (0) | 2018.08.04 |
[ATmega328] ADC 사용하기 (0) | 2018.08.03 |