stm32——SPI协议

06-01 1409阅读

stm32——SPI协议


STM32的SPI(Serial Peripheral Interface,串行外设接口)协议是一种高速、全双工、同步的串行通信协议,广泛评估微控制器与各种外设(如传感器、器件、显示器、模块等)之间的数据传输。STM32微控制器内置的SPI外设具有高度可配置性,支持多种操作模式和数据格式。

1. SPI协议概述

  • 主从架构(Master-Slave Architecture):SPI通信采用主从模式。通常有一个主设备(Master)和多个从设备(Slave)。主设备负责发起通信、提供时钟信号,并选择通信的从设备。从设备在被选中时响应主设备的请求。
  • 同步通信(Synchronous Communication):数据传输由一个共享的时钟信号(SCK)同步。主设备产生并控制SCK信号。
  • 全双工(Full-Duplex):SPI支持同时进行数据发送和接收,即发送和接收通道是独立的。

    2. SPI的四根基本信号线

    典型的SPI通信使用四根信号线:

    1. SCK (Serial Clock):串行时钟线。由主设备生成,用于同步主设备和从设备之间的数据传输。
    2. MOSI (Master Out Slave In):主设备输出,从设备输入。主设备通过此线向从设备发送数据。
    3. MISO(Master In Slave Out):主设备输入,从设备输出。从设备通过此线向主设备发送数据。
    4. SS/ CS (Slave Select / Chip Select) :从设备选择/片选线。由主设备控制,用于选择通信的从设备。当SS/CS线为低电平(通常为活动低电平)时,对应的从设备被选中并准备好进行通信;当为高电平时,从设备在非选中状态,其MISO线通常会呈高阻态,允许从其他设备共享MISO线。

    图1:SPI通信基本连接图(单主多从)

                 +---------------------+                 +---------------------+
                 |       Master        |                 |       Slave 1       |
                 |                     |                 |                     |
         SCK  SCK 
      /* MCU Configuration--------------------------------------------------------*/
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init(); // 1. HAL库初始化
      /* Configure the system clock */
      SystemClock_Config(); // 2. 系统时钟配置
      /* Initialize all configured peripherals */
      MX_GPIO_Init();   // 3. GPIO初始化
      MX_SPI1_Init();   // 4. SPI外设初始化
      /* Infinite loop */
      while (1)
      {
        /* Add user code here */
      }
    }
    
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOA_CLK_ENABLE(); // Enable GPIOA clock (assuming SPI1 uses PA5, PA6, PA7)
      __HAL_RCC_GPIOC_CLK_ENABLE(); // Enable GPIOC clock (assuming PC4 for SS/CS)
      /*Configure GPIO pin : PC4 (CS pin) */
      GPIO_InitStruct.Pin = GPIO_PIN_4;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // Output Push-Pull for SS/CS
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // Low speed for SS/CS
      HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
      /*Configure GPIO pins : PA5 (SCK), PA6 (MISO), PA7 (MOSI) */
      GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; // SCK, MISO, MOSI
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // Alternate Function Push-Pull
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // High speed for SPI data
      GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; // Set alternate function to SPI1
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }
    
      /* SPI1 parameter configuration*/
      hspi1.Instance = SPI1; // 选择SPI1外设
      hspi1.Init.Mode = SPI_MODE_MASTER; // 配置为SPI主模式
      hspi1.Init.Direction = SPI_DIRECTION_2LINES; // 双线全双工模式 (MOSI和MISO)
      hspi1.Init.DataSize = SPI_DATASIZE_8BIT; // 数据帧大小为8位
      hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; // 时钟极性:空闲时SCK为低电平 (CPOL=0)
      hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; // 时钟相位:数据在第一个时钟边沿采样 (CPHA=0)
      hspi1.Init.NSS = SPI_NSS_SOFT; // 软件片选管理 (如果使用硬件SS,改为SPI_NSS_HARD_INPUT/OUTPUT)
      hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // 波特率预分频,例如PCLK / 16
      hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; // MSB优先传输
      hspi1.Init.TIMode = SPI_TIMODE_DISABLE; // 禁用TI模式
      hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // 禁用CRC校验
      hspi1.Init.CRCPolynomial = 10; // CRC多项式 (如果CRC开启)
      // 调用HAL库函数进行SPI初始化
      if (HAL_SPI_Init(&hspi1) != HAL_OK)
      {
        Error_Handler(); // 初始化失败,调用错误处理函数
      }
    }
    0x01, 0x02, 0x03};
    uint8_t rxData[3];
    HAL_StatusTypeDef status;
    // 1. 拉低片选信号,选择从设备
    HAL_GPIO_WritePin(SLAVE_CS_PORT, SLAVE_CS_PIN, GPIO_PIN_RESET); // CS low
    // 2. 发送数据 (阻塞模式)
    status = HAL_SPI_Transmit(&hspi1, txData, sizeof(txData), HAL_MAX_DELAY); // 发送3个字节
    if (status != HAL_OK)
    {
        // Handle Error
    }
    // 或者:接收数据 (阻塞模式)
    status = HAL_SPI_Receive(&hspi1, rxData, sizeof(rxData), HAL_MAX_DELAY); // 接收3个字节
    if (status != HAL_OK)
    {
        // Handle Error
    }
    // 或者:发送和接收数据 (阻塞模式)
    status = HAL_SPI_TransmitReceive(&hspi1, txData, rxData, sizeof(txData), HAL_MAX_DELAY); // 同时发送和接收3个字节
    if (status != HAL_OK)
    {
        // Handle Error
    }
    // 3. 拉高片选信号,释放从设备
    HAL_GPIO_WritePin(SLAVE_CS_PORT, SLAVE_CS_PIN, GPIO_PIN_SET); // CS high
    // 4. 等待一段时间或执行其他操作
    HAL_Delay(10); // 例如,等待10ms
    
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码