恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

STM32 SPI软件设计方案

  • 首页
  • 资讯中心
  • /
  • STM32 SPI软件设计方案

相关资讯

React面试核心考点与实战优化解析 2026/8/22 17:38:51
AI写作的边界与风险:从科幻作家批判看人机协作新范式 2026/8/22 17:38:51
济南能华机电设备远程供电系统落地应用指南 2026/8/22 17:38:51

最新资讯

量化LLM代理评估陷阱:为何平均分掩盖了真实任务中的灾难性失败?
Living Harness:交互式智能体进化框架的核心架构与实践挑战
元强化学习与自我反思机制在智能搜索中的应用与实践
AI自动化数学建模:从数据驱动到智能决策的实战指南
相关系数假设检验:Matlab与SPSS实战指南
Claude Code CLI 环境配置与实战指南:从安装到集成开发工作流

今日推荐

markdown-it-vue 踩坑排障:从安装到渲染的 6 个高频问题快速讲清
多尺度智能体控制:从宏观密度场到微观决策的架构与实践
CUBE标准:统一AI智能体评测的度量衡与架构解析

本周热门

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码
【双层规划,节点出清价,绿证交易,CVaR方法】两级电力市场环境下计及风险的省间交易商最优购电模型附Matlab代码
隐式mpc+自适应mpc+时变mpc,线性时变模型预测控制附Simulink仿真

本月精选

如何用DamaiHelper实现演唱会门票的智能自动化抢购:完整技术解决方案指南
第4篇:59 倍性能差距的索引瓶颈定位——一次教科书级的全表扫描调优
终极歌词批量下载神器:5分钟解决离线音乐库歌词同步难题

STM32 SPI软件设计方案

