AnsweredAssumed Answered

STM32F446ZE - no stable SPI communication

Question asked by mar 999 on Sep 5, 2017

Hello,

 

I have a NUCLEO-F446ZE board (wtih STM32F446ZE uC) connected by SPI with STM32VLDISCOVERY board (with STM32F100RBT6B uC). STM32F446ZE is configured as a slave. STM32F446ZE receives commands from STM32F100RBT6B and controls the DC motor by PWM (using LMD18200 bridge). It is connected in that way:

To test the program SPI Master sends 0, waits ~1 second, sends 1, waits ~1 second, sends 0 and so on (in while loop).

When SPI Slave receives 0, it turns on LED1 and stops the motor.

When SPI Slave receives 1, it turns on LED2 and starts the motor.

 

Everything is working perfectly if LMD18200 is not connected to power supply. Then SPI Slave always receive 0 or 1.

When power supply is connected to the LMD18200, then after several SPI transactions, Slave receives incorrect data (e.g. 0x80, 0xC0 or other), motor stops and never starts again. When I reset Slave microcontroller, it is ok, but again only for few transactions.

 

I have connected logic analyzer and the SPI signal looks ok. Here is an example of correct operation:

When Slave receives 1, it starts generating PWM signal. I can also see that in next transaction SPI receives 0 and stops generating PWM signal.

However, after few transactions I can see on logic analyzer that 0 has been sent, but PWM signal is still generated. 

After that, I can see incorrect data is received.

 

Could you check if everything is internalized correctly? Here is the code:

#include "stm32f4xx.h"

void spi_init(void)
{
   GPIO_InitTypeDef GPIO_InitStruct;
   SPI_InitTypeDef SPI_InitStruct;

   // enable peripheral clock
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI4, ENABLE);
   // enable clock for used IO pins
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

   /* configure pins used by SPI3
   * PE12 = SCK
   * PE14 = MOSI
   * PD0 = MISO
   */
   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_14;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
   GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_Init(GPIOE, &GPIO_InitStruct);

   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
   GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_Init(GPIOD, &GPIO_InitStruct);

   // connect SPI4 pins to SPI alternate function
   GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_SPI4);
   GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_SPI4);
   GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_SPI4);

   SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
   SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;
   SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
   SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
   SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
   SPI_InitStruct.SPI_NSS = SPI_NSS_Hard;
   SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
   SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
   SPI_Init(SPI4, &SPI_InitStruct);

   SPI_Cmd(SPI4, ENABLE); // enable SPI4
}

void pwm_out_init(void)
{
   GPIO_InitTypeDef GPIO_InitStruct;
   TIM_TimeBaseInitTypeDef TIM_InitStruct;
   TIM_OCInitTypeDef TIM_OCInitStruct = {0};

   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

   // PE9 - PWM
   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
   GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_Init(GPIOE, &GPIO_InitStruct);
   // connect PE9 pin to TIM1 alternate function
   GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_TIM1);

   // PE2 - DIR
   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
   GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
   GPIO_Init(GPIOE, &GPIO_InitStruct);
   GPIO_ResetBits(GPIOE, GPIO_Pin_2);

   // Initialize TIMER 1
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
   TIM_InitStruct.TIM_Prescaler = 2;
   TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV4;
   TIM_InitStruct.TIM_Period = 60000;
   TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
   TIM_InitStruct.TIM_RepetitionCounter = 0;
   TIM_TimeBaseInit(TIM1, &TIM_InitStruct);
   TIM_Cmd(TIM1, ENABLE);

   // Configure 1. output of TIMER 1 as PWM
   TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
   TIM_OCInitStruct.TIM_Pulse = 0;
   TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
   TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;

   TIM_OC1Init(TIM1, &TIM_OCInitStruct);
   TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
   TIM_CtrlPWMOutputs(TIM1, ENABLE);
}

int main(void)
{
   unsigned char byte = 0;
   GPIO_InitTypeDef GPIO_InitStruct;

   SystemInit();

   // Initialize three LEDs
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_7 | GPIO_Pin_14;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
   GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_Init(GPIOB, &GPIO_InitStruct);
   GPIO_ResetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_7 | GPIO_Pin_14);

   spi_init();
   pwm_out_init();

   while(1) {
      // Receive byte from SPI4
      while (!(SPI4->SR & SPI_I2S_FLAG_RXNE));
      byte = ((SPI4->DR) & 0x00FF);

      if (byte == 0) {
         // Turn on first LED and turn off motor
         GPIO_SetBits(GPIOB, GPIO_Pin_0);
         GPIO_ResetBits(GPIOB, GPIO_Pin_7);
         TIM1->CCR1 = 0;
      } else if (byte == 1) {
         // Turn on second LED and turn on motor
         GPIO_SetBits(GPIOB, GPIO_Pin_7);
         GPIO_ResetBits(GPIOB, GPIO_Pin_0);
         TIM1->CCR1 = 40000;
      } else {
         // Turn on third LED
         GPIO_SetBits(GPIOB, GPIO_Pin_14);
      }
   }
}

Thanks.

Outcomes