Hi Buddies!
Today on our BuddyKit, let’s explore one of the essential communication protocols – the I2C Protocol.
Microcontrollers support many protocols like I2C, SPI, and Serial. Among these, I2C (Inter-Integrated Circuit) is widely used for communication between devices on the same board or across boards.
I2C works with one master and multiple slave devices. Each slave device has a unique address, and communication starts when the master sends a data packet with the slave address.
Basics of I2C
I2C has two main lines:
- SDA – Serial Data Line
- SCL – Serial Clock Line
The master controls communication, initiates data transfer, and makes decisions. We’ll be writing the code from the master side.
I2C has 3 Main Stages:
- Start Condition
- Data Transfer (Write/Read)
- Stop Condition
Start Condition:
Start condition occurs when SDA goes from HIGH to LOW while SCL is HIGH.
1 2 3 4 5 6 7 8 | // Confirm both SDA and SCL are HIGH SDA = 1; SCL = 1; // Then create a falling edge on SDA SDA = 0; SCL = 0; |
Stop Condition:
Stop condition occurs when SDA goes from LOW to HIGH while SCL is HIGH.
1 2 3 4 | SDA = 0; SCL = 1; SDA = 1; |
Data Transfer:
During a write, master sets SDA as output, sends each bit with clock pulses. After 8 bits, 9th bit is ACK (acknowledge).
During a read, master sets SDA as input and reads data on each clock pulse.
1 2 3 4 5 6 7 8 9 10 11 | // Read ACK after writing SDA = 1; SCL = 1; ack = SDA; SCL = 0; // Send ACK after reading SDA = ack; SCL = 1; SCL = 0; |
I2C Write Operation
1 2 3 4 5 6 7 | u8 mask = 0x80; while (mask) { SDA = (dat & mask) ? 1 : 0; SCL = 1; SCL = 0; mask >>= 1; } |
I2C Read Operation
1 2 3 4 5 6 7 8 | SDA = 1; for (i = 0; i < 8; i++) { dat <<= 1; SCL = 1; if (SDA) dat++; SCL = 0; } |
Interfacing DS1307 RTC with I2C
Now let’s apply the I2C concept with DS1307 – a Real Time Clock (RTC) module.
This is an I2C slave device with these addresses:
0xD0
– for Write0xD1
– for Read
RTC stores data in specific memory locations:
- 0x00 – Seconds
- 0x01 – Minutes
- 0x02 – Hours
- 0x03 – Day of Week
- 0x04 – Date
- 0x05 – Month
- 0x06 – Year
Note: The RTC uses 1970 as the base year. So, if you see 55 in RTC memory, it means 2025 (1970 + 55).
All values are stored in BCD format.
RTC Write Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void RTC_Write(void) { I2C_Start(); I2C_Write(0xD0); // Slave Write I2C_Write(0x00); // Start address I2C_Write(HEX2BCD(seconds) & 0x3F); I2C_Write(HEX2BCD(minutes)); I2C_Write(HEX2BCD(hours)); I2C_Write(HEX2BCD(dayOfWeek)); I2C_Write(HEX2BCD(date)); I2C_Write(HEX2BCD(month)); I2C_Write(HEX2BCD(year + 30)); I2C_Stop(); } |
RTC Read Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | u8 RTC_Read(void) { I2C_Start(); I2C_Write(0xD0); // Slave Write I2C_Write(0x00); // Start address I2C_Start(); I2C_Write(0xD1); // Slave Read seconds = BCD2HEX(I2C_Read(0)) & 0x3F; minutes = BCD2HEX(I2C_Read(0)); hours = BCD2HEX(I2C_Read(0)); dayOfWeek = BCD2HEX(I2C_Read(0)); date = BCD2HEX(I2C_Read(0)); month = BCD2HEX(I2C_Read(0)); year = BCD2HEX(I2C_Read(1)) - 30; I2C_Stop(); return 0; } |
Circuit Diagram
RTC Clock Display Demo
Using the above code and our BuddyKit RTC & LCD libraries, we can display a real-time clock on LCD.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #include "../library/I2C/I2C.h" #include "../library/LCD4/LCD4.h" #include "../library/DS1307/DS1307.h" #include "../library/Delay/Delay.h" void main() { u8 buff[17]; I2C_Init(); // Initialize I2C LCD_Init(); // Initialize LCD RTC_Init(); // Initialize RTC LCD_LeftToRight(); // Default: Left-to-right text LCD_NoAutoscroll(); // Disable autoscroll (manual scrolling only) LCD_Puts("RTC CLOCK DEMO"); while (1) { // Infinite loop RTC_Read(); // Read current time from RTC RTC_Time2Str(buff); // Convert time to string format LCD_ClearRow(0); // Clear first row of LCD LCD_Puts(buff); // Display time on LCD Delay1s(); // Wait 1 second before updating again } } |
Final Note
We hope this I2C protocol explanation and RTC example helped you understand how real-world sensors and timekeeping modules communicate with microcontrollers.
There are many more I2C-based devices like gyroscopes, ADCs, temperature & humidity sensors, accelerometers, and more. In our upcoming videos, we’ll cover many of them using BuddyKit.
Stay tuned for our next topic. See you soon!
Leave Your Reply
You must be logged in to post a comment.