发布时间:2026/8/22 17:38:51
STM32 SPI软件设计方案 硬件平台STM32F103SPI1开发方式C面向接口分层标准库实现单SPI总线挂载多个SPI从设备(W25Q‑Flash SPI‑ADC示例)核心思想依赖抽象不依赖具体硬件寄存器/标准库全部收敛在驱动层设备层与MCU完全解耦一、SPI硬件底层原理SPI是同步全双工串行总线SCK时钟由主机产生。物理信号SCK串行时钟MOSI主机输出从机输入MISO从机输出主机输入CS(NSS)片选每个从设备独立一根CS GPIO关键特性SCK/MOSI/MISO是共享总线所有从机并联CS是设备私有信号。同一时刻只能拉低1个CS被选中设备驱动MISO未选中设备MISO高阻不干扰总线。SPI硬件是移位寄存器背对背连接每8个SCK脉冲同时收发1字节。不存在单纯“读”操作想要读取从机数据主机必须发送哑字节(一般0xFF)来产生时钟。本示例时序CPOL0CPHA0W25Q、MCP3202常用模式。CS不属于SPI外设本身CS是普通GPIO输出。二、整体分层架构四层架构严格隔离实现可移植单总线多设备。层级文件职责是否接触STM32库/寄存器抽象接口层spi_base.hpp、gpio_out_base.hpp定义SPI、GPIO输出纯虚接口只定义行为无实现❌完全不接触硬件硬件驱动层spi1_stdlib.hpp/cpp、stm32_gpio_stdlib.hpp/cpp实现SPI1硬件、GPIO输出调用标准库MCU强相关✅唯一操作硬件的层设备层w25q_flash.hpp/cpp、spi_adc_demo.hpp/cpp外设业务逻辑实现W25Q、ADC命令协议只依赖抽象接口❌无硬件代码可跨MCU复用应用层(main)main.cpp对象实例化、依赖注入业务调用少量硬件实例创建业务逻辑与硬件解耦硬件接线SPI1_SCK PA5SPI1_MOSI PA7SPI1_MISO PA6W25Q CS → PA4SPI‑ADC CS → PA3SCK/MOSI/MISO两个设备并联各自独立CS引脚。三、完整全部代码1. gpio_out_base.hpp 【抽象GPIO输出接口】#ifndefGPIO_OUT_BASE_HPP#defineGPIO_OUT_BASE_HPPclassGpioOutBase{public:virtual~GpioOutBase()default;virtualvoidsetLow()0;virtualvoidsetHigh()0;};#endif2. spi_base.hpp 【SPI抽象接口移除csSet】#ifndefSPI_BASE_HPP#defineSPI_BASE_HPP#includecstdintclassSpiBase{public:virtual~SpiBase()default;virtualboolinit()0;virtualuint8_treadWriteByte(uint8_ttx)0;virtualvoidreadWriteBuffer(constuint8_t*txBuf,uint8_t*rxBuf,uint16_tlen)0;};#endif3. stm32_gpio_stdlib.hpp 标准库GPIO输出驱动头文件#ifndefSTM32_GPIO_STDLIB_HPP#defineSTM32_GPIO_STDLIB_HPP#includegpio_out_base.hpp#includestm32f10x.hclassStm32GpioOut:publicGpioOutBase{private:GPIO_TypeDef*_port;uint16_t_pin;public:Stm32GpioOut(GPIO_TypeDef*port,uint16_tpin);voidgpioInit();voidsetLow()override;voidsetHigh()override;};#endifstm32_gpio_stdlib.cpp#includestm32_gpio_stdlib.hppStm32GpioOut::Stm32GpioOut(GPIO_TypeDef*port,uint16_tpin):_port(port),_pin(pin){}voidStm32GpioOut::gpioInit(){GPIO_InitTypeDef gpio_cfg;if(_portGPIOA)RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);elseif(_portGPIOB)RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);gpio_cfg.GPIO_Pin_pin;gpio_cfg.GPIO_ModeGPIO_Mode_Out_PP;gpio_cfg.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(_port,gpio_cfg);GPIO_SetBits(_port,_pin);// CS默认高电平}voidStm32GpioOut::setLow(){GPIO_ResetBits(_port,_pin);}voidStm32GpioOut::setHigh(){GPIO_SetBits(_port,_pin);}4. spi1_stdlib.hpp SPI1标准库驱动头文件#ifndefSPI1_STDLIB_HPP#defineSPI1_STDLIB_HPP#includespi_base.hpp#includestm32f10x.hclassSpi1StdLib:publicSpiBase{public:boolinit()override;uint8_treadWriteByte(uint8_ttx)override;voidreadWriteBuffer(constuint8_t*txBuf,uint8_t*rxBuf,uint16_tlen)override;};#endifspi1_stdlib.cpp#includespi1_stdlib.hppboolSpi1StdLib::init(){GPIO_InitTypeDef gpio_cfg;SPI_InitTypeDef spi_cfg;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1,ENABLE);// PA5 SCK PA7 MOSI 复用推挽输出gpio_cfg.GPIO_PinGPIO_Pin_5|GPIO_Pin_7;gpio_cfg.GPIO_ModeGPIO_Mode_AF_PP;gpio_cfg.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,gpio_cfg);// PA6 MISO 浮空输入gpio_cfg.GPIO_PinGPIO_Pin_6;gpio_cfg.GPIO_ModeGPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA,gpio_cfg);SPI_I2S_DeInit(SPI1);spi_cfg.SPI_DirectionSPI_Direction_2Lines_FullDuplex;spi_cfg.SPI_ModeSPI_Mode_Master;spi_cfg.SPI_DataSizeSPI_DataSize_8b;spi_cfg.SPI_CPOLSPI_CPOL_Low;spi_cfg.SPI_CPHASPI_CPHA_1Edge;spi_cfg.SPI_NSSSPI_NSS_Soft;spi_cfg.SPI_BaudRatePrescalerSPI_BaudRatePrescaler_4;spi_cfg.SPI_FirstBitSPI_FirstBit_MSB;spi_cfg.SPI_CRCPolynomial7;SPI_Init(SPI1,spi_cfg);SPI_Cmd(SPI1,ENABLE);returntrue;}uint8_tSpi1StdLib::readWriteByte(uint8_ttx){while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)RESET);SPI_I2S_SendData(SPI1,tx);while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_BSY)SET);returnstatic_castuint8_t(SPI_I2S_ReceiveData(SPI1));}voidSpi1StdLib::readWriteBuffer(constuint8_t*txBuf,uint8_t*rxBuf,uint16_tlen){for(uint16_ti0;ilen;i){uint8_ttxtxBuf?txBuf[i]:0xFFU;uint8_trxreadWriteByte(tx);if(rxBuf){rxBuf[i]rx;}}}5. w25q_flash.hpp W25Q设备层头文件#ifndefW25Q_FLASH_HPP#defineW25Q_FLASH_HPP#includespi_base.hpp#includegpio_out_base.hpp#includecstdintclassW25qFlashDevice{private:SpiBase*_spi;GpioOutBase*_cs;public:W25qFlashDevice(SpiBase*spi,GpioOutBase*cs_gpio);uint32_treadJedecId();voidreadData(uint32_taddr,uint8_t*buf,uint16_tlen);private:staticconstexpruint8_tCMD_JEDEC_ID0x9F;staticconstexpruint8_tCMD_READ0x03;};#endifw25q_flash.cpp#includew25q_flash.hppW25qFlashDevice::W25qFlashDevice(SpiBase*spi,GpioOutBase*cs_gpio):_spi(spi),_cs(cs_gpio){}uint32_tW25qFlashDevice::readJedecId(){_cs-setLow();_spi-readWriteByte(CMD_JEDEC_ID);uint8_tmfr_spi-readWriteByte(0xFF);uint8_tmem_spi-readWriteByte(0xFF);uint8_tcap_spi-readWriteByte(0xFF);_cs-setHigh();return(static_castuint32_t(mfr)16)|(static_castuint32_t(mem)8)|cap;}voidW25qFlashDevice::readData(uint32_taddr,uint8_t*buf,uint16_tlen){_cs-setLow();_spi-readWriteByte(CMD_READ);_spi-readWriteByte((addr16)0xFFU);_spi-readWriteByte((addr8)0xFFU);_spi-readWriteByte(addr0xFFU);_spi-readWriteBuffer(nullptr,buf,len);_cs-setHigh();}6. spi_adc_demo.hpp SPI‑ADC设备层头文件#ifndefSPI_ADC_DEMO_HPP#defineSPI_ADC_DEMO_HPP#includespi_base.hpp#includegpio_out_base.hpp#includecstdintclassSpiAdcDevice{private:SpiBase*_spi;GpioOutBase*_cs;public:SpiAdcDevice(SpiBase*spi,GpioOutBase*cs_gpio);uint16_treadChannel(uint8_tch);};#endifspi_adc_demo.cpp#includespi_adc_demo.hppSpiAdcDevice::SpiAdcDevice(SpiBase*spi,GpioOutBase*cs_gpio):_spi(spi),_cs(cs_gpio){}uint16_tSpiAdcDevice::readChannel(uint8_tch){_cs-setLow();uint8_tcmdstatic_castuint8_t(0x04|(ch1));_spi-readWriteByte(cmd);uint8_thigh_spi-readWriteByte(0xFF);uint8_tlow_spi-readWriteByte(0xFF);_cs-setHigh();uint16_tresult(static_castuint16_t(high0x0F)8)|low;returnresult;}7. main.cpp 应用层对象组装#includespi1_stdlib.hpp#includestm32_gpio_stdlib.hpp#includew25q_flash.hpp#includespi_adc_demo.hppintmain(void){// 1.初始化唯一SPI总线Spi1StdLib spi1_bus;spi1_bus.init();// 2.每个设备独立CS GPIO实例Stm32GpioOutcs_w25q(GPIOA,GPIO_Pin_4);Stm32GpioOutcs_adc(GPIOA,GPIO_Pin_3);cs_w25q.gpioInit();cs_adc.gpioInit();// 3.设备注入共享同一个SPI总线各自独立CSW25qFlashDeviceflash(spi1_bus,cs_w25q);SpiAdcDeviceadc(spi1_bus,cs_adc);uint32_tflash_idflash.readJedecId();uint16_tadc_valadc.readChannel(0);while(1){// 用户业务循环}}四、关键接口说明SpiBasevirtualboolinit()0;virtualuint8_treadWriteByte(uint8_ttx)0;virtualvoidreadWriteBuffer(constuint8_t*txBuf,uint8_t*rxBuf,uint16_tlen)0;readWriteByte(tx)全双工交换1字节只想读传入哑字节0xFF。readWriteBuffer(txBuf, rxBuf, len)批量收发txBufnullptr自动填充0xFF哑字节。GpioOutBasevirtualvoidsetLow()0;virtualvoidsetHigh()0;只描述引脚高低语义无硬件信息。W25Q readJedecId时序说明_cs-setLow();_spi-readWriteByte(0x9F);// MOSI发送JEDEC标准命令0x9Fmfr_spi-readWriteByte(0xFF);// 发哑字节产生SCK读取厂商IDmem_spi-readWriteByte(0xFF);// 读取存储类型cap_spi-readWriteByte(0xFF);// 读取容量ID_cs-setHigh();JEDEC为电子器件行业标准化组织0x9F是SPI‑NOR Flash标准读ID命令后面三次0xFF为哑字节MOSI输出会被FLASH忽略仅用来产生时钟读取MISO数据。五、新增SPI外设步骤例SPI‑OLED编写设备类构造入参SpiBase* spi、GpioOutBase* cs_gpio设备内部调用_cs-setLow()/setHigh()、_spi-readWriteByte()实现协议main中新建Stm32GpioOut作为该设备CS并初始化构建设备对象传入全局spi总线指针与CS指针SPI驱动代码无需修改。六、Keil MDK编译约束文件后缀使用.cpp工程开启C编译禁止全局域实例化对象全部在main函数内实例若使用new保证启动文件Heap_Size配置足够通信结束务必拉高CS否则MISO持续驱动总线干扰其他设备。七、常见踩坑清单SPI没有纯读操作读必须发送哑字节惯例用0xFF不要用0x00多设备禁止同时拉低两个CS会造成MISO总线冲突BSY标志位为1代表移位还在进行TXE只是发送缓冲为空不等于收发完成CS硬件初始化默认输出高电平CPOL、CPHA必须和外设datasheet保持一致。八、移植特性移植其他MCUGD32等无需改动spi_base.hpp、gpio_out_base.hpp、全部设备层h/cpp需要重写SPI驱动、GPIO输出驱动main仅修改硬件驱动实例创建部分。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号