rtc - ds1307 - web viewthe arduino twowire class is loaded with the wire.h include which activates...

20
RTC - DS1307 2015 Adrian Krag Objective The real time clock chip, DS1307, can be connected to the Arduino and used in a wide range of projects that require the processor to know the time and date. Using this device is easy if you have a basic understanding of the Wire.h library functions and I2C communication protocol. In this document we will discuss the basic operation of the device, how to set the date and time and how to read the information. This document also includes several Arduino programs that can be referenced to get started with the RTC. RTC overview The DS1307 chip is a simple device integrated circuit that counts clock pulses. The chip requires a 32.768 kHz oscillator commonly known as a watch crystal. You will remember the binary number 0x7FFF is 32768. This means that a 15 bit counter would count from 0 up to its maximum value an role over to 0 again in exactly 1 second, if clocked at this frequency. The chip includes a built in processor which includes the counter and several registers that keep track of the day, the date and the time. The device also has additional memory for storage. The design is intended to use very little power, less than 0.5µA and it runs on 5 volts, but if the supply voltage drops to 3, the oscillator will continue to operate and keep accurate time. The device is intended to have a CR1220 back up battery to support continued operation when the power has been unplugged. The DS1307 interfaces with the outside world using the I2C protocol, making it easy to program and read with the Arduino I2C internal peripheral. The Arduino I2C port uses analog pin A4 and A5 as the data and clock lines. The Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are used in this product description.

Upload: duongnga

Post on 03-Feb-2018

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

RTC - DS13072015 Adrian Krag

ObjectiveThe real time clock chip, DS1307, can be connected to the Arduino and used in a wide range of projects that require the processor to know the time and date. Using this device is easy if you have a basic understanding of the Wire.h library functions and I2C communication protocol. In this document we will discuss the basic operation of the device, how to set the date and time and how to read the information. This document also includes several Arduino programs that can be referenced to get started with the RTC.

RTC overviewThe DS1307 chip is a simple device integrated circuit that counts clock pulses. The chip requires a 32.768 kHz oscillator commonly known as a watch crystal. You will remember the binary number 0x7FFF is 32768. This means that a 15 bit counter would count from 0 up to its maximum value an role over to 0 again in exactly 1 second, if clocked at this frequency. The chip includes a built in processor which includes the counter and several registers that keep track of the day, the date and the time. The device also has additional memory for storage.

The design is intended to use very little power, less than 0.5µA and it runs on 5 volts, but if the supply voltage drops to 3, the oscillator will continue to operate and keep accurate time. The device is intended to have a CR1220 back up battery to support continued operation when the power has been unplugged.

The DS1307 interfaces with the outside world using the I2C protocol, making it easy to program and read with the Arduino I2C internal peripheral. The Arduino I2C port uses analog pin A4 and A5 as the data and clock lines. The Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are used in this product description.

RTC registersRegisters are 8 bit (1 byte) memory locations that can store values. The RTC uses the I2C interface to write and read bytes from these registers. The DS1307 has 0x37 (64) of these registers, however only the first 8 are important to the operation of the device.

Page 2: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

This table shows the registers that are important. Setting the date and time is done by writing to these registers. Once set and activated, these registers update ever second to contain the correct date and time.

Understanding and using BCD and ASCIIThe register data is stored in BCD (Binary Coded Decimal) format. This means that each digit of a number is given 4 bytes (1 nibble). Each of these nibbles is allowed to use values 0 to 9 or 0000 to 1001. This means that when we write a number in hex, we can read the number as a decimal number.

The BCD number 0011 0100 is understood to be 34 in decimal. BCD is seldom used, but this device make use of it. To format the data correctly one must make use of the ">>" shift right and "<<" shift left operators to create numbers that will properly represent the information. Also, it is necessary to be familiar with AND "&" and the OR "|" functions. In addition, it is often more useful to think in of numbers in terms of hex and binary than in decimal.

