Teensy SPI question

Status
Not open for further replies.

CanopyR&D

Member
Hey all,

I have a few questions about the SPI protocol & pins specifically on the Teensy. I've read through the SPI page on the site a few times, as well as other guides, but there are some things I still don't quite grasp.

First off, the SPI page mentions that there are specific SPI pins, and that if you can't use those pins, you must use the alternate pins specified in that page (14, 7, 8). However, on the Teensy pinouts they show pins labeled as MOSI/MISO1, MOSI/MISO2, SCK1/SCK2. In the past I've seen this for UART (Tx1, Tx2, Rx1, Rx2) which meant you could connect multiple devices through UART. This seems to stand in contrast to what I'm gathering from the SPI page where it seems only the main SPI pins (13, 11, 12) or the alternates (14, 7, 8) can be used, rather than simply having two SPI devices connected.

My second question is kind of a continuation of the first. In the SPI page, it mentions that some of the SPI Pins are used by the Audio Adapter, and therefore that would be a situation where you'd want to move them to their alternate positions. However, from the pinout of the audio adapter board, it still shows the alternate pins 7 & 14 would still be used by the audio adapter board. It would seem to me that switching the SPI pins to the alternate positions would still mess with the audio adapter.

Any clarification or insight is greatly appreciated!
 
SPI is meant to work like a bus. MOSI, MISO & SCK can connect to more than 2 chips. Which chip uses those 3 pins depends on which CS signal is active. So chip needs a dedicated CS signal, but the other 3 signals are shared among SPI chips.

I2C works similarly, but without CS signals. Complex rules about the data patters allow SDA & SCL to be shared among many chips, as long as each chip's pre-assigned address is unique. Many I2C have one or more pins you connect to GND or VCC to configure which address they'll use, which is meant to give you options to use more chips on the same 2 signals.
 
With the reference card the fainter text is alternate pins, XXX2 labels are for the second SPI interface which runs completely separate to the default one on pins 10/11/12/13 - however most libraries are not yet organised to allow you to switch to SPI2 from your code so you probably would need to edit the actual library to use them. In any case you can't mix main and alternate pins such clk1 and MISO2, just the pins within each SPI set.

With the Audio shield, it uses pin 13, but is not using it as SPI clock so that is still available if you use the alternate pin.
 
Thank you both for your replies. I was mistakenly thinking that the Audio board was using those same SPI pins for SPI, but as I see now as you pointed out, 13 was being used for RX, and pin 11 for a clock signal.

I haven't gotten SPI to work yet with the audio board (despite moving MOSI to 7 & SCK to pin 14), regardless of how I set the clock divider. The acting slave is an Uno, but seeing as I don't have much more information to provide at the time, I'll follow up once I take a look at the signals more closely.
 
If you have access to a scope you this is fairly easy to look into, but if you don't have one may be worth writing some basic code on the uno side that polls a pin and if change happens writes the millis() value to an array at least 16 cells deep. Once array is full write out the values to serial or display. Then point the code at each SPI pin in turn and see what it does (without any SPI libraries in code). Clock should toggle at your target clock rate, data should be toggling at multiples of your clock rate and chip select should toggle for the duration of one data send.
 
Last edited:
Good morning,
in my project use the interface spi,i want to use a pin which does not exist in the original teensy 3.6,that pin is PTC16 and i want to use it as chip select(CS).
I have written the program but it does not work properly,if i change pin chip select it works just fine.I have not defined correctly the pin PTC16?
The code is that:

Code:
#include <SPI.h>

byte lowByte, highByte;
int measurements;
double gyroscope_value_roll, gyroscope_sum_measurements_roll, gyroscope_average_roll;
double gyroscope_value_pitch, gyroscope_sum_measurements_pitch, gyroscope_average_pitch;
double gyroscope_value_yaw, gyroscope_sum_measurements_yaw, gyroscope_average_yaw;

