Help - no SPI on 411

Post here first, or if you can't find a relevant section!
Post Reply
Tardishead
Posts: 12
Joined: Sun Dec 27, 2020 10:07 am

Help - no SPI on 411

Post by Tardishead »

Sorry I am complete beginner here
I have used DACS MPC4822 and 4922 with success with Teensy 3.6 and 4.0
I decided to migrate a project from Teensy to STM32F411
The code I used successfully with Teensy does not seem to be working on the 411. I cannot get any clock or SDI to begin
I believe the lines
SPI.setMOSI(MOSI_pin);
SPI.setSCLK(SCK_pin);
are Teensy extensions to the SPI library. Can anyone help?



Code: Select all

//
//#define  package_one_cs_pin  PA15 
//#define  package_two_cs_pin  PB4 
//#define  MOSI_pin PB5
//#define  SCK_pin PB3 

#define playStatePin PB12
#define playStateLed PB13
#define recordStatePin PB14
#define recordStateLed PB15
#define restPin PA8
#define restPinLed PA9
#define clearPin PA10
#define legatoPin PB7
#define legatoPinLed PB8
#define resetPin PA11
#define playClockPin PB6
#define recordPulsePin PB9
#define gateOutputAPin PC13
#define gateOutputBPin PC14
#define gateOutputCPin PC15
//#define gateOutputDPin 18
#define voiceSelectPin PA1
#define voiceSelectALed PA2
#define voiceSelectBLed PA3
#define voiceSelectCLed PA4
#define voiceSelectDLed PA5


volatile int playState = 0;
volatile int recordState = 1;
volatile int playCursor = -1;
volatile int recordCursor = -1;
volatile int legatoState = 0;
volatile int gateState = 0;
volatile int clearState = 0;
volatile int resetState = 0;
int endFirstSequenceCounter;
int voiceSelect = 0;
volatile int restFlag = 0;
int restButtonPress;
int legatoButtonPress;
uint32_t lastRestInterrupt = 0;
uint32_t timer = millis();

long restButtonDebounceTime;
bool restButton;
bool restReading;
bool restReadingLast;

int voltageA;
int voltageB;
int voltageC;
int voltageD;
bool gateOutputA;
bool gateOutputB;
bool gateOutputC;
bool gateOutputD;
bool playClock;

int buffA [1000];                                         // Set Up Buffers for the VOICE A
bool gateA [1000];
bool legatoA [1000];

int buffB [1000];                                         // Set Up Buffers for the VOICE B
bool gateB [1000];
bool legatoB [1000];

int buffC [1000];                                         // Set Up Buffers for the VOICE C
bool gateC [1000];
bool legatoC [1000];

int buffD [1000];                                         // Set Up Buffers for the VOICE D
bool gateD [1000];
bool legatoD [1000];

#include <SPI.h>
const unsigned int dac_one =    0B0001000000000000 ;      // First 4 bits of register are Channel, Buffered, Gain x2 and Enable
const unsigned int dac_two =    0B1001000000000000 ;
const unsigned int dac_three =  0B0001000000000000 ;
const unsigned int dac_four =   0B1001000000000000 ;
const int package_one_cs_pin = PA15 ;
const int package_two_cs_pin = PB4 ;
const int MOSI_pin(PB5);
const int SCK_pin(PB3);