Consider the first register which contains the current seconds. Suppose the current time is 7:44:26 - 7 AM, 44 minutes and 26 seconds. To set this time correctly, the appropriate values must be written to the correct registers. Register 00 contains the seconds value. It needs to set to be the binary number 0010 0110 or hex 0x26. The program must convert the decimal number 26 into the hex number 0x26.

Assume the operator is going to set the date and time using the serial monitor. When the PC sends data to the Arduino, all data is considered to be ASCII characters. If the operator types the number 26 and return, the Arduino will read two bytes 50 (0x32), and 54 (0x36)- These are the ASCII representations of a 2 and a 6. These need to be converted to decimal digits and combined into the BCD equivalent. Consider the following code.

We will be reading several digits so it is appropriate to use a subroutine to read the digits and accumulate them into the final number. This routine is a modification of the readDec() routine.

This function assumes that the user has or will enter a series of digits that will be converted into a byte. The first line creates a local variable that will be used to store the final result. This value is initialized to 0.

Next we wait for the Serial.available() routine to tell the program that there are characters in the buffer. This while loop has no block, no instructions. It just reads the number of bytes in the buffer repeatedly until there are more than 0. Note, at 9600 baud, it takes time for all the digits to get across the USB cable. We follow with a short delay to allow all the digits to come across.

Page 3: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

The "for" loop will read the digits and assemble them into a number. Each digit will be converted into a hex digit and assembled. It will read digits until the buffer is empty. The "for" loop reads digits and assembles them.

Each time a new digit is read, the accumulation to that point is multiplied by 16 to shift the number to the left and make room for the next digit. The next digit to be read in is then added to the accumulation. The first time through the loop, Nmbr is 0 so the multiply does nothing. If there is only 1 digit, the number ends up in the "ones" place. If there 2 digits, the first digit is multiplies by 16 and the next digit added. This continues until there are no more characters to be read in.

Remember, the "*= 16" code means Nmbr = Nmbr * 16. The previous value of Nmbr gets multiplied by 16 and stored in the Nmbr memory location. In the next line we see "+=" This means the value on the right gets added to the current value of Nmbr and the result is stored in the Nmbr memory location.

A word about the line Nmbr += (Serial.read() - '0'); The serial monitor only sends ASCII coded bytes from the PC to the Arduino. These values can be seen in the table below.

A65

1000001 N

78

1001110 a 97 1100001 n 110 1101110 0

48

110000

B66

1000010 O

79

1001111 b 98 1100010 o 111 1101111 1

49

110001

C67

1000011 P

80

1010000 c 99 1100011 p 112 1110000 2

50

110010

D68

1000100 Q

81

1010001 d

100 1100100 q 113 1110001 3

51

110011

E69

1000101 R

82

1010010 e

101 1100101 r 114 1110010 4

52

110100

F70

1000110 S

83

1010011 f

102 1100110 s 115 1110011 5

53

110101

G71

1000111 T

84

1010100 g

103 1100111 t 116 1110100 6

54

110110

H72

1001000 U

85

1010101 h

104 1101000 u 117 1110101 7

55

110111

I 73

1001001 V

86

1010110 i

105 1101001 v 118 1110110 8

56

111000

J74

1001010 W

87

1010111 j

106 1101010 w 119 1110111 9

57

111001

K75

1001011 X

88

1011000 k

107 1101011 x 120 1111000

Space

32

100000

L76

1001100 Y

89

1011001 l

108 1101100 y 121 1111001      

M77

1001101       m

109 1101101 z 122 1111010      

Notice the ASCII values for digits are no 0 to 9, but 48 to 57. It is necessary to convert the value read (ASCII characters) into numbers. To do this we subtract the value of ASCII 0, 48. In this line of code the program subtracts the value '0'. remember putting a letter or number in single quotes (' ') will tell the processor we mean the ASCII value of the character.

