0% found this document useful (0 votes)
17 views41 pages

Class Notes

Chapter 18 discusses the TWI (I2C) protocol and its interfacing with the DS1307 RTC. It explains the functionality of the TWI protocol, which allows communication between multiple devices using two wires, and details the electrical characteristics and operational modes of I2C nodes. Additionally, the chapter covers the DS1307 RTC's features, pin connections, and how to configure it for accurate timekeeping.

Uploaded by

005blueharry
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views41 pages

Class Notes

Chapter 18 discusses the TWI (I2C) protocol and its interfacing with the DS1307 RTC. It explains the functionality of the TWI protocol, which allows communication between multiple devices using two wires, and details the electrical characteristics and operational modes of I2C nodes. Additionally, the chapter covers the DS1307 RTC's features, pin connections, and how to configure it for accurate timekeeping.

Uploaded by

005blueharry
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

Microprocessor and Microcontroller

Chapter 18: TWI (I2C) Protocol and


DS1307 RTC Interfacing
Engr. Rashid Farid Chishti
http://youtube.com/rfchishti
http://sites.google.com/site/chi
shtiH-10, Islamabad, Pakistan
International Islamic University
2-wire Serial Interface BUS Protocol
■ The 2-wire Serial Interface (TWI) is ideally suited for typical microcontroller
applications.
■ The TWI protocol allows the systems designer to interconnect up to 120
different devices using only two bi-directional bus lines.
■ one for clock (SCL) and one for data (SDA).
■ The only external hardware needed to implement the bus is a single pull-up
resistor for each of the TWI bus lines.
■ All devices connected to the bus have individual addresses, and mechanisms
for resolving bus contention are inherent in the TWI protocol.
■ The TWI is also referred to as I2C (I2C) or I square C in many technical
literatures.
Connecting devices using I2C
■ These two pins, SDA and SCK, make the I2C a 2-wire interface. In many
application notes, including AVR datasheets, I2C is referred to as Two-Wire
Serial Interface (TWI).

TWI Bus Interconnection


I2C Line Electrical Characteristics
■ Synchronous
■ I2C devices use only 2 bidirectional open-drain pins for data communication.
To implement I2C, only a 4.7 kilohm pull-up resistor for each of bus lines is
needed (see Figure)
■ This implements a wired-AND, which is needed to implement I2C protocols.
■ This means that if one or more devices pull the line to low (zero) level, the line
state is zero and the level of line will be 1 only if none of devices pull the line
to low level.
I2C Nodes
■ In the AVR up to 120 different devices can share an I2C bus. Each of these
devices is called a node. In I2C terminology, each node can operate as either
master or slave.
I2C Line Electrical Characteristics
■ Master is a device that generates the clock for the system; it also initiates and
terminates a transmission.
■ Slave is the node that receives the clock and is addressed by the master. In
I2C, both master and slave can receive or transmit data, so there are four
modes of operation. They are:
■ Master Transmitter
■ Master Receiver
■ Slave Transmitter
■ Slave Receiver.
■ Notice that each node can have more than one mode of operation at different
times, but it has only one mode of operation at a given time.
Start and Stop Condition

■ START

■ STOP
Sending bits of data
The SDA values changes
when SCL is low.

The receiver reads SDA on


the falling edge of SCL.
Data Packet Format
■ Each packet is 9 bits long.
■ First 8 bits are put on SDA by the transmitter
■ The 9th bit is an acknowledge by the receiver
❑ NACK (leave high) or ACK (pull down)
Sending a Byte
Sta W AC A St
rt rit K C op
e K
Slave address Data Byte
S 0 0 1 1 0 0 1 0 A 0 0 0 1 0 0 1 1 A P

Slave Address + W(0) Send 0x13


= 0x32+0 = 0x32 to Slave
Receiving a Byte
Sta R AC A St
rt ea K C op
d K
Slave address Data Byte
S 0 0 1 1 0 0 1 1 A 0 0 0 1 1 0 1 1 A P