void setup() {

  delay(200);


  pinMode (gateOutputAPin, OUTPUT);
  pinMode (gateOutputBPin, OUTPUT);
  pinMode (gateOutputCPin, OUTPUT);
  //  pinMode (gateOutputDPin, OUTPUT);
  pinMode (voiceSelectPin, INPUT_PULLUP);
  pinMode (voiceSelectALed, OUTPUT);
  pinMode (voiceSelectBLed, OUTPUT);
  pinMode (voiceSelectCLed, OUTPUT);
  //  pinMode (voiceSelectDLed, OUTPUT);


  pinMode (playStateLed, OUTPUT);
  pinMode (recordStateLed, OUTPUT);
  pinMode (restPinLed, OUTPUT);
  pinMode (legatoPinLed, OUTPUT);
  pinMode (playStatePin, INPUT_PULLUP);
  pinMode (recordStatePin, INPUT_PULLUP);
  pinMode (clearPin, INPUT_PULLUP);
  pinMode (resetPin, INPUT_PULLUP);
  pinMode (restPin, INPUT_PULLUP);
  pinMode (legatoPin, INPUT_PULLUP);
  pinMode (playClockPin, INPUT);
  pinMode (recordPulsePin, INPUT);
  attachInterrupt (playStatePin, playFunction, FALLING);
  attachInterrupt (recordStatePin, recordFunction, FALLING);
  attachInterrupt (clearPin, clearFunction, FALLING);
  attachInterrupt (resetPin, resetFunction, FALLING);
  //  attachInterrupt (restPin, restFunction, FALLING);
  attachInterrupt (legatoPin, legatoFunction, FALLING);
  attachInterrupt (recordPulsePin, recordPulseReceive, RISING);
  attachInterrupt (playClockPin, playClockReceive, RISING);


  pinMode(PA0, INPUT);                                     // Define A0 as ADC input
  analogReadResolution(12);
  analogWriteResolution(12);


  pinMode ( package_one_cs_pin , OUTPUT ) ;               //    Set DAC output CS pins
  digitalWrite ( package_one_cs_pin , HIGH ) ;
  pinMode ( package_two_cs_pin , OUTPUT ) ;
  digitalWrite ( package_two_cs_pin , HIGH ) ;
  SPI.setMOSI(MOSI_pin);
  SPI.setSCLK(SCK_pin);
  SPI.begin() ;

  delay(200);

}


