Code:
/********************************************************************/
/* DEMO1307.c */
/* program example for DS1307, DS1337/38/39/40 */
/********************************************************************/
#include /* Prototypes for I/O functions */
#include /* Register declarations for DS5000 */
/***************************** Defines *****************************/
#define ACK 0
#define NACK 1
#define ADDRTC 0xd0 /* I2C slave address */
#define DS1307 /* compile directive, modify as required */
/************************* bit definitions *************************/
sbit scl = P0^0; /* I2C pin definitions */
sbit sda = P0^1;
sbit sqw = P3^2; /* pin function depends upon device */
/* General Notes: Define one device to compile options for that device. */
/* Will not compile correctly if no device is defined. Not all options */
/* for each device are supported. There is no error checking for data */
/* entry. Defines may not remove all code that is not relevant to the */
/* device. This example was written for an 8051-type micro, the DS2250/ */
/* DS5000. The program must be modified to work properly on typical */
/* 8051 variants (i.e. assign I2C bus to unused port pins). This */
/* program is for example only and is not supported by Dallas Maxim */
void I2C_start();
void I2C_stop();
void I2C_write(unsigned char d);
uchar I2C_read(uchar);
void readbyte();
void writebyte();
void initialize();
void disp_clk_regs(uchar);
void burstramwrite(uchar);
void burstramread();
void alrm_int();
void alrm_read();
void tc_setup();
/* global variables */
uchar sec, min, hr, dy, dt, mn, yr;
void I2C_start() /* ----------------------------------------------- */
{
sda = 1; scl = 1; /* Initiate start condition */
sda = 0;
}
void I2C_stop() /* ----------------------------------------------- */
{
sda = 0; sda = 0; sda = 0; sda = 0; /* Initiate stop condition */
scl = 1; scl = 1; sda = 1;
}
void I2C_write(uchar d) /* ----------------------------- */
{
uchar i;
scl = 0;
for (i = 1; i <= 8; i++)
{
sda = (d >> 7);
scl = 1;
d = d << 1; /* increase scl high time */
scl = 0;
}
sda = 1; /* Release the sda line */
scl = 0;
scl = 1;
if(sda) printf("Ack bit missing %02X
",(unsigned int)d);
scl = 0;
}
uchar I2C_read(uchar b) /* ----------------------------------- */
{
uchar d, i;
sda = 1; /* Let go of sda line */
scl = 0;
for (i = 1; i <= 8; i++) /* read the msb first */
{
scl = 1;
d = d << 1;
d = d | (unsigned char)sda;
scl = 0;
}
sda = b; /* Hold sda low for acknowledge */
scl = 0;
scl = 1;
if(b == NACK) sda = 1; /* sda = 1 if next cycle is reset */
scl = 0;
sda = 1; /* Release the sda line */
return d;
}
void readbyte() /* -- read one byte of data from the specified address -- */
{
uchar Add;
printf("
ADDRESS: "); /* Get Address */
scanf("%bx", &Add);
I2C_start();
I2C_write(ADDRTC);
I2C_write(Add);
I2C_start();
I2C_write(ADDRTC | 1);
printf("%2bx", I2C_read(NACK) );
I2C_stop();
}
void writebyte() /* -- write one byte of data to the specified address -- */
{
uchar Add;
uchar Data;
printf("
Address: "); /* Get Address */
scanf("%bx", &Add);
printf("DATA: ");
scanf("%bx", &Data); /* and data */
I2C_start();
I2C_write(ADDRTC);
I2C_write(Add);
I2C_write(Data);
I2C_stop();
}
void initialize() /* -- initialize the time and date using entries from stdin -- */
/* Note: NO error checking is done on the user entries! */
{
uchar yr, mn, dt, dy, hr, min, sec, day;
I2C_start(); /* The following Enables the Oscillator */
I2C_write(ADDRTC); /* address the part to write */
I2C_write(0x00); /* position the address pointer to 0 */
I2C_write(0x00); /* write 0 to the seconds register, clear the CH bit */
I2C_stop();
printf("
Enter the year (0-99): ");
scanf("%bx", &yr);
printf("Enter the month (1-12): ");
scanf("%bx", &mn);
printf("Enter the date (1-31): ");
scanf("%bx", &dt);
printf("Enter the day (1-7): ");
scanf("%bx", &dy);
printf("Enter the hour (1-23): ");
scanf("%bx", &hr);
hr = hr & 0x3f; /* force clock to 24 hour mode */
printf("Enter the minute (0-59): ");
scanf("%bx", &min);
printf("Enter the second (0-59): ");
scanf("%bx", &sec);
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(0x00); /* write register address, 1st clock register */
I2C_write(sec);
I2C_write(min);
I2C_write(hr);
I2C_write(dy);
I2C_write(dt);
I2C_write(mn);
I2C_write(yr);
#if defined DS1307 || defined DS1338
{
I2C_write(0x10); /* enable sqwe, 1Hz output */
}
#elif defined DS1337 || defined DS1339
{
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(0x0e); /* write register address, control register */
I2C_write(0x20); /* enable osc, bbsqi */
I2C_write(0); /* clear OSF, alarm flags */
/* could enable trickle charger here */
}
#elif defined DS1340
{
I2C_write(0x10); /* enable sqwe, 1Hz output */
I2C_start(); /* address pointer wraps at 7, so point to flag register */
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(0x09); /* write register address, control register */
I2C_write(0); /* clear OSF */
}
#endif
I2C_stop();
}
void disp_clk_regs(uchar prv_sec) /* ----------------------------------------- */
{
uchar Sec, Min, Hrs, Dte, Mon, Day, Yr, mil, pm;
printf("
Yr Mn Dt Dy Hr:Mn:Sc");
while(!RI) /* Read & Display Clock Registers */
{
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(0x00); /* write register address, 1st clock register */
I2C_start();
I2C_write(ADDRTC | 1); /* write slave address + read */
Sec = I2C_read(ACK); /* starts w/last address stored in register pointer */
Min = I2C_read(ACK);
Hrs = I2C_read(ACK);
Day = I2C_read(ACK);
Dte = I2C_read(ACK);
Mon = I2C_read(ACK);
Yr = I2C_read(NACK);
I2C_stop();
if(Hrs & 0x40)
mil = 0;
else
mil = 1;
if(Sec != prv_sec) /* display every time seconds change */
{
if(mil)
{
printf("
%02bX/%02bX/%02bX %2bX", Yr, Mon, Dte, Day);
printf(" %02bX:%02bX:%02bX", Hrs, Min, Sec);
}
else
{
if(Hrs & 0x20)
pm = 'A';
else
pm = 'P';
Hrs &= 0x1f; /* strip mode and am/pm bits */
printf("
%02bx/%02bx/%02bx %02bx", Yr, (Mon & 0x1f), Dte, Day);
printf(" %02bx:%02bx:%02bx %cM", Hrs, Min, Sec, pm);
}
}
if(prv_sec == 0xfe) return;
prv_sec = Sec;
}
RI = 0; /* Swallow keypress before exiting */
}
void burstramwrite(uchar Data) /* -------- fill RAM with data -------- */
{
uchar j;
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(0x08); /* write register address, 1st RAM location */
for (j = 0; j < 56; j++) /* write until the pointer wraps around */
{
I2C_write(Data);
}
I2C_stop();
}
void burstramread() /* ----------------------------------------- */
{
uchar j;
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(8); /* write register address, 1st RAM location -1*/
I2C_start();
I2C_write(ADDRTC | 1); /* write slave address + read */
for (j = 0; j < 56; j++)
{
if(!(j % 16)) printf("
%02bX ", j);
printf("%02bX ", I2C_read(ACK) );
}
I2C_read(NACK);
I2C_stop();
}
void alrm_int() /* ----- initialize alarm registers ------ */
{
uchar M, Sec, Min, Hr, DyDt;
printf("
1-Alarm each second
2-Alarm match=sec
3-Alarm match=sec+min");
printf("
4-Alarm match=sec+min+hr
5-Alarm match=sec+min+hr+date");
printf("
6-Alarm match=sec+min+hr+day
Enter selection: ");
M = _getkey(); /* Note-No error checking is done on entries! */
switch(M)
{
case '1': M = 0xf; break;
case '2': M = 0xe; break;
case '3': M = 0xc; break;
case '4': M = 8; break;
case '5': M = 0; break;
case '6': M = 0x40; break;
}
if(M & 0x40)
{
printf("
Enter the day (1-7): ");
scanf("%bx", &DyDt);
}
else
{
printf("
Enter the date (1-31): ");
scanf("%bx", &DyDt);
}
printf("Enter the hour (1-23): ");
scanf("%bx", &Hr);
printf("Enter the minute (0-59): ");
scanf("%bx", &Min);
printf("Enter the second (0-59): ");
scanf("%bx", &Sec);
if( (M & 1) ) Sec |= 0x80;
if( ((M >> 1) & 1) ) Min |= 0x80;
if( ((M >> 2) & 1) ) Hr |= 0x80;
if( ((M >> 3) & 1) ) DyDt |= 0x80;
if(M & 0x40) DyDt |= 0x40;
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(7); /* write register address */
I2C_write(Sec);
I2C_write(Min);
I2C_write(Hr);
I2C_write(DyDt);
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(0x0e); /* write register address */
I2C_write(5); /* enable interrupts, alarm 1 */
I2C_stop();
}
void alrm_read() /* ----- read alarm registers ------ */
{
uchar Sec, Min, Hr, DyDt;
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(7); /* write register address */
I2C_start();
I2C_write(ADDRTC | 1); /* write slave address + read */
Sec = I2C_read(ACK);
Min = I2C_read(ACK);
Hr = I2C_read(ACK);
DyDt = I2C_read(NACK);
printf("
Alarm 1: %02bx %02bx %02bx %02bx", Sec, Min, Hr, DyDt);
}
void tc_setup() /* ---- trickle charger set up routine ---- */
{
uchar M, val;
#if defined DS1339
#define TC 0x10 /* address for DS1339 trickle charge register */
#else
#define TC 0x08 /* address for DS1340 trickle charge register */
#endif
printf("
Enable Trickle Charger (Y/N)? ");
M = _getkey();
if(M == 'Y' || M == 'y')
{
printf("
1-250 ohm res
2-2K res=sec
3-4K res");
M = _getkey(); /* Note-No error checking is done on entries! */
switch(M)
{
case '1': val = 1; break;
case '2': val = 2; break;
case '3': val = 3; break;
}
printf("
1-no diode
2-1 diode");
M = _getkey(); /* Note-No error checking is done on entries! */
switch(M)
{
case '1': val += 4; break;
case '2': val += 8; break;
}
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(TC); /* write register address */
I2C_write(val | 0xa0); /* enable trickle charger per user input */
I2C_stop();
}
else
{
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(TC); /* write register address */
I2C_write(0); /* disable trickle charger */
I2C_stop();
}
I2C_start();
I2C_write(ADDRTC); /* write slave address + write */
I2C_write(TC); /* write register address */
I2C_start();
I2C_write(ADDRTC | 1); /* write slave address + read */
printf("
Trickle Charger: %02bx", I2C_read(NACK) );
}
main (void) /* ----------------------------------------------------- */
{
uchar M, M1;
sqw = 1; /* set up for read, weak pull-up */
while (1)
{
#if defined DS1307
printf("
DEMO1307 build %s
", __DATE__);
#elif defined DS1337
printf("
DEMO1337 build %s
", __DATE__);
#elif defined DS1338
printf("
DEMO1338 build %s
", __DATE__);
#elif defined DS1339
printf("
DEMO1339 build %s
", __DATE__);
#elif defined DS1340
printf("
DEMO1340 build %s
", __DATE__);
#endif
printf("CI Init RTC CR Read Clock
");
printf("BR Byte Read BW Write Byte
");
#if defined DS1337 || defined DS1339 /* only print if part has alarms */
printf("AI Alarm 1 Int AR Alarm Read
");
#endif
#if defined DS1340 || defined DS1339 /* parts that have trickle charger */
printf("Tc Trickle charger
");
#endif
#if defined DS1307 || defined DS1338 /* only print if part has RAM */
printf("RR RAM Read RW RAM Write
");
#endif
printf("Enter Menu Selection:");
M = _getkey();
switch(M)
{
case 'A':
case 'a':
printf("
Init or Read: ");
M1 = _getkey();
switch(M1)
{
case 'I':
case 'i': alrm_int(); break;
case 'R':
case 'r': alrm_read(); break;
}
break;
case 'B':
case 'b':
printf("
Read or Write: ");
M1 = _getkey();
switch(M1)
{
case 'R':
case 'r': readbyte(); break;
case 'W':
case 'w': writebyte(); break;
}
break;
case 'C':
case 'c':
printf("\rEnter Clock Routine to run:C");
M1 = _getkey();
switch(M1)
{
case 'I':
case 'i': initialize(); break;
case 'R':
case 'r': disp_clk_regs(0x99); break;
}
break;
case 'R':
case 'r':
printf("\rEnter Ram Routine to run:R");
M1 = _getkey();
switch(M1)
{
case 'R':
case 'r': burstramread(); break;
case 'W':
case 'w': printf("
Enter the data to write: ");
scanf("%bx", &M1);
burstramwrite(M1); break;
}
break;
case 'T':
case 't': tc_setup(); break;
}
}
}
Lesezeichen