Page 4: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

Finally the subroutine uses a return() statement to pass the final value of Nmbr back to the calling program (loop()). Notice when we defined the subroutine with byte ReadHex() we used byte rather than void. void defines a routine that does not return a value. byte creates a routine that will calculate and return an integer value. Because of this the statement in the loop() routine that calls the ReadHex() routine looks like:

Sec = ReadHex(); Notice how the ReadHex() routine is called. The loop() function defines byte variables, Hrs,

Min or Sec - These will store the values we calculate in the ReadHex() subroutine.

Notice, we could just as easily write this string of text and numbers to the LCD display if we wished and we will explore this a little later in the discussion.

For now, let's put these numbers into the appropriate registers in the Real Time Clock module.

Bit Manipulations in HoursWe can immediately write the minutes and seconds numbers to the registers. The hour byte needs a little work. From the data sheet for the DS1307 we read "The DS1307 can be run in either 12-hour or 24-hour mode. Bit 6 of the hours register is defined as the 12-hour or 24-hour mode-select bit. When high, the 12-hour mode is selected. In the 12-hour mode, bit 5 is the AM/PM bit with logic high being PM. In the 24-hour mode, bit 5 is the second 10-hour bit (20 to 23 hours). The hours value must be re-entered whenever the 12/24-hour mode bit is changed."

If we want to be in 12 hour mode, bit we need to set bits 5 and 6 - 5 specifies AM or PM - 6 defines the mode and must be 1 if we are in 12 hour mode. 5 must be set if we are entering a PM hour. In 24 hour mode 6 is 0, and 5 is already either 0 or 1 if the hour is greater than 19. That means we are already set to do 24 hour mode, but if we wish to change to 12 hour mode, we need to make some changes.

We need to change the way data is entered - that's simple enough, but we also need to know how to set or clear bits. To do this we must understand some simple bit manipulation routines. We can use the bitSet(Nmbr, bit) and bitClear(Nmbr, bit) functions that are built into the Arduino IDE. However, this is an excellent opportunity to explore some new and very interesting bit manipulations.

First the AND and OR functions. When we want to AND two numbers we use the "&" symbol. The OR function uses "|". When we AND two numbers together, each bit in the first number is anded with the same bit in the second number - The rule is: 1 & 1 = 1, 1 & 0 = 0, 0 & 0 = 0, 0 & 1 = 0.

Page 5: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

Consider the two binary numbers B011011001 & B01101011 = B011010001. Notice how when there is a 0 in either number the result has a 0 in that place - to get a 1 you must have a 1 in that place in the first number AND the second number.

The OR function follows a different rule:1 & 1 = 1, 1 & 0 = 1, 0 & 0 = 0, 0 & 1 = 1.

In this case a 1 in either the first number OR the second number will give a 1 as a result.

B011011001 | B01101011 = B011011011

To turn on a particular bit in a number, we use a "mask". This is a particular binary string that is all 0s except for a 1 in the place where we want to change make sure there is a 1 in the answer. In our problem, we want to turn on bit 6 in the hour register to set the operation to 12 hour mode.

We would use the mask B01000000. This number OR with Hrs will give us a number that has a 1 in the 12/24 select bit. Note the "B" in front of the binary number - The easiest way to define a mask is to write it in Binary. Just as "0x" in front of a hex number will tell the compiler the digit that follow are hex digits, the "B" in front of a series of 1s and 0s will tell the compiler that what follows is binary.

Hrs | B01000000 would give us the correct result. A 0 in the mask leaves the Hrs unchanged, but a 1 forces the result to have a 1 in that position.

To turn this bit off, we could use an and mask B10111111 an AND this with Hrs to put us in 24 hour mode.

Hrs & B10111111. A "1" in the mask leaves the Hrs unchanged, but a 0 forces the result to have a 0 in that position.

