• AVR Freaks

PIC16F1805 SPI Master and Slave mode switching

Page: < 123 Showing page 3 of 3
Author
vijayaraghavan
Starting Member
  • Total Posts : 57
  • Reward points : 0
  • Joined: 2015/01/01 21:32:30
  • Location: 0
  • Status: offline
Re: PIC16F1805 SPI Master and Slave mode switching 2016/10/12 03:28:25 (permalink)
+1 (1)
When I changed my I2C initialization as mentioned below I was able to see the data being send on the SDA line.
 

void OpenI2C1()

{

  PIE1bits.SSP1IE=0;

  SSP1STAT=0x80;

  SSP1CON1=0x28;

  SSP1CON2=0x00;

}


 
Now I need help with slave PIC code. I need to receive the data being sent from master PIC and then send it to the bluetooth after the I2C communication is over. Can anyone please guide me on how I can achieve this?
#41
vijayaraghavan
Starting Member
  • Total Posts : 57
  • Reward points : 0
  • Joined: 2015/01/01 21:32:30
  • Location: 0
  • Status: offline
Re: PIC16F1805 SPI Master and Slave mode switching 2016/10/14 03:24:44 (permalink)
0
Hi All,
 
I have developed the Master code to send the data to slave. And then I have developed a slave code too which works on an interrupt. But for some reason I am not getting an acknowledge signal from slave in the first transaction itself i.e. when master sends out the address of the slave (7 bit) along with R/nW bit.
 
Please find the code given below and do correct me where I went wrong.
 
main.c for master

#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

#define   SLEW_OFF   0b10000000

#define   MASTER     0b00001000

 

//Configure I2C module

void I2C_Init()

{

    SDA_TRIS = 1;

    SCL_TRIS = 1;

 

    OpenI2C(MASTER,SLEW_OFF);  //Initialize I2C module

    SSP1ADD = 19;  //100KHz Baud Clock @8MHz

 

//Master mode

}

 

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()

{

    SYSTEM_Initialize();

   I2C_Init();

   I2C_Wait();

    while (1)

    {

        StartI2C1();

        I2C_Wait();

        WriteI2C(0xD0);

        I2C_Wait();

        while(SSP1CON2bits.ACKSTAT);

        WriteI2C(0x1D);

        I2C_Wait();

        WriteI2C(0b00010011);

        I2C_Wait();

        StopI2C1();

    }

}


 
main.c for slave

#include "mcc_generated_files/mcc.h" 

short z;

char c;

 

void I2C_Slave_Init()

{

  SSP1STAT = 0x80;

  SSP1ADD = 0xD0; //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()

{

  if(SSP1IF == 1)

  {

    SSP1CON1bits.CKP = 0;

 

    if ((SSP1CON1bits.SSPOV) || (SSP1CON1bits.WCOL)) //If overflow or collision

    {

      z = SSPBUF; // Read the previous value to clear the buffer

      SSP1CON1bits.SSPOV = 0; // Clear the overflow flag

      SSP1CON1bits.WCOL = 0; // Clear the collision bit

      SSP1CON1bits.CKP = 1;

    }

  }

 

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

  {

    z = SSPBUF;

    while(!BF);

    c = SSPBUF;

    SSP1CON1bits.CKP = 1;

    SSPM3 = 0;

  }

 

  SSP1IF = 0;

  }

 

 

void main(void)

{

    // initialize the device

    SYSTEM_Initialize();

 

    while (1)

    {

    }

}


 
Could someone please help me identify the issue in the above code?
#42
vijayaraghavan
Starting Member
  • Total Posts : 57
  • Reward points : 0
  • Joined: 2015/01/01 21:32:30
  • Location: 0
  • Status: offline
Re: PIC16F1805 SPI Master and Slave mode switching 2016/10/24 06:11:53 (permalink)
0
Hi All,
 
I have been stuck with this issue for two weeks now. I tried taking help from the internet and also from people around me. But no one seems to be able to find out what is going wrong. I am able to send data to slave. I can see the data in an oscilloscope. But the problem is I am not getting an Acknowledge signal from the slave. I compared my slave PIC settings with other similar codes. I didn't find any issues with it. I have included my code for slave below. Please go through it and correct me where I went wrong.
 

short z;

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

}

char c;

void interrupt I2C_Slave_Read()

