Use both SPI and I2C on ATtiny202

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Hi,

 

I'm using a SPI and a I2C slave connected to an ATtiny202 so I need to share the GPIOs for I2C and SPI and it is working however I can't understand why do I need to disable I2C before use SPI but it is ok to let SPI enable before use I2C.

 

The first image show a I2C communication followed by a try to do a SPI communication without disable I2C.

 

This image show the same chunk of time however in this case before try to do a SPI communication I disable the I2C peripheral.

 

I have other parts of the code where the SPI communication is done before I2C and in this case I don't need to disable SPI to get a working I2C communication.

 

Channel 1 (yellow): SPI_CS

Channel 2 (Cyan): SPI_MOSI/SDA

Channel 3 (Pink): SPI_MISO/SCL

Channel 4 (Blue): SPI_CLOCK

 

Reading the datasheet it says the following about SPI:

 

 

This is my SPI and I2C init and deinit code:

 

void SPI0_init(void) {
    
  PORTA.PIN1CTRL = 0;
  PORTA.PIN2CTRL = 0;
  PORTA.PIN3CTRL = 0;
  PORTA.PIN6CTRL = 0;

  PORTA.DIR |= PIN1_bm;  /* Set MOSI pin direction to output */
  PORTA.DIR &= ~PIN2_bm; /* Set MISO pin direction to input */
  PORTA.DIR |= PIN3_bm;  /* Set SCK pin direction to output */
  PORTA.DIR |= PIN6_bm;  /* Set SS pin direction to output */
  
  PORTA.OUT &= ~PIN1_bm;
  PORTA.OUT &= ~PIN2_bm;
  
  SPI0_slave_deselect();

  SPI0.CTRLB = SPI_BUFEN_bm; /* Buffer Mode Enable */

  SPI0.CTRLA = SPI_CLK2X_bm         /* Enable double-speed */
               | SPI_ENABLE_bm      /* Enable module */
               | SPI_MASTER_bm      /* SPI module in Master mode */
               | SPI_PRESC_DIV4_gc; /* System Clock divided by 16 */
}

void SPI0_deinit(void) {
  SPI0.CTRLA &= ~SPI_ENABLE_bm;      /* Disable module */
}

void i2c_init() {
  PORTA.DIR &= ~PIN1_bm;
  PORTA.DIR &= ~PIN2_bm;

  uint32_t baud = 4;//((F_CPU / I2C_FREQUENCY) -
                  //(((F_CPU * I2C_T_RISE) / 1000) / 1000) / 1000 - 10) /
                  //2;
  TWI0.MBAUD = (uint8_t)baud;
  TWI0.MCTRLA = TWI_ENABLE_bm;  // Enable as master, no interrupts
  TWI0.MSTATUS = TWI_BUSSTATE_IDLE_gc;
}

void i2c_deinit() {
  //while (!(TWI0.MSTATUS & TWI_WIF_bm) && !(TWI0.MSTATUS & TWI_RIF_bm)) {
  //};  // Wait for write interrupt flag
  TWI0.MCTRLA &= ~TWI_ENABLE_bm;  // Enable as master, no interrupts
}

 

Can you suggest why this is happens?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can use pins however you want.    I suspect that you are always Master SPI or Master I2C.    In which case you know when you want to talk to which bus.   Configure the peripherals for the appropriate bus.

 

Just realise that certain bit patterns on MOSI, MISO might appear as a valid i2c_start(slave) to one of the I2C slaves.

The other way is safe.   The SPI slave will not care what happens on MOSI, MISO providing CS is non-active.

 

Life would be better if you chose a chip with more legs.

 

David.

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:

Just realise that certain bit patterns on MOSI, MISO might appear as a valid i2c_start(slave) to one of the I2C slaves.

 

I'm aware of that however it is not the case. My problem is that if I don't disable I2C it takes control of the IOs even after enable SPI.

Last Edited: Mon. Apr 20, 2020 - 05:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course you have to disable I2C before enabling SPI.

And disable SPI before using I2C.

 

Since you are a Master,  you might just as well enable SPI, perform SPI, disable SPI and enable I2C, perform I2C, disable I2C.

 