Let's modify our loop() routine to include these new features. Now in addition to reading the hours value the program asks the user to enter either 12 or 24 to set the mode. Notice how the program uses an "if" statement to check the entry and set bit 6 if a 12 was entered.

If a 12 was entered, a "nested if" (if inside an if statement) checks to see if the user also wants to specify that these are PM hours and turn on bit 5 for this condition.

The resulting Hrs variable is ready to write to the register, but to check that everything is correct, the program writes the result to the Serial monitor so the operator can verify the values.

Alternative Bit Manipulation MethodsBit manipulation involves "masks" and "shifts". The above discussion explains how to do this directly. Writing the AND, OR functions and the masks directly can make understanding the

Page 6: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

program less intuitive. An alternative is to use subroutines to set and clear individual bits in the variables.

One method for doing this would be to write subroutines that perform these functions. These subroutines would be very simple, only one line to set a bit in the bit set subroutine or one line in the bit clear subroutines.

When faced with very simple subroutines, it is often better to write simple "inline" routines using the #define compiler directive. Consider the following code

In this program two global functions are defined, bitSetN(var, bit) bitClrN(var, bit)

These are inline function "prototypes" When the compiler encounters the

function names (bitSetN() or bitClrN()) it uses the actual variable value and shift bit count in the operation defined by the code that follows 1<<N | X to set the Nth bit in the variable X or ~(1<<N) & to clear the Nth bit.

In these two operations we see the "<<" function. This is the left shift operator. In both functions, 1<<N, means take B0…0000001 and shift the 1 to the left by N places, creating the OR mask.

In the clear function, this value is then complimented (all 1s become 0s and 0s become 1s) with the "~" operator then the mask is AND "&" with the X variable.

In the setup() routine we see how this works. In the first example, the program prints the result of bitSetN(15, 14) The variable is the number 15 and the 14th bit is set. The program identifies which bit is variable and which is shift count by their position in the parenthesis. The result is B0100000000001111

In the second example the function bitClrN(15,2) is printed to the monitor. The result isB0000000000001011. Note, the variable 15 is B0000000000001111 - This operation turns bit 2 from a 1 to a 0.

These definitions are very simple and can be easily incorporated into Arduino programs. As they are definitions, they do not require extra memory or computer cycles when not used.

#define bitSetN(X,N) 1<<N | X#define bitClrN(X,N) ~(1<<N) & X

Lastly, the Arduino IDE incorporates two functions for bit manipulations.

bitSet(x, n); and bitClear(x, n); These are subroutines and work just like the define functions above, but require extra programming space.

Page 7: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

Using I2C to write to the RTCNow that we have prepared our variables the program can write these values to the memory of the DS1307 real time clock device. The following is an alteration from another document developed to work with the AT24C256 EEPROM.

The wire library comes with the basic Arduino installation. It interfaces the Arduino with the TwoWire class and allows you to communicate using I2C. I2C requires 4 wires - Power (5Volts) Ground (GND), SCL (Serial Clock - A5) and SDA (Serial Data - A4) On the red Robo Arduinos, these 4 pins are together in the lower left hand corner of the board - 4 male pins in a blue base.

Here we see the 4 pins connected to the Red (GND), Blue (VCC), Yellow (SDA) and Green (SCL) wires.

Connect these pins directly to the wires on the device - RTC or other I2C device. Add the line

#include <wire.h>

to your Arduino program. We are ready to begin using the I2C interface to write to and read from the device. We will be working with the DS1307 device, but the information is useful for most any

I2C device.

These are the functions that are available in the TwoWire class. In this case the constructor does not require any parameters and is inserted automatically as part of the include file and is names "Wire". The last line in the include file and acts as the constructor for the class

extern TwoWire Wire;

It constructs a copy of the TwoWire Class and calls it Wire. Throughout our program we will precede all functions with "Wire." This will tell the program that we are accessing one of the functions listed below and that the code can be found in the Wire.cpp program from the library.

