SPI partly working when using hardware, library or code CS management

Post here first, or if you can't find a relevant section!
mrguen
Posts: 24
Joined: Tue Mar 03, 2020 1:21 pm
Answers: 2

SPI partly working when using hardware, library or code CS management

Post by mrguen »

Hello,

Maybe some of you know well the SPI?

I am trying to communicate between STM32F401RCT6 and an ADC module MCP3561.

The expected com on SPI is attached at the end of the message.

The SPI used is SPI2 with alternate pins

Code: Select all

const byte SPI_MOSI = PC3;
const byte SPI_MISO = PC2;
const byte SPI_SCK = PB13;
const byte SPI_CS = PB12;
const uint32_t spiClk = 5000000; // or 10 MHz
byte passedValue = (MCP3561DeviceAddress << 6) & REGISTER_CONFIG1 << 2 & COMMAND_STATIC_READ_REGISTER;
1) It is partly working when using the hardware CS pin. The device answers correctly. But since the CS pin probably goes up after each transfer I can't read the data after sending a command.

Code: Select all

SPIClass mySPI2(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS);
SPISettings mySPIsettings = SPISettings(spiClk, MSBFIRST, SPI_MODE0); 

mySPI2.begin();
mySPI2.beginTransaction(mySPIsettings);

returnedValue =  mySPI2.transfer(passedValue);
// The returned value is as expected (returning the MCP3561DeviceAddress): 00011111

returnedData =  mySPI2.transfer(0);
// Not correct all "1" . The device is supposed to send the data immediatly after receiving and answering to the command, never mind what is on MOSI.  But indeed if CS goes high MISO is supposed to return to HIGH. Or maybe I didn't catch the data ? (I did not find a shiftIn method).

mySPI2.endTransaction();


2) Using the CS management in the library: not working

Code: Select all

SPIClass mySPI2(SPI_MOSI, SPI_MISO, SPI_SCK);
SPISettings mySPIsettings = SPISettings(spiClk, MSBFIRST, SPI_MODE0); 

mySPI2.begin(SPI_CS);
mySPI2.beginTransaction(mySPIsettings);

returnedValue =  mySPI2.transfer(passedValue, SPI_CONTINUE);
// The returned value is NOT as expected - all "1"

returnedData =  mySPI2.transfer(0, SPI_LAST);
// The returned value is NOT as expected 

mySPI2.endTransaction();


3) Managing CS pin in the code: working as with hardware management

Code: Select all

pinMode(SPI_CS, OUTPUT);
digitalWrite(SPI_CS, HIGH);
   
SPIClass mySPI2(SPI_MOSI, SPI_MISO, SPI_SCK);
SPISettings mySPIsettings = SPISettings(spiClk, MSBFIRST, SPI_MODE0); 

mySPI2.begin();
mySPI2.beginTransaction(mySPIsettings);

digitalWrite(SPI_CS, LOW);
  
returnedValue =  mySPI2.transfer(passedValue);
// The returned value is as expected (returning the MCP3561DeviceAddress): 00011111

returnedData =  mySPI2.transfer(0);
// The returned value is  NOT as expected 

digitalWrite(SPI_CS, HIGH);

mySPI2.endTransaction();

What might be wrong? Also I could not find a shiftIn() method.
Attachments
SP2.gif
SP2.gif (38.99 KiB) Viewed 6490 times
by mrguen » Wed Sep 02, 2020 12:28 pm
The command was not correct. I can have it work when managing the CS pin in the code. I did not tested more the other two methods.
Go to full post
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: SPI partly working when using hardware, library or code CS management

Post by fpiSTM »

Hi @mrguen
did you read the wiki:
https://github.com/stm32duino/wiki/wiki/API#spi

Maybe you need the SPI_CONTINUE ?
mrguen
Posts: 24
Joined: Tue Mar 03, 2020 1:21 pm
Answers: 2

Re: SPI partly working when using hardware, library or code CS management

Post by mrguen »

@fpiSTM Yes I did read the WIKI and use SPI_CONTINUE in example 2, but maybe not correctly?
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: SPI partly working when using hardware, library or code CS management

Post by fpiSTM »

Well, like this I see nothing wrong. Anyway, I don't know this component (MCP3561),
is your value correct

Code: Select all

byte passedValue = (MCP3561DeviceAddress << 6) & REGISTER_CONFIG1 << 2 & COMMAND_STATIC_READ_REGISTER;
mrguen
Posts: 24
Joined: Tue Mar 03, 2020 1:21 pm
Answers: 2

Re: SPI partly working when using hardware, library or code CS management

Post by mrguen »

@fpiSTM Yes this is a recent component (2019). So there is hardly any info available. I guess I have to analyze the signals. I will do some more test and let you know.
mrguen
Posts: 24
Joined: Tue Mar 03, 2020 1:21 pm
Answers: 2

Re: SPI partly working when using hardware, library or code CS management

Post by mrguen »

The command was not correct. I can have it work when managing the CS pin in the code. I did not tested more the other two methods.
moustachedbird
Posts: 2
Joined: Sat Feb 13, 2021 2:33 am

Re: SPI partly working when using hardware, library or code CS management

Post by moustachedbird »

Sorry, I read your post and I wanted to know if you managed to program the 24 bit ADC. I'm trying to use this ADC with the ESP32 but can't get the SPI communication work.
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: SPI partly working when using hardware, library or code CS management