void setup() {

  PORTC_PCR16 = PORT_PCR_MUX(1);
  GPIOC_PDDR |= (1 << 16);
  
  Serial.begin(9600);
  while(!Serial);

  SPI.begin();
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE3));

  GPIOC_PCOR |= (1 << 16);
  SPI.transfer(0x20 & 0x7F);
  SPI.transfer(0x0F);
  GPIOC_PSOR |= (1 << 16);

  GPIOC_PCOR |= (1 << 16);
  SPI.transfer(0x22 & 0x7F);
  SPI.transfer(0x08);
  GPIOC_PSOR |= (1 << 16);

  GPIOC_PCOR |= (1 << 16);
  SPI.transfer(0x23 & 0x7F);
  SPI.transfer(0x90);
  GPIOC_PSOR |= (1 << 16);

  Serial.print("Starting calibration...");
  for (measurements = 0; measurements < 5000; measurements ++) {
    read_gyroscope();
    gyroscope_sum_measurements_roll += gyroscope_value_roll;
    gyroscope_sum_measurements_pitch += gyroscope_value_pitch;
    gyroscope_sum_measurements_yaw += gyroscope_value_yaw;
    if(measurements%100 == 0)Serial.print(".");
    delay(4);
  }

  gyroscope_average_roll = gyroscope_sum_measurements_roll / 5000;
  gyroscope_average_pitch = gyroscope_sum_measurements_pitch / 5000;
  gyroscope_average_yaw = gyroscope_sum_measurements_yaw / 5000;

}

void loop() {

  delay(250);
  read_gyroscope();
  print_output();

}

void print_output()
{
  Serial.print("Pitch:");
  if(gyroscope_value_pitch >= 0)Serial.print("+");
  Serial.print(gyroscope_value_pitch/57.14286);               //Convert to degree per second
  if(gyroscope_value_pitch/57.14286 - 2 > 0)Serial.print(" NoU");
  else if(gyroscope_value_pitch/57.14286 + 2 < 0)Serial.print(" NoD");
  else Serial.print(" ---");
  Serial.print("  Roll:");
  if(gyroscope_value_roll >= 0)Serial.print("+");
  Serial.print(gyroscope_value_roll/57.14286);                //Convert to degree per second
  if(gyroscope_value_roll/57.14286 - 2 > 0)Serial.print(" RwD");
  else if(gyroscope_value_roll/57.14286 + 2 < 0)Serial.print(" RwU");
  else Serial.print(" ---");
  Serial.print("  Yaw:");
  if(gyroscope_value_yaw >= 0)Serial.print("+");
  Serial.print(gyroscope_value_yaw/57.14286);                 //Convert to degree per second
  if(gyroscope_value_yaw/57.14286 - 2 > 0)Serial.println(" NoR");
  else if(gyroscope_value_yaw/57.14286 + 2 < 0)Serial.println(" NoL");
  else Serial.println(" ---");

}

void read_gyroscope() {

  GPIOC_PCOR |= (1 << 16);
  SPI.transfer(0x28 | 0x80);
  lowByte = SPI.transfer(0x00);
  GPIOC_PSOR |= (1 << 16);
  GPIOC_PCOR |= (1 << 16);
  SPI.transfer(0x29 | 0x80);
  highByte = SPI.transfer(0x00);
  GPIOC_PSOR |= (1 << 16);
  gyroscope_value_roll = (int16_t)((highByte << 8) | lowByte);
  if (measurements == 5000)gyroscope_value_roll -= gyroscope_average_roll;

  GPIOC_PCOR |= (1 << 16);
  SPI.transfer(0x2A | 0x80);
  lowByte = SPI.transfer(0x00);
  GPIOC_PSOR |= (1 << 16);
  GPIOC_PCOR |= (1 << 16);
  SPI.transfer(0x2B | 0x80);
  highByte = SPI.transfer(0x00);
  GPIOC_PSOR |= (1 << 16);
  gyroscope_value_pitch = (int16_t)((highByte << 8) | lowByte);
  gyroscope_value_pitch *= -1;
  if (measurements == 5000)gyroscope_value_pitch -= gyroscope_average_pitch;

  GPIOC_PCOR |= (1 << 16);
  SPI.transfer(0x2C | 0x80);
  lowByte = SPI.transfer(0x00);
  GPIOC_PSOR |= (1 << 16);
  GPIOC_PCOR |= (1 << 16);
  SPI.transfer(0x2D | 0x80);
  highByte = SPI.transfer(0x00);
  GPIOC_PSOR |= (1 << 16);
  gyroscope_value_yaw = (int16_t)((highByte << 8) | lowByte);
  gyroscope_value_yaw *= -1;
  if (measurements == 5000)gyroscope_value_yaw -= gyroscope_average_yaw;

}
 
