您好,欢迎来到华拓科技网。
搜索
您的当前位置:首页I2C串行实时时钟与微控制器的接口

I2C串行实时时钟与微控制器的接口

来源:华拓科技网
I2C串行实时时钟与微控制器的接口

应用笔记提供了Dallas I2C接口实时时钟的通用硬件配置和软件例程。本例程适用于采用BCD码时间和日期格式的RTC。

引脚配置

说明

本应用笔记描述了Dallas I2C串行接口实时时钟(RTC)的通用硬件配置,并提供了基本通信软件例程。这些器件包括BCD格式的I2C时钟:DS1307、DS1337、DS1338、DS1339和DS1340。如果对电路进行某些修改,为CLK输入引脚提供数字时钟信号(32,768Hz、8,192Hz、60H或50Hz),还可支持DS1375。本范例中使用了DS2250微控制器,软件为C语言程序。

示意图如图1所示,图中给出了DS1340的连接方式。对于其它型号的RTC,可能需要修改电路。例如:DS1337,用中断输出替代了备用电池输入端。对于低电压RTC,需要用适当的低电压微控制器替代DS2250/DS5000。图2给出了软件清单。#定义说明用来表示特定器件有条件的编译代码。本例程用于DS1307。编译代码之前,用于DS1307的#定义说明应该用正确的器件代替。

放大图形

图1. DS1340和微控制器电路示意图

图2. 软件清单

/********************************************************************/

/* 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 */

2

bus to unused port pins). This */ /* 8051 variants (i.e. assign IC

/* program is for example only and is not supported by Dallas Maxim */

void I2C_start();

2

void IC_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;

2

/* void IC_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 \ scl = 0; }

2

/* ----------------------------------- */ uchar IC_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\

2

IC_start(); I2C_write(ADDRTC);

2

IC_write(Add); I2C_start(); I2C_write(ADDRTC | 1); printf(\"%2bx\2C_read(NACK) );

2

IC_stop(); }

void writebyte() /* -- write one byte of data to the specified address -- */ {

uchar Add; uchar Data; printf(\"

Address: \"); /* Get Address */ scanf(\"%bx\ printf(\"DATA: \"); scanf(\"%bx\/* and data */ I2C_start(); I2C_write(ADDRTC); I2C_write(Add);

2

IC_write(Data);

2

IC_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;

2

/* The following Enables the Oscillator IC_start();

*/ I2C_write(ADDRTC); /* address the part to write */

2

IC_write(0x00); /* position the address pointer to 0 */

2

IC_write(0x00); /* write 0 to the seconds register, clear the CH bit */

2

IC_stop(); printf(\"

Enter the year (0-99): \"); scanf(\"%bx\ printf(\"Enter the month (1-12): \"); scanf(\"%bx\ printf(\"Enter the date (1-31): \"); scanf(\"%bx\ printf(\"Enter the day (1-7): \"); scanf(\"%bx\ printf(\"Enter the hour (1-23): \"); scanf(\"%bx\ hr = hr & 0x3f; /* force clock to 24 hour mode */ printf(\"Enter the minute (0-59): \"); scanf(\"%bx\ printf(\"Enter the second (0-59): \"); scanf(\"%bx\

2

IC_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);

2

IC_write(yr);

#if defined DS1307 || defined DS1338 {

2

/* enable sqwe, 1Hz output */ IC_write(0x10);

}

#elif defined DS1337 || defined DS1339 { I2C_start();

2

/* write slave address + write */ IC_write(ADDRTC);

I2C_write(0x0e); /* write register address, control register */ I2C_write(0x20); /* enable osc, bbsqi */

2

IC_write(0); /* clear OSF, alarm flags */ /* could enable trickle charger here */ }

#elif defined DS1340 { I2C_write(0x10); /* enable sqwe, 1Hz output */

2

IC_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 */

2

IC_start();

I2C_write(ADDRTC | 1); /* write slave address + read */ Sec = I2C_read(ACK); /* starts w/last address stored in register pointer */

2

