Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

I2C serial communication

Status
Not open for further replies.

vead

Full Member level 5
Joined
Nov 27, 2011
Messages
285
Helped
3
Reputation
6
Reaction score
3
Trophy points
1,298
Location
india
Activity points
3,815
Hello
I want to interface ds1307 with 8051. I am looking help to build routine for I2C Protocols.

Code:
#include<reg51.h>
sbit SDA = P0^0;
sbit SCL = P0^1;

#define SDA_Low   (0)
#define SDA_High   (1)
#define SCL_Low    (0) 
#define SCL_High   (1)

//Set initial values of SCK and SDA pins //   
 void I2C_Inlization(void)         
  {
    SDA = SDA_High;
    SCL = SCL_High;
  }

//I2C_Start sends start bit sequence//         
 void I2C_Start(void)
  {
     SDA = SDA_Low;
     SCL = SCL_Low;
  }

// I2C_ReStart sends start bit sequence        
 void I2CRestart(void)
  {
     SDA = SDA_High;
     SCL = SCL_Low;
     SDA = SDA_Low;
     SCL = SCL_Low;
  }

//I2C_Stop sends stop bit sequence//	
  void I2CStop()
  {
     SCL = SCL_Low;
     SDA = SDA_Low;
     SCL = SCL_High;
     SDA = SDA_High;
  }
 
//I2C_Send_ACK sends ACK bit sequence
  void I2CAck()
  {
     SDA = SDA_Low;
     SCL = SCL_High;
     SCL = SCL_Low;
     SDA = SDA_High;
  }

//I2C_Send_NACK sends NACK bit sequence //	
  void I2CNak()
  {
     SDA = SDA_High;
     SCL = SDA_High;
     SCL = SCL_Low;
     SDA = SDA_High;
  }
 	
 unsigned char I2CSend(unsigned char Data)
  {
      unsigned char i, ack_bit;
      for (i = 0; i < 8; i++)
	   {
      if ((Data & 0x80) == 0)
         SDA = SDA_Low;
      else
       SDA = SDA_High;
       SCL = SCL_High;
       SCL = SCL_Low;
       Data<<=1;
     }
       SDA = SDA_High;
       SCL = SCL_High;
       ack_bit = SDA;
       SCL = SCL_Low;
       return ack_bit;
  }
         
  unsigned char I2CRead()
        {
        	unsigned char i, Data=0;
        	for (i = 0; i < 8; i++) {
        		SCL = SCL_High;
        		if(SDA)
        			Data |=1;
        		if(i<7)
        			Data<<=1;
        		SCL = SCL_Low;
        	}
        	return Data;
        }
Am I missing something in this routine ?
 

Hi,

This has been discussed often enough in this forum.

Or do you encounter a special problem?

Klaus
 

Hi,

This has been discussed often enough in this forum.

Or do you encounter a special problem?

Klaus

Yes first I wanted to confirm that my routine is correct. I am facing problem to write routine for DS1307. I have downloaded datasheet for 1307. Is there any problem in I2C routine ?
 

Yes first I wanted to confirm that my routine is correct. I am facing problem to write routine for DS1307

Let me introduce you to some concepts of how things work: No one is going to tell you what is wrong with your program, but you are the one who should seek ways to debug part by part, whether in the simulation or in the real world.

Anyway, back to the initial question, the following instructions (and others alike) are candidates for failure, especially if you have wired up the RTC at a certain distance from the uC and are operating at a high speed. Try as a first attempt, insert a small delay between each one:

Code:
     SDA = SDA_High;
     SCL = SCL_Low;
     SDA = SDA_Low;
     SCL = SCL_Low;
 
  • Like
Reactions: vead

    vead

    Points: 2
    Helpful Answer Positive Rating
Basically agree with andre_teprom about the debug methodology. In addition, notice that the repeated sequence is incorrect, it misses the SDA falling edge while SCL is high.

Suggest to review the Philips/NXP I2C specification as a starting point.

Regarding delays, standard 8051 operates at 1 MIPS, resulting in 1 µs delay per simple port bit set or reset. That's a bit faster than standard 100 kHz I2C specification of DS1307, but not much. It's however much too fast if using a modern 8051 type with higher MIPS rate.
 
  • Like
Reactions: vead

    vead

    Points: 2
    Helpful Answer Positive Rating
Try as a first attempt, insert a small delay between each one:
Does it make any sense ?
Code:
// I2C_ReStart sends start bit sequence        
 void I2CRestart(void)
  {
     SDA = SDA_High;
    delay (1000);
     SCL = SCL_High;
    delay (1000);
     SDA = SDA_Low;
    delay (1000);
     SCL = SCL_Low;
    delay (1000);
  }
 

Hi,

Does it make any sense ?
if you want to reinvent the wheel ... then I´d say it is your job to read I2C specifications.

Klaus
 

Hi,
if you want to reinvent the wheel ... then I´d say it is your job to read I2C specifications.

Klaus
I don't want to repeat someone code. I want to implement my own with proper understanding. I just want someone who can tell me weather my code is right or wrong. I said previously I want to interface ds1307. If my I2C routine is OK than I will write code for DS1307. I am just asking confirmation for I2C routine. I will post all code for i2c routine
 

Please someone assist me with this code. Does it complete routine for I2C ?
Code:
#include<reg51.h>
sbit SDA = P0^0;
sbit SCL = P0^1;

#define SDA_Low		 (0)
#define SDA_High   (1)
#define SCL_Low    (0) 
#define SCL_High   (1)

//Set Delay Function //
void delay(unsigned int d)
{
   unsigned int i;

   for(i=0;i<d;i++);
}
//Set initial values of SCK and SDA pins //   
 void I2C_Inlization(void)         
  {
    SDA = SDA_High;
    SCL = SCL_High;
  }

