Skip to content

Instantly share code, notes, and snippets.

@tokolist
Last active August 29, 2015 14:25
Show Gist options
  • Save tokolist/0d99eae496dc7c4529d6 to your computer and use it in GitHub Desktop.
Save tokolist/0d99eae496dc7c4529d6 to your computer and use it in GitHub Desktop.
AVR ds1302 RTC library
#include "ds1302.h"
#include <avr/io.h>
#include <util/delay.h>
void ds1302_write(unsigned char cmd)
{
DS1302_CE_DDR |= (1<<DS1302_CE_PNUM);
DS1302_SCLK_DDR |= (1<<DS1302_SCLK_PNUM);
DS1302_CE_PORT |= (1<<DS1302_CE_PNUM);
_delay_us(4);
DS1302_IO_DDR |= (1<<DS1302_IO_PNUM);
for(unsigned char i=0; i<8; i++)
{
if((cmd&(1<<i)) == 1<<i)
{
DS1302_IO_PORT |= (1<<DS1302_IO_PNUM);
}
else
{
DS1302_IO_PORT &= ~(1<<DS1302_IO_PNUM);
}
DS1302_SCLK_PORT |= (1<<DS1302_SCLK_PNUM);
_delay_us(1);
DS1302_IO_PORT &= ~(1<<DS1302_IO_PNUM);
DS1302_SCLK_PORT &= ~(1<<DS1302_SCLK_PNUM);
}
}
unsigned char ds1302_read()
{
unsigned char readbyte=0;
DS1302_IO_DDR &= ~(1<<DS1302_IO_PNUM);
for(unsigned char i=0; i<8; i++)
{
DS1302_SCLK_PORT |= (1<<DS1302_SCLK_PNUM);
if((DS1302_IO_PIN & (1<<DS1302_IO_PNUM))==0)
{
readbyte &= ~(1<<i);
}
else
{
readbyte |= 1<<i;
}
_delay_us(10);
DS1302_SCLK_PORT &= ~(1<<DS1302_SCLK_PNUM);
_delay_us(2);
}
DS1302_CE_PORT &= ~(1<<DS1302_CE_PNUM);
_delay_us(4);
return readbyte;
}
unsigned char ds1302_read_byte(unsigned char byte_r)
{
ds1302_write(byte_r);
return ds1302_read();
}
void ds1302_write_byte(unsigned char byte_w, unsigned char val)
{
ds1302_write(byte_w);
ds1302_write(val);
DS1302_CE_PORT &= ~(1<<DS1302_CE_PNUM);
}
void ds1302_rw(Ds1302_operation oper, Ds1302_register reg, Ds1302_rtc_time &rtc_time)
{
unsigned char byte;
if(oper == READ){
switch(reg){
case CH:
byte = ds1302_read_byte(DS1302_SEC_R);
rtc_time.ch = byte & 0b10000000;
break;
case SEC:
byte = ds1302_read_byte(DS1302_SEC_R);
rtc_time.sec = (byte & 0b00001111) + ((byte>>4) & 0b00000111) * 10;
break;
case MIN:
byte = ds1302_read_byte(DS1302_MIN_R);
rtc_time.min = (byte & 0b00001111) + ((byte>>4) & 0b00000111) * 10;
break;
case HOUR:
byte = ds1302_read_byte(DS1302_HOUR_R);
rtc_time.hour.mode12h = (byte & 0b10000000);
if(rtc_time.hour.mode12h)
{
rtc_time.hour.pm = (byte & 0b00100000);
rtc_time.hour.hour = (byte & 0b00001111) + ((byte>>4) & 0b00000001) * 10;
}
else
{
rtc_time.hour.hour = (byte & 0b00001111) + ((byte>>4) & 0b00000011) * 10;
}
break;
case DATE:
byte = ds1302_read_byte(DS1302_DATE_R);
rtc_time.date = (byte & 0b00001111) + ((byte>>4) & 0b00000011) * 10;
break;
case MONTH:
byte = ds1302_read_byte(DS1302_MONTH_R);
rtc_time.month = (byte & 0b00001111) + ((byte>>4) & 0b00000001) * 10;
break;
case DAY:
byte = ds1302_read_byte(DS1302_DAY_R);
rtc_time.day = byte & 0b00000111;
break;
case YEAR:
byte = ds1302_read_byte(DS1302_YEAR_R);
rtc_time.year = (byte & 0b00001111) + ((byte>>4) & 0b00001111) * 10;
break;
case WP:
byte = ds1302_read_byte(DS1302_WP_R);
rtc_time.wp = byte & 0b10000000;
break;
}
} else { //WRITE
switch(reg){
case CH:
byte = ds1302_read_byte(DS1302_SEC_R);
if(rtc_time.ch){
byte |= 0b10000000;
} else {
byte &= 0b01111111;
}
ds1302_write_byte(DS1302_SEC_W, byte);
break;
case SEC:
//preserve CH bit value
byte = ds1302_read_byte(DS1302_SEC_R) & 0b10000000;
byte |= (((rtc_time.sec/10)<<4) & 0b01110000) | (rtc_time.sec%10);
ds1302_write_byte(DS1302_SEC_W, byte);
break;
case MIN:
ds1302_write_byte(DS1302_MIN_W, (((rtc_time.min/10)<<4) & 0b01110000) | (rtc_time.min%10));
break;
case HOUR:
if(rtc_time.hour.mode12h){
byte = 0b10000000 | (((rtc_time.hour.hour/10)<<4) & 0b00010000) | (rtc_time.hour.hour%10);
if(rtc_time.hour.pm) byte |= 0b00100000;
} else {
byte = (((rtc_time.hour.hour/10)<<4) & 0b00110000) | (rtc_time.hour.hour%10);
}
ds1302_write_byte(DS1302_HOUR_W, byte);
break;
case DATE:
ds1302_write_byte(DS1302_DATE_W, (((rtc_time.date/10)<<4) & 0b00110000) | (rtc_time.date%10));
break;
case MONTH:
ds1302_write_byte(DS1302_MONTH_W, (((rtc_time.month/10)<<4) & 0b00010000) | (rtc_time.month%10));
break;
case DAY:
ds1302_write_byte(DS1302_DAY_W, rtc_time.day & 0b00000111);
break;
case YEAR:
ds1302_write_byte(DS1302_YEAR_W, (((rtc_time.year/10)<<4) & 0b11110000) | (rtc_time.year%10));
break;
case WP:
ds1302_write_byte(DS1302_WP_W, rtc_time.wp ? 0b10000000 : 0b00000000);
break;
}
}
}
#ifndef DS1302_H_
#define DS1302_H_
#define F_CPU 8000000 //8MHz
#define DS1302_CE_PIN PIND
#define DS1302_CE_DDR DDRD
#define DS1302_CE_PORT PORTD
#define DS1302_CE_PNUM 5
#define DS1302_IO_PIN PIND
#define DS1302_IO_DDR DDRD
#define DS1302_IO_PORT PORTD
#define DS1302_IO_PNUM 6
#define DS1302_SCLK_PIN PIND
#define DS1302_SCLK_DDR DDRD
#define DS1302_SCLK_PORT PORTD
#define DS1302_SCLK_PNUM 7
#define DS1302_SEC_W 0x80
#define DS1302_SEC_R 0x81
#define DS1302_MIN_W 0x82
#define DS1302_MIN_R 0x83
#define DS1302_HOUR_W 0x84
#define DS1302_HOUR_R 0x85
#define DS1302_DATE_W 0x86
#define DS1302_DATE_R 0x87
#define DS1302_MONTH_W 0x88
#define DS1302_MONTH_R 0x89
#define DS1302_DAY_W 0x8a
#define DS1302_DAY_R 0x8b
#define DS1302_YEAR_W 0x8c
#define DS1302_YEAR_R 0x8d
#define DS1302_WP_W 0x8e
#define DS1302_WP_R 0x8f
#define DS1302_TRICKLE_CHARGE_W 0x90
#define DS1302_TRICKLE_CHARGE_R 0x91
#define DS1302_CLOCK_BURST_W 0xbe
#define DS1302_CLOCK_BURST_R 0xbf
#define DS1302_RAM_BURST_W 0xfe
#define DS1302_RAM_BURST_R 0xff
typedef struct {
unsigned char hour;
bool pm;
bool mode12h;
} Ds1302_hour;
typedef struct {
bool ch;
unsigned char sec;
unsigned char min;
Ds1302_hour hour;
unsigned char date;
unsigned char month;
unsigned char day;
unsigned char year;
bool wp;
} Ds1302_rtc_time;
enum Ds1302_operation {READ, WRITE};
enum Ds1302_register {CH, SEC, MIN, HOUR, DATE, MONTH, DAY, YEAR, WP};
void ds1302_write(unsigned char cmd);
unsigned char ds1302_read();
unsigned char ds1302_read_byte(unsigned char byte_r);
void ds1302_write_byte(unsigned char byte_w, unsigned char val);
void ds1302_rw(Ds1302_operation oper, Ds1302_register reg, Ds1302_rtc_time &rtc_time);
#endif /* DS1302_H_ */
#include "ds1302.h"
Ds1302_rtc_time rtc_time;
//read
ds1302_rw(READ, YEAR, rtc_time);
ds1302_rw(READ, MONTH, rtc_time);
ds1302_rw(READ, DATE, rtc_time);
//write
rtc_time.year = 15;
rtc_time.month = 7;
rtc_time.date = 25;
ds1302_rw(WRITE, YEAR, rtc_time);
ds1302_rw(WRITE, MONTH, rtc_time);
ds1302_rw(WRITE, DATE, rtc_time);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment