|
|
View previous topic :: View next topic |
Author |
Message |
SteveVdb
Joined: 21 Apr 2020 Posts: 1
|
I2C master/slave configuration |
Posted: Wed Jun 10, 2020 8:19 am |
|
|
For a project I use a PIC16F18326 with two MSSP modules: one is used as an I2C master, and the other as an I2C slave.
The microcontroller supports Peripheral Pin Select. I'm struggling to understand the configuration to use both I2C's.
Here are some snippets from my code:
Code: | // MASTER
#pin_select SCL1IN = PIN_C4
#pin_select SCL1OUT = PIN_C4
#pin_select SDA1IN = PIN_C5
#pin_select SDA1OUT = PIN_C5
#use i2c(master, stream=IOX_LIB_STREAM, I2C1, FORCE_HW, fast=100000)
// SLAVE
#pin_select SCL2IN = PIN_C0
//#pin_select SCL2OUT = PIN_C0
#pin_select SDA2IN = PIN_C1
//#pin_select SDA2OUT = PIN_C1
#use i2c(slave, stream=SAA1064_STREAM, FORCE_HW, address=0x76)
|
This seems the only working configuration, but I don't quite understand why.
If I specify I2C2 in the SLAVE configuration and uncomment the pin select lines it doesn't work.
Thanks! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Thu Jun 11, 2020 12:06 am |
|
|
It's working, because the compiler is being 'smart' and doing part of the
mappings for you.
On I2C, the data sheet tells you that for both SDA and SCL, the input
and output PPS mappings must be the same. The 'full' setup should really
be:
Code: |
#pin_select SCL1IN = PIN_C4
#pin_select SCL1OUT = PIN_C4
#pin_select SDA1IN = PIN_C5
#pin_select SDA1OUT = PIN_C5
#use i2c(master, I2C1, stream=IOX_LIB_STREAM, fast=100000)
// SLAVE
#pin_select SCL2IN = PIN_C0
#pin_select SCL2OUT = PIN_C0
#pin_select SDA2IN = PIN_C1
#pin_select SDA2OUT = PIN_C1
#use i2c(slave, I2C2, stream=SAA1064_STREAM, address=0x76)
|
Just using the port name, always implies FORCE_HW. So for both ports
you need to set both the input & output connections, and then just use
the port name. So add the port name to the slave.
On I2C, both lines are actually 'bi directional' at different points in the
transaction. So though the 'master' actually generates the SCL, the
slave can 'clock stretch' by holding this low. So also drives the pin
(without this there is a risk of overrun depending on how quick the
ISR handler is, compared to the speed of the bus...). Then the SDA line
is driven by the master for a write, but by the slave for a read, so again
bi directional.
Now the compiler 'knows' about the double mapping, so is doing part
of this for you. However there is also an explicit way of doing this:
Code: |
#pin_select SCL1 = PIN_C4
#pin_select SDA1 = PIN_C5
#use i2c(master, I2C1, stream=IOX_LIB_STREAM, fast=100000)
// SLAVE
#pin_select SCL2 = PIN_C0
#pin_select SDA2 = PIN_C1
#use i2c(slave, I2C2, stream=SAA1064_STREAM, address=0x76)
|
If you just use the signal name, without a direction, this automatically
ensures both input and output mappings are done in one opoeration.
So 'why have the separate names'?.
This is because on quite a few other functions, the pins don't have to
be mapped to the same function. So on SPI (for example), the input
clock can be separate from the output clock. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|