Wire FunctionsThese are the functions that the TwoWire class brings to our program. begin()requestFrom()beginTransmission()endTransmission()write()available()read()

Page 8: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

The first function to consider is Wire.begin(); The program uses the internal I2C block in the Arduino processor. To use this in communication, we must initialize it, set internal Arduino registers and dedicate the A4 and A5 pins to the communication functions. Wire.begin(); does this. If you have multiple I2C devices connected the Arduino, such as an LCD, EEPROM clock, etc, each will have a begin() function. Some will require parameters. I have not evaluated all possible combinations, but in many cases, only one begin() is required.

When using the Wire library, it is important to understand how the writing process work. To write to the DS1307 we use the beginTransmission(Address); function. Here we must specify the address of the RTC device. All I2C devices have a 7 bit address. For the DS1307 chip, the address is B1101000 or in hex 0x68. We add a leading 0 to these 7 bits to create a byte. For the LCD this address becomes 00100111 or in hex 0x27.

After the we have initialize the transmission, and set the device address, the next step is to send the register number for the first location. I2C communication is based on the idea that we send a series of bytes and these get stored in successive registers. To set the date and time in RTC we need to write registers 0 through 6 (7 bytes total).

First we send the register location for the seconds byte (00h). After sending the start address we write the byte value that is to be stored in this location. After this, the register location automatically increments to the next location (01h minutes), then hours, and so on.

Let's look at a program. In this case the program assumes that global variables Sec, Min, Hrs, Day, Date, Mnth, and Yr exist and have been initialized by the full version of the program discussed earlier

In this subroutine we again have to work with the extra bits in the Hrs variable - Namely the 12 or 24 hour mode, and if in 12 hour mode, the AM or PM condition.

The program uses a mask in line 53 to determine if we are in 12 hour mode. If in 24 hour mode, there is no issue and the display continues.

If 12 hour mode is selected, the program needs to eliminate bits 5 and 6 from the hex number. In line 54 this is done with a mask. The mask we

want is B10011111, but this is not as easy to read as B01100000. To make the program more understandable the '~' is used to convert B01100000 into the correct mask B10011111.

Line 54 does not change Hrs. Bits 5 and 6 are not altered, only they are forced to be 0 in the printing. If 12 hour mode is selected the program should print either AM or PM after the time.

Page 9: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

Again in line 62, the program checks if bit 6 and bit 5 are set and PM is in order. If only bit 6 is set AM is printed instead.

Notice the sequence. First beginTransmission(0x68); to start the communication process. Next we send the address of the first register the program will be writing to. Finally, 7 writes to 7 bytes in successive addresses. Lastly endTransmission()

endTransmission() is required before another write or read can be started. Good practice to end the transmission as soon as the program is done with a block transfer.

This sets the time and date in the RTC. As long as power is applied to the chip, the seconds will continue to update each second. After 1 minute the minute register will update and the second register begin again at 0 and so on. The RTC shield (board with a chip on it) usually includes a battery to keep help keep the time updating even when the Arduino is unplugged and no longer supplying power to the chip.

Reading the RTC Date and TimeTo read the RTC, the Arduino must begin by again setting the RTC (I2C slave) address with the Wire.beginTransmission(0x68); // Set the address we are talking to.

Then the program must send the address of the first register we wish to read. Finally the program requests that a certain number of sequential bytes be read out of sequential registers.

This code sequence reads 7 bytes from the DS1307 chip registers. Note, after the beginTransmission(0x68); the program writes 0x00 to the device to set the I2C address pointer to the first register

location. After this, the program ends the transmission, because this is the only byte that needs to be written.

Now that the address pointer is at the beginning of the memory, the program asks the RTC to send 7 sequential bytes out of the 7 registers, starting with 0x00. These bytes go into the I2C buffer.

Just as with the serial monitor, the Wire.available() function returns the number of bytes that are available in the receive buffer. The for loop reads these bytes and writes them to the serial