Use digitalWriteFast. When giving constant inputs, it compiles to the same direct register access, but you get to use the easy Arduino syntax.
 
So as i have written the code why not works?Has not been set correctly the pin PTC16?
If i run this code

Code:
void setup() {                
  
  PORTC_PCR16 = PORT_PCR_MUX(1);

  GPIOC_PDDR |= (1 << 16);                // SET PTC16 OUTPUT
       
}

void loop() {

  GPIOC_PSOR |= (1 << 16);     // turn the LED on (HIGH is the voltage level)
  delay(1000);                          // wait for a second
  GPIOC_PCOR |= (1 << 16);   // turn the LED off by making the voltage LOW
  delay(1000);                        // wait for a second
}

flashes the led.
I have something wrong in these lines
Code:
 PORTC_PCR16 = PORT_PCR_MUX(1);
 GPIOC_PDDR |= (1 << 16);                // SET PTC16 OUTPUT

i have to add something else??Could you help me so that the error is found to learn what is going and not working.
 
Have you looked at what pinMode(N, OUTPUT); does?

Actually the code uses the bit band address for the registers as to avoid issues of your above code is not atomic. So if somehting else happens in the system that touches PORTC during an interrupt...
Code:
void pinMode(uint8_t pin, uint8_t mode)
{
	volatile uint32_t *config;

	if (pin >= CORE_NUM_DIGITAL) return;
	config = portConfigRegister(pin);

	if (mode == OUTPUT || mode == OUTPUT_OPENDRAIN) {
#ifdef KINETISK
		*portModeRegister(pin) = 1;
#else
		*portModeRegister(pin) |= digitalPinToBitMask(pin); // TODO: atomic
#endif
		*config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
		if (mode == OUTPUT_OPENDRAIN) {
		    *config |= PORT_PCR_ODE;
		} else {
		    *config &= ~PORT_PCR_ODE;
                }
	} else {
So you will notice that when it sets the pin to output, not only does it set the pin as an IO pin: PORT_PCR_MUX(1)
It also turns on Drive Strength Enable(DSE) and Slew Rate Enable(SRE)

Personally if it were me, and I added new pins, I would probably define a new Board type, and add these pins to the tables, such that I could then do as Paul suggested of using standard Arduino syntax.
 
Personally if it were me, and I added new pins, I would probably define a new Board type, and add these pins to the tables, such that I could then do as Paul suggested of using standard Arduino syntax.

Before i do this change that you say i can do something else to work properly the above code?
 
Did you try enabling the DSE and SRE in your program in the way I mentioned in previous post?

Also the PSOR and PCOR registers are write only like registers. so you should simply: GPIOC_PSOR = (1 << 16);

Likewise for the other one..
 
Here is your sketch altered as Kurt suggested and I changed it to use pin 13 (PTC5) so I can see if it blinks
Code:
void setup() {                
  
  PORTC_PCR5 =  PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);

  GPIOC_PDDR |= (1 << 5);                // SET PTC5 OUTPUT
       
}

void loop() {

  GPIOC_PSOR = (1 << 5);     // turn the LED on (HIGH is the voltage level)
  delay(1000);                          // wait for a second
  GPIOC_PCOR = (1 << 5);   // turn the LED off by making the voltage LOW
  delay(1000);                        // wait for a second
}
this flashes LED every second on my T3.6
 
Last edited:
Did you try enabling the DSE and SRE in your program in the way I mentioned in previous post?

Yes i tried to activate the DSE and SRE writing

Code:
PORTC_PCR16 = PORT_PCR_MUX(1) | PORT_PCR_SRE | PORT_PCR_DSE;

Also the PSOR and PCOR registers are write only like registers. so you should simply: GPIOC_PSOR = (1 << 16);
Likewise for the other one..

I did not understand what you mean by that,you can explain to me?
 
Since the program manitou posted works properly on PTC5, maybe something is wrong with PTC16 your custom hardware?

Or if you are using a Teensy 3.6, then you can be pretty sure that program is indeed changing the voltage on 1 of the unconnected pins underneath the chip.
 
I did not understand what you mean by that,you can explain to me?

With GPIOC_PSOR |= (1 << 16); the "|=" works, but if you look at the K66 ref manual 63.3.2, you'll see that reading GPIOx_PSOR always returns 0. So the "|" is not really necessary. Same for GPIOx_PCOR.

For a test of your PCB, maybe just set PTC16 high and check it with voltmeter. Do you still have an LED on PTC5? did you test sketch in post #12?
 
Paul i just want to learn why she does not work,
Αlso the pin PTC16 it is not registered how will i use it?
 
I did not understand what you mean by that,you can explain to me?

If you look at the manual for processor (K66P144M...) at the two registers In mine it is section 63.3.2 for PSOR
You will See on Read operation it return 0
So you don't need (or want to first read) the contents.

The line: GPIOC_PSOR |= (1 << 16); // turn the LED on (HIGH is the voltage level)

Is sort of a short hand for:
GPIOC_PSOR = GPIOC_PSOR | (1 << 16);

But again all of the bits will read back as 0, so instead just set the value you wish to change, i.e.
GPIOC_PSOR = (1 << 16);

Remember with this register any bit that is set, will turn on that bit in the data output register (PDOR). Any bit that is not set in PSOR is left along in the PDOR.

Likewise with the PCOR register. Any bit you set in it (PCOR) will clear the corresponding bit in the PDOR and leave the other bits unchanged.
 
Paul i just want to learn why she does not work,

You're asking me to diagnose why something you are trying is not working, but I do not even know how you are trying to observe the voltage of PTC16.

Maybe you could share a photo (and explain, but show a photo of your test setup) to show us what you are really doing to test this pin?

I ask for this (photo) because PTC16 is not any of the pins on Teensy 3.6. So I really need to actually *see* what you are doing to be able to answer your question.
 
Manitou and paul in post #8 i have mentioned that i have run the program:
Code:
void setup() {                
  
  PORTC_PCR16 = PORT_PCR_MUX(1);

  GPIOC_PDDR |= (1 << 16);                // SET PTC16 OUTPUT
       
}

void loop() {

  GPIOC_PSOR |= (1 << 16);     // turn the LED on (HIGH is the voltage level)
  delay(1000);                          // wait for a second
  GPIOC_PCOR |= (1 << 16);   // turn the LED off by making the voltage LOW
  delay(1000);                        // wait for a second
}

and this flashes LED in port PTC16 every second.
I tried it now did sketch of manitou in post #12?
Code:
void setup() {                
  
  PORTC_PCR5 =  PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);

  GPIOC_PDDR |= (1 << 5);                // SET PTC5 OUTPUT
       
}

