STM32F1标准库硬件SPI驱动代码,含C和C++版本

#ifndef __SPI_H
#define __SPI_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stm32f10x_spi.h>

#include <stdint.h>

void SPI1_SendRecvData(const uint8_t *send_data, uint8_t *recv_data, uint16_t len);
void SPI1_SendData(const uint8_t *data, uint16_t len);
void SPI1_RecvData(uint8_t *data, uint16_t len);

#ifdef __cplusplus
}
#endif

#endif /* __SPI_H */

#include "spi.h"

#include <stm32f10x_gpio.h>
#include <stm32f10x_spi.h>

#include <stdint.h>

/**
 * @brief SPI1 时序开始
 *
 */
static inline void SPI1_Start(void)
{
    GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 拉低NSS
}

/**
 * @brief SPI1 时序结束
 *
 */
static inline void SPI1_Stop(void)
{
    GPIO_SetBits(GPIOA, GPIO_Pin_4); // 拉高NSS
}

/**
 * @brief SPI1 交换一个字节
 *
 * @param byte 待交换的字节
 * @return uint8_t 交换后的字节
 */
static uint8_t SPI1_SwapByte(uint8_t byte)
{
    // 1. 等待 TXE
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET);

    // 2. 发送数据
    SPI_I2S_SendData(SPI1, byte);

    // 3. 等待 RXNE
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET);

    // 4. 读取 DR
    return SPI_I2S_ReceiveData(SPI1);
}

/**
 * @brief SPI1 发送一个字节
 *
 * @param byte 待发送的字节
 */
static void SPI1_SendByte(uint8_t byte)
{
    SPI1_SwapByte(byte);
}

/**
 * @brief SPI1 接收一个字节
 *
 * @return uint8_t 接收到的字节
 */
static uint8_t SPI1_RecvByte(void)
{
    return SPI1_SwapByte(0xFF);
}

/**
 * @brief SPI1 发送和接收数据
 *
 * @param send_data 待发送的数据
 * @param recv_data 接收到的数据
 * @param len 发送和接收的字节数
 */
void SPI1_SendRecvData(const uint8_t *send_data, uint8_t *recv_data, uint16_t len)
{
    SPI1_Start();
    for (uint16_t i = 0; i < len; i++) {
        recv_data[i] = SPI1_SwapByte(send_data[i]);
    }
    SPI1_Stop();
}

/**
 * @brief SPI1 发送数据
 *
 * @param data 待发送的数据
 * @param len 发送的字节数
 */
void SPI1_SendData(const uint8_t *data, uint16_t len)
{
    SPI1_Start();
    for (uint16_t i = 0; i < len; i++) {
        SPI1_SendByte(data[i]);
    }
    SPI1_Stop();
}

/**
 * @brief SPI1 接收数据
 *
 * @param data 接收到的数据
 * @param len 接收的字节数
 */
void SPI1_RecvData(uint8_t *data, uint16_t len)
{
    SPI1_Start();
    for (uint16_t i = 0; i < len; i++) {
        data[i] = SPI1_RecvByte();
    }
    SPI1_Stop();
}

enum class Status {
    Ok,
    Error,
    Busy,
    Timeout,
};

#pragma once

#include <stm32f10x.h>

#include <cstddef>
#include <cstdint>
#include <span>

#include "main.hpp"

class SPI_Handle
{
public:
    static constexpr uint32_t DefaultTimeout = 1000;

    SPI_Handle(SPI_TypeDef *spi_x = nullptr);

    operator bool() const;

    void set_spi_handle(SPI_TypeDef *spi_x);
    void set_cs_pin(GPIO_TypeDef *port, uint16_t pin);
    void set_timeout(uint32_t Timeout);

    auto spi_handle() const;
    auto timeout() const;
    auto cs_port() const;
    auto cs_pin() const;

    void Start();
    void Stop();

    Status SPI_TransmitReceive(uint8_t send_byte, uint8_t &receive_byte);
    Status Transmit(uint8_t send_byte);
    Status Receive(uint8_t &receive_byte);

    Status SPI_TransmitReceive(std::span<const uint8_t> transmit_data, std::span<uint8_t> receive_buffer);
    Status Transmit(std::span<const uint8_t> transmit_data);
    Status Receive(std::span<uint8_t> receive_buffer);

protected:
    SPI_TypeDef *spi_x_;

    GPIO_TypeDef *cs_port_;
    uint16_t      cs_pin_;

    uint32_t timeout_;

    Status SPI_WaitFlagStatus(uint16_t SPI_I2S_FLAG);
    Status SPI_SwapByte(uint8_t send_byte, uint8_t &receive_byte);
};