monitor.

Good programming practice would indicate that this process should be in a separate subroutine.

Page 10: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

The routine requires no variables and sets global variables so there is no return values. In the final program this routine is only called once.

Some may be tempted to insert the block of code in the loop() function rather than separate this out as a subroutine. Good practice suggests this should be a separate routine. It performs a single function and the resulting program is easier to read if this is put in a separate subroutine.

The same may be said for the writeRTC() routine. Again, no parameters are required (empty parenthesis) and no return value (void return). This program is only called when the operator needs to reset the date or time. Putting this in a separate routine makes the resulting code easy to read, understand, and of course, fix if errors are discovered.

Also, putting this in a separate routine means this code can be tested independent of the main program. It performs a singular function.

The Final ProgramThe final version of the program is quite lengthy, and may seem a little complicated at first. Don't be dismayed - Well written programs are very easy to understand. The program begins with a brief comment about the program, how it works and when it was written. This is followed by the include files, the constructors and the global variables.

Even though this program is 141 lines, it is very simple. To understand the full program, only need be concerned with setup() and loop(). setup() initializes the variables. Look to see what it does and what resources will be available. Notice in setup() the user is given the opportunity to set the date and time, that is load the RTC registers. This only happens once and belongs in setup().

Next go to loop(). This is a simple program. The if (millis() - time > 500) says we are going to do this twice a second. Then the entire program consists of 2 lines - read the RTC write the LCD. Actually, that's all there is to this program. The subroutines readRTC() and writeLCD() do what the name suggests. Don't think of these things as part of the program any more than a function call like digitalWrite(13, HIGH);

Treat subroutines as separate functions that do a specific thing. If there is a problem, these functions should be evaluated separately and if possible separate from the program.

Consider how much more difficult this would be if the code from writeRTC() had been part of the setup() routine, or if readRTC() and writeLCD() had been included in the loop() program. It would be very difficult to sort through and figure out what was being done.

Page 11: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

/* This program will operate with an LCM1602 IIC 2 line 16 character display and aDS1307 Real Time Clock (RTC). The user is allowed to set the correct time and datewhen the program first starts. 12 or 24 hour mode can be selected. When in operationthe program reads the RTC every half second and updates the display to show current date and time. 2015 Adrian Krag *//*************** Include Files ********************************/#include <Wire.h>#include <LiquidCrystal_I2C.h>/*************** Constructors ********************************/LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address/*************** Global Variables *****************************/String DoW[] = {"Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"};String Mn[] = {"Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"};byte Hrs, Min, Sec, Day, Date, Mnth, Yr;long time;/************** Setup Runs Once at Startup*********************/void setup() { Serial.begin (9600); lcd.begin(16,2); // initialize the lcd for 16 chars 2 lines, turn on backlight lcd.clear(); //Start writing at character 0 on line 0 (the first line) writeLCD(); // Display date and time on LCD Serial.println ("Do you wish to reset the date and time Y or N"); while (!Serial.available()); if (Serial.read() == 'Y') writeRTC(); // Store the global values in the RTC registers time = millis();}/*************** Loop Runs Continuously ***********************/void loop() { if (millis() - time > 500) { time = millis(); readRTC(); writeLCD(); }}/* This routine will read the Serial.monitor buffer and return the BCD valuethat was entered. Each digit will be a hex number. This routine wis a modification of the ReadDec() function. 2015 Adrian Krag */byte ReadHex(){ byte Nmbr = 0; // Initializa the result.

Page 12: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

