Netduino home hardware projects downloads community

Jump to content


Photo

STM8S and SPI to Mini - Help Request


  • Please log in to reply
31 replies to this topic

#1 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1070 posts
  • LocationNorth Yorkshire, UK

Posted 11 May 2012 - 08:53 PM

I've been looking at SPI communication between a Netduino Mini and an STM8S and I'm having some problems getting the two to understand each other. I think it's just a matter of getting the comms settings to match but I'm having no joy. I'm hoping someone can see what I'm doing wrong.

So let's start with the Netduino Mini. It's not really doing much other than writing three bytes out, waiting a second and then repeating. Here is the code:


SPI.Configuration config = new SPI.Configuration(SPI_mod: SPI.SPI_module.SPI1,
					       ChipSelect_Port: Pins.GPIO_PIN_5,
					       ChipSelect_ActiveState: false,
					       ChipSelect_SetupTime: 0,
					       ChipSelect_HoldTime: 0,
					       Clock_IdleState: false,
					       Clock_Edge: false,
					       Clock_RateKHz: 500);

SPI spi = new SPI(config);

byte[] buffer = new byte[] { 1, 2, 3 };
while (true)
{
	spi.Write(buffer);
	Thread.Sleep(1000);
}

I've hooked up the logic analyser and I appear to be getting the bytes output as expected with a clock of 500 KHz.

So on to the STM8S. For this I'm using the STD Peripheral driver and have used some of the code from ByteMaster's posting on SPI. I'm trying to use interrupts to process the data on the SPI bus.

So firstly the clock. I have reset the clock on the STM8S to use the internal 16 MHz clock. Here's the code:


CLK_DeInit();
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);                // CPU Prescaler = 1.
CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);                // Prescaler = 1, 16 MHz.
CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO,              // Automatically switch
				  	CLK_SOURCE_HSI,               	// Switch to iternal timer.
				  	DISABLE,                          // Disable the clock switch interrupt.
				  	CLK_CURRENTCLOCKSTATE_DISABLE);   // Disable the previous clock.

Next thing is to setup the SPI interface. Here I follow Bytemaster's posting with some changes for speed etc. So I have the following code to setup the SPI bus:


SPI_DeInit();
SPI_Init(SPI_FIRSTBIT_MSB,                      // MSB first.
	     SPI_BAUDRATEPRESCALER_32,              // SPI frequency = clock / 32 (i.e. 500 KHz).
	     SPI_MODE_SLAVE,                        // SPI Slave
	     SPI_CLOCKPOLARITY_LOW,             	// Clock is high when the bus is idle.
	     SPI_CLOCKPHASE_1EDGE,                  // First clock edge clocks the first data bit.
	     SPI_DATADIRECTION_2LINES_FULLDUPLEX,   // Full duplex transmission.
	     SPI_NSS_HARD,                          // Disable slave management by software.
	     0x07);                             	// CRC style.
SPI_ITConfig(SPI_IT_RXNE, ENABLE);              // Interrupt when Rx buffer is not empty.
SPI_Cmd(ENABLE);

I have an interrupt routine set up and have set a breakpoint on the first line. Running the code on both systems (Mini and STM8S) results in nothing.

Just to check that the interrupt is actually set up I change the SPI_IT_RXNE to SPI_IT_TXE (i.e. Rx not empty to Tx Empty). If I run the code now the interrupt fires OK. So the interrupts look to be set up and working.

I've double checked the wiring and I think this is also OK. I have the following:

Mini MOSI -> STM8S MOSI
Mini MISO -> STM8S MISO
Mini SPCK -> STM8S CLK
Mini D65 -> STM8S SPI_NSS

Anyone have any ideas as to where I can go next?

Regards,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#2 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 11 May 2012 - 10:54 PM

Hi Nevyn! As you know, the Netduino can act as an SPI master only and so it could be you should wire this thing the opposite way around, that is: Mini mosi -> stm miso Mini miso -> stm mosi Make sure you've configured the STM for slave mode and remember that the mini is the one responsible for generating the clock and chip select signals. Hopefully this helps!