void loop() {

  digitalWrite (playStateLed, playState);
  digitalWrite (recordStateLed, recordState);
  legatoButtonPress = !digitalRead(legatoPin);
  digitalWrite (legatoPinLed, legatoButtonPress);
  restButtonPress = !digitalRead (restPin);
  digitalWrite (restPinLed, restButtonPress);




  if (recordState == 1) {

    int restReading = digitalRead (restPin);
    if (restReading != restReadingLast) {
      restButtonDebounceTime = millis();
    }

    if ((millis() - restButtonDebounceTime) > 50 ) {
      if (restReading != restButton) {
        restButton = restReading;
        if (restButton == LOW) {
          recordCursor++;
          gateState = 0;
          legatoState = 0;
        }
      }
    }

    restReadingLast = restReading;


    if (voiceSelect == 0) {
      if (clearState == 1) {
        for (int i = 0; i < 1000; i++) {                       //Initialize the buffer contents to all zero THIS CLEARS THE MEMORY
          buffA[i] = 0;
          gateA[i] = 0;
          legatoA[i] = 0;
        }
        recordCursor = -1;
      }
      clearState = 0;
      endFirstSequenceCounter = recordCursor;                  // Writing Voice A pattern determines the length of the Sequence
      gateA[recordCursor] = gateState;
      legatoA[recordCursor] = legatoState;
      voltageA = analogRead (A0);
      buffA[recordCursor] = voltageA;
      SPI.beginTransaction (SPISettings( 20000000, MSBFIRST , SPI_MODE0)) ;
      digitalWrite (package_one_cs_pin , LOW) ;                // Playthru while writing sequence in
      SPI.transfer16 (dac_one | voltageA ) ;
      digitalWrite (package_one_cs_pin , HIGH) ;
      SPI.endTransaction () ;
      int playThruGateA = digitalRead (recordPulsePin);
      digitalWrite (gateOutputAPin , playThruGateA);
    }


    if (voiceSelect == 1) {
      if (clearState == 1) {
        for (int i = 0; i < 1000; i++) {                       //Initialize the buffer contents to all zero THIS CLEARS THE MEMORY
          buffB[i] = 0;
          gateB[i] = 0;
          legatoB[i] = 0;
        }
        recordCursor = 0;

      }
      clearState = 0;
      if (recordCursor > endFirstSequenceCounter) {            // On voices B,C,D more steps than recorded on voice A will write over the start of the sequence B,C,D
        recordCursor = 0;
      }
      gateB[recordCursor] = gateState;
      legatoB[recordCursor] = legatoState;
      voltageB = analogRead (A0);
      buffB[recordCursor] = voltageB;
      SPI.beginTransaction (SPISettings( 20000000, MSBFIRST , SPI_MODE0)) ;
      digitalWrite (package_one_cs_pin , LOW) ;                // Playthru while writing sequence in
      SPI.transfer16 (dac_two | voltageB ) ;
      digitalWrite (package_one_cs_pin , HIGH) ;
      SPI.endTransaction () ;
      int playThruGateB = digitalRead (recordPulsePin);
      digitalWrite (gateOutputBPin , playThruGateB);
    }


    if (voiceSelect == 2) {
      if (clearState == 1) {
        for (int i = 0; i < 1000; i++) {                       //Initialize the buffer contents to all zero THIS CLEARS THE MEMORY
          buffC[i] = 0;
          gateC[i] = 0;
          legatoC[i] = 0;
        }
        recordCursor = 0;
      }
      clearState = 0;
      if (recordCursor > endFirstSequenceCounter) {
        recordCursor = 0;
      }
      gateC[recordCursor] = gateState;
      legatoC[recordCursor] = legatoState;
      voltageC = analogRead (A0);
      buffC[recordCursor] = voltageC;
      SPI.beginTransaction (SPISettings( 20000000, MSBFIRST , SPI_MODE0)) ;
      digitalWrite (package_two_cs_pin , LOW) ;                // Playthru while writing sequence in
      SPI.transfer16 (dac_three | voltageC ) ;
      digitalWrite (package_two_cs_pin , HIGH) ;
      SPI.endTransaction () ;
      int playThruGateC = digitalRead (recordPulsePin);
      digitalWrite (gateOutputCPin , playThruGateC);
    }


    //    if (voiceSelect == 3) {
    //      if (clearState == 1) {
    //        for (int i = 0; i < 1000; i++) {                       //Initialize the buffer contents to all zero THIS CLEARS THE MEMORY
    //          buffD[i] = 0;
    //          gateD[i] = 0;
    //          legatoD[i] = 0;
    //        }
    //        recordCursor = 0;
    //      }
    //      clearState = 0;
    //      if (recordCursor > endFirstSequenceCounter) {
    //        recordCursor = 0;
    //      }
    //      gateD[recordCursor] = gateState;
    //      legatoD[recordCursor] = legatoState;
    //      voltageD = analogRead (A0);
    //      buffD[recordCursor] = voltageD;
    //      SPI.beginTransaction (SPISettings( 20000000, MSBFIRST , SPI_MODE0)) ;
    //      digitalWrite (package_two_cs_pin , LOW) ;                // Playthru while writing sequence in
    //      SPI.transfer16 (dac_four | voltageD ) ;
    //      digitalWrite (package_two_cs_pin , HIGH) ;
    //      SPI.endTransaction () ;
    //      int playThruGateD = digitalRead (recordPulsePin);
    //      digitalWrite (gateOutputDPin , playThruGateD);
    //
    //    }

  }


  if (playState == 1) {
    playClock = digitalRead (playClockPin);
    gateOutputA = (playClock && gateA[playCursor]) || legatoA[playCursor];
    gateOutputB = (playClock && gateB[playCursor]) || legatoB[playCursor];
    gateOutputC = (playClock && gateC[playCursor]) || legatoC[playCursor];
    gateOutputD = (playClock && gateD[playCursor]) || legatoD[playCursor];

    digitalWrite (gateOutputAPin, gateOutputA);
    digitalWrite (gateOutputBPin, gateOutputB);
    digitalWrite (gateOutputCPin, gateOutputC);
    //    digitalWrite (gateOutputDPin, gateOutputD);

    if (playCursor > endFirstSequenceCounter) {
      playCursor = 0;
    }
    if (resetState == 1) {
      playCursor = endFirstSequenceCounter;
    }


    SPI.beginTransaction(SPISettings( 20000000, MSBFIRST , SPI_MODE0)) ;

    digitalWrite (package_one_cs_pin , LOW) ;
    SPI.transfer16(dac_one | buffA[playCursor] ) ;
    digitalWrite (package_one_cs_pin , HIGH) ;

    digitalWrite (package_one_cs_pin , LOW) ;
    SPI.transfer16(dac_two | buffB[playCursor] ) ;
    digitalWrite (package_one_cs_pin , HIGH) ;

    digitalWrite (package_two_cs_pin , LOW) ;
    SPI.transfer16(dac_three | buffC[playCursor] ) ;
    digitalWrite (package_two_cs_pin , HIGH) ;

    digitalWrite (package_two_cs_pin , LOW) ;
    SPI.transfer16(dac_four | buffD[playCursor] ) ;
    digitalWrite (package_two_cs_pin , HIGH) ;

    SPI.endTransaction () ;

  }


}