while (!Serial.available()); // Wait until the user presses enter delay (50); // allow tiem fo the digits to come across the USB for (int i = 0; Serial.available() > 0; i++) // Read until no more digitis { Nmbr *= 16; // Multiply accumulation by 16, not 10. Nmbr += (Serial.read() - '0'); // Read ASCII nd conver to number } return (Nmbr); // Return the accumulated result.}/* This routine will cause the LCD to display the current date and timeas dictated by the global variables Hrs, Min, Sec, Date, Day, Mnth, andYr. It will erase the LCD and rewrite it with the current date and time.2015 Adrian Krag */void writeLCD(){ lcd.clear(); // erase the lcd in preparation for next write. lcd.setCursor(0,0); // set the cursor row 0, col 0 if (Hrs & B01000000) // Check for 12 hour mode lcd.print (Hrs & ~B01100000, HEX); // clear 2 bits if 12 hour mode else lcd.print (Hrs, HEX); // 24 hour mode clear bit not necessary lcd.print (':'); lcd.print (Min, HEX); lcd.print (':'); lcd.print (Sec, HEX); lcd.print (' '); if ((Hrs & B01000000) && (Hrs & B00100000)) // Check for 12 hour mode and PM lcd.print ("PM "); else if (Hrs & B01000000) // Check for 12 hour mode and AM lcd.print ("AM "); lcd.print (DoW[Day - 1]); lcd.setCursor(0,1); lcd.print (Mn[Mnth]); lcd.print (' '); lcd.print (Date, HEX); lcd.print (' '); lcd.print ("20"); lcd.print (Yr, HEX);}/* This routine will read the 7 registers from the DS1307 and fill the appropriate global variables. 2015 Adrian Krag */void readRTC(){ Wire.beginTransmission(0x68); // set the RTC address Wire.write (0x00); // Send the Register Address Wire.endTransmission(); // done transmitting

Page 13: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

Wire.requestFrom(0x68, 7); // request the 7 date and time registers while (!Wire.available()); // wait until the read is complete delay (50); // wait for the transfer to complete. Sec = Wire.read(); Min = Wire.read(); Hrs = Wire.read(); Day = Wire.read(); Date = Wire.read(); Mnth = Wire.read(); Yr = Wire.read();}/* This routine is used to write the registers. When the program starts, the operator is asked if he or she wishes to reset the clock date and time.If the answer is yes, this function is run. 2015 Adrian Krag */void writeRTC() { Serial.println ("Enter the Hour 0 to 12/23"); Hrs = ReadHex(); // Read digits from the buffer Serial.println ("Enter 12 or 24 to select mode"); if (ReadHex() == 0x12) // read 0x12 or 0x24 { Hrs |= B01000000; // Set the bit for 12 hour mode Serial.println ("Enter A for AM or P for PM"); while (!Serial.available()); if (Serial.read() == 'P') Hrs |= B00100000; } Serial.println ("Enter the Minutes"); Min = ReadHex(); // Read the minutes hex value Serial.println ("Enter the seconds"); Sec = ReadHex(); // Read the minutes hex value Serial.println ("Enter the Day of the Week Sunday is 1"); Day = ReadHex(); // Read the Day of the week hex value Serial.println ("Enter the Date 0 to 31"); Date = ReadHex(); // Read the Date hex value Serial.println ("Enter the Month January is 1"); Mnth = ReadHex(); // Read the Month hex value Serial.println ("Enter the year 0 to 99"); Yr = ReadHex(); // Read the Year hex value Wire.beginTransmission(0x68); Wire.write (0x00); // Send the Register Address Wire.write (Sec); // write the seconds value Wire.write (Min); // Write the minutes Wire.write (Hrs); // Hours 12 hour, PM 7 PM Wire.write (Day); // Thursday Wire.write (Date); // 9th of the month

Page 14: RTC - DS1307 - Web viewThe Arduino TwoWire class is loaded with the Wire.h include which activates the I2C peripheral and includes the routines that are ... A word about the line

Wire.write (Mnth); // Month 3 March Wire.write (Yr); // Year is 2015 Wire.endTransmission();}

As always, if you have any problems, or certainly if you find any errors in the code, contact me

Adrian [email protected] 321 6985