#3 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1070 posts
  • LocationNorth Yorkshire, UK

Posted 12 May 2012 - 05:12 AM

As you know, the Netduino can act as an SPI master only and so it could be you should wire this thing the opposite way around, that is:

Mini mosi -> stm miso
Mini miso -> stm mosi

Make sure you've configured the STM for slave mode and remember that the mini is the one responsible for generating the clock and chip select signals.

I did wonder about changing the wiring so I ended up checking WikIpedia for their description of SPI and their diagrams have MOSI -> MOSI and MISO -> MISO.

In terms of clock etc, the logic analyser is showing me the data I am expected so the Mini appears to be doing the job of putting the data out on the bus OK, so clock and data are all there.

Regards,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#4 Fred

Fred

    Advanced Member

  • Members
  • PipPipPip
  • 302 posts
  • LocationUK

Posted 12 May 2012 - 07:07 AM

Have you tried SPI out on the STM8? I know that's not what you're trying to do, but might help find a bug in your SPI setup.

#5 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 12 May 2012 - 07:28 AM

In terms of clock etc, the logic analyser is showing me the data I am expected so the Mini appears to be doing the job of putting the data out on the bus OK, so clock and data are all there.

It could be the data line is sampled at the wrong moment in time, have you tried different clock-edges, setup-times, etc?

EDIT: I find it a bit strange that you need to set the speed on the STM side aswell, isn't there supposed to be some autobaud scheme instead? I mean since the mini is driving the bus, the STM should adapt to the bus clock which it generally knows little or nothing about.

Also maybe its just the interrupt routine that doest get triggered and the data bytes are actually received ok?

#6 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 12 May 2012 - 09:14 AM

...Running the code on both systems (Mini and STM8S) results in nothing.

Just to check that the interrupt is actually set up I change the SPI_IT_RXNE to SPI_IT_TXE (i.e. Rx not empty to Tx Empty). If I run the code now the interrupt fires OK. So the interrupts look to be set up and working.

So, what exactly does not work then? Could you show the rest of STM8S code? What STM8S do you have and what SPI_NSS pin did you use (if there is more than one, i.e. alternate function)?

Also please note that SPI slave has to fill the data register before the communication begins, this is the byte getting clocked out during the reception of the first byte from the master. Otherwise, you'd have to ignore this byte from processing on the master.

You could also lower the SPI clock speed and then you can use UART for diagnostic output.

#7 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 12 May 2012 - 09:25 AM

EDIT: I find it a bit strange that you need to set the speed on the STM side aswell, isn't there supposed to be some autobaud scheme instead?

SPI clock speed setting is ignored in slave mode; and SPI does not support clock stretching (unlike I2C). It is the responsibility of the master to ensure the correct speed, with regard to slave limitations (i.e. ~ 7MHz for STM8S, which does not account for any code processing the data - it has about 4 SPI clock cycles between TXE and RXNE flags to read, handle and transmit the data).

#8 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1070 posts
  • LocationNorth Yorkshire, UK

Posted 12 May 2012 - 10:02 AM

So, what exactly does not work then?

Unless I have misunderstood the set up, I am expecting that the Mini will put a byte out on the SPI bus. The STM8S will read the byte into the data register and then generate an interrupt.

I am not seeing any interrupts generated for receiving the data.

Could you show the rest of STM8S code?

I have attached the project for the STM8S - there's not a lot of it.

What STM8S do you have and what SPI_NSS pin did you use (if there is more than one, i.e. alternate function)?


I am using the STM8S103F3P6 and I used SPI_NSS is connected to pin 10 - hmmmm, this is also Tim2_CH3 and I'm using timer 2 - will this interfere with the SPI_NSS signal?


Also please note that SPI slave has to fill the data register before the communication begins, this is the byte getting clocked out during the reception of the first byte from the master. Otherwise, you'd have to ignore this byte from processing on the master.

I have tried adding a SPI_SendData(0) after I enable the interrupts and I still have no luck.