{

  if(SSP1IF == 1)

  {

    SSP1CON1bits.CKP = 0;

 

    if ((SSP1CON1bits.SSPOV) || (SSP1CON1bits.WCOL)) //If overflow or collision

    {

      z = SSPBUF; // Read the previous value to clear the buffer

      SSP1CON1bits.SSPOV = 0; // Clear the overflow flag

      SSP1CON1bits.WCOL = 0; // Clear the collision bit

      SSP1CON1bits.CKP = 1;

    }

  }

 

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

  {

    z = SSPBUF;

    while(!BF);

    c = SSPBUF;

    SSP1CON1bits.CKP = 1;

    SSPM3 = 0;

  }

 

  SSP1IF = 0;

  }

 

 

void main(void)

{

    // initialize the device

    SYSTEM_Initialize();

 

    I2C_Slave_Init();

 

    while (1)

    {

        // Add your application code

    }

}


 


#pragma config IESO = ON    // Internal/External Switchover Mode->Internal/External Switchover Mode is enabled

#pragma config BOREN = ON    // Brown-out Reset Enable->Brown-out Reset enabled

#pragma config PWRTE = OFF    // Power-up Timer Enable->PWRT disabled

#pragma config FOSC = INTOSC    // Oscillator Selection Bits->INTOSC oscillator: I/O function on CLKIN pin

#pragma config FCMEN = ON    // Fail-Safe Clock Monitor Enable->Fail-Safe Clock Monitor is enabled

#pragma config MCLRE = ON    // MCLR Pin Function Select->MCLR/VPP pin function is MCLR

#pragma config CP = OFF    // Flash Program Memory Code Protection->Program memory code protection is disabled

#pragma config WDTE = OFF    // Watchdog Timer Enable->WDT disabled

#pragma config CLKOUTEN = OFF    // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin

 

// CONFIG2

#pragma config WRT = OFF    // Flash Memory Self-Write Protection->Write protection off

#pragma config LPBOR = OFF    // Low-Power Brown Out Reset->Low-Power BOR is disabled

#pragma config LVP = OFF    // Low-Voltage Programming Enable->High-voltage on MCLR/VPP must be used for programming

#pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset

#pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.

 

#include "mcc.h"

 

void SYSTEM_Initialize(void)

{

    OSCILLATOR_Initialize();

    PIN_MANAGER_Initialize();

}

 

void OSCILLATOR_Initialize(void)

{

    // SCS INTOSC; IRCF 8MHz_HF; 

    OSCCON = 0x72;

    // OSTS intosc; HFIOFR disabled; HFIOFS not0.5percent_acc; LFIOFR disabled; 

    OSCSTAT = 0x00;

    // Set the secondary oscillator

    

}



 

#include <xc.h>

#include "pin_manager.h"

 

void PIN_MANAGER_Initialize(void)

{

    LATA = 0x00;

    TRISA = 0x3F;

    ANSELA = 0x17;

    WPUA = 0x00;

 

    LATB = 0x00;

    TRISB = 0xF0;

    ANSELB = 0x20;

    WPUB = 0x00;

 

    LATC = 0x00;

    TRISC = 0xFF;

    ANSELC = 0xCF;

 

    OPTION_REGbits.nWPUEN = 0x01;

 

    APFCON = 0x00;      

}


 
I have been stuck with this problem for the past one week now. I am in dire need of help. Please help me sort out my issues. Waiting for response.
#43
vijayaraghavan
Starting Member
  • Total Posts : 57
  • Reward points : 0
  • Joined: 2015/01/01 21:32:30
  • Location: 0
  • Status: offline
Re: PIC16F1805 SPI Master and Slave mode switching 2016/10/24 20:26:56 (permalink)
0
Can someone please help me with this? I know its some minor issue but its been bothering me for quite some time now. I would deeply appreciate your help.
#44
Aussie Susan
Super Member
  • Total Posts : 3607
  • Reward points : 0
  • Joined: 2008/08/18 22:20:40
  • Location: Melbourne, Australia
  • Status: offline
Re: PIC16F1805 SPI Master and Slave mode switching 2016/10/25 18:04:54 (permalink)
0
As you have switched from an SPI to an I2C question, perhaps you should start a new thread with I2C in the title so people with the required knowledge will look at it.
Susan
#45
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: PIC16F1805 SPI Master and Slave mode switching 2016/10/25 18:24:21 (permalink)
+1 (1)
From your Master's main.c
while(SSP1CON2bits.ACKSTAT);