#include "spi_handle.hpp"

#include <stm32f10x.h>

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <ranges>
#include <span>

#include "main.hpp"

SPI_Handle::SPI_Handle(SPI_TypeDef *spi_x)
    : spi_x_(spi_x),
      cs_port_(nullptr), cs_pin_(0),
      timeout_(Defaulttimeout)
{
}

SPI_Handle::operator bool() const
{
    return this->spi_x_ != nullptr and
           this->cs_port_ != nullptr and
           this->cs_pin_ != 0;
}

void SPI_Handle::set_spi_handle(SPI_TypeDef *spi_x) { this->spi_x_ = spi_x; }

void SPI_Handle::set_cs_pin(GPIO_TypeDef *port, uint16_t pin)
{
    this->cs_port_ = port;
    this->cs_pin_  = pin;
}

void SPI_Handle::set_timeout(uint32_t timeout) { this->timeout_ = timeout; }

auto SPI_Handle::spi_handle() const { return this->spi_x_; }

auto SPI_Handle::timeout() const { return this->timeout_; }

auto SPI_Handle::cs_port() const { return this->cs_port_; }

auto SPI_Handle::cs_pin() const { return this->cs_pin_; }

void SPI_Handle::Start()
{
    if (this->cs_port_ != nullptr and this->cs_pin_ != 0) {
        GPIO_ResetBits(this->cs_port_, this->cs_pin_);
    }
}

void SPI_Handle::Stop()
{
    if (this->cs_port_ != nullptr and this->cs_pin_ != 0) {
        GPIO_SetBits(this->cs_port_, this->cs_pin_);
    }
}

Status SPI_Handle::SPI_TransmitReceive(uint8_t send_byte, uint8_t &receive_byte)
{
    return this->SPI_TransmitReceive(
        std::span<const uint8_t>{&send_byte, 1},
        std::span<uint8_t>{&receive_byte, 1});
}

Status SPI_Handle::Transmit(uint8_t send_byte)
{
    return this->Transmit(std::span<const uint8_t>{&send_byte, 1});
}

Status SPI_Handle::Receive(uint8_t &receive_byte)
{
    return this->Receive(std::span<uint8_t>{&receive_byte, 1});
}

Status SPI_Handle::SPI_TransmitReceive(std::span<const uint8_t> transmit_data, std::span<uint8_t> receive_buffer)
{
    if (transmit_data.size() != receive_buffer.size()) {
        return Status::Error;
    }

    for (auto [send, receive] : std::ranges::views::zip(transmit_data, receive_buffer)) {
        auto ret = this->SPI_SwapByte(send, receive);
        if (ret != Status::Ok) {
            return ret;
        }
    }

    return Status::Ok;
}

Status SPI_Handle::Transmit(std::span<const uint8_t> transmit_data)
{
    static uint8_t dummy = 0xFF;

    for (auto transmit_byte : transmit_data) {
        auto ret = this->SPI_SwapByte(transmit_byte, dummy);
        if (ret != Status::Ok) {
            return ret;
        }
    }

    return Status::Ok;
}

Status SPI_Handle::Receive(std::span<uint8_t> receive_buffer)
{
    for (auto &receive_byte : receive_buffer) {
        auto ret = this->SPI_SwapByte(0xFF, receive_byte);
        if (ret != Status::Ok) {
            return ret;
        }
    }
    return Status::Ok;
}

Status SPI_Handle::SPI_WaitFlagStatus(uint16_t SPI_I2S_FLAG)
{
    for (uint32_t i = 0; i < this->timeout_; i++) {
        if (SPI_I2S_GetFlagStatus(this->spi_x_, SPI_I2S_FLAG) == SET) {
            return Status::Ok;
        }
    }

    return Status::timeout;
}

Status SPI_Handle::SPI_SwapByte(uint8_t send_byte, uint8_t &receive_byte)
{
    auto ret = Status::Ok;

    // 1. 等待 TXE
    ret = this->SPI_WaitFlagStatus(SPI_I2S_FLAG_TXE);
    if (ret != Status::Ok) {
        return ret;
    }

    // 2. 发送数据
    SPI_I2S_SendData(this->spi_x_, send_byte);

    // 3. 等待 RXNE
    ret = this->SPI_WaitFlagStatus(SPI_I2S_FLAG_RXNE);
    if (ret != Status::Ok) {
        return ret;
    }

    // 4. 读取 DR
    receive_byte = SPI_I2S_ReceiveData(this->spi_x_);

    return ret;
}

posted @ 2026-01-18 00:51  ~夏至、微风~  阅读(2)  评论(0)    收藏  举报