Slave Address + R(1) Receive 0x1B


= 0x32+1 = 0x33 from Slave
Repeated START Condition
■ A new START condition before the Stop condition
TWI (i2C) Unite in AVR
Clock (SCL) Frequency
TWBR (TWI Bit Rate) Register

TWSR (TWI Status) Register


TWCR (TWI Control Register)
TWCR (TWI Control) Register

■ TWINT: TWI Interrupt flag


■ TWEA: TWI Enable Acknowledge bit
❑ 1:ACK, 0:NACK
■ TWSTA: TWI Start condition bit
■ TWSTO: TWI Stop condition bit
■ TWWC: TWI Write Collision flag
■ TWEN: TWI Enable bit
■ TWIE: TWI Interrupt Enable
TWCR (TWI Control Register)
TWAR (TWI Address Register)
TWAR (TWI Address) Register

■ TWA6:TWA0 (TWI slave Address)


■ TWGCE (TWI General Call Recognition Enable bit)
❑ If the TWGCE is set, the TWI will respond to the general call address (0x00)

❑ Otherwise it will ignore the general call address.


Example 1: Master Transmitter (1/2)
void Wire_Begin(){
TWSR = 0x00; // Set prescaler bits to zero
TWBR = 152; // SCL frequency is 50K for XTAL = 16M
TWCR = 0x04; // Enable the TWI module
}
void Wire_Begin_Transmission(byte address){
// transmit START condition and Clear TWINT Flag Bit
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
while (( TWCR & (1 << TWINT)) == 0); // Wait for TWINT Flag Bit to become 1
Wire_Write(address); // Connect to Slave Device of Address 0x32+W(0)
}
void Wire_End_Transmission(){ // transmit STOP condition Note: we cannot poll the
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // TWINT flag after transmitting the STOP condition
}

void Wire_Write(byte aByte){


TWDR = aByte; // Place One Byte in Data Register
TWCR = (1<<TWINT)|(1<<TWEN); // Send One Byte Data
while ((TWCR & (1<<TWINT)) == 0); // Wait for 8-bit data to be Sent.
} // Wait for TWINT Flag to Clear 17
Example 1: Master Transmitter (2/2)
byte Wire_Read(bool ack) {
TWCR = (1<<TWINT)|(1<<TWEN)|(ack<<TWEA);
while ( (TWCR & (1<<TWINT) ) == 0);
return TWDR;
}
void setup(){
Wire_Begin(); // join i2c bus
}