//I2C_Start sends start bit sequence//         
 void I2C_Start(void)
  {
     SDA = SDA_Low;
     SCL = SCL_Low;
  }

	// I2C_ReStart sends start bit sequence        
 void I2CRestart(void)
  {
     SDA = SDA_High;
    delay (1000);
     SCL = SCL_High;
    delay (1000);
     SDA = SDA_Low;
    delay (1000);
     SCL = SCL_Low;
    delay (1000);
  }
//I2C_Stop sends stop bit sequence//	
  void I2CStop()
  {
     SCL = SCL_Low;
		 delay (1000);
     SDA = SDA_Low;
		 delay (1000);
     SCL = SCL_High;
		 delay (1000);
     SDA = SDA_High;
		  delay (1000);
  }
 
//I2C_Send_ACK sends ACK bit sequence
  void I2CAck()
  {
     SDA = SDA_Low;
		 delay (1000);
     SCL = SCL_High;
		 delay (1000);
     SCL = SCL_Low;
		 delay (1000);
     SDA = SDA_High;
		  delay (1000);
  }

//I2C_Send_NACK sends NACK bit sequence //	
  void I2CNak()
  {
     SDA = SDA_High;
		  delay (1000);
     SCL = SDA_High;
		   delay (1000);
     SCL = SCL_Low;
		   delay (1000);
     SDA = SDA_High;
		 delay (1000);
  }
 	
 unsigned char I2CSend(unsigned char Data)
  {
      unsigned char i, ack_bit;
      for (i = 0; i < 8; i++)
	   {
      if ((Data & 0x80) == 0)
         SDA = SDA_Low;
			    delay (1000);
      else
       SDA = SDA_High;
			  delay (1000);
       SCL = SCL_High;
			 delay (1000);
       SCL = SCL_Low;
			  delay (1000);
       Data<<=1;
     }
       SDA = SDA_High;
       SCL = SCL_High;
		    delay (1000);
       ack_bit = SDA;
       SCL = SCL_Low;
		    delay (1000);
       return ack_bit;
  }
         
  unsigned char I2CRead()
        {
        	unsigned char i, Data=0;
        	for (i = 0; i < 8; i++) {
        		SCL = SCL_High;
						 delay (1000);
        		if(SDA)
        			Data |=1;
        		if(i<7)
        			Data<<=1;
        		SCL = SCL_Low;
						 delay (1000);
        	}
        	return Data;
        }
 

The huge delays make no sense. You want to introduce maximal µs delays to conform with 100 kHz I2C requirements.
 

The huge delays make no sense. You want to introduce maximal µs delays to conform with 100 kHz I2C requirements.

Thanks. DS 1307 RTC require 32kHz crystal. I have no idea where and when to set delay in program ?
 

Delays should be at the end of routines such as I2CRead() or I2CSend, a Delay_ms(20) should work, but, as everyone as stated you should debug your code on the real system and then figure out if those delays worked
 

I2c standart speed is 100kHz, so, basically, single delay for at least 10uS should be enought for all cases.
 

Hi,

If the OP is able to read the forum posts, then it should be no problem to read datasheets. All the timings are given.
It makes no sense that we read datasheets and post the datasheet contents.

The I2C specification as well as the DS1307 datsheet gives all that one needs to know. Like the reqested delay time...

Klaus
 

99% of all treads and topics on this forum are similar :)
I provided complete code. Even that did not helped. But there I specially put delay function out from the code to make it optional and not hw related.
 

99% of all treads and topics on this forum are similar :)
I provided complete code. Even that did not helped. But there I specially put delay function out from the code to make it optional and not hw related.

I saw the links that you gave me. I said previously I don't want to copy paste someones code. Without proper understanding How can someone write code. Have you seen there are much difference between your code and my cod.

I divided whole program into three parts for easy learning. I wanted to develop my own with understanding

1. LCD programming
2. I2C Programming
3. DS1307 Programming

I don't have much knowledge of programming. I want to understand the basics of I2C protocols.so that's the reason I was trying to complete big program into small parts. So I was trying to complete I2C programming But Now I am struggling
 

Hi,

I said previously I don't want to copy paste someones code. Without proper understanding How can someone write code.
I don't understand this. This is why there are existing programs and libraries.
If you want to drive an car...you won't build your own car, especially when you don't have the knowledge to build a car.
You use it. It works. And you don't need to know about how the engine works and all that physics that is behind this.

If you want to creat a PCB layout on a computer. You won't design your own computer hardware, you won't design the OS and you won't write your own PCB layout software. You use existing, proven parts. Then read the manual on how to use it.

It is the wrong way to write software.

But you are free to go your own way.
If you want to do all this on your own, then I see no way around to go to school, learn how to read datasheets and specifications, and find ways to verify your work on your own. A forum can't replace all this.

Klaus
 

Hi,


I don't understand this. This is why there are existing programs and libraries.
If you want to drive an car...you won't build your own car, especially when you don't have the knowledge to build a car.
You use it. It works. And you don't need to know about how the engine works and all that physics that is behind this.

If you want to creat a PCB layout on a computer. You won't design your own computer hardware, you won't design the OS and you won't write your own PCB layout software. You use existing, proven parts. Then read the manual on how to use it.

It is the wrong way to write software.

But you are free to go your own way.
If you want to do all this on your own, then I see no way around to go to school, learn how to read datasheets and specifications, and find ways to verify your work on your own. A forum can't replace all this.

Klaus

Hello
I am really sorry. I didn't mean to hurt someone. I was requesting to someone to look my code that I wrote myself. I did forum search and I have read datasheet but still I am struggling on it. fine I will re-read again and try to short out some issues
 

I would say easier: no one will review your code for free. It is a huch work. Up to me - to much effort.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top