• AVR Freaks

PIC16F1508 I2C and Bleutooth communication

Author
vijayaraghavan
Starting Member
  • Total Posts : 57
  • Reward points : 0
  • Joined: 2015/01/01 21:32:30
  • Location: 0
  • Status: offline
2016/10/26 21:20:59 (permalink)
0

PIC16F1508 I2C and Bleutooth communication

Hi All,
 
I am facing an issue while transferring data to bluetooth. My experimental setup is as mentioned below.
 
I have two PCBs, say PCB1 and PCB2. PCB1 has my Master PIC (PIC16F1508) while PCB2 has Slave PIC (PIC16F1508) and a bluetooth module (HC-05). I want to send data from Master PIC to Slave PIC via I2C and then Slave PIC should send this data to bluetooth via UART.
I have individually tested I2C communication and bluetooth communication. Both seems to be working fine. But when I integrate both I2C code and bluetooth code, I am not receiving any data via bluetooth while I am receiving acknowledge signal from Slave PIC. I could see the data sent from Master PIC via oscilloscope too.
 
My codes are as given below
 
Master code

#include <stdio.h>

#include <stdlib.h>

#include <xc.h>

#include "mcc_generated_files/mcc.h"

#include"pic16f1508.h"

 

void OpenI2C1();

void WriteI2C1(unsigned char data_out);

void StartI2C1();

void StopI2C1();

 

#define SDA_TRIS TRISB4

#define SCL_TRIS TRISB6

#define SDA_LAT LATB4

#define SCL_LAT  LATB6

 

void I2C_Init()

{

    SDA_TRIS = 1;

    SCL_TRIS = 1;

    OpenI2C1();

    SSP1ADD = 19;

}

 

void StartI2C1()

{

    SSP1CON2bits.SEN=1;

    while(SSP1CON2bits.SEN);

}

 

void StopI2C1()

{

    SSP1CON2bits.PEN=1;

    while(SSP1CON2bits.PEN);

}

 

void OpenI2C1()

{

    PIE1bits.SSP1IE=0;

    SSP1STAT=0x80;

    SSP1CON1=0x28;

    SSP1CON2=0x00;

}

 

void WriteI2C1(unsigned char data_out)

{

    SSP1BUF = data_out;

    while(SSP1STATbits.BF);

}

 

void I2C_Wait()

{

    while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_nW));

}

 

void main()

{

    char b='A';

    SYSTEM_Initialize();

    I2C_Init();

    I2C_Wait();

    StartI2C1();

    I2C_Wait();

    WriteI2C1(0x30);

    I2C_Wait();

    if(SSP1CON2bits.ACKSTAT == 1)

    {

        StopI2C1();

    }

    else

    {

        while (1)

        {

            WriteI2C1(b);

            I2C_Wait();

        }

    }

    StopI2C1();

}

 
 
Slave code

char z;

char c;

void I2C_Slave_Init()

{

  SSP1STAT = 0x80;

  SSP1ADD = 0x30; //Setting address

  SSP1CON1 = 0x36;    //As a slave device

//  SSP1CON2 = 0x01;

 

  GIE = 1;          //Global interrupt enable

  PEIE = 1;         //Peripheral interrupt enable

  PIR1bits.SSP1IF=0;   //Clear interrupt flag

  PIE1bits.SSP1IE=1;   //Synchronous serial port interrupt enable

}

 

void interrupt I2C_Slave_Read()

{

    PIR1bits.SSP1IF = 0;

    c = SSPBUF;

    if(!SSP1STATbits.D_nA && !SSP1STATbits.R_nW) //If last byte was Address + Write

    {

        z = SSPBUF;

        while(!BF);

        c = SSPBUF;

        TXREG = c;

        SSPM3 = 0;

    }

}

 

void bluetoothinit()

{


    TRISBbits.TRISB5=1;

    TRISBbits.TRISB7=0;

    SPBRGL=0XA0;

    SPBRGH=0X01;

    BAUDCON=0X48;

    RCSTA=0X80;

    TXSTA=0X26;


}

 