Thanks to all for taking the time to look at this and make suggestions,
Mark

Attached Files


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#9 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1070 posts
  • LocationNorth Yorkshire, UK

Posted 12 May 2012 - 10:04 AM

It could be the data line is sampled at the wrong moment in time, have you tried different clock-edges, setup-times, etc?

I've tried a few different setup. I've ended up feeding the RGB LED module assembly to ILSpy to have a look what settings it is using to try and replicate the GO!'s bus settings.

Regards,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#10 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 12 May 2012 - 10:49 AM

I am using the STM8S103F3P6 and I used SPI_NSS is connected to pin 10 - hmmmm, this is also Tim2_CH3 and I'm using timer 2 - will this interfere with the SPI_NSS signal?

Yep - in this package, SPI_NSS is alternate function of PA3 and has to be enabled by programming AFR1 in option byte (see How to set STM8S alternate function remapping option (AFRx)). Until then hardware slave select does not work.

#11 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1070 posts
  • LocationNorth Yorkshire, UK

Posted 12 May 2012 - 10:49 AM

Have you tried SPI out on the STM8? I know that's not what you're trying to do, but might help find a bug in your SPI setup.

I changed the SPI_Init statement to make the STM8S a master (i.e. SPI_MODE_SLAVE changed to SPI_MODE_MASTER) and also added some statements into the code to send some data. So I immediately send a 0x00 byte. The interrupt handler writes a 0x01 byte every time it is called. So I think this will:

1 - send the 0 byte
2 - the buffer will empty and the interrupt will be called
3 - the interrupt routine will queue to 0x01 byte
4 - the buffer will empty and the interrupt will be called and we go back to step 3.

I downloaded this program to the chip and hooked up the LA and that is what appears to be happening.

Only one odd thing - this is not changing SPI_NSS at all. This signal is permanently high

Regards,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#12 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 12 May 2012 - 10:51 AM

Hi Nevyn,

The wiring of MISO -> MISO and MOSI -> MOSI is correct. MISO means "master input, slave output" and MOSI means "master output, slave input" so the sides should always be matched. Unlike UARTs, where RX goes to TX both ways.

If you're using SPI_SS on your STM8S device, you need to make sure of two things:
  • If you're letting the MCU auto-detect SPI_SS, make sure you're using it in "hard(ware) select" mode instead of "soft(ware) select" mode.
  • Make sure that you're using the proper "alternate function" that SPI_SS needs. This setting is usually set with the fuses in the third tab of the ST Visual Programmer.

Chris

#13 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 12 May 2012 - 11:04 AM

Thanks to all for taking the time to look at this and make suggestions,

One suggestion: In the SPI interrupt handler, manipulate the data register only when the respective flag is set. In simple words

// Pseudo-code
if(TXE is set) SPI_SendData(...);
if(RXNE is set) SPI_ReceiveData(...);
The reason is because SPI_DR access reset the flags: the TXE flag is reset when writing the SPI_DR register, the RXNE flag is reset when SPI_DR is read.

#14 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1070 posts
  • LocationNorth Yorkshire, UK

Posted 12 May 2012 - 11:26 AM

Yep - in this package, SPI_NSS is alternate function of PA3 and has to be enabled by programming AFR1 in option byte (see How to set STM8S alternate function remapping option (AFRx)). Until then hardware slave select does not work.


If you're using SPI_SS on your STM8S device, you need to make sure of two things:

  • If you're letting the MCU auto-detect SPI_SS, make sure you're using it in "hard(ware) select" mode instead of "soft(ware) select" mode.
  • Make sure that you're using the proper "alternate function" that SPI_SS needs. This setting is usually set with the fuses in the third tab of the ST Visual Programmer.

Spot on - I'm now getting the interrupts fired. I've taken the advice of checking the status flags on board before sending/receiving data.

Now all I have to do is find out why I appear to be receiving corrupted data.

Thanks all for the help so far,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#15 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 12 May 2012 - 12:05 PM

