0
\$\begingroup\$

I've made a simple SPI test for Teensy 3.2 board.

While trying to get the communication up and running I noticed that while the alternative SCLK pin14 generated the clock, no MOSI data was outputted from the default DOUT pin11 of the Teensy 3.2 board. I checked the levels with an oscilloscope.

I set the alternative MOSI pin and voila, that pin works fine.

By calling SPI.begin() I assume the default pins are configured: MOSI pin 11 SCLK pin 13 (but used by LED so I use alternative on pin 14) nCS pin 10 (I do control it manually, as stated in Arduino documentation)

For some reason pin 11 doesn't work, even when I try to declare it manually.

Whoever can try and test it out as well , please see the Arduino code attached. Do you have issues as well or am I missing here smth ?

Arduino code (no actual chip required): Commenting or uncommenting //#define ALT_DOUT helps to select the correct pin easily.

#include <SPI.h>  // include the SPI library:


//#define ALT_DOUT //DEBUG Select Teensy DOUT location
#define OSC     //Use PWM input of the MAX chip

// === PIN Definitions ==== //
const int led = 13;

//MAX6967 === SPI

#ifdef ALT_DOUT
  const int MAX6967_DIN = 7;  //Using Alternative pin to send data out
#else  
  const int MAX6967_DIN = 11;  //Teensy 3.2 default doesn't seem to work
#endif
  
const int MAX6967_SCLK = 14; //Configured as Aleternative. on Rising edge, data shifts.
const int MAX6967_nCS = 10;  //Must be low to data to enter. Recent 16bit latch on rising edge of nCS
const int MAX6967_DOUT_OSC = 11;
   

// === Control ===
/*
uint16_t MAX6967_D15; //Read / Write

//Register Aadresses
uint16_t MAX6967_P0_REG = 0x00;  
//uint16_t MAX6967_P1_REG = 0x01;

uint16_t MAX6967_CNFG_REG = 0x10;

uint16_t MAX6967_RUN_NORAMPUP =  
*/



//LED intensity control
//Individual 8-bit PWM per CC output
//Individual 1bit analog
//Global 3bit analog control to all outputs


// === Data === //


// === DEBUG ===
char dbuf[100]; //Debug sprintf buffer
int once = 1;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); //USB
  
  SPI.begin();
  MAX6967_init(); //Led driver specific inits

  pinMode(led, OUTPUT);
  digitalWrite(led, HIGH);

}

void loop() {
  // put your main code here, to run repeatedly:
    
  MAX6967_write(0x82, 0x04);
  
  delay(1000);
}


// ====== Custom functions =====

void MAX6967_init(void){ 

  #ifdef ALT_DOUT
    SPI.setMOSI(MAX6967_DIN);
    digitalWrite(MAX6967_DIN, 0);
  #else
    //SPI.setMOSI(MAX6967_DIN); not even with this.
    //otherwise SPI.begin should init the default, right ?
    pinMode(MAX6967_DIN, OUTPUT);
  #endif
    Serial.println(MAX6967_DIN);
  
  SPI.setSCK(MAX6967_SCLK); //Use the alternative on pin 14
  pinMode(MAX6967_nCS, OUTPUT);
  pinMode(MAX6967_DOUT_OSC, OUTPUT); //Set as DOUT

  digitalWrite(MAX6967_SCLK, 0); //Clocked on the rising edge, so default is low.
  digitalWrite(MAX6967_nCS, 1);
  //digitalWrite(MAX6967_DOUT_OSC, 0); //if set as DOUT
  
}

void MAX6967_write(uint8_t address, uint8_t value) {
  
  // [R/W][D14 - D8]{D7 - D0] 
  address &= ~(1 << 7); //The MSB bit of the address is R/W - 1/0
  
  //address |= (1 << 7); //The MSB bit of the address is R/W - 1/0

  // take the SS pin low to select the chip:
  digitalWrite(MAX6967_nCS,LOW);
  //  send in the address and value via SPI:
  SPI.transfer(address);
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(MAX6967_nCS,HIGH);

  sprintf(dbuf, "address: %04X Value: %04X \r\n", address, value);
  Serial.print(dbuf);
  
}
\$\endgroup\$
1
  • \$\begingroup\$ Try a stock example for the board absolutely 100% exactly as published, even if you don't have the corresponding target chip \$\endgroup\$ Jan 9 '21 at 16:18
1
\$\begingroup\$

ah, I now found my error!

I can, indeed set alternative pins separately (as one should).

Error was in my code where I accidentally pinned OSC_DOUT pin also to 11 and set it to LOW in MAX6967_init().

//const int MAX6967_DOUT_OSC = 11; //<=== This here was the mistake along with setting this to LOW after the _DIN define.

Once corrected / removed, the default MOSI and alternative SCLK worked together nicely.

Example code:

#include <SPI.h>  // include the SPI library:


//#define ALT_DOUT //DEBUG Select Teensy DOUT location
#define OSC     //Use PWM input of the MAX chip

// === PIN Definitions ==== //


//MAX6967 === SPI
#ifdef ALT_DOUT
  const int MAX6967_DIN = 7;    //Using Alternative pin to send data out
  const int MAX6967_SCLK = 14;  //Configured as Alternative. on Rising edge, data shifts.
  const int led = 13;           //on-board LED available
