Configure Arduino Mega UART (Any?) as an SPI Port

Hi All. I have two devices that can communicate over SPI with Arduino Mega that I have. I have tested their communication with Arduino Mega individually. They are tested OK. But as they have different features/characteristics, I can not put them on the same SPI Bus of Arduino Mega, which has one SPI Port. While going through some forums, I came to know that UART of Arduino Mega can be configured as SPI if more than one SPI Port are required. I do not know about this solution. Is it possible? If yes, how? If no, what is the alternate?

Thank you.

  • tinu

Please explain this in more details

@UKHeliBob
One of them is a communication protocol converter and one of them is a component driver. Former is only receiving data and later is only sending data.

You are aware that SPI is a bus and can have multiple devices connected to it? If you want to read from or write to the protocol converter, you first select it by activating its chip select line; once finished, you deselect it. Same for the component driver.

If you really come to the conclusion that you need two SPI buses, check the microcontroller's datasheet. I've never used it so can't advise further.

Please explain how these features or characteristics mean they cannot be on the same bus.

Please post the datasheets of your devices.

@sterretje Thank you for the explanation. I can have these two devices connected at same SPI Bus based on your suggestions.

@PaulRB I was only concerned about the Clock, which, I think, would be different for both devices. Hence I had a confusion about to have two different devices having different Clock requirements on the same SPI Bus or not.

@Rintin No need now for sharing the datasheets as the query is resolved.

tinu

Should not be a problem, if SPIsettings, .beginTransaction() and .endTransaction() are used correctly:

Post here again if you have difficulties.

What if both the devices have different requirements of SCK? LED Driver TLC5940 is one of the devices used that can be operated in both SPI and BitBang mode. MCP2515 - CAN to SPI Converter Module is the other device. Both devices work separately over SPI. To resolve this SCK conflict, I want to operate the TLC5940 in BitBang mode, but can not find any method to do it.

I doubt very much that you need bit-banging; why do you think that you need it? See post #8.

Note:
I would never mix hardware SPI and bit-banging on the same bus.

I am concerned about different SCK.

You seem to be repeating yourself.

Did you read the link I posted?

@PaulRB I am not using the Arduino SPI Library in the code. I am using the TLC5940 and MCP2515 user developed libraries. Anyways, I do not seem to find the solution here, so I will try to get it and post here.

Those libraries will use the SPI library, so you are using it, but indirectly. If those libraries use the SPI library correctly, there will be no problem with different clock speeds. If they do not use SPI library correctly, and assume they have sole ownership of the SPI bus, then there will be a problem.

Tell us how you installed these libraries. Either give us a link to the zip file you downloaded, or if you used the library manager, tell us the author and version that you installed.

Here are the links to the libraries :
TLC5940 : GitHub - PaulStoffregen/Tlc5940: 16 channel PWM LED driver based on the Texas Instruments TLC5940 chip.
MCP2515 : GitHub - Seeed-Studio/Seeed_Arduino_CAN: Seeed Arduino CAN-BUS library - MCP2518FD&MCP2515&MCP2551

Unfortunately, that library does not use SPI transactions and may not share the bus with other libraries. However, it does not, as I expected, use the Arduino SPI library. Instead, it accesses the SPI hardware on atmega328 (and maybe some similar chips) directly. The code it uses is:

#elif DATA_TRANSFER_MODE == TLC_SPI

/** Initializes the SPI module to double speed (f_osc / 2) */
void tlc_shift8_init(void)
{
    output_pin(SIN_DDR, SIN_PIN);       // SPI MOSI as output
    output_pin(SCLK_DDR, SCLK_PIN);     // SPI SCK as output
    output_pin(TLC_SS_DDR, TLC_SS_PIN); // SPI SS as output

    clear_pin(SCLK_PORT, SCLK_PIN);

    SPSR = _BV(SPI2X); // double speed (f_osc / 2)
    SPCR = _BV(SPE)    // enable SPI
         | _BV(MSTR);  // master mode
}

/** Shifts out a byte, MSB first */
void tlc_shift8(uint8_t byte)
{
    SPDR = byte; // starts transmission
    while (!(SPSR & _BV(SPIF)))
        ; // wait for transmission complete
}

#endif

Also unfortunate is that the tlc_shift8_init() function is only called once, from Tlc5940::init(), not each time the library needs to use the SPI bus.

This library does use the Arduino SPI library and does use SPI transactions:

#define spi_readwrite      pSPI->transfer
#define spi_read()         spi_readwrite(0x00)
#define spi_write(spi_val) spi_readwrite(spi_val)
#define SPI_BEGIN()        pSPI->beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0))
#define SPI_END()          pSPI->endTransaction()
...
void mcp2515_can::mcp2515_setRegister(const byte address, const byte value) {
    #ifdef SPI_HAS_TRANSACTION
    SPI_BEGIN();
    #endif
    MCP2515_SELECT();
    spi_readwrite(MCP_WRITE);
    spi_readwrite(address);
    spi_readwrite(value);
    MCP2515_UNSELECT();
    #ifdef SPI_HAS_TRANSACTION
    SPI_END();
    #endif
}

Can you find another TLC library that uses SPI transactions? The TLC library you are using now is probably quite old and written before the Arduino SPI library was written, or at least before it was enhanced to allow transactions.

@PaulRB The TLC Library works quite well separately, so I don't think to replace it with another one.
@sterretje I will stay with your advice of not mixing bitbang with SPI on same bus and will share the solution soon.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.