Now all I have to do is find out why I appear to be receiving corrupted data.

If that happens while debugging (i.e. the first byte is transmitted and received correctly), then you'd have to read/write data from/to buffers from within the SPI interrupt handler and debug the main loop, e.g. when a certain number of bytes is received or transmitted. Otherwise, you have SPI settings wrong (clock phase, polarity) Posted Image

#16 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 12 May 2012 - 12:07 PM

Sorry for the dumb question, but sometime the problem relies on the plug disconnected from the mains. Is the STM8 powered at +3.3V as the Netduino? It accepts a pretty wide range of supplies, but I'd try at the same voltage as the Netduno first. Cheers
Biggest fault of Netduino? It runs by electricity.

#17 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1070 posts
  • LocationNorth Yorkshire, UK

Posted 12 May 2012 - 01:27 PM

Sorry for the dumb question, but sometime the problem relies on the plug disconnected from the mains.
Is the STM8 powered at +3.3V as the Netduino? It accepts a pretty wide range of supplies, but I'd try at the same voltage as the Netduno first.

Everything is good with power - the Mini has power from the FTDI cable and the STM8S has 3.3V power from a breadboard supply.

And for those who are interested, the difference in power supply voltages is to make sure that the STM8S recognises the 3.3V high signal from the Mini. And they are both sharing a common ground.

Regards,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#18 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1070 posts
  • LocationNorth Yorkshire, UK

Posted 12 May 2012 - 01:32 PM

If that happens while debugging (i.e. the first byte is transmitted and received correctly), then you'd have to read/write data from/to buffers from within the SPI interrupt handler and debug the main loop, e.g. when a certain number of bytes is received or transmitted. Otherwise, you have SPI settings wrong (clock phase, polarity) Posted Image

I think it's the later and that's where I intended starting.

Regards,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#19 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 12 May 2012 - 02:19 PM

Mark, what kind of circuit are you using? Any eval board? Also which kind of toolchain? I'm just bumping my head against the wall (due the C and the STM8L discovery)... I'll share my depression with you sooner!
Biggest fault of Netduino? It runs by electricity.

#20 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1070 posts
  • LocationNorth Yorkshire, UK

Posted 12 May 2012 - 05:28 PM

Mark, what kind of circuit are you using? Any eval board?
Also which kind of toolchain?

I'm just bumping my head against the wall (due the C and the STM8L discovery)...
I'll share my depression with you sooner!

I am currently using the STM8S103F3P6 which I have mounted on a DIP adapter so that I can plug it into my breadboard. For final testing I use the STM8S003F3 which again I have in a DIP adapter. I use two different chips because the STM8S103F3P6 can be programmed 10,000 times whilst the STM8S003F3 can only be programmed 100 times.

I start out developing with the STM8S Discovery and then move to 103 when I need to move to breadboard. I have not had any problems with that Discovery board - it just plugs in and works.

I also have the ST-LINK/V2 for programming the chips when they are on breadboard. I found that no additional adapter is required if working on breadboard.

I have tried a couple of development environments, namely ST's own IDE and IAR. I am much preferring IAR and work with this all the time at the moment. You are restricted to 32 KBytes of program but I will be shocked if I get to a program that is that large. The IAR environment keeps surprising me - I found out today you can display the register values when at a breakpoint - useful.

I have also been using the STD Peripheral Library released by ST as the method of accessing the functions on the chip. I am doing this as I find they make the programs I am writing a little less opaque. There is a price for that though, the programs are larger and slower. Larger because you have to compile and link in ST's libraries and slower because of the overhead of parameter checking and function calls. I deviate from this when working on an Interrupt Service Routine as I need these to be fast and so here I access the chips registers more directly - it's a compromise.

I have produced a couple of posts on the exploits so far - there's nothing ground breaking but hoping it will help:

Connecting to the STM8S003
Some first step to module development

if nothing else they will act as memory aids for myself.

I also have the STM32F4 Discovery board and that works well too. For that board I have the Atollic development environment. I have not used this much.

Hope this helps,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.