void main(void)

{  

    SYSTEM_Initialize();

    I2C_Slave_Init();

    bluetoothinit();

    while (1)

    {

 

    }

}


 
I am fairly certain of the bluetooth initialization as I was able to get the bluetooth working in a separate stand alone project with the same settings. But I am not sure where I should place the

TXREG=SSPBUF

statement. Please help me in any way you can as I have been stuck with this project for quite some time now. Any help would be highly appreciated.
#1

18 Replies Related Threads

    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/26 21:53:05 (permalink)
    +2 (2)
    Comes from http://www.microchip.com/...m951407-p3.aspx#955877
    Why did you start a new topic?
    That means anyone seeing only this topic isn't aware of all that has already been discussed.
     
    #2
    vijayaraghavan
    Starting Member
    • Total Posts : 57
    • Reward points : 0
    • Joined: 2015/01/01 21:32:30
    • Location: 0
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 00:32:22 (permalink)
    0
    I started a new thread for the same reasons as Aussie Susan pointed out. But it was my mistake to not have included the URL to the thread where all the previous discussions were going on and thanks for doing the same. I will make sure not to do this same mistake twice if faced with the same problem again.
     
    @qhb Do you know how I can solve my current issue?
    #3
    vijayaraghavan
    Starting Member
    • Total Posts : 57
    • Reward points : 0
    • Joined: 2015/01/01 21:32:30
    • Location: 0
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 03:48:52 (permalink)
    0
    Thinking further on it, one thing that I noticed was that I am trying to shift the value from SSPBUF to TXREG while I2C is still ON. So it will try to transfer data via UART while I2C is still ON. Will that be a problem? Should I switch OFF the I2C before I shift the value to TXREG?
    #4
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 03:53:23 (permalink)
    0
    vijayaraghavan
     Should I switch OFF the I2C before I shift the value to TXREG?




    If you mean "turn off the module", I'd definitely say No. Just keep it idle when you're not using it.

    GENOVA :D :D ! GODO
    #5
    vijayaraghavan
    Starting Member
    • Total Posts : 57
    • Reward points : 0
    • Joined: 2015/01/01 21:32:30
    • Location: 0
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 03:55:59 (permalink)
    0
    Hi Dario,
     
    How do you suggest I should go about it? I am receiving a continuous stream of characters from master PIC and I need to send these data to bluetooth over UART.
    #6
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 03:58:42 (permalink)
    0
    I don't know Smile
    I am not sure at what point are you know and what exactly you must achieve...

    GENOVA :D :D ! GODO
    #7
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 04:13:18 (permalink)
    +1 (1)
    I suggest you need to rethink your whole strategy.
    You should not be trying to transfer directly from one peripheral to another, and you most definitely should NOT be putting "blocking" code inside interrupt services.
    You should implement a FIFO buffer (First in, first out) to receive data from I2C, and then output that data to the USART when you can.
    That way you can get your receive code working and debugged seperate from your transmit code.
     
    #8
    vijayaraghavan
    Starting Member
    • Total Posts : 57
    • Reward points : 0
    • Joined: 2015/01/01 21:32:30
    • Location: 0
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 04:19:28 (permalink)
    +1 (1)
    Hi Dario,
    My aim is to send data from master PIC to slave PIC. Slave PIC then should transmit this data to bluetooth. I chose I2C as the mode of communication between the two PICs. My codes are as given below
    Master code

    #include <stdio.h>
    #include <stdlib.h>
    #include <xc.h>
    #include "mcc_generated_files/mcc.h"
    #include"pic16f1508.h"
    void OpenI2C1();
    void WriteI2C1(unsigned char data_out);
    void StartI2C1();
    void StopI2C1();
    #define SDA_TRIS TRISB4
    #define SCL_TRIS TRISB6
    #define SDA_LAT LATB4
    #define SCL_LAT LATB6
    void I2C_Init()
    {
    SDA_TRIS = 1;
    SCL_TRIS = 1;
    OpenI2C1();
    SSP1ADD = 19;
    }
    void StartI2C1()
    {
    SSP1CON2bits.SEN=1;
    while(SSP1CON2bits.SEN);
    }
    void StopI2C1()
    {
    SSP1CON2bits.PEN=1;
    while(SSP1CON2bits.PEN);
    }
    void OpenI2C1()
    {
    PIE1bits.SSP1IE=0;
    SSP1STAT=0x80;
    SSP1CON1=0x28;
    SSP1CON2=0x00;
    }
    void WriteI2C1(unsigned char data_out)
    {
    SSP1BUF = data_out;
    while(SSP1STATbits.BF);
    }
    void I2C_Wait()
    {
    while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_nW));
    }
    void main()
    {
    char b='E';
    SYSTEM_Initialize();
    I2C_Init();
    I2C_Wait();
    StartI2C1();
    I2C_Wait();
    WriteI2C1(0x30);
    I2C_Wait();
    while (1)
    {
    if(!SSP1CON2bits.ACKSTAT == 1)
    {
    WriteI2C1(b);
    I2C_Wait();
    }
    else
    {
    StopI2C1();
    }
    }
    StopI2C1();
    }


    Slave code

    char z;
    static char c;
    void I2C_Slave_Init()
    {
    SSP1STAT = 0x80;
    SSP1ADD = 0x30; //Setting address
    SSP1CON1 = 0x36; //As a slave device
    // SSP1CON2 = 0x01;
    GIE = 1; //Global interrupt enable
    PEIE = 1; //Peripheral interrupt enable
    PIR1bits.SSP1IF=0; //Clear interrupt flag
    PIE1bits.SSP1IE=1; //Synchronous serial port interrupt enable
    }
    void interrupt I2C_Slave_Read()
    {
    PIR1bits.SSP1IF = 0;

    TXREG = SSPBUF;
    if(SSP1STATbits.D_nA && !SSP1STATbits.R_nW) //If last byte was Data + Write
    {
    z = SSPBUF;
    while(!BF);
    TXREG = SSPBUF;
    SSP1CON1bits.CKP = 1;
    SSPM3 = 0;
    }
    }
    void bluetoothinit()
    {
    TRISBbits.TRISB5=1;
    TRISBbits.TRISB7=0;
    SPBRGL=0XA0;
    SPBRGH=0X01;
    BAUDCON=0X48;
    RCSTA=0X80;
    TXSTA=0X26;
    }
    void main(void)
    {
    SYSTEM_Initialize();
    I2C_Slave_Init();
    bluetoothinit();
    while (1)
    {
    }
    }

    I have been stuck with this project for quite some time. Please have a look at this and suggest some changes that i could try.
    Thanks in advance.
    #9
    vijayaraghavan
    Starting Member
    • Total Posts : 57
    • Reward points : 0
    • Joined: 2015/01/01 21:32:30
    • Location: 0
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 04:25:22 (permalink)
    0
    qhb
    I suggest you need to rethink your whole strategy.
    You should not be trying to transfer directly from one peripheral to another, and you most definitely should NOT be putting "blocking" code inside interrupt services.
    You should implement a FIFO buffer (First in, first out) to receive data from I2C, and then output that data to the USART when you can.
    That way you can get your receive code working and debugged seperate from your transmit code.
     




    To make it a whole lot easier what if I send just one data from master instead of sending a continuous stream of data? Should I be using FIFO buffer for this improved scenario?
    I didn't get what you meant by "blocking" code. Could you please elaborate on it?
     
    Thanks for your replies.
    #10
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 04:36:18 (permalink)
    +1 (1)
    If by "one data" you mean one data byte, then it could work.
    What use is that though, surely you need to send more than one?
     
    "Blocking" code is any code that waits for something to happen.
    That is just the sort of thing you do NOT put inside an interrupt service.
    You are doing it in your slave code, where you try to read SSPBUF twice with a wait for BF between them.
    Your whole slave code looks too simplistic., are you sure it's actually working?
    #11
    vijayaraghavan
    Starting Member
    • Total Posts : 57
    • Reward points : 0
    • Joined: 2015/01/01 21:32:30
    • Location: 0
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 05:50:45 (permalink)
    0
    qhb
    If by "one data" you mean one data byte, then it could work.
    What use is that though, surely you need to send more than one?
     
    "Blocking" code is any code that waits for something to happen.
    That is just the sort of thing you do NOT put inside an interrupt service.
    You are doing it in your slave code, where you try to read SSPBUF twice with a wait for BF between them.
    Your whole slave code looks too simplistic., are you sure it's actually working?




    I do need to send more than one byte of data. But what I thought was that if I could get it working for one data byte then I could make the necessary tweaks and get it ready for multiple data bytes.
     
    I removed the "blocking" code and made a few changes to my ISR similar to a working code that I found in the thread http://www.microchip.com/forums/m568464.aspx 
     

    unsigned char dummy_read = 0;
    unsigned char data_rx = 0;
    void I2C_Slave_Init()
    {
    SSP1ADD = 0x30; //Setting address
    SSP1CON1 = 0x36; //As a slave device
    SSP1STAT = 0x80;
    SSP1CON2 = 0x00;
    GIE = 1; //Global interrupt enable
    PEIE = 1; //Peripheral interrupt enable
    PIR1bits.SSP1IF=0; //Clear interrupt flag
    PIE1bits.SSP1IE=1; //Synchronous serial port interrupt enable
    }
    void interrupt I2C_Slave_Read()
    {
    if(PIR1bits.SSP1IF)
    {
    // MASTER WRITE, LAST BYTE RECEIVED WAS ADDRESS, BUFFER FULL
    if((SSPSTAT & 0x2D) == 0x09)
    {
    dummy_read = SSPBUF;
    }
    if((SSPSTAT & 0x2D) == 0x29)
    {
    data_rx = SSPBUF; // Read received sample data request from I2C data buffer
    }
    PIR1bits.SSP1IF = 0;
    }
    }
    void bluetoothinit()
    {
    TRISBbits.TRISB5=1;
    TRISBbits.TRISB7=0;
    SPBRGL=0XA0;
    SPBRGH=0X01;
    BAUDCON=0X48;
    RCSTA=0X80;
    TXSTA=0X26;
    }
    void main(void)
    {
    SYSTEM_Initialize();
    I2C_Slave_Init();
    bluetoothinit();
    while (1)
    {

    }
    }

     
    What more should I add to the ISR code? Collecting the data from SSPBUF is the only procedure that I see in most codes that i have found elsewhere.
    #12
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 11:55:42 (permalink)
    0
    Just a note: why use interrupt and make it more complicated?I'd use a polling loop, that waits for the I2C Master: as a byte is received you send it to USART *without* waiting (i.e. you only check if the TX buffer is empty).
    This should work at least as a starting point

    GENOVA :D :D ! GODO
    #13
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 12:19:25 (permalink)
    +1 (1)
    vijayaraghavan
    ...
    I do need to send more than one byte of data. But what I thought was that if I could get it working for one data byte then I could make the necessary tweaks and get it ready for multiple data bytes.

    And I am suggesting you should be allowing for multiple bytes from the start.
    "Tweaking" is just asking for trouble if you've chosen the wrong method to start with.



    In particular, the I2C is probably running faster than the USART, so the slave would still be waiting for the previous value to send via the USART when the next byte arrives from the Master.
    Yes, you could tweak it, by adding sufficient delays between byytes coming from the MAster to allow it to send,
    but a muc better solution is to buffer the bytes in the slave (with a FIFO buffer), and send them when you can.
    If you are always sending a fixed number bytes, with a significant pause between batches, then you could just use a fixed buffer.
    #14
    vijayaraghavan
    Starting Member
    • Total Posts : 57
    • Reward points : 0
    • Joined: 2015/01/01 21:32:30
    • Location: 0
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 19:31:42 (permalink)
    0
    What bit should I be polling for to know master has send the data?? My belief is that I should be checking for "SSP1STATbits.D_nA" bit to go high and "SSP1STATbits.R_nW" bit to go low. Am I right? If both the conditions are satisfied it implies master is writing a data to slave.
    Please correct me if I am wrong.
    #15
    vijayaraghavan
    Starting Member
    • Total Posts : 57
    • Reward points : 0
    • Joined: 2015/01/01 21:32:30
    • Location: 0
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/10/27 19:38:16 (permalink)
    +1 (1)
    qhb
    And I am suggesting you should be allowing for multiple bytes from the start.
    "Tweaking" is just asking for trouble if you've chosen the wrong method to start with.



    In particular, the I2C is probably running faster than the USART, so the slave would still be waiting for the previous value to send via the USART when the next byte arrives from the Master.
    Yes, you could tweak it, by adding sufficient delays between byytes coming from the MAster to allow it to send,
    but a muc better solution is to buffer the bytes in the slave (with a FIFO buffer), and send them when you can.
    If you are always sending a fixed number bytes, with a significant pause between batches, then you could just use a fixed buffer.




    Ok. I will take your advice. Lets say the batch of data being sent by the master will be 10 bytes (fixed number of bytes scenario). So I have to implement a fixed buffer like you have mentioned. From my limited knowledge, I guess you are implying to use an array which can store all 10 values being sent by the master. Is it so?
     
    When you mentioned "send them when you can", did you mean I should be sending the previous batch of data when master has stopped I2C? How will I detect that master has stopped I2C?
    #16
    Hari21
    Starting Member
    • Total Posts : 72
    • Reward points : 0
    • Joined: 2014/07/23 00:22:47
    • Location: 0
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/11/21 01:01:23 (permalink)
    +1 (1)

    In the program I am able to send a character from Master to Slave and get the same character in the Bluetooth device. This is the same code posted by Vijayraghavan after making some correction. (FYI Vijayraghavan and I have been working on the same project). I have attached the code as I was not able to include it with thos post

    The above code is to send only a character(in hex form) from my master to slave device.
    Now I have to send an ADC voltage value (floating values) from my master to slave.
    I tried the same using itoa(), and sprintf() as my code is for sending an unsigned character (I made it as an array).
    I also tried splitting the decimal value and sending each byte of data separately but I am not being able to receive each of my characters seperately. I am able to isolate only the last character being sent. And hence I am not able to recreate the floating point number I am sending from the Master.
    If anyone could suggest any method whereby I can send a floating character from my master to slave it would be really helpful.
    Thank you
    #17
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/11/21 01:26:32 (permalink)
    +1 (1)
    Your slave code is too simplistic.
    It is simply outputting whatever is in the column_data_rx variable over and over, with no attempt to only send one character each time a new byte is received from the master.
     
    #18
    Hari21
    Starting Member
    • Total Posts : 72
    • Reward points : 0
    • Joined: 2014/07/23 00:22:47
    • Location: 0
    • Status: offline
    Re: PIC16F1508 I2C and Bleutooth communication 2016/11/21 22:25:39 (permalink)
    +1 (1)
    Thank you qhb.
    I got what you meant. 
    Say for example I want to send a floating decimal 10.2. Can I multiply this number by 10. Then convert each of the number ie 1, 0, 2 into hex and send each characters from my master one at a time. In the slave I would capture each value using a for loop. Then append the same using a function like string concatenate. Then in the concatenated string ie 102, I have to divide by ten and then send the same to the Bluetooth.
    Is this the way to go about doing it. Since I can send only 8 bit at a time from my master to slave, I cannot send a floating decimal directly right. 
    If my method sounds too complicated or prone to error, could u suggest any method that I could adopt to get a better result in sending a floating decimal from my master to slave. 
     
    #19
    Jump to:
    © 2019 APG vNext Commercial Version 4.5