This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

8051 - I2C BitBang

Im using I2C bitbang and Im facing an issue. I think I need a delay between SCL and SDA lines. Im not sure how much the delay needs to be.
Can someone check my I2C code to see if everything checks out? I want to make sure its not a software mistake.

#include <at89c51ic2.h>
#include <stdio.h>

#define SDA P0_0
#define SCL P0_1

void I2CInit(){
        SDA = 1;
        SCL = 1;
}
void I2CStart(){
        SCL = 1;
        I2CDelay();
        SDA = 0;
        I2CDelay();
        SCL = 0;
        I2CDelay();
}
void I2CRestart(){
        SDA = 1;
        SCL = 1;
        SDA = 0;
        SCL = 0;
}
void I2CStop(){
        SDA = 0;
        I2CDelay();
        SCL = 1;
        I2CDelay();
        SDA = 1;
        I2CDelay();
}
void I2CAck(){
        I2CDelay();
        SDA = 0;
        I2CDelay();
        SCL = 1;
        I2CDelay();
        SCL = 0;
        I2CDelay();
        SDA = 1;
        I2CDelay();
}
void I2CNak(){
        SDA = 1;
        SCL = 1;
        SCL = 0;
        SDA = 1;
}
void I2CSend(unsigned char Data){
        unsigned char i;
        for (i = 0; i < 8; i++) {
                if ((Data & 0x80) == 0)
                        SDA = 0;
                else
                        SDA = 1;
                SCL = 1;
                I2CDelay();
                SCL = 0;
                I2CDelay();
                Data <<= 1;
        }
        SDA = 1;
        I2CDelay();
        SCL = 1;
        I2CDelay();
        if (SDA)
                SCL = 0;
        I2CDelay();
        SDA = 1;
        SCL = 1;
        }

char I2CRead(unsigned char lastone){ // last one == 1 for last byte; 0 for any other byte
        char i, Data=0;
        for (i = 0; i < 8; i++){
                SCL = 1;
                I2CDelay();
                if(SDA) Data |=1;
                if(i<7) Data<<=1;
                SCL = 0;
                I2CDelay();
}
        SDA = lastone;
        SCL = 1;
        I2CDelay();
        SCL = 0;
        SDA = 1;
        SCL = 1;
        I2CDelay();
        return Data;
}

void I2CSendAddr(unsigned char addr, unsigned char rd){
        I2CStart();
        I2CSend(addr+rd);
}
void I2CDelay(){
        unsigned int i;
        for (i = 0; i < 4000; i++);
        return;
}

Parents
  • Done that before, but decades ago. What I have learned at that time, take an oscilloscope and inspect the signals; which is not too hard, as there are only two of them and the signal frequency is pretty low.

    There were some topics I have never thought about (at that time) like signal rise time on an 8051 port pin.

    I would recommend, look at the signals, compare it with the specification and then think again about the software.

    And by the way, if you really think you need software delay loops, don't do that in C, do it in assembler. Why? The C compiler if free to optimize your code here to none and nothing; and that would be legal to do so.

Reply
  • Done that before, but decades ago. What I have learned at that time, take an oscilloscope and inspect the signals; which is not too hard, as there are only two of them and the signal frequency is pretty low.

    There were some topics I have never thought about (at that time) like signal rise time on an 8051 port pin.

    I would recommend, look at the signals, compare it with the specification and then think again about the software.

    And by the way, if you really think you need software delay loops, don't do that in C, do it in assembler. Why? The C compiler if free to optimize your code here to none and nothing; and that would be legal to do so.

Children