SPI1 funktioniert nicht

Ich arbeite an einem einfachen Projekt. Ich möchte eine Zeichenfolge senden. die Zeichenfolge ist "Rohalamin". Die zweite Platine nach Erhalt der Saite sollte die LED einschalten.

Das Programm für das erste Board ist (die MCU für dieses Board ist STM32F030F4):

/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_hal.h"

/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

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

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

  /* System interrupt init*/
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

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

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

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

  }
  /* USER CODE END 3 */

}

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

  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  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.PLLMUL = RCC_PLL_MUL6;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);

  __SYSCFG_CLK_ENABLE();

}

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

  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLED;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
  HAL_SPI_Init(&hspi1);

}

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

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __GPIOF_CLK_ENABLE();
  __GPIOA_CLK_ENABLE();

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

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

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif

die stm32f0xx_it.hDatei zur Behandlung von Interrupts:

/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_hal.h"
#include "stm32f0xx.h"
#include "stm32f0xx_it.h"

/* External variables --------------------------------------------------------*/

extern SPI_HandleTypeDef hspi1;

uint8_t aTxBuffer[] = "Rohalamin";

/******************************************************************************/
/*            Cortex-M4 Processor Interruption and Exception Handlers         */ 
/******************************************************************************/

/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
  HAL_IncTick();
  HAL_SYSTICK_IRQHandler();
}

/**
* @brief This function handles SPI1 global interrupt.
*/
void SPI1_IRQHandler(void)
{
  HAL_NVIC_ClearPendingIRQ(SPI1_IRQn);
  HAL_SPI_IRQHandler(&hspi1);
}

/**
* @brief This function handles EXTI Line 0 and Line 1 interrupts.
*/
void EXTI0_1_IRQHandler(void)
{
  HAL_NVIC_ClearPendingIRQ(EXTI0_1_IRQn);
  HAL_SPI_Transmit_IT( &hspi1 , (uint8_t*)aTxBuffer , 10 );
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
} 

Und jetzt das Programm für das zweite Board (die MCU für dieses Board ist STM32F103RET6):

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include <string.h>

/* Private macro -------------------------------------------------------------*/

#define RxBufferSize   0x20

/* Private variables ---------------------------------------------------------*/

char RxBuffer[RxBufferSize];
uint8_t NbrOfDataToRead = RxBufferSize;
uint16_t RxCounter = 0;
char aTxBuffer[0x20] = "Rohalamin";

/* Private functions ---------------------------------------------------------*/

RCC_ClocksTypeDef RCC_ClockFreq;
ErrorStatus HSEStartUpStatus;
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

void SetSysClockTo72(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void _SPI1(void);

/*******************************************************************************
* Function Name  : main
* Description    : Main Programme
* Input          : None
* Output         : None
* Return         : None
* Attention      : None
*******************************************************************************/


int main(void)
{
    SetSysClockTo72();
    GPIO_Configuration();
    _SPI1();
    NVIC_Configuration();

    SPI_I2S_ITConfig( SPI1 , SPI_I2S_IT_RXNE , ENABLE );

    SPI_Cmd( SPI1 , ENABLE );

    /* Infinite loop */
    while (1)
        {
            if( strcmp(RxBuffer , aTxBuffer) == 0 )
            {
                GPIOB->ODR ^= GPIO_Pin_0;

            }

        }
}



/**
  * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2 
  *         and PCLK1 prescalers. 
  * @param  None
  * @retval None
  */
void SetSysClockTo72(void)
{
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------------*/   
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if (HSEStartUpStatus == SUCCESS)
  {
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 

    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1); 

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* PLLCLK = 8MHz * 6 = 48 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6);

    /* Enable PLL */ 
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }
}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configure GPIO Pin
* Input          : None
* Output         : None
* Return         : None
* Attention      : None
*******************************************************************************/

void GPIO_Configuration(void)
{
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE);                        
/**
 *  LED1 -> PB0
 */                  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
  GPIO_Init( GPIOB , &GPIO_InitStructure );

    /**
 *  NSS -> PA4
        SCK -> PA5
        MISO -> PA6
        MOSI -> PA7
 */
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA , ENABLE );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init( GPIOA , &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init( GPIOA , &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init( GPIOA , &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init( GPIOA , &GPIO_InitStructure );


}

void _SPI1(void)
{   
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1 , ENABLE );

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;

    SPI_Init( SPI1 , &SPI_InitStructure );

}


void NVIC_Configuration(void)
{
  /* Enable and configure SPI1 global IRQ channel */
  NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;    
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;      
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure); 

    /* Enable and configure RCC global IRQ channel */
  NVIC_InitStructure.NVIC_IRQChannel = RCC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

}

/******************************************************************************/
/*            STM32F10x Peripherals Interrupt Handlers                        */
/******************************************************************************/

/**
  * @brief  This function handles SPI1 global interrupt request.
  * @param  None
  * @retval None
  */