void loop(){
delay(100);
static byte val = 'A';
Wire_Begin_Transmission(0x32+0); // transmit START condition and transmit SLA + W(0)
Wire_Write(val); // transmit One Byte of Data
Wire_End_Transmission(); // transmit STOP condition
val++; // increment value
if(val > 'z'){ // if reached
val = 'A'; // start over from lowest value
}
} 18
Example 1: Slave Receiver
void Wire_Begin(byte address){ void setup(){
TWAR = address; Wire_Begin(0x32); // join i2c bus with
} // address 0x32 as LSB of address 0x32 is
void Wire_onConnect(bool ack){ // 0 that means do not answer to general
TWCR = (1<<TWINT)|(1<<TWEN)|(ack<<TWEA); // call(Address 0x00).
// poll the TWINT flag to see when the slave
// is addressed by a master device Serial.begin(9600);
while ((TWCR & (1<<TWINT)) == 0); }
}
void loop(){
byte Wire_Read(bool ack){ byte R;
TWCR = (1<<TWINT)|(1<<TWEN)|(ack<<TWEA); Wire_onConnect(1); // Send acknowledge to
while ((TWCR & (1<<TWINT)) == 0); // Master Device
return TWDR; R = Wire_Read (1); // Receive Data and
} // send an acknowledge
void Wire_Write(byte aByte){ Serial.write(R); // Show Received Data
TWDR = aByte; // on Serial Terminal
TWCR = (1<<TWINT)|(1<<TWEN); }
while ((TWCR & (1<<TWINT)) == 0);
} Page 1 Page
19 2
Master Transmitter Slave Receiver
Example 2: Master Receiver
void Wire_Begin(void){ byte Wire_Read(byte ack){
TWSR = 0x00; //set prescaler bits to zero TWCR= (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
TWBR = 152; // SCL frequency = 50K if XTAL = 16M while ((TWCR & (1<<TWINT)) == 0);
TWCR = 0x04; // enable the TWI module return TWDR;
} }
void setup(){
void Wire_Begin_Transmission(byte address){ Wire_Begin(); // join i2c bus
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); Serial.begin(9600);
while ((TWCR & (1 << TWINT)) == 0); }
Wire_Write(address); void loop(){
} delay(100);
void Wire_End_Transmission(){ byte R;
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); Wire_Begin_Transmission(0x32+1);
} // transmit to device 0x32
R = Wire_Read(0);
void Wire_Write(byte aByte){ // sends value byte
TWDR = aByte; Wire_End_Transmission();
TWCR = (1<<TWINT)|(1<<TWEN); // stop transmitting
while ((TWCR & (1<<TWINT)) == 0); Serial.write(R);
} Page 1 } Page
21 2
Example 2: Slave Transmitter
void Wire_Begin(byte address){ void setup(){
TWAR=address; Wire_Begin(0x32); // join i2c bus
} // with address 0x32 as LSB of
void Wire_onConnect(bool ack){ // address 0x32 is 0 that means do
TWCR = (1<<TWINT)|(1<<TWEN)|(ack<<TWEA); // not answer to general call.
while ( (TWCR & (1<<TWINT) ) == 0); Serial.begin(9600);
} }

byte Wire_Read(bool ack){ void loop(){


TWCR = (1<<TWINT)|(1<<TWEN)|(ack<<TWEA); static byte S='A';
while ( (TWCR & (1<<TWINT) ) == 0); Wire_onConnect(1);
return TWDR; Wire_Write(S);
} S++;
}
void Wire_Write(byte aByte){
TWDR = aByte;
TWCR = (1<<TWINT)|(1<<TWEN);
while ( (TWCR & (1<<TWINT) ) == 0);
}
Page 1 Page
22 2
Master Receiver Slave Transmitter
Using Real Time Clock (RTC) DS1307
■ The RTC is widely used device that provides accurate time and date
information.
■ The DS1307 IC provides seconds, minutes, hours, day, date, month and year
information.
■ The end of the month date is automatically adjusted for months with fewer
than 31 days, including corrections for leap year.
■ The clock operates in either the 24-hour or 12-hour format with AM/PM
indicator.
■ The DS1307 has a built-in power-sense circuit that detects power failures and
automatically switches to the battery supply.
■ The DS1307 does not support the Daylight Savings Time option. Next, we
describe the pins of the DS1307. See Figure 18-14.
Using Real Time Clock (RTC) DS1307
■ X1-X2: These are input pins that allow the DS1307 connec-
tion to an external crystal oscillator to provide the clock
source to the chip. We must use the standard 32.768 kHz
quartz crystal.
■ Vbat: Pin 3 can be connected to an external +3 V lithium
battery, thereby providing the power source to the chip when the external
supply voltage is not available. We must connect this pin to ground if it is not
used. A 48mAh lithium battery can provide the power needed for more than
10 years to back up the chip.
■ GND: Pin 4 is the ground.
■ SDA (Serial Data): Pin 5 is the SDA Pin and must be connected to the SDA line
of the I2C bus.
Using Real Time Clock (RTC) DS1307
■ SCL (Serial Clock): Pin 6 is the SCL Pin and must be connected
to the SCL line of the I2C bus.
■ SWQ/OUT: Pin 7 is an Output Pin providing 1 kHz, 4.096 kHz,
8.192 kHz, or 32.768 kHz frequency if enabled.
This pin needs an external Pull-up resistor to generate the frequency because
it is open drain. If you do not want to use this pin you can omit the external
pull-up resistor.
■ Vcc: Pin 8 is used as the primary voltage supply to the chip. This primary
voltage source is generally set to +5 V. When Vcc falls below the Vbat level, the
DS1307 switches to Vbat and the external lithium battery provides power to
the RTC.
Power Connections for DS1307
Address map of the DS1307
■ The DS1307 has a 64 bytes of RAM with addresses 00-3FH.
■ Addresses 00H to 06H is used to read/write time and date.
■ Control Register is located at Address 07H.
■ Addresses 08H to 3FH is available for general purpose data storage.
■ Bit 7 of address 00H should be zero to enable the oscillator.
The DS1307 Control Register
■ The DS1307 provides data in BCD format only.
CH bit at address 00H
■ One of the most important bits in the Seconds address location in the DS1307
is the CH (Clock Halt) bit. It is the seventh bit of address location 00. Setting
the CH bit to one disables the oscillator, while setting CH to zero enables the
oscillator.
■ The CH bit is undefined upon reset. In order to enable the oscillator, we must
clear the CH during initial configuration.
Register Pointer
■ In DS1307 there is a register pointer that specifies the byte that will be
accessed in the next read or write command.
■ After each read or write operation, the content of the register pointer is
automatically incremented.
■ It is useful in multi-byte read or write.
12-hour or 24-hour mode
■ The byte addresses 00H to 06H are set aside for the time and date.
■ The DS1307 provides data in BCD format only.
■ We can select 12-hour or 24-hour mode with bit 6 of hour location 02H.
❑ If Bit6 = 0 then 24-hour mode is selected.
❑ If Bit6 = 1 then 12-hour mode is selected
❑ In the 12-hour mode, we decide the AM and PM with the Bit5.
■ If Bit5 = 0 then AM is selected
■ If Bit5 = 1 then PM is selected