void loop() {

  GPIOC_PSOR = (1 << 5);     // turn the LED on (HIGH is the voltage level)
  delay(1000);                          // wait for a second
  GPIOC_PCOR = (1 << 5);   // turn the LED off by making the voltage LOW
  delay(1000);                        // wait for a second
}
and this flashes LED in port PTC5 every second.
I also measured with the multimeter the pin PTC16 and measure 3.27v when i turn on this pin,this pin works it is not damaged.
 
So if the above program works to flash LED, what is the current problem?

Example is the SPI not working? Here is a hacked up version of your first program, in this, I added the SRC and DSE as maybe you need these items, especially as you
are doing really quick changing of CS state, so maybe never actually see some of the changes.

In this hacked up version, I setup macros for setting the CS_HIGH or CS_LOW, which I then used. This way you should be able to replace these with digitalWrite to some other pin and see if the code works...
Does this device need you to release the CS after each command? If so maybe you need to add some delays in order for it to see this?


Code:
#include <SPI.h>
#define CS_HIGH   GPIOC_PSOR = (1 << 16)
#define CS_LOW    GPIOC_PCOR = (1 << 16)
byte lowByte, highByte;
int measurements;
double gyroscope_value_roll, gyroscope_sum_measurements_roll, gyroscope_average_roll;
double gyroscope_value_pitch, gyroscope_sum_measurements_pitch, gyroscope_average_pitch;
double gyroscope_value_yaw, gyroscope_sum_measurements_yaw, gyroscope_average_yaw;

