Author Topic: STM32F103C8T6 SPI communication with ADS1220 stops  (Read 5888 times)

0 Members and 1 Guest are viewing this topic.

Offline aleks_sitnoTopic starter

  • Newbie
  • Posts: 2
  • Country: mk
STM32F103C8T6 SPI communication with ADS1220 stops
« on: March 01, 2017, 09:43:12 am »
Hello,
I'am using and STM32F103C8T6 development board to communicate via SPI with ADS1220(Analog to Digital Converter). My code needs to read the buffer of the ADS1220 at certain times. When i run the code the SPI works only for a few minutes(max 14 min) before it stops. The SPI code i am using is :
 
void SPIx_Init()
{
// Initialization struct
SPI_InitTypeDef SPI_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
// Step 1: Initialize SPI
RCC_APB2PeriphClockCmd(SPIx_RCC, ENABLE);
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
//SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
SPI_Init(SPIx, &SPI_InitStruct);
SPI_Cmd(SPIx, ENABLE); // Enables SPIx peripheral.
// Step 2: Initialize GPIO
RCC_APB2PeriphClockCmd(SPI_GPIO_RCC, ENABLE);
// GPIO pins for MOSI and SCK
GPIO_InitStruct.GPIO_Pin = SPI_PIN_MOSI | SPI_PIN_SCK;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(SPI_GPIO, &GPIO_InitStruct);
// GPIO pins for MOSI, MISO
GPIO_InitStruct.GPIO_Pin = SPI_PIN_MISO;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(SPI_GPIO, &GPIO_InitStruct);
}
 
uint8_t SPIx_Receive(uint8_t data)
{

// Write data to be transmitted to the SPI data register
SPIx->DR = data;
// Wait until transmit complete
while (!(SPIx->SR & (SPI_I2S_FLAG_TXE)));

// Wait until receive complete
while (!(SPIx->SR & (SPI_I2S_FLAG_RXNE)));

// Wait until SPI is not busy anymore
while (SPIx->SR & (SPI_I2S_FLAG_BSY));
//Return received data from SPI data register
return SPIx->DR;
}
 
The program always stops at this line of code :
while (!(SPIx->SR & (SPI_I2S_FLAG_TXE)));
Before the code stops, it has done at least 1000 reads(usually more than a 1000,maybe even 50000) of the buffer successfully. Why does my code stop after successfully running for so long time. Is there a problem with the SPI buffer, some data not being send. The data I am transmitting is a dummy byte 0x00.
 
Any help would be greatly appreciated.
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6580
  • Country: nl
Re: STM32F103C8T6 SPI communication with ADS1220 stops
« Reply #1 on: March 01, 2017, 09:56:23 am »
not sure if this is the answer for you but did you read this topic:
https://www.eevblog.com/forum/beginners/problems-with-stm32-spi-and-chip-select/msg940848/#msg940848
 
The following users thanked this post: aleks_sitno

Offline capt bullshot

  • Super Contributor
  • ***
  • Posts: 3033
  • Country: de
    • Mostly useless stuff, but nice to have: wunderkis.de
Re: STM32F103C8T6 SPI communication with ADS1220 stops
« Reply #2 on: March 01, 2017, 10:45:48 am »
Edit:
I believe your code stops at some point because you're reading the TX empty too soon. Place a few cycles of delay in between, or try my approach (below)
/Edit

From my experience, a better approach would be to wait for the TX to be empty and then send:

// Wait until transmit complete
while (!(SPIx->SR & (SPI_I2S_FLAG_TXE)));
// Write data to be transmitted to the SPI data register
SPIx->DR = data;

then wait for the receiver register
// Wait until receive complete
while (!(SPIx->SR & (SPI_I2S_FLAG_RXNE)));

then read the data and return
//Return received data from SPI data register
return SPIx->DR;

