Trying to get SPI1 working on Teensy-LC

Status
Not open for further replies.

hemsy

Active member
I'm trying to get SPI1 working on Teensy-LC. For now I'm using the library functions, though I eventually want to start using the SPI FIFO. Here's a program that I think demonstrates my problem. I have pin 21(MOSI1) jumpered to pin 5(MISO1). Since I'm sending 3 bits of 1, I should receive 0x010101 as my result, but instead I'm getting 0xFFFFFF. In addition, if I ground pin 5(MISO), I still get 0xFFFFFF. Looking at the pins with my scope, I get a clock signal on pin 20, the CS signal on pin 6 is toggling correctly, but I get no signal on pin 21(MOSI). So it's almost like SPI1 is not wired to the port pins. Uncommenting SPI1.setMISO(5) and SPI1.setMOSI(21) in the program doesn't help.

Code:
// Hardware: Teensy-LC, jumper connecting pin 21 (MOSI1) to pin 5 (MISO1)

#include <SPI.h>
#define cs 6

unsigned long readADC(){
  int i;
  unsigned long adcdata = 0;
  digitalWrite(cs, LOW);
  for (i=0; i<3; i++) adcdata = (adcdata << 8) + SPI1.transfer(1);
  digitalWrite(cs, HIGH);
  return adcdata;
}

void setup(){
  pinMode(cs, OUTPUT);
  digitalWrite(cs, HIGH);
  SPI1.begin();
  //SPI1.setMISO(5);
  //SPI1.setMOSI(21);
  SPI1.beginTransaction(SPISettings(2400000ul, MSBFIRST, SPI_MODE0));
  Serial.begin(9600);
  delay(1000);
}

void loop(){
  char c;
  if (Serial.available()){
    c = Serial.read();
    switch(c){
      case 'r': 
        Serial.println(readADC()); // read once to display in serial monitor
        break; 
      case 's': 
        Serial.println("Now reading continuously, press a key to stop");
        while(!Serial.available()) 
        readADC(); // read continuously to look at oscilloscope
        break;
    }
  }
}
 
Ages later, I had to use SPI1 for an RFM69HCW radio module with the Teensy LC.
Here's my adaptation.

Code:
#include <SPI.h>
#include <RH_RF69.h>
#include <RHHardwareSP1I.cpp>

// ^^ Sorry about including a .cpp file, but the filename is a typo
//    so this works without renaming the file.
//
///   PINOUT:
///   =======
///                 Teensy LC    RFM69W
///                 GND----------GND   (ground in)
///                 3V3----------3.3V  (3.3V in)
/// interrupt 0 pin D2-----------DIO0  (interrupt request out)
///          SS pin D6-----------NSS   (chip select in)
///         SCK pin D20----------SCK   (SPI clock in)
///        MOSI pin D0-----------MOSI  (SPI Data in)
///        MISO pin D1-----------MISO  (SPI Data out)

RH_RF69 rf69(6, 2, hardware_spi1); // For RF69 on PJRC breakout board with Teensy LC
                                   // Interrupt pin may be any other unused interrupt
                                   // pin out of the 18 available.
void setup() {
  //....
  SPI1.setMISO(1); // May also be 5
  SPI1.setMOSI(0); // May also be 21
  SPI1.setSCK(20); 
  SPI1.begin();
  //....
}

void loop(){
  //...
}

After running SPI1.begin(), SPI1 is ready for use, for example with SPI1.transfer('H').
 
Last edited:
hello kuashio,
have you succeed using SPI1 with mosi(21) ?
I tried and SPI1.setMOSI(21); is not changing the pin to 21
On teensy LC.
 
sorry, actually I'm working with SPI1 with DMASPI library,

Code:
  {
    SPI1_SR = 0xFF0F0000;
    SPI1_RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS | SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS;
  }
@kuashio

do you have any idea where to find some hardware/library references?
 
@Po Ting - Are you having issues, with the SPI library? with trying to set SPI to MOSI1 to pin21? Or are you actually using DMASPI? Not sure if that library has support for setting the MOSI/MISO pins?

However you probably should be able to get it to work with using the SPI library to do it.
That is you should be able to do:
Code:
SPI1.setMOSI(21);
SPI1.begin();
...
DMASPI1.begin();
...

There is lots of documents and the like up on the main PJRC website, including hardware reference documents: https://www.pjrc.com/teensy/datasheets.html
 
@Po Ting - Are you having issues, with the SPI library? with trying to set SPI to MOSI1 to pin21? Or are you actually using DMASPI? Not sure if that library has support for setting the MOSI/MISO pins?