void setup() {

  PORTC_PCR16 =  PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
  GPIOC_PDDR |= (1 << 16);
  CS_HIGH;  // Start of with the CS not selected (HIGH)

  Serial.begin(9600);
  while (!Serial);

  SPI.begin();
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE3));

  CS_LOW;
  SPI.transfer(0x20 & 0x7F);
  SPI.transfer(0x0F);
  CS_HIGH;

  CS_LOW;
  SPI.transfer(0x22 & 0x7F);
  SPI.transfer(0x08);
  CS_HIGH;

  CS_LOW;
  SPI.transfer(0x23 & 0x7F);
  SPI.transfer(0x90);
  CS_HIGH;

  Serial.print("Starting calibration...");
  for (measurements = 0; measurements < 5000; measurements ++) {
    read_gyroscope();
    gyroscope_sum_measurements_roll += gyroscope_value_roll;
    gyroscope_sum_measurements_pitch += gyroscope_value_pitch;
    gyroscope_sum_measurements_yaw += gyroscope_value_yaw;
    if (measurements % 100 == 0)Serial.print(".");
    delay(4);
  }

  gyroscope_average_roll = gyroscope_sum_measurements_roll / 5000;
  gyroscope_average_pitch = gyroscope_sum_measurements_pitch / 5000;
  gyroscope_average_yaw = gyroscope_sum_measurements_yaw / 5000;

}

void loop() {

  delay(250);
  read_gyroscope();
  print_output();

}

void print_output()
{
  Serial.print("Pitch:");
  if (gyroscope_value_pitch >= 0)Serial.print("+");
  Serial.print(gyroscope_value_pitch / 57.14286);             //Convert to degree per second
  if (gyroscope_value_pitch / 57.14286 - 2 > 0)Serial.print(" NoU");
  else if (gyroscope_value_pitch / 57.14286 + 2 < 0)Serial.print(" NoD");
  else Serial.print(" ---");
  Serial.print("  Roll:");
  if (gyroscope_value_roll >= 0)Serial.print("+");
  Serial.print(gyroscope_value_roll / 57.14286);              //Convert to degree per second
  if (gyroscope_value_roll / 57.14286 - 2 > 0)Serial.print(" RwD");
  else if (gyroscope_value_roll / 57.14286 + 2 < 0)Serial.print(" RwU");
  else Serial.print(" ---");
  Serial.print("  Yaw:");
  if (gyroscope_value_yaw >= 0)Serial.print("+");
  Serial.print(gyroscope_value_yaw / 57.14286);               //Convert to degree per second
  if (gyroscope_value_yaw / 57.14286 - 2 > 0)Serial.println(" NoR");
  else if (gyroscope_value_yaw / 57.14286 + 2 < 0)Serial.println(" NoL");
  else Serial.println(" ---");

}