Min = IC_read(ACK); Hrs = I2C_read(ACK); Day = I2C_read(ACK); Dte = I2C_read(ACK);

2

Mon = IC_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\ printf(\" %02bX:%02bX:%02bX\Sec); } else { if(Hrs & 0x20) pm = 'A'; else pm = 'P'; Hrs &= 0x1f; /* strip mode and am/pm bits */ printf(\"

%02bx/%02bx/%02bx %02bx\ printf(\" %02bx:%02bx:%02bx %cM\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 */

2

/* write register address, 1st RAM IC_write(0x08);

location */ for (j = 0; j < 56; j++) /* write until the pointer wraps around */ {

2

IC_write(Data); } I2C_stop(); }

void burstramread() /*

----------------------------------------- */ {

uchar j; I2C_start(); I2C_write(ADDRTC); /* write slave address + write */

2

IC_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 \ printf(\"%02bX \2C_read(ACK) ); }

2

IC_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; case '2': M = 0xe; case '3': M = 0xc; case '4': M = 8; case '5': M = 0; case '6': M = 0x40; } if(M & 0x40) { printf(\" Enter the day (1-7): \"); scanf(\"%bx\ } else { printf(\" Enter the date (1-31): \"); scanf(\"%bx\ } printf(\"Enter the hour (1-23): \"); scanf(\"%bx\ printf(\"Enter the minute (0-59): \"); scanf(\"%bx\ printf(\"Enter the second (0-59): \"); scanf(\"%bx\ 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;

I2

C_start();

break; break; break; break; break; break; I2C_write(ADDRTC); /* write slave address + write */ I2C_write(7); /* write register address */

2

IC_write(Sec); I2C_write(Min); I2C_write(Hr); I2C_write(DyDt); I2C_start();

2

/* write slave address + write */ IC_write(ADDRTC);

I2C_write(0x0e); /* write register address */

2

IC_write(5); /* enable interrupts, alarm 1 */

2

IC_stop(); }

void alrm_read() /* ----- read alarm registers ------ */ {

uchar Sec, Min, Hr, DyDt; I2C_start(); I2C_write(ADDRTC); /* write slave address + write */

2

/* write register address */ IC_write(7);

I2C_start(); I2C_write(ADDRTC | 1); /* write slave address + read */ Sec = I2C_read(ACK); Min = I2C_read(ACK);

2

Hr = IC_read(ACK); DyDt = I2C_read(NACK); printf(\"

Alarm 1: %02bx %02bx %02bx %02bx\}

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')

{

1-250 ohm res printf(\"

2-2K res=sec 3-4K res\"); entries! */ 1-no diode 2-1 diode\"); entries! */ write */

user input */ } else { write */ charger */

M = _getkey(); /* Note-No error checking is done on

switch(M)

{ case '1': val = 1; break; case '2': val = 2; break; case '3': val = 3; break;

}

printf(\"

M = _getkey(); /* Note-No error checking is done on

switch(M) { case '1': val += 4; break; case '2': val += 8; break;

} I2

C_start(); I2

C_write(ADDRTC);

/* write slave address +

I2C_write(TC); /* write register address */ I2

C_write(val | 0xa0); /* enable trickle charger per I2

C_stop();

I2C_start();

I2C_write(ADDRTC);

/* write slave address +

I2

C_write(TC); /* write register address */ I2C_write(0);

/* disable trickle

I2

C_stop();

} I2C_start();

2

/* write slave address + write */ IC_write(ADDRTC);

2

IC_write(TC); /* write register address */

2

IC_start(); I2C_write(ADDRTC | 1); /* write slave address + read */ printf(\"

2

Trickle Charger: %02bx\C_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 \

#elif defined DS1337 printf(\" DEMO1337 build %s \

#elif defined DS1338 printf(\" DEMO1338 build %s \

#elif defined DS1339 printf(\" DEMO1339 build %s \

#elif defined DS1340 printf(\" DEMO1340 build %s \#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\ burstramwrite(M1); break; }

}

}

}

break; case 'T': case 't':

tc_setup(); break;

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo6.cn 版权所有 赣ICP备2024042791号-9

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务