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. 等待 TXEwhile (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET);// 2. 发送数据SPI_I2S_SendData(SPI1, byte);// 3. 等待 RXNEwhile (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET);// 4. 读取 DRreturn 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 andthis->cs_port_ != nullptr andthis->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. 等待 TXEret = this->SPI_WaitFlagStatus(SPI_I2S_FLAG_TXE);if (ret != Status::Ok) {return ret;}// 2. 发送数据SPI_I2S_SendData(this->spi_x_, send_byte);// 3. 等待 RXNEret = this->SPI_WaitFlagStatus(SPI_I2S_FLAG_RXNE);if (ret != Status::Ok) {return ret;}// 4. 读取 DRreceive_byte = SPI_I2S_ReceiveData(this->spi_x_);return ret;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1175403.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Keil5添加文件自动化脚本:简化批量导入流程

让Keil5项目管理不再痛苦&#xff1a;用Python脚本一键批量导入文件 你有没有过这样的经历&#xff1f; 接手一个新项目&#xff0c;或者要集成一个新的外设驱动、RTOS组件——比如FreeRTOS、LwIP、USB Stack……打开Keil5&#xff0c;点开“Add Files”&#xff0c;然后在层层…

voxCPM-1.5-WEBUI交通信息:实时路况语音推送

voxCPM-1.5-WEBUI交通信息&#xff1a;实时路况语音推送 1. 技术背景与应用场景 随着智能交通系统的发展&#xff0c;实时路况信息的获取与传播已成为城市出行服务的重要组成部分。传统的文本式路况提示存在阅读不便、信息吸收效率低等问题&#xff0c;尤其在驾驶场景中容易分…

AI读脸术与其他模型对比:轻量化设计优势全面评测

AI读脸术与其他模型对比&#xff1a;轻量化设计优势全面评测 1. 引言 在计算机视觉领域&#xff0c;人脸属性分析是一项基础且关键的技术&#xff0c;广泛应用于安防监控、智能零售、人机交互等场景。其中&#xff0c;年龄与性别识别作为最常见的人脸属性任务之一&#xff0c…

模板库怎么建?GLM-4.6V-Flash-WEB场景化Prompt管理

模板库怎么建&#xff1f;GLM-4.6V-Flash-WEB场景化Prompt管理 在多模态AI快速落地的今天&#xff0c;如何高效组织和复用视觉语言模型&#xff08;VLM&#xff09;的交互逻辑&#xff0c;已成为工程实践中的关键挑战。以智谱AI推出的轻量级视觉大模型 GLM-4.6V-Flash-WEB 为例…

如何快速调用Qwen3-1.7B?这份指南请收好

如何快速调用Qwen3-1.7B&#xff1f;这份指南请收好 1. 引言&#xff1a;为什么选择Qwen3-1.7B&#xff1f; 随着大语言模型在实际业务场景中的广泛应用&#xff0c;轻量级、高响应速度且具备良好推理能力的模型成为开发者关注的重点。阿里巴巴于2025年4月29日开源的通义千问…

大规模语音生成:VibeVoice-TTS批处理部署策略

大规模语音生成&#xff1a;VibeVoice-TTS批处理部署策略 1. 引言&#xff1a;从对话式TTS到长文本语音合成的工程挑战 随着AIGC技术的发展&#xff0c;文本转语音&#xff08;TTS&#xff09;已不再局限于单人短句朗读。在播客、有声书、虚拟角色对话等场景中&#xff0c;用…

Qwen3-4B API快速测试:云端免部署,1块钱验证想法

Qwen3-4B API快速测试&#xff1a;云端免部署&#xff0c;1块钱验证想法 你是不是也遇到过这样的情况&#xff1f;作为App开发者&#xff0c;想在产品里集成一个大模型API来提升用户体验——比如加个智能客服、自动摘要或者内容生成功能。但公司采购流程太慢&#xff0c;走正式…

中小企业AI落地实战:DeepSeek-R1-Distill-Qwen-1.5B低成本方案

中小企业AI落地实战&#xff1a;DeepSeek-R1-Distill-Qwen-1.5B低成本方案 1. 引言 在当前人工智能技术快速发展的背景下&#xff0c;越来越多的中小企业开始探索如何将大模型能力融入自身业务系统。然而&#xff0c;高昂的算力成本、复杂的部署流程以及对专业人才的高度依赖…

day139—链表—删除排序链表中的重复元素(LeetCode-83)

题目描述给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。示例 1&#xff1a;输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2]示例 2&#xff1a;输入&#xff1a;head [1,1,2,3,3] 输出&#x…

I2C总线在工业控制中的应用:系统学习指南