void read_gyroscope() {

  CS_LOW;
  SPI.transfer(0x28 | 0x80);
  lowByte = SPI.transfer(0x00);
  CS_HIGH;
  CS_LOW;
  SPI.transfer(0x29 | 0x80);
  highByte = SPI.transfer(0x00);
  CS_HIGH;
  gyroscope_value_roll = (int16_t)((highByte << 8) | lowByte);
  if (measurements == 5000)gyroscope_value_roll -= gyroscope_average_roll;

  CS_LOW;
  SPI.transfer(0x2A | 0x80);
  lowByte = SPI.transfer(0x00);
  CS_HIGH;
  CS_LOW;
  SPI.transfer(0x2B | 0x80);
  highByte = SPI.transfer(0x00);
  CS_HIGH;
  gyroscope_value_pitch = (int16_t)((highByte << 8) | lowByte);
  gyroscope_value_pitch *= -1;
  if (measurements == 5000)gyroscope_value_pitch -= gyroscope_average_pitch;

  CS_LOW;
  SPI.transfer(0x2C | 0x80);
  lowByte = SPI.transfer(0x00);
  CS_HIGH;
  CS_LOW;
  SPI.transfer(0x2D | 0x80);
  highByte = SPI.transfer(0x00);
  CS_HIGH;
  gyroscope_value_yaw = (int16_t)((highByte << 8) | lowByte);
  gyroscope_value_yaw *= -1;
  if (measurements == 5000)gyroscope_value_yaw -= gyroscope_average_yaw;

}
 
but it still does not work.

Does "not work" mean pin PTC16 isn't changing? Are you observing that pin with something fast enough to see the changes, like an oscilloscope or logic analyzer?

Or does "not work" mean it doesn't perform some other function you intended, even if PTC16 works?
 
Sorry paul,i mean it does not work as i want it to work.:D
I tested the following code and i have set the pin 10(PTC4) as chip selsct using the "pinMode(CS, OUTPUT);", "digitalWrite(CS, LOW);" and "digitalWrite(CS, HIGH);" and i get the measurements correctly from the gyroscope.
Code:
#include <SPI.h>

#define CS 10

byte lowByte, highByte;
int measurements;
double gyroscope_value_roll, gyroscope_sum_measurements_roll, gyroscope_average_roll;
double gyroscope_value_pitch, gyroscope_sum_measurements_pitch, gyroscope_average_pitch;
double gyroscope_value_yaw, gyroscope_sum_measurements_yaw, gyroscope_average_yaw;

void setup() {

  Serial.begin(9600);
  while(!Serial);

  SPI.begin();
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE3));

  pinMode(CS, OUTPUT);

  digitalWrite(CS, LOW);
  SPI.transfer(0x20 & 0x7F);
  SPI.transfer(0x0F);
  digitalWrite(CS, HIGH);

  digitalWrite(CS, LOW);
  SPI.transfer(0x22 & 0x7F);
  SPI.transfer(0x08);
  digitalWrite(CS, HIGH);

  digitalWrite(CS, LOW);
  SPI.transfer(0x23 & 0x7F);
  SPI.transfer(0x90);
  digitalWrite(CS, HIGH);

  Serial.print("Starting calibration...");
  for (measurements = 0; measurements < 5000; measurements ++) {
    read_gyroscope();
    gyroscope_sum_measurements_roll += gyroscope_value_roll;
    gyroscope_sum_measurements_pitch += gyroscope_value_pitch;
    gyroscope_sum_measurements_yaw += gyroscope_value_yaw;
    if(measurements%100 == 0)Serial.print(".");
    delay(4);
  }

  gyroscope_average_roll = gyroscope_sum_measurements_roll / 5000;
  gyroscope_average_pitch = gyroscope_sum_measurements_pitch / 5000;
  gyroscope_average_yaw = gyroscope_sum_measurements_yaw / 5000;

}

void loop() {

  
  read_gyroscope();
  print_output();
  delay(250);

}