void playFunction () {                                      // Does not need DeBouncing
  playState = 1;
  recordState = 0;
  playCursor = -1;
}


void recordFunction () {                                    // Does not need DeBouncing
  playState = 0;
  recordState = 1;
}


void clearFunction () {                                     // Does not need DeBouncing
  if (recordState == 1) {
    clearState = 1;
  }
}

void resetFunction () {                                     //Returns Play Counter to start of sequence
  resetState = 1;                                           // Does not need DeBouncing
}


//void restFunction () {                                      //Inputs Zero Gate
//  if (recordState == 1) {                                   //NEEDS DEBOUNCING*****************************************************************************************************
//    restFlag = 1;
//    recordCursor++;
//    gateState = 0;
//    legatoState = 0;
//  }
//}


void legatoFunction () {                                    // Does not need DeBouncing
  if (recordState == 1) {
    legatoState = 1;
  }
}


void recordPulseReceive () {
  if (recordState == 1) {
    recordCursor++;
    gateState = 1;
    legatoState = 0;
    restFlag = 0;
  }
}


void playClockReceive () {
  if (playState == 1) {
    playCursor++;
    resetState = 0;
  }

}
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Help - no SPI on 411

Post by stevestrong »

Which core do you use? Which board have you selected in Arduino IDE?
Tardishead
Posts: 12
Joined: Sun Dec 27, 2020 10:07 am

Re: Help - no SPI on 411

Post by Tardishead »

stevestrong wrote: Tue Dec 29, 2020 9:45 pm Which core do you use? Which board have you selected in Arduino IDE?
I am using this core
https://github.com/stm32duino/BoardMana ... index.json
And I have selected Black Pill F411CE
Tardishead
Posts: 12
Joined: Sun Dec 27, 2020 10:07 am

Re: Help - no SPI on 411

Post by Tardishead »

I would use the SPIClass command but I do not know how to omit MISO pin because I do not need it
so
SPIClass SPI(SPI_MOSI, SPI_MISO, SPI_SCK);
can I do
SPIClass SPI(SPI_MOSI,, SPI_SCK);
or
SPIClass SPI(SPI_MOSI, 0, SPI_SCK);
??
Cant find info on this
Tardishead
Posts: 12
Joined: Sun Dec 27, 2020 10:07 am

Re: Help - no SPI on 411

Post by Tardishead »

Do I need to download and install this SPI library? I am confused
https://github.com/stm32duino/Arduino_C ... raries/SPI
And if so how do I keep both SPI Teensy and STM32 on the Arduino IDE?
User avatar
fpiSTM
Posts: 1746
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Help - no SPI on 411

Post by fpiSTM »

SPI is a built in library so no need to do a specific install.
By default a SPI instance is instantiate and uses those pins (SPI1 peripheral instance):
https://github.com/stm32duino/Arduino_C ... .h#L89-L97
  • MOSI: PA7
  • MISO: PA6
  • SCK: PA5
the SPI.set[MISO|MOSI|SCLK] simply allow to change the default SPI pins and must be called before the begin().
See the wiki: https://github.com/stm32duino/wiki/wiki/API#spi

You can't omit the MISO pin.
If you want use the PB3 and PB5 you have to set all pins to the same SPI3 peripheral instance as described in the PeripheralPins.c:

Code: Select all

    SPI.setMISO(PB4);
    SPI.setMOSI(PB5);
    SPI.setSCLK(PB3);
    SPI.begin();
Tardishead
Posts: 12
Joined: Sun Dec 27, 2020 10:07 am

Re: Help - no SPI on 411

Post by Tardishead »

fpiSTM wrote: Wed Dec 30, 2020 7:41 am
You can't omit the MISO pin.
If you want use the PB3 and PB5 you have to set all pins to the same SPI3 peripheral instance as described in the PeripheralPins.c:
Amazing thanks. So if I understand correctly my instance was not working because I had not changed the MISO pin together with the SCLK and MOSI pin?

And I presume once PB4 is set as MISO pin I cannot use it for anything else?
User avatar
fpiSTM
Posts: 1746
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Help - no SPI on 411

Post by fpiSTM »

Tardishead wrote: Wed Dec 30, 2020 9:09 am And I presume once PB4 is set as MISO pin I cannot use it for anything else?
Yes.
Post Reply

Return to “General discussion”