I2C总线在工业控制中的实战应用&#xff1a;从原理到系统设计你有没有遇到过这样的场景&#xff1f;一个紧凑的工业控制器&#xff0c;需要连接温度传感器、IO扩展芯片、ADC采集模块和EEPROM存储器——但主控MCU的GPIO引脚早已捉襟见肘。传统的并行接口动辄占用8~16根线&#x…

语音识别延迟高?CAM++推理速度优化实战技巧

语音识别延迟高&#xff1f;CAM推理速度优化实战技巧 1. 背景与问题分析 在实际部署说话人验证系统时&#xff0c;推理延迟是影响用户体验的关键因素。尽管 CAM 模型本身具备轻量级、高精度的优势&#xff0c;但在资源受限或并发请求较高的场景下&#xff0c;仍可能出现响应缓…

没GPU怎么跑Python3.9?云端1小时1块,5分钟部署

没GPU怎么跑Python3.9&#xff1f;云端1小时1块&#xff0c;5分钟部署 你是不是也遇到过这种情况&#xff1a;作为一名数据分析师&#xff0c;手头有个紧急项目要用 Python 3.9 的新特性处理大量数据&#xff0c;比如用更简洁的字典合并语法、更高效的类型提示优化代码结构。可…

Hunyuan翻译系统稳定性测试:长时间运行压力部署教程

Hunyuan翻译系统稳定性测试&#xff1a;长时间运行压力部署教程 1. 引言 1.1 业务场景描述 在企业级机器翻译服务中&#xff0c;模型的稳定性与持续服务能力是决定其能否投入生产环境的核心指标。Tencent-Hunyuan/HY-MT1.5-1.8B 是一款基于 Transformer 架构构建、参数量达 …

Stable Diffusion+ASR双模型对比:云端GPU3小时完成,成本降70%

Stable DiffusionASR双模型对比&#xff1a;云端GPU3小时完成&#xff0c;成本降70% 你是不是也遇到过这种情况&#xff1f;作为一家初创团队的技术负责人&#xff0c;老板让你快速验证两个AI方向&#xff1a;一个是用AI生成产品图做营销素材&#xff0c;另一个是开发方言语音…

Z-Image-Turbo横版竖版怎么选?16:9与9:16尺寸应用实战

Z-Image-Turbo横版竖版怎么选&#xff1f;16:9与9:16尺寸应用实战 1. 引言&#xff1a;图像比例选择的现实挑战 在AI图像生成的实际应用中&#xff0c;输出图像的宽高比&#xff08;Aspect Ratio&#xff09;直接影响最终内容的可用性与视觉表现力。阿里通义Z-Image-Turbo We…

通义千问2.5 vs 文心一言:指令遵循能力实战评测

通义千问2.5 vs 文心一言&#xff1a;指令遵循能力实战评测 1. 背景与评测目标 随着大语言模型在企业服务、智能助手和自动化内容生成等场景的广泛应用&#xff0c;指令遵循能力已成为衡量模型实用性的重要指标。一个优秀的语言模型不仅要具备广泛的知识覆盖和流畅的语言生成…

screen命令开机自启:服务化部署配置教程

如何让screen开机自启&#xff1f;一套真正可用的生产级服务化部署方案你有没有遇到过这样的场景&#xff1a;深夜&#xff0c;服务器重启后&#xff0c;早上一来发现那个跑了三天的数据采集脚本没了——因为没人手动启动&#xff1b;或者你在远程调试一个 Python 爬虫&#xf…

5个开源大模型镜像推荐:DeepSeek-R1免配置一键部署实战测评

5个开源大模型镜像推荐&#xff1a;DeepSeek-R1免配置一键部署实战测评 1. 引言&#xff1a;本地化大模型的实践需求与选型背景 随着大语言模型在推理、编程、数学等复杂任务中的表现不断提升&#xff0c;越来越多开发者和企业开始关注本地化部署的可能性。然而&#xff0c;主…

SGLang-v0.5.6性能优化:减少序列化开销的技巧

SGLang-v0.5.6性能优化&#xff1a;减少序列化开销的技巧 SGLang-v0.5.6 是当前大模型推理部署领域中备受关注的一个版本更新。该版本在吞吐量、延迟控制和资源利用率方面进行了多项关键优化&#xff0c;其中减少序列化开销成为提升整体性能的重要突破口。本文将深入剖析 SGLa…

opencode错误修复建议实战:真实Bug案例处理流程

opencode错误修复建议实战&#xff1a;真实Bug案例处理流程 1. 引言 1.1 业务场景描述 在现代AI驱动的开发环境中&#xff0c;开发者越来越依赖智能编码助手来提升效率。OpenCode 作为一个2024年开源的终端优先AI编程框架&#xff0c;凭借其多模型支持、隐私安全和插件化架构…