STM32基于CubeMX与HAL库的SPI应用

1.SPI协议

SPI(Serial Peripheral interface)串行外围设备接口,是同步全双工的通信总线,在芯片的管脚上最多只占用根线。

1.1 物理层

SPI接口是Motorola 首先提出的全双工三线/四线同步串行外围接口,采用主从模式(Master Slave)架构。时钟由Master控制,在时钟移位脉冲下,数据按位传输,高位在前,低位在后(MSB first);SPI接口有2根单向数据线,为全双工通信。 SPI总线被广泛地使用在FLASH、ADC、LCD等设备与MCU间,要求通讯速率较高的场合。

SS/NSS/CS:从设备选择信号线(片选信号线)。由主设备控制,选择指定的从设备。

当主机要选择从设备时,把该从设备的SS信号线设置为低电平,该从设备即被选中,即片选有效,接着主机开始与被选中的从设备进行SPI通讯。所以SPI通讯以SS线置低电平为开始信号,以SS线被拉高作为结束信号。 

SCK (Serial Clock):时钟信号线。用于通讯数据同步,只能由主设备产生,两个设备之间通讯时,通讯速率受限于低速设备

MOSI(Master Output, Slave Input):主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。

MISO(Master Input, Slave Output):主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。

1.2 协议

在时钟信号控制下,主机将要发送的数据写到数据缓存区(Memory),缓存区经过8位移位寄存器,移位寄存器通过MOSI信号线将数据一位一位的移到从机,从机将MISO接口收到的数据经过移位寄存器一位一位的移到数据缓存区(Memory)。同时从机也将自己移位寄存器数据通过MOSI发送给主机,两个移位寄存器数据完成交互,读写同时进行。

因此,SPI读写操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;若主机要读取从机的一个字节,就必须发送一个空字节引发从机传输。

1.2.1 时钟极性与相位极性 

1.2.1 时钟极性与时钟相位(对应着SPI的4个模式)

  • 时钟极性CPOL:指SPI通讯设备处于空闲状态时,SCK信号线的电平信号(即SPI通讯开始前、 CS片选线为高电平时SCK的状态)。

                CPOL = 0:SCK在空闲状态时为低电平
                CPOL = 1 :SCK在空闲状态时为高电平

  • 时钟相位CPHA:指数据的采样的时刻

                CPHA = 0:MOSI/MISO数据线上的信号将会在SCK时钟线的“奇数边沿”被采样(第一个跳变沿开始)
                CPHA = 1:MOSI/MISO数据线上的信号将会在SCK时钟线的“偶数边沿”被采样(第二个跳变沿开始)

模式CPOLCPHACLK空闲采样时刻
000低电平第一个边沿(奇)
101低电平第二个边沿(偶)
210高电平第一个边沿(奇)
311高电平第二个边沿(偶)

CPOLCPHA的不同状态,SPI分成了四种模式,主机与从机必须工作在相同的模式下才可以正常通讯,实际中采用较多的是“模式0”与“模式3”。

2.CubeMx初始化

 

2.1 硬件设置

2.1.1 模式配置
  • 全双工主机/从机模式
  • 办双工主机/从机模式
  • 只接收主机/从机模式
  • 只发送主机/从机模式

2.1.2 硬件NSS信号
  • 不使能
  • NSS输入信号
  • NSS输出信号
2.1.3 基本参数
  • Frame Format帧格式:Motorola摩托罗拉 或 TI
  • Data size数据大小:8位 或 16位
  • First Bit:MSB/LSB先行
2.1.4 时钟参数
  • 波特率分配因子:总线频率/分频比 = SPI波特率
2.1.5 极性配置
  • CPOL时钟极性:low or high
  • CPHA时钟相位:1 edge or 2 edge

2.1.6 高级参数
  • CRC循环校验:使能/失能
  • NSS信号类型:软件

3 MX SPI库函数 

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;     //8位数据宽度
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;   // CPOL=0, CLK极性为低电平
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;       // CPHA=0, CLK相位为第一个边沿采样
  hspi1.Init.NSS = SPI_NSS_SOFT;               //软件片选信号
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; //分频比256 波特率=总线频率/256
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;      //最高位在前
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;      // 不使用TI模式
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; //不使用CRC校验
  hspi1.Init.CRCPolynomial = 7;                //CRC多项式为7
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }

}

发送,接收,发送接收函数

HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout);

如果需要用到中断或者DMA,则使用相应的函数即可

结束,由于作者水平有限,欢迎读者指正。

HAL SpiTransmit 函数通常用于STM32Cube库中,用于在硬件抽象层(Hardware Abstraction Layer)级别发送数据到串行外围接口(Serial Peripheral Interface,SPI)。下面是一个简单的示例,展示如何使用 HAL SPI API 来写入SPI Flash: ```c #include "stm32f4xx_hal.h" #include "stm32f4xx_spi.h" // 假设SPIx是你的SPI外设编号,Flash_CS是Flash芯片的片选信号 GPIO_TypeDef* GPIOx = GPIOA; __IO uint16_t Flash_CS; // SPI_HandleTypeDef实例初始化 SPI_HandleTypeDef SpiHandle; void SpiFlashWrite(uint8_t *data, uint16_t length) { // 初始化GPIO HAL_GPIO_WritePin(GPIOx, Flash_CS, GPIO_PIN_SET); // 高电平拉选Flash HAL_Delay(10); // 可能需要等待时间让CS有效 // 初始化SPI Handle SpiHandle.Instance = SPIx; SpiHandle.Init.Mode = SPI_MODE_Master; // 主模式 SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; // 全双工 SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; SpiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH; SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; SpiHandle.Init.CRCPolynomial = 7; // 如果你的Flash支持CRC校验 HAL Spi_Init(&SpiHandle); // 开始传输 while (length > 0) { uint16_t tx_length = MIN(length, SPI_MAX Burst Length); HAL Spi_Transmit(&SpiHandle, data, tx_length, 100); // 设置超时时间 data += tx_length; length -= tx_length; } // 数据传输完成后,释放资源并拉低CS HAL_Delay(10); HAL_GPIO_WritePin(GPIOx, Flash_CS, GPIO_PIN_RESET); // 低电平释放Flash HAL_SPI_DeInit(&SpiHandle); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工匠Sola

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值