void SPI1_IRQHandler(void)
{
  if(SPI_I2S_GetITStatus( SPI1 , SPI_I2S_FLAG_RXNE ) != RESET)
  {
    /* Read one byte from the receive data register */
    RxBuffer[RxCounter++] = (SPI_I2S_ReceiveData(SPI1) & 0x7F);

    if(RxCounter == NbrOfDataToRead)
    {
      /* Disable the SPI1 Receive interrupt */
      SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, DISABLE);
    }
  }
}


#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

mehrere Bilder von meinem Projekt:

Bild1

Bild2

Bild3

die Schaltung funktioniert nicht. Ich weiß nicht warum! Meine Saleae-Logik zeigt mir Folgendes:

Figur 4

Was ist das Problem?

Bearbeiten : Ich habe die Codes geändert und jetzt funktionieren sie besser! Das erste Problem war, dass ich vergessen habe, den NSS-Pin hoch und niedrig zu setzen. Ich habe den Code geändert und jetzt funktioniert es besser als zuvor. Wie Sie in Saleae sehen können, sind die Daten seltsam (mit anderen Worten, es ist nicht "Rohalamin").

Nach einem kurzen Blick auf Ihren Code habe ich keine Zuordnungen von SPI-Pins zu SPI-Alternativfunktionen gefunden

Antworten (2)

Die GPIO-Pins, die Sie für die SPI-Kommunikation verwenden, sollten der alternativen SPI-Funktion zugewiesen werden. Der folgende Code weist beispielsweise Pin5 von PORTA SPI AF zu:

GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);

Die gleiche Zuordnung muss für alle verwendeten SPI-Pins vorgenommen werden (MISO, MOSI, SCK, NSS)

Ich konnte eine solche Funktion in der HAL-Bibliothek beider MCUs nicht finden. Beachten Sie, dass die HAL-Bibliothek von MCUs nicht dieselbe ist (Cortex-M-Serie von STM32). dann ist deine Antwort falsch.
Welche Bibliothek meinst du? Verwenden Sie eine Bibliothek von ST? Ich habe gerade STM32F0 Standard Peripheral Library von ST überprüft und es enthält function GPIO_PinAFConfig.
Tatsächlich verwende ich STM32CubeMX (es ist ein kostenloses Programm von ST zum Konfigurieren Ihrer MCUs) und es verwendet das STM32Cube_FW_F0_V1.0.0, das die HAL-Bibliothek V1.0.1 von ST für sich selbst enthält. Ich habe den GPIO-Header und die Quelldatei überprüft, um diese API zu finden, aber ich konnte sie nicht finden. Ich bezweifle völlig, dass es die von Ihnen erwähnte Funktion benötigt. Außerdem habe ich diese API in STM32F0xx_StdPeriph_Lib_V1.3.1 gefunden
Wenn Sie die GPIO-Pins nicht richtig konfigurieren, funktioniert Ihr SPI überhaupt nicht , es sei denn, es wird irgendwie von HAL erledigt. Weitere Einzelheiten finden Sie auf Seite 27 des Datenblatts Ihres uC. Die Funktion, die ich erwähnt habe, finden Sie hier . Ich kenne CubeMX, habe aber nie damit gearbeitet. Soweit ich weiß, verwendet es die gleiche StdPeriphLibrary von ST.
Übrigens hat ST viele SPI-Beispiele und Sie können sich den Quellcode und die GPIO-Initialisierungsroutine ansehen.
Ich habe ein Programm für UART geschrieben und es gab keine solche API, und das funktioniert gut. Ich denke, die HAL-Bibliothek konfiguriert die GPIOs automatisch ...

Laut Ihrem Logikanalysator erhalten Sie eine gewisse Datenübertragung, sodass Sie nicht zu weit davon entfernt sein können. Angenommen, es handelt sich nicht nur um einen einfachen Verdrahtungsfehler, sondern wahrscheinlich um die Buskonfiguration.

SPI hat verschiedene Konfigurationsoptionen – ob die Daten an der steigenden oder fallenden Flanke des Takts gesendet werden und wo im Taktzyklus sie abgetastet werden sollen. Stellen Sie sicher, dass das, was Sie auf Ihrem Mikrocontroller konfiguriert haben, mit dem übereinstimmt, was das Slave-Gerät erwartet. Siehe Datenblatt für das Slave-Gerät und "Modusnummern" hier , um die richtigen auszuwählen CLKPPolarityund CLKPhase. Stellen Sie außerdem sicher, dass die von Ihnen gewählte Taktrate nicht höher ist, als der Slave unterstützen kann.

Sie müssen sicherstellen, dass auch die Logikanalysator-Software auf die gleiche Weise konfiguriert ist, indem Sie rechts auf das kleine Zahnradsymbol klicken. Nur für den Fall, dass Sie es nicht wissen: Der Logikanalysator beginnt möglicherweise mitten in einem Byte mit der Erfassung, sodass Sie ihm möglicherweise mitteilen müssen, wo ein Byte beginnt. Klicken Sie dazu rechts auf das unterstrichene „T1“ und dann auf den Anfang eines Bytes in der Grafik.

Danke für die Hilfe, ich habe die Frage geändert, weil ich das erste Problem gefunden habe. schau dir die frage nochmal an.