PIC16F as i2C Slave - Begineer

Use this section to discuss your embedded Flowcode projects.
Post Reply
jay_dee
Posts: 215
http://meble-kuchenne.info.pl
Joined: Sun Dec 20, 2020 6:06 pm
Has thanked: 81 times
Been thanked: 56 times

Flowcode v10 PIC16F as i2C Slave - Begineer

Post by jay_dee »

Hi,
Use a PIC16F15324 as an I2C slave in FC10
Current project has some tricky little tasks that need constant attension, this is a sledgehammer approach but I'm thinking about using the feature rich but small PIC16F15324 to do the dedicated work and just read the data out over i2C with the main PIC18F.

Has anyone else tried this approach? I've not done a i2C slave before and any obvious traps or examples would be welcome.
I want to avoid a rabbit hole playing with i2C slaves....but it could become a super flexible codeable periferal for this and other projects.
Thanks, J.

mnfisher
Valued Contributor
Posts: 1512
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 138 times
Been thanked: 725 times

Re: PIC16F as i2C Slave - Begineer

Post by mnfisher »

An i2c slave probably needs to be interrupt driven.

See - https://flowcode.co.uk/forums/viewtopic ... 285#p16285 - although this thread is for ATMega MCUs, I think the general principals will be the same.
Basically to ensure correct timing - it is difficult to busy-wait on a i2c transaction being received.

Martin

chipfryer27
Valued Contributor
Posts: 1574
Joined: Thu Dec 03, 2020 10:57 am
Has thanked: 356 times
Been thanked: 560 times

Re: PIC16F as i2C Slave - Begineer

Post by chipfryer27 »

Hi

I have no access to hardware just noe so can't really try anything but a year or so ago I did get slightly involved on a slave project.

The chip I used was a PIC and it had an inbuilt Interrupt on I2C (if I remember correctly) which could be selected.

This made things quite easy - ish.

Won't be able to dig out the project anytime soon, but depending on your chip capabilities it should be quite doable.

Regards

jay_dee
Posts: 215
Joined: Sun Dec 20, 2020 6:06 pm
Has thanked: 81 times
Been thanked: 56 times

Re: PIC16F as i2C Slave - Begineer

Post by jay_dee »

Hi,
I've been trawling the datasheets and trying to examine the C from the i2C slave component. I've probably just got confused.

A) The PIC16F15324 used does have a dedicated i2C periferal with slave support, I would love to use the interupt driven features at some point but I am currently just trying to get a basic level of i2C comms.
The channel is set to 1. The Pins are re-mapped correctly. (I'm fairly sure)

B) What seemed odd, when i read the FC Slave 'C' for the Slave Status function, it refers to register "SSPSTAT" for channel 1, the chip only responds to the register name given in the datasheet of SSP1STAT. Indeed most of the FC 'C' register names dont seem to have exacly the same names as the Datasheet. Is this just becuase the 'C' is generic across lots of PICs and a Cal file or similar sorts out the correct naming? to SSP1STAT

C) I dont really know the correct way to apply the existing slave component so its mostly guess work. The attached FC is suppossed to be reciving the address and two bytes of data.
I never seem to be able to read a TRUE BufferFull bit for the i2C_Status byte. But I see the register SSP1STAT toggle its BF bit on/off.
PIC16F15324_i2C_V1.fcfx
(47.71 KiB) Downloaded 36 times
D) I was unsure what was set in the registers so I read out everything associated with i2C and send them to a Terminal program and display them as bits, MSB to the left.
i2c_Reg.JPG
i2c_Reg.JPG (78.84 KiB) Viewed 4921 times

mnfisher
Valued Contributor
Posts: 1512
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 138 times
Been thanked: 725 times

Re: PIC16F as i2C Slave - Begineer

Post by mnfisher »

Looks like the chip has a MSSP module.

Code: Select all

    SSP1STATbits.SMP = 1;       // Slew rate control disabled
    SSP1CON1bits.SSPM = 0x06;   // Set to Slave mode, 7-bit address
    SSP1CON1bits.SSPEN = 1;     // Enable I2C module
    SSP1CON1bits.CKP = 1;       // Release SCL clock
    SSP1ADD = SLAVE_ADDRESS;    // Set the slave address
Use an interrupt (here in C) something like...

Code: Select all

    if (SSP1IF) { // Check if the interrupt is from the SSP1 module
        uint8_t received_data;
        
        // Check if it's a read or write operation
        if (SSP1STATbits.D_A) { // If D_A is 1, it's a data address (write)
            // Write operation
            received_data = SSP1BUF; // Read the received data
            i2c_data = received_data; // Store data in buffer
            SSP1IF = 0; // Clear interrupt flag
        }
        else { // It's a read operation
            // Read operation, send data back to the master
            SSP1BUF = i2c_buffer; // Write data to be sent to master
            SSP1IF = 0; // Clear interrupt flag
        }
    }
As with the AVR it's a bit involved....


Martin

jay_dee
Posts: 215
Joined: Sun Dec 20, 2020 6:06 pm
Has thanked: 81 times
Been thanked: 56 times

Re: PIC16F as i2C Slave - Begineer

Post by jay_dee »

OK, so I have gone back to check the basics. Great info from Martin but I'm not attempting the Interupt approach yet, until I can understand the possible issue with the standard i2C Slave component.

If I use the FC i2C Slave component to retrive the SSP1STAT register and put it in variable i2C_Status, I cant read out values for the (BF) BufferFull bit.

Code: Select all

i2C_BF = i2C_Status AND 0x01
i2C_Last = (i2C_Status AND 0x10) >> 4
However If I directly read the Register into my own variable.

Code: Select all

FCV_REG1 = SSP1STAT;
then

Code: Select all

i2C_BF = Reg1 AND 0x01
i2C_Last = (Reg1 AND 0x10) >> 4
I now read what look like good Values for BF and Last.
So is this a bug or am I doing something I dont understand?
J.
PIC16F15324_i2C_V2.fcfx
(46.29 KiB) Downloaded 36 times

jay_dee
Posts: 215
Joined: Sun Dec 20, 2020 6:06 pm
Has thanked: 81 times
Been thanked: 56 times

Re: PIC16F as i2C Slave - Begineer

Post by jay_dee »

So looking sat the PIC i2C CAL C, whilst i dont understand it , the Code handles the different naming conventions.

Code: Select all

	//Ensure SSPSTAT register is defined correctly
	#ifndef _SSPSTAT_BF_POSN
	  #ifdef _SSP1STAT_BF_POSN
		#define SSPSTAT	SSP1STAT

		#ifdef _SSP1STAT_R_nW_POSN
			#define SSPSTAT_R_NOT_W R_nW
		#else
			#define SSPSTAT_R_NOT_W R_NOT_W
		#endif
Just cant work out why calling the same register values gives a different outcome... must be something dumb I'm doing.

Post Reply