Post by stevestrong »

@moustachedbird , you issue is related to ESP32 and not to STM32, so you better post on ESP32 forum.
moustachedbird
Posts: 2
Joined: Sat Feb 13, 2021 2:33 am

Re: SPI partly working when using hardware, library or code CS management

Post by moustachedbird »

@stevestrong not really, the issue is related to the 24 bit ADC, but anyway, the question was: @mrguen did you managed to program the 24 bit ADC with the STM32? Thank you :)
mrguen
Posts: 24
Joined: Tue Mar 03, 2020 1:21 pm
Answers: 2

Re: SPI partly working when using hardware, library or code CS management

Post by mrguen »

@moustachedbird

Yes I did succeed in configuring the MCP3561 and reading data on IRQ . I don' t remember exactly what was the keypoint for solving this issue. But here are the important code parts:

In a header file:

Code: Select all

...


// Parameters of the Master Clock Output pin
#define MCO1_GPIO_PORT        GPIOA
#define MCO1_PIN              GPIO_PIN_8

// ADC Clock settings
const uint32_t clockFrequency = 8000000;

// MCU data ready IRQ input pin
const byte irqPin = PC6;

// These are alternate pins of SPI2
const byte SPI_MOSI   = PC3;
const byte SPI_MISO   = PC2;
const byte SPI_SCK    = PB13;
const byte SPI_CS     = PB12;
...
In the .ino file

Code: Select all

// ***********************************************************************************************************
// IRQ HANDLER

extern "C" {

  // handle IRQs from MCP3561 to MCI pin PC6
  void pin_IRQ() {
    //Serial.println(EXTI->PR, BIN);
    availableADCvalue = true;

    // Ajouter un compteur pour voir si on saute des IRQs et gérer l'erreur
    
  } // PC6_IRQ
  
} // extern

Code: Select all

// ***********************************************************************************************************
// Configure interrupt pin 
void irqPinSetup(void) {
  pinMode(irqPin,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(irqPin),pin_IRQ,FALLING);
  //__HAL_RCC_SYSCFG_CLK_ENABLE();   
}

Code: Select all

// ***********************************************************************************************************
// Set up PA8 pin as MCO output to feed MCP356x external clock
void MCOSetup() {
  GPIO_InitTypeDef GPIO_InitStruct;  
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /* Configure the MCO1 pin in alternate function mode */
  GPIO_InitStruct.Pin = MCO1_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;   
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
  HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);

  // Mask MCO1 and MCO1PRE[2:0] bits then Select MCO1 clock source and prescaler  
   MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCO1 | RCC_CFGR_MCO1PRE), (RCC_MCO1SOURCE_HSE | RCC_MCODIV_1));
}

Code: Select all

/ ***********************************************************************************************************
// SETUP
void setup() {
  
...
  MCOSetup();

  // This sequence to clear the ~POR status after startup: !!! Still POR
  pinMode(SPI_CS, OUTPUT);
  digitalWrite(SPI_CS, HIGH);
  digitalWrite(SPI_CS, LOW);
  digitalWrite(SPI_CS, HIGH);
  
  MCP356x.begin(SPI_CS, &mySPI2);
  MCP356x.setFrequencies(clockSourceExternal, clockFrequency, PSC_1, OSR_32);
  freqEchantillonnage = MCP356x.getDataRateClock();
  frequencyResolution = freqEchantillonnage / nbEchantillons;
   
  Serial.println("CONFIG2 Boost 2");
  MCP356x.writeRegister(REGISTER_CONFIG2, CONFIG2_DEFAULT | CONFIG2_BOOST_2 | CONFIG2_GAIN_1, 1);

  Serial.println("CONFIG3 Data format 32 bits with channel ID and continuous conversion");
  MCP356x.writeRegister(REGISTER_CONFIG3, CONFIG3_CONV_MODE_CONTINUOUS | CONFIG3_DATA_FORMAT_32_CHANNEL4_SGN4_24, 1);

  Serial.println("CONFIG_IRQ ");
//  MCP356x.writeRegister(REGISTER_IRQ, IRQ_MODE_IRQ | IRQ_MODE_INACTIVE_FLOAT | IRQ_FASTCMD_ENABLE);
  MCP356x.writeRegister(REGISTER_IRQ, IRQ_MODE_IRQ | IRQ_MODE_INACTIVE_HIGH | IRQ_FASTCMD_ENABLE, 1);

  Serial.println("CONFIG_MUX ");
  MCP356x.writeRegister(REGISTER_MUX, MUX_VINP_CH0 | MUX_VINM_AGND, 1);
//  MCP356x.writeRegister(REGISTER_MUX, MUX_VINP_AVDD | MUX_VINM_AGND);

  Serial.println("Start ADC");
  MCP356x.writeFastCommand(FAST_COMMAND_START);
  Serial.println("Start reading ADC");
  MCP356x.startReadADC();
...  
}

Code: Select all

void loop() {

  if (availableADCvalue) {

   // Fills the table 
   if (cptEchantillons < nbEchantillons) {
      MCP356x.readADC(&mesADC, &channelADC); // REvoir après prise en compte du signe, ajouter 2^23
      mesuresfloat[cptEchantillons] = mesADC;
      cptEchantillons++;
    }
    
	...
    
    availableADCvalue = false;
 }
   
}
Post Reply

Return to “General discussion”