I2C Bitbang on pic16f716

General discussion on mikroC.
Post Reply
Author
Message
Kiyoshi7
Posts: 17
Joined: 14 Mar 2016 17:55

I2C Bitbang on pic16f716

#1 Post by Kiyoshi7 » 17 Jun 2016 15:15

Hi I'm trying to connect my pic to a ds1307 (rtc) but it does not have an I2C peripheral (MSSP) built-in. So i'm trying to adapt an i2c bitbang from http://saeedsolutions.blogspot.com.br/2 ... oteus.html but it isn't working. does anyone know of a tutorial or place where i can get the code written in mikroc?

// Update
after messing around with the code I think that I almost got it to work the only problem is that I'm being told that there are to many initializers here is the code, its kinda long. the error is popping up here:static bit ACK = 0; on line 149

Code: Select all

// Define i2c pins
#define SDA		PORTA.F0			// Data pin for i2c
#define SCK		PORTA.F1			// Clock pin for i2c
#define SDA_DIR		TRISA.f0			// Data pin direction
#define SCK_DIR		TRISA.f1			// Clock pin direction

#define DataPinADCMask	ADCON0	// It is attached on RA0 pin
#define ClockPinADCMask ADCON1

// Define i2c speed
#define I2C_SPEED	1				// kbps
#define HalfBitDelay 500/I2C_SPEED	// usec

// Define macros
#define Set_SDA_Low	SDA_DIR = 0
#define Set_SDA_High	SDA_DIR = 1
#define Set_SCK_Low	SCK_DIR = 0
#define Set_SCK_High	SCK_DIR = 1

//Function Declarations
void InitI2C(void);
void I2C_Start(void);
void I2C_ReStart(void);
void I2C_Stop(void);
void I2C_Send_ACK(void);
void I2C_Send_NACK(void);
unsigned  I2C_Write_Byte(unsigned char);
unsigned char I2C_Read_Byte(void);

/*  main explained
note: may have to turn off adc and comparator

i2c pins are initialized using InitI2C() function. 
Then I2C_Start() function sends a start bit S on i2c
bus. Then a value of 0xA0 is written on the i2c bus
using I2C_Write_Byte(0xA0); statement. After that, 
I2C_Read_Byte() function reads a byte from the i2c 
bus, because there is no slave attached on the i2c
bus, that is why RxByte will receive a value of 0xFF*.

*
Because SDA pin is pulled up normally and when PIC 
is not driving it, then it will always stay high 
because of the pull up. That is why when there is 
no slave, then a value of 0xFF will be read.
*

After that, an ACK 'A' is transmitted on i2c bus 
using I2C_Send_ACK() function. And in the end a 
stop bit 'P' is transmitted on i2c bus using 
I2C_Stop() function.

*/
void main(){

     unsigned char RxByte = 0;
     InitI2C();    //Initialize i2c pins
     
     I2C_Start();
     I2C_Write_Byte(0xA0);       // send 0A0 in i2c
     RxByte = I2C_Read_byte();   // Read from i2c
     I2C_Send_ACK();             // send acknolage bit on i2c
     I2C_Stop();                 // Send stop bit on I2c

}


 // Function Purpose: Set initial values of SCK and SDA pins
