Usando SPI para comunicarse entre stm 32 f4 y stm32 f3

0

Quiero usar un bus SPI para transmitir un mensaje entre un descubrimiento STM32F4 y un descubrimiento STM32F3, usando un canal semidúplex. El maestro es F4, el esclavo es F3 y la comunicación es de tipo MOSI. Cuando hago clic en el botón de comando del usuario en F4, envía un mensaje en modo de bloqueo, F3 recibe el mensaje y alterna un led con una interrupción. Cuando F3 no recibe ningún mensaje, en el modo de sondeo alterna otro led cada 500 ms, usando un temporizador SysTick; mientras tanto, muestra el estado del led conmutado por la interrupción. Mi problema es que el mensaje se transmite correctamente, pero el led de interrupción no se alterna. ¿Cuál es el problema? Te muestro mi código ... Código maestro:

#include "main.h"
#include "stm32f4xx_hal.h"

SPI_HandleTypeDef hspi1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);

int main(void)
{


  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();

  /* USER CODE BEGIN 2 */
  char *msg={"Hello"};
  HAL_StatusTypeDef state;
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      /* USER CODE END WHILE */

      if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)){
          while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0));
          HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_RESET);
          switch(state=HAL_SPI_Transmit(&hspi1,(uint8_t*)msg,sizeof(msg),5000)){
          /*Only for debug*/
            case HAL_OK:
                printf("OK!");
              break;
            case HAL_ERROR:
              //hal error
              asm("bkpt 255");
                break;
            case HAL_BUSY:
              //hal error
              asm("bkpt 255");
                break;
            case HAL_TIMEOUT:
                //hal error
                asm("bkpt 255");
                break;
            default:
              asm("bkpt 255");
                break;
          }
      HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_SET);



  /* USER CODE BEGIN 3 */

  }
 /* USER CODE END 3 */

  }
}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Configure the main internal regulator output voltage 
    */
  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

/**Initializes the CPU, AHB and APB busses clocks 
*/
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 96;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks 
*/
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                          |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  /**Configure the Systick interrupt time 
   */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  /**Configure the Systick 
   */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

 /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* SPI1 init function */
static void MX_SPI1_Init(void)
{

  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_1LINE;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

/** Configure pins as 
    * Analog 
    * Input 
    * Output
    * EVENT_OUT
    * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PB2  (CS SPI)*/
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_SET);

}

Código esclavo (la interrupción llega cuando PB2 en el valor de cambio maestro de 1 a 0):

#include "main.h"
#include "stm32f3xx_hal.h"


SPI_HandleTypeDef hspi1;
volatile GPIO_PinState currentstatepin=GPIO_PIN_RESET;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);


int main(void)
{


  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_SPI1_Init();

  while (1)
  {
      HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_11);
      HAL_Delay(500);
      HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,currentstatepin);


  }

}

void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;


  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }


  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* SPI1 init function */
static void MX_SPI1_Init(void)
{

  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_SLAVE;
  hspi1.Init.Direction = SPI_DIRECTION_1LINE;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOE_CLK_ENABLE();


  /*Configure GPIO pin : PB2 */
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : PE9 PE11 */
  GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_11;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI2_TSC_IRQn, 0, 7);
  HAL_NVIC_EnableIRQ(EXTI2_TSC_IRQn);

}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    uint8_t msg;

    if(HAL_SPI_Receive_IT(&hspi1,&msg,sizeof(msg))==HAL_OK){
        HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_9);
        currentstatepin=HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_9);
        }
}
    
pregunta alukard990

2 respuestas

2

Esta parte de tu código:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    uint8_t msg;

    if(HAL_SPI_Receive_IT(&hspi1,&msg,sizeof(msg))==HAL_OK){
        HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_9);
        currentstatepin=HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_9);
        }
}

Representa una completa incomprensión de la recepción SPI controlada por interrupción.

El valor de retorno de HAL_SPI_Receive_IT() no indica si se han recibido datos, pero solo si el motor SPI se puede armar para la recepción (en lugar de estar ocupado, atascado en un estado de error o lo que sea). En el mejor de los casos, el éxito puede indicar que este es el primer intento o que el intento anterior ha finalizado, pero esa es una forma retrasada de hacer las cosas

Los datos reales recibidos (o la falla) se entregarían al HAL_SPI_RxCpltCallback() en el que tendría que registrarse.

Además, deberá averiguar si es posible armar la recepción solo después de recibir el disparador GPIO (que tal vez esté tratando como un software esclavo seleccionado) o si hacerlo puede ser demasiado tarde, si es , o bien necesitará un mayor retraso entre el disparador en el transmisor, o para estar siempre intentando recibir, y desencadenar todo el éxito de la recepción.

En su estado actual, el uso de las interrupciones no está justificado en su código; puede lograr mejor su intento actual de funcionalidad simplemente mediante una encuesta en su ciclo principal.

Sin embargo, si este es un paso inicial hacia una funcionalidad general más complicada, entonces tratar de solucionar la implementación de la interrupción puede tener sentido.

    
respondido por el Chris Stratton
-2

Cambia la prioridad de las interrupciones. Tuvo dos interrupciones ejecutándose en el mismo ISR: 1. Las interrupciones GPIO y la interrupción de recepción SPI. No están sucediendo al mismo tiempo. Es una mala idea utilizar múltiples interrupciones simultáneamente, a menos que sea necesario. Intente una interrupción de recepción SPI y desde allí inicie el temporizador para cambiar el led de su interés.
Aún así, si desea probar la idea que estaba planeando, realice un cambio de prueba en el nivel de prioridad desde STM32CubeMx

    
respondido por el sbz

Lea otras preguntas en las etiquetas