void print_output()
{
  Serial.print("Pitch:");
  if(gyroscope_value_pitch >= 0)Serial.print("+");
  Serial.print(gyroscope_value_pitch/57.14286);               //Convert to degree per second
  if(gyroscope_value_pitch/57.14286 - 2 > 0)Serial.print(" NoU");
  else if(gyroscope_value_pitch/57.14286 + 2 < 0)Serial.print(" NoD");
  else Serial.print(" ---");
  Serial.print("  Roll:");
  if(gyroscope_value_roll >= 0)Serial.print("+");
  Serial.print(gyroscope_value_roll/57.14286);                //Convert to degree per second
  if(gyroscope_value_roll/57.14286 - 2 > 0)Serial.print(" RwD");
  else if(gyroscope_value_roll/57.14286 + 2 < 0)Serial.print(" RwU");
  else Serial.print(" ---");
  Serial.print("  Yaw:");
  if(gyroscope_value_yaw >= 0)Serial.print("+");
  Serial.print(gyroscope_value_yaw/57.14286);                 //Convert to degree per second
  if(gyroscope_value_yaw/57.14286 - 2 > 0)Serial.println(" NoR");
  else if(gyroscope_value_yaw/57.14286 + 2 < 0)Serial.println(" NoL");
  else Serial.println(" ---");

}

void read_gyroscope() {

  digitalWrite(CS, LOW);
  SPI.transfer(0x28 | 0x80);
  lowByte = SPI.transfer(0x00);
  digitalWrite(CS, HIGH); 
  digitalWrite(CS, LOW);
  SPI.transfer(0x29 | 0x80);
  highByte = SPI.transfer(0x00);
  digitalWrite(CS, HIGH); 
  gyroscope_value_roll = (int16_t)((highByte << 8) | lowByte);
  if (measurements == 5000)gyroscope_value_roll -= gyroscope_average_roll;

  digitalWrite(CS, LOW);
  SPI.transfer(0x2A | 0x80);
  lowByte = SPI.transfer(0x00);
  digitalWrite(CS, HIGH); 
  digitalWrite(CS, LOW);
  SPI.transfer(0x2B | 0x80);
  highByte = SPI.transfer(0x00);
  digitalWrite(CS, HIGH); 
  gyroscope_value_pitch = (int16_t)((highByte << 8) | lowByte);
  gyroscope_value_pitch *= -1;
  if (measurements == 5000)gyroscope_value_pitch -= gyroscope_average_pitch;

  digitalWrite(CS, LOW);
  SPI.transfer(0x2C | 0x80);
  lowByte = SPI.transfer(0x00);
  digitalWrite(CS, HIGH); 
  digitalWrite(CS, LOW);
  SPI.transfer(0x2D | 0x80);
  highByte = SPI.transfer(0x00);
  digitalWrite(CS, HIGH); 
  gyroscope_value_yaw = (int16_t)((highByte << 8) | lowByte);
  gyroscope_value_yaw *= -1;
  if (measurements == 5000)gyroscope_value_yaw -= gyroscope_average_yaw;

}

then i tried the same pin(PTC4) with my own program but i do not get measurements from the gyroscope.

Code:
#include <SPI.h>

byte lowByte, highByte;
int measurements;
double gyroscope_value_roll, gyroscope_sum_measurements_roll, gyroscope_average_roll;
double gyroscope_value_pitch, gyroscope_sum_measurements_pitch, gyroscope_average_pitch;
double gyroscope_value_yaw, gyroscope_sum_measurements_yaw, gyroscope_average_yaw;

void setup() {

  PORTC_PCR4 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
  GPIOC_PDDR |= (1 << 4);
  
  Serial.begin(9600);
  while(!Serial);

  SPI.begin();
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE3));

  GPIOC_PCOR = (1 << 4);
  SPI.transfer(0x20 & 0x7F);
  SPI.transfer(0x0F);
  GPIOC_PSOR = (1 << 4);

  GPIOC_PCOR = (1 << 4);
  SPI.transfer(0x22 & 0x7F);
  SPI.transfer(0x08);
  GPIOC_PSOR = (1 << 4);

  GPIOC_PCOR = (1 << 4);
  SPI.transfer(0x23 & 0x7F);
  SPI.transfer(0x90);
  GPIOC_PSOR = (1 << 4);

  Serial.print("Starting calibration...");
  for (measurements = 0; measurements < 5000; measurements ++) {
    read_gyroscope();
    gyroscope_sum_measurements_roll += gyroscope_value_roll;
    gyroscope_sum_measurements_pitch += gyroscope_value_pitch;
    gyroscope_sum_measurements_yaw += gyroscope_value_yaw;
    if(measurements%100 == 0)Serial.print(".");
    delay(4);
  }

  gyroscope_average_roll = gyroscope_sum_measurements_roll / 5000;
  gyroscope_average_pitch = gyroscope_sum_measurements_pitch / 5000;
  gyroscope_average_yaw = gyroscope_sum_measurements_yaw / 5000;

}

