rtc
-
Upload
david-tanady -
Category
Documents
-
view
45 -
download
0
Transcript of rtc
RTC
Tujuan :
Agar kami dapat memahami Real Time Clock dan memanfaatkan untuk membuat program
dengan mengimpelentasi penggunaan data , control dan status bus dari AVR untuk
menghubungkan dengan Real Time Clock DS1307.
Teori :
Prinsip dari Real Time Clock
Real time clock pada dasarnya seperti jam biasa yang bekerja dengan baterai dan tetap
menghitung waktu walaupun supply daya dimatikan. Dengan menggunakan RTC, kamu dapat
tetap menjaga perhitungan waktu walaupun microcontroller yang digunakan diprogram ulang
ataupun dicabut dari USB ataupun dari sumber daya.
Kebanyakan microcontroller, termasuk ABR pada Codevision ABR mempiliki built-in
timekeeper yang disebut dengan millis() dan terdapat timer yang terintegrasi dalam chip yang
dapat menghitung periode waktu seperti menit ataupun hari. Permasalahan penggunaan chip
RTC yang terpisah karena millis90 hanya menghitung waktu ketika chip AVR dinyalakan yaitu
ketika power on, kemudian ketika dimatikan maka timer akan di set kembali ke 0. AVR tidak
akan tahu kapan akan hari “Selasa” atau bulan “Maret” atau tanggal 8 , yang bisa dilaporkan
hanya “ sudah 14,000 milisecond sejak saya terakhir dinyalakan.”
Jadi , ketika kita ingin menentukan waktu pada AVR maka kita harus membuat program hari dan
waktu dengan menghitung dari hasil laporan dari millis, tetapi perlu diingat jika daya mati maka
perhitungan waktu akan diulang dari awal kembali.
Untuk beberapa project sederhana, metode timekeeping sederhana ini dapat digunakan , namun
untuk beberapa project seperti data-loggers , clock dsbnya memerlukan perhitungan waktu yang
konsisten yang tidak memerlukan reset ketika arduino battery mati ataupun di program ulang.
Oleh karena itu, kami menambahkan chip RTC secara terpisah. . Chip RTC adalah chip khusus
yang hanya menjaga perhitungan waktu. RTC dapat menghitung tahun dan dapat mengetahui
hari dalam bulan , namun dengan catatan bahwa RTC tidak mengurusi masalah daylight savings
time ( waktu pada musim panas karena hal ini berbeda beda pada tiap daerah).
IC DS1307
The DS1307adalah IC serial real-time clock (RTC) yang berdaya rendah , full binary-coded
decimal.(BCD) clock/calendar dengan 56 bytes N SRAM. Alamat dan data dikirim secara Serial
melalui I2C, bidirectional bus. The clock/calendar menyediakan informasi detik, menit , jam,
hari, bulan , dan tahun. Akhir dari bulan secara otomatis disesuaikan untuk bulan yang kurang
dari 31 hari , termasuk koreksi untuk tahun kabisat . Jam dapat beroperasi baik dalam mode 24
jam ataupun format 12 jam dengan indicator AM/PM.
Gambar 7.1 Konfigurasi Pin pada IC DS1307
A. Procedure
a. Initializing RTC
I/O Configuration PORT B LCD
PORT C IC DS1307
Main.c
#include <avr/io.h>
#include "i2c.h"
#include "lcd.h"
#define CLOCK_ADDRESS 0xD0
char bcd2bin(char input)
{
return ((input>>4)*10)+(input&0x0f);
}
char bin2bcd(char binary)
{
return ((binary/10)<<4)+(binary%10);
}
unsigned char rtcReadByte(unsigned char address)
{
unsigned char data;
i2c_start();
i2c_write(CLOCK_ADDRESS);
i2c_write(address);
i2c_start();
i2c_write(CLOCK_ADDRESS+1);
data=i2c_read(0);
i2c_stop();
return data;
}
void rtcWriteByte(unsigned char address,unsigned char data)
{
i2c_start();
i2c_write(CLOCK_ADDRESS);
i2c_write(address);
i2c_write(data);
i2c_stop();
}
void rtcInitialize(unsigned char rs,unsigned char sqwe,unsigned char
out)
{
rs&=3;
if (sqwe) rs|=0x10;
if (out) rs|=0x80;
i2c_start();
i2c_write(CLOCK_ADDRESS);
i2c_write(7);
i2c_write(rs);
i2c_stop();
}
void rtcGetTime(unsigned char *hour,unsigned char *min,unsigned char
*sec)
{
i2c_start(); // Wake up everyone on I2C
Bus
i2c_write(CLOCK_ADDRESS); // Select one device to talk on I2C
Bus
i2c_write(0); // Write the register to R/W
Info
i2c_start(); // RepeatStart to Read in
info
i2c_write(CLOCK_ADDRESS+1); // Chip address to read from
*sec=bcd2bin(i2c_read(1)); // Read data, if more data to read,
send ACK
*min=bcd2bin(i2c_read(1));
*hour=bcd2bin(i2c_read(0)); // Send NACK --> End
Transmission
i2c_stop(); // End I2C Transaction
}
void rtcSetTime(unsigned char hour,unsigned char min,unsigned char sec)
{
i2c_start();
i2c_write(CLOCK_ADDRESS);
i2c_write(0); // Address to write first
byte to
i2c_write(bin2bcd(sec)); // Continue writing data, DS1307
automatically increments address
i2c_write(bin2bcd(min)); // Write to next register
i2c_write(bin2bcd(hour));
i2c_stop(); // End transaction
}
void rtcGetDate(unsigned char *date,unsigned char *month,unsigned char
*year)
{
i2c_start();
i2c_write(CLOCK_ADDRESS);
i2c_write(4);
i2c_start();
i2c_write(CLOCK_ADDRESS+1);
*date=bcd2bin(i2c_read(1));
*month=bcd2bin(i2c_read(1));
*year=bcd2bin(i2c_read(0));
i2c_stop();
}
void rtcSetDate(unsigned char date,unsigned char month,unsigned char
year)
{
i2c_start();
i2c_write(CLOCK_ADDRESS);
i2c_write(4);
i2c_write(bin2bcd(date));
i2c_write(bin2bcd(month));
i2c_write(bin2bcd(year));
i2c_stop();
}
unsigned char rtcGetDayOfWeek(void)
{
unsigned char day;
i2c_start();
i2c_write(CLOCK_ADDRESS);
i2c_write(3);
i2c_start();
i2c_write(CLOCK_ADDRESS+1);
day=bcd2bin(i2c_read(0));
i2c_stop();
return day;
}
void rtcSetDayOfWeek(unsigned char day)
{
i2c_start();
i2c_write(CLOCK_ADDRESS);
i2c_write(3);
i2c_write(day);
i2c_stop();
}
int main(void)
{
unsigned char hour =1, min =1 , sec =1;
i2c_init();
DDRB = 0xFF;
initlcd();
rtcSetTime(11,30,0);
while(1)
{
rtcGetTime(&hour, &min, &sec);
lcd_gotoxy(0,0);
lcd_putnum(hour);
LCD_putch(' ');
lcd_putnum(min);
LCD_putch(' ');
lcd_putnum(sec);
LCD_putch(' ');
}
}
I2c.c
#include <avr/io.h>
#include "i2c.h"
void i2c_init(void)
{
PORTC |= (1<<1)|(1<<0);
// SCL freq = F_CPU/(16+2*TWBR*(4^Prescaler)))
TWSR &= ~((1<<TWPS1)|(1<<TWPS0));
TWBR = 4; //SCL = 50KHz
TWCR |= (1<<TWEN)|(1<<TWEA); // Enable I2C Hardware bit
}
void i2cWaitForComplete(void)
{
while(!(TWCR&(1<<TWINT)));
}
void i2c_start(void)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
i2cWaitForComplete();
}
void i2c_stop(void)
{
TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
}
void i2cSendByte(char data)
{
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
}
void i2cReceiveByte(char ackFlag)
{
if(ackFlag)
TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWEA);
else
TWCR = (1<<TWEN)|(1<<TWINT);
}
unsigned char i2c_write(char data)
{
i2cSendByte(data);
i2cWaitForComplete();
if((TWSR & 0xF8) == 0x18) return 1;
if((TWSR & 0xF8) == 0x28) return 1;
return 0;
}
char i2c_read(char ack)
{
i2cReceiveByte(ack);
i2cWaitForComplete();
return TWDR;
}
I2c.h
#ifndef __I2C_H__
#define __I2C_H__
void i2c_init(void);
void i2cWaitForComplete(void);
void i2c_start(void);
void i2c_stop(void);
void i2cSendByte(char data);
void i2cReceiveByte(char ackFlag);
unsigned char i2c_write(char data);
char i2c_read(char ack);
#endif
Lcd.c
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"
void LCD_putch(unsigned char data)
{
LCD_PORT = (1<<EN)|(1<<RS)|(data & 0xF0);
LCD_PORT &= ~(1<<EN);
_delay_us(1);
LCD_PORT = (1<<RS)|(1<<EN)|((data & 0x0F) << 4);
LCD_PORT &= ~(1<<EN);
_delay_ms(5);
}
void LCD_putcmd(unsigned char data,unsigned char cmdtype)
{
LCD_PORT = (1<<EN)|(data & 0xF0);
LCD_PORT &= ~(1<<EN);
_delay_us(1);
if(cmdtype){
LCD_PORT = (1<<EN)|((data & 0x0F) << 4);
LCD_PORT &= ~(1<<EN);
}
_delay_ms(5);
}
void initlcd()
{
_delay_ms(30);
LCD_putcmd(0x30,LCD_1CYCLE);
_delay_ms(8);
LCD_putcmd(0x30,LCD_1CYCLE);
_delay_us(200);
LCD_putcmd(0x30,LCD_1CYCLE);
LCD_putcmd(0x20,LCD_1CYCLE);
LCD_putcmd(0x28,LCD_2CYCLE);
LCD_putcmd(0x0C,LCD_2CYCLE);
LCD_putcmd(0x01,LCD_2CYCLE);
LCD_putcmd(0x06,LCD_2CYCLE);
}
void lcd_puts(char *s)
{
while(*s != 0)
{
if (*s == '\n')
LCD_putcmd(0xC0,LCD_2CYCLE);
else
LCD_putch(*s);
s++;
}
}
void lcd_gotoxy (unsigned char x, unsigned char y)
{
unsigned char Position = (1 << 7);
if (y==1)
Position |= 0x40;
else if (y==2)
Position |= 0x14;
else if (y==3)
Position |= 0x54;
Position += x;
LCD_putcmd(Position, LCD_2CYCLE);
}
void lcd_clear()
{
LCD_putcmd(0x01, LCD_2CYCLE);
}
void lcd_putnum(int number)
{
unsigned char digit;
digit = '0';
while(number >= 100)
{
digit++;
number -= 100;
}
if (digit != '0')
LCD_putch(digit);
else
LCD_putch('0');
digit = '0';
while(number >= 10)
{
digit++;
number -= 10;
}
if (digit != '0')
LCD_putch(digit);
else
LCD_putch('0');
LCD_putch('0' + number);
}
Lcd.h
#ifndef __LCD_H__
#define __LCD_H__
#define LCD_PORT PORTB
#define EN PB2
#define RD PB1
#define RS PB0
#define LCD_1CYCLE 0
#define LCD_2CYCLE 1
void LCD_putch(unsigned char data);
void LCD_putcmd(unsigned char data, unsigned char cmdtype);
void initlcd();
void lcd_puts(char *s);
void lcd_gotoxy(unsigned char x, unsigned char y);
void lcd_clear();
void lcd_putnum(int number);
#endif