However you probably should be able to get it to work with using the SPI library to do it.
That is you should be able to do:
Code:
SPI1.setMOSI(21);
SPI1.begin();
...
DMASPI1.begin();
...

There is lots of documents and the like up on the main PJRC website, including hardware reference documents: https://www.pjrc.com/teensy/datasheets.html

@kurtE
thank you,
I have a working teensyLC used with apa102, DMASPI1(with pin MOSI 0, CLK20)
but with
Code:
{
SPI1.setMOSI(21);
SPI1.begin();
DMASPI1.begin();
}
in any order, the devices seems still using pin 0 as MOSI , or the SPI fails to work.

I believe I can achieve by the code in DMASPI1.begin();
Code:
  static void pre_cs_impl()
  {
    SPI1_SR = 0xFF0F0000;
    SPI1_RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS | SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS;
  }

and by far reference I can find is
Code:
void SPIClass::setMOSI(uint8_t pin)
{
	if (pin != hardware().mosi_pin[mosi_pin_index]) {
		for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
			if  (pin == hardware().mosi_pin[i]) {
				if (hardware().clock_gate_register & hardware().clock_gate_mask) {
					volatile uint32_t *reg;
					reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
					*reg = 0;
					reg = portConfigRegister(hardware().mosi_pin[i]);
					*reg = hardware().mosi_mux[i];
				}	
				mosi_pin_index = i;
				return;
			}
		}
	}
}
at SPI.cpp

also I did some looking in the LC datasheet, but didn't find the section talk about SPI1_SR, SPI1_RSER yet,
please~ can you post more reference sites?

thank you
:)
 
wait, I came up with something,
{
SPI1.setMOSI(21);
SPI1.begin();
DMASPI1.begin();
} in this case the hardware LED strip hangs, I should also look further in hardware and other settings
to see if they interrupt each other.
 
hello again, I've got my answer and the device worked!!!
the original pin use on SPI1 (pin 0 )
was set to output/LOW
and was hard-connected to apa102
no wonder it hangs and didn't work,

btw,
putting SPI1.setMOSI(21);
below SPI1.begin(); or DMASPI1.begin();
doesn't change the SPI pin.
 
I might be getting somewhat confused here:

Note: Whenever you see names like these SPI1_RSER - The first place I look is in the Teensy core directory for you Arduino install.
In my case that is: D:\arduino-1.8.5\hardware\teensy\avr\cores\teensy3
And look at the file kinetis.h

You are talking about a Teensy LC, but mention SPI1_RSER and SPI1_SR
If you search for SPI1_RSER you will see:
Code:
#define SPI1_RSER		(KINETISK_SPI1.RSER)	// DSPI DMA/Interrupt Request Select and Enable Register

Those two registers are for the KINETISK objects i.e. 3.x objects like a Teensy 3.6

If you look at chapter 37 of the Teensy LC manual (https://www.pjrc.com/teensy/KL26P121M48SF4RM.pdf)
You will see the SPI registers associated with the LC. Notes These names are combining the Object names with the register names. So if you search in the above file for other variables (registers) that start with SPI1_ you will find:
Code:
#define SPI1_S			(KINETISL_SPI1.S)		// Status
#define SPI1_BR			(KINETISL_SPI1.BR)		// Baud Rate
#define SPI1_C2			(KINETISL_SPI1.C2)		// Control Register 2
#define SPI1_C1			(KINETISL_SPI1.C1)		// Control Register 1
#define SPI1_ML			(KINETISL_SPI1.ML)		// Match Low
#define SPI1_MH			(KINETISL_SPI1.MH)		// Match High
#define SPI1_DL			(KINETISL_SPI1.DL)		// Data Low
#define SPI1_DH			(KINETISL_SPI1.DH)		// Data High
#define SPI1_CI			(KINETISL_SPI1.CI)		// Dlear Interrupt
#define SPI1_C3			(KINETISL_SPI1.C3)		// Control Register 3
These point to the KINETISL_SPI structure which are for T-LC... And these register names match the register names in chapter 37...

Hope that helps
 
@Po, I'm glad you got it to work!

Yes, begin() performs initialization on the pins previously configured by setMISO() and others.

I haven't used the DMASPI library before, sorry.
 
Thank you @KurtE

I thought the SPI1_RSER is related with pin used and SPI settings
I didn't find where the definition is
there are a lot of files in the cores\teensy3 :eek:

in my case its some other problem I didn't think of during past few days.
but it's good to know more about SPI registers at different chips
and sorry my fault,
I DID miss the part that separates LC and 3.5/3.6
Code:
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)

#elif defined(KINETISL)
 
Status
Not open for further replies.
Back
Top