[STM32F0] 如何在F0上通过LL(低层)配置SPI

[复制链接]
218|4
jerry尧 发表于 2025-10-13 23:17 | 显示全部楼层 |阅读模式
用CubeIDE为F0构建了一个项目。项目构建成功,但在执行MX_SPI2_Init();命令之后,我们还需要发出命令 ->LL_SPI_Enable(SPI2);才能启动SPI。
但SPI_CLK在LL_SPI_Enable(SPI2);之后就开始运行,即使没有接收或传输命令。注释掉了adc_raw8 = LL_SPI_ReceiveData8(SPI2);

而SPI_CLK仍然像之前运行。如果我在所有操作之前发出片选命令,LL_SPI_EnableNSSPulseMgt(SPI2);在时钟计数之间,SPI的机器会插入一个100毫秒的空隙。

有没有人有可用的低层SPI示例,最好是“仅接收”的例子。甚至可以是“仅发送”的例子。

在同一个MCU板上,HAL_Receive命令仅在接收时工作,如果我将SPI机器定义为“全双工主模式”。定义为“单工接收”时,SPI_CLK不会出现...

tpgf 发表于 2025-10-14 13:08 | 显示全部楼层
确保CPOL和CPHA的设置与从机设备的时序要求相匹配,这是成功通信的关键之一
jcky001 发表于 2025-10-14 15:42 | 显示全部楼层
仅接收(Receive-Only)的LL库示例
c
#include "stm32f0xx_ll_spi.h"
#include "stm32f0xx_ll_gpio.h"
#include "stm32f0xx_ll_bus.h"

void SPI2_Init_ReceiveOnly(void) {
    // 1. 启用SPI2和GPIO时钟
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);

    // 2. 配置SPI2引脚(SCK, MISO, NSS)
    LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_13, LL_GPIO_MODE_ALTERNATE); // SCK
    LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_14, LL_GPIO_MODE_ALTERNATE); // MISO
    LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_12, LL_GPIO_MODE_ALTERNATE); // NSS (可选)
    LL_GPIO_SetAFPin_8_15(GPIOB, LL_GPIO_PIN_13, LL_GPIO_AF_0);        // SPI2 AF
    LL_GPIO_SetAFPin_8_15(GPIOB, LL_GPIO_PIN_14, LL_GPIO_AF_0);
    LL_GPIO_SetAFPin_8_15(GPIOB, LL_GPIO_PIN_12, LL_GPIO_AF_0);

    // 3. 配置SPI2为全双工主模式(STM32F0单工接收需主设备生成时钟)
    LL_SPI_InitTypeDef SPI_InitStruct = {0};
    SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX; // 必须用全双工,否则时钟不输出
    SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
    SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
    SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
    SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
    SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; // 手动控制NSS
    SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV256;
    SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
    SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
    LL_SPI_Init(SPI2, &SPI_InitStruct);

    // 4. 启用SPI2
    LL_SPI_Enable(SPI2);
}

uint8_t SPI2_ReceiveData(void) {
    // 手动拉低NSS(片选)
    LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_12);

    // 发送哑元数据(0xFF)以触发时钟,同时接收数据
    LL_SPI_TransmitData8(SPI2, 0xFF);
    while (!LL_SPI_IsActiveFlag_RXNE(SPI2)); // 等待接收完成
    uint8_t data = LL_SPI_ReceiveData8(SPI2);

    // 拉高NSS
    LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_12);

    return data;
}
2. 仅发送(Transmit-Only)的LL库示例
c
void SPI2_Init_TransmitOnly(void) {
    // 初始化步骤同上(接收示例),但配置为全双工主模式
    // ...
}

void SPI2_SendData(uint8_t data) {
    LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_12); // 拉低NSS
    LL_SPI_TransmitData8(SPI2, data);
    while (!LL_SPI_IsActiveFlag_TXE(SPI2)); // 等待发送完成
    LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_12); // 拉高NSS
}
jcky001 发表于 2025-10-14 15:43 | 显示全部楼层
仅接收:使用全双工主模式,手动发送哑元数据触发时钟。
jcky001 发表于 2025-10-14 15:43 | 显示全部楼层
仅发送:直接使用全双工模式发送数据。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

86

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部