Never, ever wait for ACKSTAT. Only test it once.
If ACKSTAT is high when a write transaction is finished, it is never going to go low, no matter how long you wait.
It means the slave did not respond.
Send a STOP cycle, and exit whatever code you were in, as it's pointless sending more data if you didn't get an ACK.
 
In your slave code, have you tried it without enabling "clock stretching"?
(Bit 0 in SSPCON2)
I suspect you are not handling that correctly.
 
#46
vijayaraghavan
Starting Member
  • Total Posts : 57
  • Reward points : 0
  • Joined: 2015/01/01 21:32:30
  • Location: 0
  • Status: offline
Re: PIC16F1805 SPI Master and Slave mode switching 2016/10/26 05:53:03 (permalink)
0
Aussie Susan
As you have switched from an SPI to an I2C question, perhaps you should start a new thread with I2C in the title so people with the required knowledge will look at it.
Susan



I thought of starting a different thread for the same reason as you pointed out. But because I have been receiving assistance in this thread I kept on going.
#47
vijayaraghavan
Starting Member
  • Total Posts : 57
  • Reward points : 0
  • Joined: 2015/01/01 21:32:30
  • Location: 0
  • Status: offline
Re: PIC16F1805 SPI Master and Slave mode switching 2016/10/26 06:11:30 (permalink)
0
qhb
From your Master's main.c
while(SSP1CON2bits.ACKSTAT);

Never, ever wait for ACKSTAT. Only test it once.
If ACKSTAT is high when a write transaction is finished, it is never going to go low, no matter how long you wait.
It means the slave did not respond.
Send a STOP cycle, and exit whatever code you were in, as it's pointless sending more data if you didn't get an ACK.

 
Now my code for master looks like this incorporating your suggestion.

 
#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()
{
SYSTEM_Initialize();
I2C_Init();
I2C_Wait();
while (1)
{
StartI2C1();
I2C_Wait();
WriteI2C1(0x30);
I2C_Wait();
if(SSP1CON2bits.ACKSTAT == 1)
{
StopI2C1();
}
else
{
WriteI2C1(0b01100001);
I2C_Wait();
StopI2C1();
}
}
}
 

 
qhb
In your slave code, have you tried it without enabling "clock stretching"?
(Bit 0 in SSPCON2)
I suspect you are not handling that correctly.

 
Again as you suggested I disabled the clock stretching. And I did get acknowledge signal from slave once i made this change though I don't understand how clock stretching affected the acknowledging part.

 
#include "mcc_generated_files/mcc.h"
 
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;
// 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)
{
 
}
}
 

 
Thanks to you now I am able to communicate successfully with my slave PIC. Now I wish to send a data from master and receive it in slave and then transmit this data from slave to bluetooth. I have tested the bluetooth code as a separate project and got the bluetooth working. So I am pretty sure that bluetooth module is functioning and the initialization is correct. I tried integrating bluetooth code into the slave code. But, as usual, I didn't get the desired results. I am not able to see the data send from master.
 
This is the bluetooth code that I tested and got it working.

 
int main()
{
 
SYSTEM_Initialize();
 
TRISBbits.TRISB5=1;
TRISBbits.TRISB7=0;
SPBRGL=0XA0;
SPBRGH=0X01;
BAUDCON=0X48;
RCSTA=0X80;
TXSTA=0X26;
 
 
 
char b='A';
 
while (1)
{
while(!(PIR1bits.TXIF));
TXREG = b;
 
}
return 1;
 
}
 

 
I was able to see the data 'A' being received by my phone via bluetooth. So i took this piece of code

 
while(!(PIR1bits.TXIF));
TXREG = b;
 

and tried inserting it in here in the slave code (in ISR)

 
z = SSPBUF;
while(!BF);
c = SSPBUF;
TXREG = c;
 

I am fairly sure this is the right place to insert this piece of code. The only difference is that the data I am sending from master is '0b01100001' while in the project that I created separately for bluetooth I am sending the character 'A'. I am not sure if this has anything to do with not seeing the data in my phone.
Please point out where I am going wrong.
#48
Page: < 123 Showing page 3 of 3
Jump to:
© 2019 APG vNext Commercial Version 4.5