The default state will be no active peripheral.   CS high.   SDA, SCL pulled high with external pullups.

SPI slave is inactive due to CS

I2C slave is inactive due to pullups

 

It all depends on how the Tiny202 registers work.

With the older USI Tinys,   one register selects 2-wire or 3-wire.

 

David.

Last Edited: Mon. Apr 20, 2020 - 06:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SPI is so dead simple to do in sw, why not do that, move your SPI slave to any two pins and do away with this silliness of sharing pins?

 

Jim

 

 

Keys to wealth:

Invest for cash flow, not capital gains!

Wealth is attracted, not chased! 

Income is proportional to how many you serve!

Lets go Brandon!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:

Since you are a Master,  you might just as well enable SPI, perform SPI, disable SPI and enable I2C, perform I2C, disable I2C.

 

That's what I do and it is working as expected for months however I was trying to identify why do I need to disable I2C to make SPI work but I don't need to disable SPI to make I2C work. 

 

ki0bk wrote:

SPI is so dead simple to do in sw, why not do that, move your SPI slave to any two pins and do away with this silliness of sharing pins?

 

Why should I do that if the SPI peripheral is simple to use, can achieve higher speeds so less time wake = low power comsunption?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Looking at the image something is driving the SCL low and it goes high only if I disable the I2C so I must be forgotten a I2C stop.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course you must release the I2C bus.   Else the Slave could hold the SCL low.

 

Regarding software.    Bit-banging I2C Master is easy.   And you can achieve regular bus speeds.

Hardware SPI is always going to be faster than bit-banging.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

metRo_ wrote:

Looking at the image something is driving the SCL low and it goes high only if I disable the I2C so I must be forgotten a I2C stop.

 

If you were reading data from the I2C slave and the master has not sent a NAK, the slave will hold the bus preventing the master from sending stop!

david.prentice wrote:
Regarding software.    Bit-banging I2C Master is easy.   And you can achieve regular bus speeds.

Yes a much better bus separation solution!

 

Jim

 

 

Keys to wealth:

Invest for cash flow, not capital gains!

Wealth is attracted, not chased! 

Income is proportional to how many you serve!

Lets go Brandon!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>I can't understand why do I need to disable I2C before use SPI

 

The TWI peripheral controls both the direction and output value of both pins. You most likely end up with an open drain like configuration-

1 = high = (pullup controls) = (DIR override = 0 = input)

0 = low =  (DIR override = 1 = output, OUT override = 0)

 

In master mode, the SPI controls the direction of only the MISO pin and MOSI/SCK are used only if you set the direction to output (direction is not under SPI control, and these outputs only get to the pin if DIR is set to output). You would also normally set SPI SSD=1 in master (only) mode so you can have the SS pin to yourself, but using it only as an output is also ok with SSD=0 (but you will get into multil-master mode if switched to an input with SSD=0).

 

Master mode (SSD=1)-

MISO = input (DIR override = 0 = input)

MOSI = output IF DIR = 1 (set by you), if set to input any MOSI value produced by SPI never gets to the pin

SCK = output IF DIR = 1 (set by you), if set to input any SCK value produced by SPI never gets to the pin

 

Channel 2 (Cyan): SPI_MOSI/SDA

Channel 3 (Pink): SPI_MISO/SCL

 

With TWI enabled, it has control of dir and output, so SDA is input because of the DIR override in effect (and high because of a pullup).

The SPI MOSI cannot produce a pin value because the TWI has control of the pin as is currently an input. The MISO is also overridden to an input, which also matches what TWI is doing, so that pin is an input regardless and just depends on what value something else is driving it to.

 

I'm not sure it this is all correct, but I think its close.

 

 

edit-

Also, when the TWI is disabled, the DIR override is no longer in effect so the original DIR setting for MOSI is now back in use so you get your output.

 

 

edit-

 

> so I need to share the GPIOs for I2C and SPI

 

The SPI pins have an alternate set for MOSI/MISO via portmux.

Last Edited: Tue. Apr 21, 2020 - 05:06 AM