void loop() {

  delay(250);
  read_gyroscope();
  print_output();

}

void print_output()
{
  Serial.print("Pitch:");
  if(gyroscope_value_pitch >= 0)Serial.print("+");
  Serial.print(gyroscope_value_pitch/57.14286);               //Convert to degree per second
  if(gyroscope_value_pitch/57.14286 - 2 > 0)Serial.print(" NoU");
  else if(gyroscope_value_pitch/57.14286 + 2 < 0)Serial.print(" NoD");
  else Serial.print(" ---");
  Serial.print("  Roll:");
  if(gyroscope_value_roll >= 0)Serial.print("+");
  Serial.print(gyroscope_value_roll/57.14286);                //Convert to degree per second
  if(gyroscope_value_roll/57.14286 - 2 > 0)Serial.print(" RwD");
  else if(gyroscope_value_roll/57.14286 + 2 < 0)Serial.print(" RwU");
  else Serial.print(" ---");
  Serial.print("  Yaw:");
  if(gyroscope_value_yaw >= 0)Serial.print("+");
  Serial.print(gyroscope_value_yaw/57.14286);                 //Convert to degree per second
  if(gyroscope_value_yaw/57.14286 - 2 > 0)Serial.println(" NoR");
  else if(gyroscope_value_yaw/57.14286 + 2 < 0)Serial.println(" NoL");
  else Serial.println(" ---");

}

void read_gyroscope() {

  GPIOC_PCOR = (1 << 4);
  SPI.transfer(0x28 | 0x80);
  lowByte = SPI.transfer(0x00);
  GPIOC_PSOR = (1 << 4);
  GPIOC_PCOR = (1 << 4);
  SPI.transfer(0x29 | 0x80);
  highByte = SPI.transfer(0x00);
  GPIOC_PSOR = (1 << 4);
  gyroscope_value_roll = (int16_t)((highByte << 8) | lowByte);
  if (measurements == 5000)gyroscope_value_roll -= gyroscope_average_roll;

  GPIOC_PCOR = (1 << 4);
  SPI.transfer(0x2A | 0x80);
  lowByte = SPI.transfer(0x00);
  GPIOC_PSOR = (1 << 4);
  GPIOC_PCOR = (1 << 4);
  SPI.transfer(0x2B | 0x80);
  highByte = SPI.transfer(0x00);
  GPIOC_PSOR = (1 << 4);
  gyroscope_value_pitch = (int16_t)((highByte << 8) | lowByte);
  gyroscope_value_pitch *= -1;
  if (measurements == 5000)gyroscope_value_pitch -= gyroscope_average_pitch;

  GPIOC_PCOR = (1 << 4);
  SPI.transfer(0x2C | 0x80);
  lowByte = SPI.transfer(0x00);
  GPIOC_PSOR = (1 << 4);
  GPIOC_PCOR = (1 << 4);
  SPI.transfer(0x2D | 0x80);
  highByte = SPI.transfer(0x00);
  GPIOC_PSOR = (1 << 4);
  gyroscope_value_yaw = (int16_t)((highByte << 8) | lowByte);
  gyroscope_value_yaw *= -1;
  if (measurements == 5000)gyroscope_value_yaw -= gyroscope_average_yaw;

}
 
Status
Not open for further replies.
Back
Top