IMO the wait for SPI not busy isn't necessary, but I'd have to check that (nice if you'd do that for me :-)


« Last Edit: March 01, 2017, 11:10:13 am by capt bullshot »
Safety devices hinder evolution
 
The following users thanked this post: aleks_sitno

Offline fsedano

  • Contributor
  • Posts: 21
  • Country: ch
Re: STM32F103C8T6 SPI communication with ADS1220 stops
« Reply #3 on: March 01, 2017, 11:45:26 pm »

IMO the wait for SPI not busy isn't necessary, but I'd have to check that (nice if you'd do that for me :-)


I've found if you only wait for tx reg to be empty you will exit too early, causing problems if you raise CS just after that.

 

Offline capt bullshot

  • Super Contributor
  • ***
  • Posts: 3033
  • Country: de
    • Mostly useless stuff, but nice to have: wunderkis.de
Re: STM32F103C8T6 SPI communication with ADS1220 stops
« Reply #4 on: March 02, 2017, 07:23:55 am »
I've found if you only wait for tx reg to be empty you will exit too early, causing problems if you raise CS just after that.

You're right, I've found that piece of code I wrote two years ago (skipped some meaningless lines):

59   unsigned short xfer_srio(void)
60    {
61            unsigned short out,in;
77            out=srio1_out | srio2_out;
78            SPI1->DR = out;
79            while (!(SPI1->SR & SPI_I2S_FLAG_TXE));
80            while ((SPI1->SR & SPI_I2S_FLAG_BSY));
81            in = SPI1->DR;
82            SRIO_LATCH_LOW;
83            asm("nop; ");
84            asm("nop; ");
85            asm("nop; ");
86            asm("nop; ");
87            asm("nop; ");
88            SRIO_LATCH_HIGH;
89            SRIO_OE_LOW;
90            srioz_out=out;
97            return in;
98    }

The nops are for creating a slightly longer latch pulse after having shifted the data in and out (some HC595 / HC 597 shift registers are involved here). I haven't touched this code since then and the device is still running. (used a STM32F303 afair). Never had problems using the SPI this way on various STM32F1 and F3 devices.

Using the SPI on a STM32F7 nucleo board (with STM HAL and Cube generated drivers) didn't work out well, these drivers appear to be quite buggy. Better roll your own.

This is the associated SPI init (GPIO init is done elsewhere):
void init_srio()
39    {
40      SPI_InitTypeDef  SPI_InitStructure;
41    
42      RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
43    
44    
45      SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
46      SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
47      SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
48      SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
49      SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
50      SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
51      SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
52      SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
53      SPI_InitStructure.SPI_CRCPolynomial = 7;
54      SPI_Init(SPI1, &SPI_InitStructure);
55      SPI_SSOutputCmd(SPI1, ENABLE);
56      SPI_Cmd(SPI1, ENABLE);
57    }
58    
« Last Edit: March 02, 2017, 07:34:58 am by capt bullshot »
Safety devices hinder evolution
 
The following users thanked this post: aleks_sitno

Offline aleks_sitnoTopic starter

  • Newbie
  • Posts: 2
  • Country: mk
Re: STM32F103C8T6 SPI communication with ADS1220 stops
« Reply #5 on: March 02, 2017, 08:34:43 am »
Thx a lot, it works. I did try the delay thing before and it didn't work, but your approach works and i removed wait for SPI not busy as you suggested. I left the program to run over night, and the SPI didn't stop.
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6580
  • Country: nl
Re: STM32F103C8T6 SPI communication with ADS1220 stops
« Reply #6 on: March 02, 2017, 09:07:45 am »
Hi just a side question:

79            while (!(SPI1->SR & SPI_I2S_FLAG_TXE));
80            while ((SPI1->SR & SPI_I2S_FLAG_BSY));

What kind of contingencies did you take if any of the two flags for any reason will not work, eg the peripheral gets stuck ?
Do you have an RTOS with a timeout arbiter resetting the peripheral or a watchdog resetting the entire uC, or.... ?
 

Offline capt bullshot

  • Super Contributor
  • ***
  • Posts: 3033
  • Country: de
    • Mostly useless stuff, but nice to have: wunderkis.de
Re: STM32F103C8T6 SPI communication with ADS1220 stops
« Reply #7 on: March 02, 2017, 10:08:05 am »
> What kind of contingencies did you take if any of the two flags for any reason will not work, eg the peripheral gets stuck ?
> Do you have an RTOS with a timeout arbiter resetting the peripheral or a watchdog resetting the entire uC, or.... ?

I've used ChibiOS (RTOS), this function is located in a low priority thread - so this thread may get stuck here. In case that happens, the whole uC is reset by either a supervising higher priority thread or lack of triggering the watchdog. I've no means to reset the peripheral alone, in case of anything getting stuck the whole thing simply reboots (and the incident ist logged for later inspection).

Except for some priority / semaphore / mutex issues at the beginning, this thing runs quite stable over more than a year now without a reset.
Safety devices hinder evolution
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6580
  • Country: nl
Re: STM32F103C8T6 SPI communication with ADS1220 stops
« Reply #8 on: March 02, 2017, 01:30:56 pm »
Except for some priority / semaphore / mutex issues at the beginning, this thing runs quite stable over more than a year now without a reset.
Impressive.
 

Offline capt bullshot

  • Super Contributor
  • ***
  • Posts: 3033
  • Country: de
    • Mostly useless stuff, but nice to have: wunderkis.de
Re: STM32F103C8T6 SPI communication with ADS1220 stops
« Reply #9 on: March 02, 2017, 02:45:55 pm »
Except for some priority / semaphore / mutex issues at the beginning, this thing runs quite stable over more than a year now without a reset.
Impressive.

Thanks!

No, not impressive at all. Simply just as expected from an embedded micro in an always on application supplying power to most of my home network boxes ( http://wunderkis.de/pvbat/ ). But quite an amount of effort to get it all up and running.
Safety devices hinder evolution
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4205
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: STM32F103C8T6 SPI communication with ADS1220 stops
« Reply #10 on: March 04, 2017, 02:16:00 pm »
The busy flag does not indicate receive has been completed. It fell for that one too.
The only way to know for sure receive is complete as master is by DMA or IRQ.
So, why not use the DMA RX IRQ?

Then when it's not finished, and you do this:
Code: (c) [Select]
// Write data to be transmitted to the SPI data register
SPIx->DR = data;
// Wait until transmit complete
while (!(SPIx->SR & (SPI_I2S_FLAG_TXE)));
You get an lockup because you're supposed to check if the spi is ready for transmit BEFORE transmitting.

Quote from: RM0008
When BSY is set, it indicates that the SPI is busy communicating. There is one exception in
master mode / bidirectional receive mode (MSTR=1 and BDM=1 and BDOE=0) where the
BSY flag is kept low during reception.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf