Share digital pin 51/52 on Mega with Shift Register (Possible?)

I’d like to know if it is possible to share pins 51(MOSI) and 52(SCK) on the Arduino Mega 2560 between an SPI bus (Touch screen with SD Card) and TLC5940 Shift Register (Other/LED’s).

The TLC5940 requires pin 51 on the mega to connect to its pin 26(SIN) and pin 52 to pin 25(SCLK).

Would this cause me issues? Is the communication handled through hardware automatically somehow?

I'd like to know if it is possible to share pins 51(MOSI) and 52(SCK) on the Arduino Mega 2560 between an SPI bus (Touch screen with SD Card) and TLC5940 Shift Register (Other/LED's).

No. If the pin is being used for SPI is can not be used for ANY other purpose.

That's what I thought. I guess I'll have to use multiple Arduino's.

Thanks Paul.

You don't have any other pins? You don't need to use the hardware SPI for the shift register. Take a look at shiftOut() function.

You have 50 plus pins. If that is not enough, you can consider the use of port expanders (I2c/SPI) or serial /parallel (or vice versa) shift registers.

As you already have an SPI device, it makes sense to me to add more if needed.

Mega has 69 IO pins. All the analog pins can be used as digital pins also.

So the TLC5940 library doesn't use SPI.transfer to send data to the device? Smart code should take advantage of the hardware.

I have a lot of available pins on the Mega, but from my understanding the TLC5940 library does not allow you to change those 2 pins (51 and 52).

Here are 2 snippets from the library, one from the Arduino_Mega.h file telling you configurable pins are in the tlc_config.h file, and that file telling you not to edit them:

Arduino_Mega.h

/** \file
    SPI and timer pins for the Arduino Mega.  Don't edit these.  All
    changeable pins are defined in tlc_config.h */


/** SIN (Mega pin 51) -> SIN (TLC pin 26) */
#define DEFAULT_BB_SIN_PIN      PB2
#define DEFAULT_BB_SIN_PORT     PORTB
#define DEFAULT_BB_SIN_DDR      DDRB
/** SCLK (Mega pin 52) -> SCLK (TLC pin 25) */
#define DEFAULT_BB_SCLK_PIN     PB1
#define DEFAULT_BB_SCLK_PORT    PORTB
#define DEFAULT_BB_SCLK_DDR     DDRB

/** MOSI (Mega pin 51) -> SIN (TLC pin 26) */
#define TLC_MOSI_PIN     PB2
#define TLC_MOSI_PORT    PORTB
#define TLC_MOSI_DDR     DDRB

/** SCK (Mega pin 52) -> SCLK (TLC pin 25) */
#define TLC_SCK_PIN      PB1
#define TLC_SCK_PORT     PORTB
#define TLC_SCK_DDR      DDRB

tlc_config.h

/* ------------------------- STOP EDITING HERE ----------------------------- */

#if DATA_TRANSFER_MODE == TLC_SPI
/** SIN (TLC pin 26) */
#define SIN_PIN        TLC_MOSI_PIN
#define SIN_PORT       TLC_MOSI_PORT
#define SIN_DDR        TLC_MOSI_DDR
/** SCLK (TLC pin 25) */
#define SCLK_PIN       TLC_SCK_PIN
#define SCLK_PORT      TLC_SCK_PORT
#define SCLK_DDR       TLC_SCK_DDR
#endif

I don't understand how exactly I can change these to use any other pin on the Mega and still work with the library.

Would the shiftOut() function work for both the SCLK pin that shifts data AND the SIN pin?

Alright, well since nobody is replying I'll just carry on as it might help someone down the road.

So I managed to change the 2 pins by bit-banging after finding a post about it online on github. The post says to change information in 3 files as seen below.

-------------------------------------------------
tlc_config.h

  #define DATA_TRANSFER_MODE    TLC_SPI
  //#define DATA_TRANSFER_MODE    TLC_BITBANG

To:

  //#define DATA_TRANSFER_MODE    TLC_SPI
  #define DATA_TRANSFER_MODE    TLC_BITBANG
-------------------------------------------------
ATmega_xx8.h

  /** SCLK (Arduino digital pin 2) -> SCLK (TLC pin 25) */
  #define DEFAULT_BB_SCLK_PIN     PD2

To:

  /** SCLK (Arduino digital pin 5) -> SCLK (TLC pin 25) */
  #define DEFAULT_BB_SCLK_PIN     PD5