#else  
  const int MAX6967_DIN = 11;   //As using defaults, no real need to define these.
  //const int MAX6967_SCLK = 13;  //Mind the LED
  const int MAX6967_SCLK = 14;  //Mind the LED
#endif
  
const int MAX6967_nCS = 10;  //Must be low to data to enter. Recent 16bit latch on rising edge of nCS

//const int MAX6967_DOUT_OSC = 11; //<=== THis here was the mistake along with setting this to LOW after the _DIN define.
   

// === Control ===
/*
uint16_t MAX6967_D15; //Read / Write

//Register Aadresses
uint16_t MAX6967_P0_REG = 0x00;  
//uint16_t MAX6967_P1_REG = 0x01;

uint16_t MAX6967_CNFG_REG = 0x10;

uint16_t MAX6967_RUN_NORAMPUP =  
*/



//LED intensity control
//Individual 8-bit PWM per CC output
//Individual 1bit analog
//Global 3bit analog control to all outputs


// === Data === //


// === DEBUG ===
char dbuf[100]; //Debug sprintf buffer
int once = 1;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); //USB
  
  SPI.begin();
  MAX6967_init(); //Led driver specific inits

  //pinMode(led, OUTPUT);
  //digitalWrite(led, HIGH);

}

void loop() {
  // put your main code here, to run repeatedly:
    
  MAX6967_write(0x82, 0x04);
  
  delay(1000);
}


// ====== Custom functions =====

void MAX6967_init(void){ 

  #ifdef ALT_DOUT
    SPI.setMOSI(MAX6967_DIN);
    SPI.setSCK(MAX6967_SCLK); //Use the alternative on pin 14

    digitalWrite(MAX6967_DIN, 0);
    digitalWrite(MAX6967_SCLK, 0); //Clocked on the rising edge, so default is low.
  #else
    //Use defaults !
    //Test if default MOSi with alternative SCLK works ?
    SPI.setSCK(MAX6967_SCLK); //Use the alternative on pin 14
    digitalWrite(MAX6967_SCLK, 0); //Clocked on the rising edge, so default is low.
  #endif
    Serial.println(MAX6967_DIN);
  
  pinMode(MAX6967_nCS, OUTPUT);
  //pinMode(MAX6967_DOUT_OSC, OUTPUT); //Set as DOUT

  digitalWrite(MAX6967_nCS, 1);
  //digitalWrite(MAX6967_DOUT_OSC, 0); //if set as DOUT
  
}

void MAX6967_write(uint8_t address, uint8_t value) {
  
  // [R/W][D14 - D8]{D7 - D0] 
  address &= ~(1 << 7); //The MSB bit of the address is R/W - 1/0
  //address |= (1 << 7); //The MSB bit of the address is R/W - 1/0

  // take the SS pin low to select the chip:
  digitalWrite(MAX6967_nCS,LOW);
  //  send in the address and value via SPI:
  SPI.transfer(address);
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(MAX6967_nCS,HIGH);

  sprintf(dbuf, "address: %04X Value: %04X \r\n", address, value);
  Serial.print(dbuf);
  
}
\$\endgroup\$
1
\$\begingroup\$

IIRC, on the Teensy 3.x the primary and alternate pins can only be switched as a group, not individually (i.e. no mix and match). If you want to use the primary clock you must use the primary data pins. The same goes for the alternates.

Edit: The above may only be true when using certain SPI libraries (such as the Teensy-specific ones whose names end in _t3). As @crypton found, the alternate pins can (at the hardware level) be freely mixed and matched (refer to his/her/their answer for details). Leaving this answer as-is for posterity.


After having taken another look at the MK20DX256VLH7 datasheet I see nothing that would indicate that this is a hardware limitation1. However, I have run into similar issues in the past with this board so I suspect any issues lie in the SPI library, not the silicon.

1 Nothing in the datasheet mentions such a limitation and §10.2.4 note 2 (p. 207) implies that (alternate) pins can be freely assigned.

\$\endgroup\$
4
  • \$\begingroup\$ ah, I now found my error! I can, indeed set alternative pins separately (as one should). Error was in my code where I accidentally pinned OSC_DOUT pin also to 11 and set it to LOW. Once corrected / removed, the default MOSI and alternative SCLK worked together nicely. I mark this as useful as this led me to investigate this further in terms of testing different alternative pins together and leading me to the mistake made. \$\endgroup\$
    – crypton
    Jan 9 '21 at 21:30
  • \$\begingroup\$ @crypton Good to know. Like I mentioned I've run into this issue myself; perhaps the issues I encountered are similar to the ones you did. \$\endgroup\$ Jan 9 '21 at 21:46
  • \$\begingroup\$ Yup, good to know. I am aware there are some Teensy specific libraries (claimed to be faster) which I currently haven't tested yet. \$\endgroup\$
    – crypton
    Jan 10 '21 at 9:34
  • \$\begingroup\$ @crypton The libraries I used are the Teensy-specific ones (names ending in _t3). \$\endgroup\$ Jan 10 '21 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.