void InitI2C(void)
{
        DataPinADCMask  = 1;        // Make analog output
        ClockPinADCMask = 1;        // Make analog output

        // Make SDA and SCK pins input initially
        SDA_DIR = 1;
        SCK_DIR = 1;

        // Write zero in output register of SDA and SCK pin
        SDA = 0;
        SCK = 0;
}
// Function Purpose: I2C_Start sends start bit sequence
void I2C_Start(void)
{
        SDA = 0;        // Write zero in output register
        SCK = 0;        // of SDA and SCK pin

        Set_SCK_High;                                // Make SCK pin high
        Set_SDA_High;                                // Make SDA pin High
        Delay_us(HalfBitDelay);        // Half bit delay
        Set_SDA_Low;                                // Make SDA Low
        Delay_us(HalfBitDelay);        // Half bit delay
}
// Function Purpose: I2C_ReStart sends start bit sequence
void I2C_ReStart(void)
{
        Set_SCK_Low;                                // Make SCK pin low

        Delay_us(HalfBitDelay/2);        // Data pin should change it's value,
                                                                // when it is confirm that SCK is low
        Set_SDA_High;                                // Make SDA pin High

        Delay_us(HalfBitDelay/2);        // 1/4 bit delay
        Set_SCK_High;                                // Make SCK pin high
        Delay_us(HalfBitDelay/2);        // 1/4 bit delay
        Set_SDA_Low;                                // Make SDA Low
        Delay_us(HalfBitDelay/2);        // 1/4 bit delay
}
//Function : I2C_Stop sends stop bit sequence
void I2C_Stop(void)
{
        Set_SCK_Low;                                // Make SCK pin low

        Delay_us(HalfBitDelay/2);        // Data pin should change it's value,
                                                                // when it is confirm that SCK is low
        Set_SDA_Low;                                // Make SDA pin low

        Delay_us(HalfBitDelay/2);        // 1/4 bit delay
        Set_SCK_High;                                // Make SCK pin high
        Delay_us(HalfBitDelay/2);        // 1/4 bit delay
        Set_SDA_High;                                // Make SDA high
        Delay_us(HalfBitDelay/2);        // 1/4 bit delay
}
//Function : I2C_Send_ACK sends ACK bit sequence
void I2C_Send_ACK(void)
{
        Set_SCK_Low;                                // Make SCK pin low
        Delay_us(HalfBitDelay/2);        // Data pin should change it's value,
                                                                // when it is confirm that SCK is low
        Set_SDA_Low;                                // Make SDA Low
        Delay_us(HalfBitDelay/2);        // 1/4 bit delay
        Set_SCK_High;                                // Make SCK pin high
        Delay_us(HalfBitDelay);        // Half bit delay
}
//Function : I2C_Send_NACK sends NACK bit sequence
void I2C_Send_NACK(void)
{
        Set_SCK_Low;                                // Make SCK pin low
        Delay_us(HalfBitDelay/2);        // Data pin should change it's value,
                                                                // when it is confirm that SCK is low
        Set_SDA_High;                                // Make SDA high
        Delay_us(HalfBitDelay/2);        // 1/4 bit delay
        Set_SCK_High;                                // Make SCK pin high
        Delay_us(HalfBitDelay);        // Half bit delay
}
// Function Purpose: I2C_Write_Byte transfers one byte
unsigned I2C_Write_Byte(unsigned char Byte)
{
        static bit ACK = 0;

        unsigned char i;                // Variable to be used in for loop

        for(i=0;i<8;i++)                // Repeat for every bit
        {
                Set_SCK_Low;                // Make SCK pin low

                Delay_us(HalfBitDelay/2);        // Data pin should change it's value,
                                                                        // when it is confirm that SCK is low

                if((Byte<<i)&0x80)  // Place data bit value on SDA pin
                        Set_SDA_High;        // If bit is high, make SDA high
                else                                // Data is transferred MSB first
                        Set_SDA_Low;        // If bit is low, make SDA low

                Delay_us(HalfBitDelay/2);        // Toggle SCK pin
                Set_SCK_High;                                // So that slave can
                Delay_us(HalfBitDelay);        // latch data bit
    }

        // Get ACK from slave
        Set_SCK_Low;
    Set_SDA_High;
    Delay_us(HalfBitDelay);
    Set_SCK_High;
    Delay_us(HalfBitDelay);

        DataPinADCMask = 0;                // Make digital input
        ACK = SDA;                                // Read data pin status
        DataPinADCMask = 1;                // Make analog output

        return ACK;
}
// Function Purpose: I2C_Read_Byte reads one byte
unsigned char I2C_Read_Byte(void)
{

Sparky1039
Posts: 1179
Joined: 24 Nov 2005 20:07
Location: Colorado, USA

Re: I2C Bitbang on pic16f716

#2 Post by Sparky1039 » 18 Jun 2016 04:27

Preprocessor directives do not allow you to initialize a value in the way you have done i.e. name = value.

Code: Select all

#define Set_SDA_Low   SDA_DIR = 0
#define Set_SDA_High   SDA_DIR = 1
#define Set_SCK_Low   SCK_DIR = 0
#define Set_SCK_High   SCK_DIR = 1
Define the alias with just a number.

Code: Select all

#define Set_SDA_Low 0
#define Set_SDA_High 1
#define Set_SCK_Low 0
#define Set_SCK_High 1

Post Reply

Return to “mikroC General”