0 = 24
1 = 12 0=AM
1=PM
12-hour or 24-hour mode example

0 = 24
1 = 12 0=AM
1=PM
Writing to DS1307
■ Transmit START condition
■ Transmit the Address of DS1307 (1101 000) followed by 0 to indicate a WRITE
operation
■ Transmit the Address of location you want to access (it stores the Address in
Register Pointer)
■ Transmit one or more bytes of Date
■ Transmit STOP condition

S W A A A A A S
T Slave RI C Register C C C C T
Sec Min Hours
A Address T K Pointer K K K K O
R E P
T
S 1101 000 0 A 0000 0000 A 0x55 A 0x59 A 0x23 N P
Reading from DS1307
■ Transmit START condition
■ Transmit the Address of DS1307 (1101 000 ) followed by 0 to indicate a WRITE operation
■ Transmit the address to be stored in Register Pointer.
■ Transmit STOP condition then transmit START condition
■ Transmit the Address of DS1307 (1001101) followed by 1 to indicate a READ operation
■ Receive one or more bytes of Date and send Acknowledge.
■ Send Not Acknowledge if you don’t want to receive more bytes of Date.
■ Transmit STOP condition.

S W A A S S R A A A N S
T Slave RI C Register C T T Slave E C C C A T
Sec Min Hours
A Address T K Pointer K O A Address A K K K C O
R E P R D K P
T T
S 1101 000 0 A 0000 0000 A P S 1101 000 1 A 0x45 A 0x59 A 0x23 N P
DS1307 Setting and Reading Time
DS1307 Setting and Reading Time
DS1307 Setting and Reading Time
#define SUN 0x01 void Start() {
#define MON 0x02 TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
#define TUE 0x03 while (!(TWCR & (1 << TWINT)));
#define WED 0x04 }
#define THU 0x05
#define FRI 0x06 void Stop() {
#define SAT 0x07 TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}
byte hh, mm, ss, WD, DD, MM, YY;
void Write( byte data) {
char* days[] = {"Sunday", "Monday", "Tuesday", TWDR = data;
"Wednesday", "Thursday", "Friday", "Saturday"}; TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1 << TWINT) ) ) ;
char* months[] = {"JAN", "FEB", "MAR", "APR", }
"MAY", "JUN", "JUL", "AUG",
"SEP", "OCT", "NOV", "DEC"}; unsigned char Read(unsigned char ack) {
void Clock_Set() { TWCR = (1<<TWINT)|(1<<TWEN)|(ack<<TWEA);
TWSR = 0; // set prescaler bits to zero while (!(TWCR & (1 << TWINT) ) );
TWBR = 72; // SCL frequency is 100K return TWDR;
} // for XTAL = 16MHz Page 1 } Page
37 2
DS1307 Setting and Reading Time
void RTC_Set_Time() { void RTC_Set_Date() {
Start(); // transmit START condition Start(); // transmit START condition
Write(0xD0); // address DS1307 for write Write(0xD0); // address DS1307 for write
Write(0); // set register pointer to 0 Write(0x03); // set register pointer to 3
Write(0x80); // Stop the clock. The seconds // at address 3 we have
// will be written last // week days
Write(mm); // set minutes
Write(hh); // set Hours Write(WD); // set week day
Stop(); // 1=Sunday ,7=Saturday

Start(); // transmit START condition Write(DD); // set date


Write(0xD0); // address DS1307 for write Write(MM); // set month
Write(0); // set register pointer to 0 // 1=January ,12=December
Write(ss); // write the seconds, with the
// stop bit clear to restart Write(YY); // Set year
Stop(); Stop();
} }

Page 3 Page
38 4
DS1307 Setting and Reading Time
void RTC_Get_Time() void RTC_Get_Date()
{ {
Start () ; // transmit START cond. Start () ; // transmit START condition
Write(0xD0); // Address of DS1307 is 0xD0 Write(0xD0); // address DS1307 for write
// here LSB is 0 for Write Write(3); // set register pointer to 3
Write(0); // set register pointer to 0 Stop(); // transmit STOP cond.
// to select Seconds
Stop(); // transmit STOP Cond. Start () ; // transmit START condition
Write(0xD1); // SLA + R(1)
Start () ; // transmit START condition WD = Read(1); // read day, return ACK
Write(0xD1); // Address of DS1307 is 0xD0 DD = Read(1); // read date, return ACK
// here LSB is 1 for Read MM = Read(1); // read mon, return ACK
YY = Read(0); // read hour, return NACK
ss = Read(1); // read sec, return ACK Stop(); // transmit STOP condition
mm = Read(1); // read min, return ACK }
hh = Read(0); // read hh, return NACK
Stop(); // transmit STOP Condition
}

Page 5 Page
39 6
DS1307 Setting and Reading Time
void setup() { void loop () {
RTC_Get_Date();
delay(1000); Serial.print(" Date: ");
Serial.begin(9600); Serial.print(days[WD - 1]);
Serial.print(", ");
// initialize I2C module Serial.print(months[MM - 1]);
Clock_Set (); Serial.print(" ");
Serial.print(DD, HEX);
hh = 0x23; mm = 0x59 ; ss = 0x55; Serial.print(", 20");
Serial.print(YY, HEX); Serial.print(" ");
// Set time 23:59:55
RTC_Set_Time(); RTC_Get_Time();
Serial.print("Time: ");
WD = SUN; DD = 0x19; MM = 0x04 ; YY = 0x20; Serial.print(hh, HEX);
Serial.print(":");
// Set date Sunday, 19-APR-2020 Serial.print(mm, HEX);
RTC_Set_Date(); Serial.print(":");
} Serial.println(ss, HEX);
delay(1000);
Page 7 } Page
40 8
DS3231 module
DS3231 RTC is Precise Real-Time Clock Module with 32Kbit EEPROM and a
built-in 10-bit temperature sensor. The maximum transmission speed is 400KHz
with working voltage of 5V.

You might also like