--------------------------------------------------
Arduino_Mega.h

  /** SIN (Mega pin 51) -> SIN (TLC pin 26) */
  #define DEFAULT_BB_SIN_PIN      PB2
  #define DEFAULT_BB_SIN_PORT     PORTB
  #define DEFAULT_BB_SIN_DDR      DDRB
  /** SCLK (Mega pin 52) -> SCLK (TLC pin 25) */
  #define DEFAULT_BB_SCLK_PIN     PB1
  #define DEFAULT_BB_SCLK_PORT    PORTB
  #define DEFAULT_BB_SCLK_DDR     DDRB

To:

  /** SIN (Mega pin 7) -> SIN (TLC pin 26) */
  #define DEFAULT_BB_SIN_PIN      PH4
  #define DEFAULT_BB_SIN_PORT     PORTH
  #define DEFAULT_BB_SIN_DDR      DDRH
  /** SCLK (Mega pin 2) -> SCLK (TLC pin 25) */
  #define DEFAULT_BB_SCLK_PIN     PE4
  #define DEFAULT_BB_SCLK_PORT    PORTE
  #define DEFAULT_BB_SCLK_DDR     DDRE

After doing that and moving pin 52 to 2, and 51 to 7, I ran my sketch and all the leds worked as intended, but at random times when they were supposed to be off some of them would flicker, which did not happen previously.

My guess is the code above might be a little old and needs updating or it has something to do with the timers not working properly with the pins they are on. The change the post states to makes in the ATmega_xx8.h file seems outdated. It states they are using version r014 of the TLC5940 library, but I am using r014_2, so there's probably been a change.

The file I have has:

/** SCLK (Arduino digital pin 4) -> SCLK (TLC pin 25) */
#define DEFAULT_BB_SCLK_PIN     PD4
#define DEFAULT_BB_SCLK_PORT    PORTD
#define DEFAULT_BB_SCLK_DDR     DDRD

and not:

/** SCLK (Arduino digital pin 2) -> SCLK (TLC pin 25) */
  #define DEFAULT_BB_SCLK_PIN     PD2

I went over the changes and tried different pins/settings, but the flicker persists. I checked the port mappings thanks to this post, and everything seems right, so I'm at a loss as to where the flicker is coming from or how to fix it.

I know the Mega has 6 timers, and the MOSI pin is using timer4 on pin 7 while SCK pin is using timer3 on pin 2. Could there be some sort of conflict there?

Somewhere along the line I had a knight_rider effect example code from the internet and had added the SD data logging to it with no ill effects so I knew it was possible in my other projects as well.

Yesterday I added an SD breakout to a project to log data and began having crazy LED flickering issues right off the bat when the arduino interacted with the SD card.
I started picking through the code and found that the only difference between my main project and the knight_rider example is the use of delay() after Tlc.update() and writting to the SD card. Below is some sample code where I stripped out everything I could and was still able to turn the issue on/off by only commenting out the delay(1);

For reference, a pic of my shield is attached to shows you which pins I am sharing. I am using a MEGA 2560.

I can’t explain why this works for me. I don’t like that it feels like a hack to me but I really hope that you (or someone later) finds this helpful. Maybe someone with more experience/knowledge can bring to light why the delay(1) works…?
I logged on tonight with the sole purpose of posting this since I could not find a solution anywhere online. If this helps you, please let me know!

Cheers!

//libraries
  #include <SD.h>
  #include <SPI.h>
  #include "Tlc5940.h"
  
//Chipselect pin for SD breakout
  const int chipSelect = 46;
  File SDlogfile; //Construct the SD object

void setup(){
// Call Tlc.init() to setup the tlc. You can optionally pass an initial PWM value (0 - 4095) for all channels
  Tlc.init();
// start serial port
  Serial.begin(9600);
  pinMode(SS, OUTPUT);

//*******************************************
//https://www.arduino.cc/en/Reference/SDbegin
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
//*******************************************

//create a new file
  char SDLogFileName[] = "BrewSD00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    SDLogFileName[6] = i/10 + '0';
    SDLogFileName[7] = i%10 + '0';
    if (! SD.exists(SDLogFileName)) {
    // only open a new file if it doesn't exist
    // https://www.arduino.cc/en/Reference/SDopen
      SDlogfile = SD.open(SDLogFileName, FILE_WRITE); 
      break;  // leave the loop!
    }
  }
}

void loop(){
// Tlc.update() sends the data to the TLCs.  This is when the LEDs will actually change
  Tlc.update();
//-----------------------------------------------------------------
//I don't know why this works... but adding a delay between Tlc.update() & when data is written
//to the SD card resolved my flickering issues
  delay(1);  //Comment out this delay and flickering occurs with my setup
//-----------------------------------------------------------------
//Writes some data to the logfile and flushes
  SDlogfile.println(millis());
  SDlogfile.flush();
}

Schematic.JPG