之前用STM32的SPI需要控制很多外部芯片,可是一个SPI的外设只有一个片选,要实现独立片选一主多从,怎么实现呢?

SPI总线拓扑

一般地,SPI总线按照下图方式进行连接,一主多从。

如上图:

  • 每个从设备都有独立的片选引脚,主机同一时间段内,与一个从设备进行通信,也即选中一个从设备。

  • MOSI/MISO/SCLK并联在一起

  • MISO须是三态门,当从设备未选中时,该脚须设置为高阻态,而不能是输出态,否则会影响总线

  • 对于MOSI/SCLK,虽然并联在一起,但是由于仅一个输出,多输入。

但是你看STM32的SPI外设,一个SPI仅有一个NSS信号,以STM32F407的SPI2为例:

那么要实现前面说的一主多从,怎么办呢?有朋友说,直接用GPIO去模拟不就可以了。

不错,SPI总线要用GPIO模拟还是很容易的,但是这样做波特率做不高,需要占用CPU时间,效率比较低!而用SPI外设控制器,底层bit流的收发由外设控制器实现,用GPIO模拟则需要CPU参与。

怎么破呢?

菊花链拓扑

这种方案,省引脚。但是要移位控制,相对独立片选效率还是低不少。

独立片选拓扑

SPI外设的MOSI、MISO、SCK还是照用不误,但是片选我们不用,设置成通用输出模式,再用其他的GPIO片选从芯片即可。

上代码看看:

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(hspi->Instance==SPI1){__HAL_RCC_SPI1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**SPI1 GPIO ConfigurationPA5     ------> SPI1_SCKPA6     ------> SPI1_MISOPA7     ------> SPI1_MOSIPA15     ------> SPI1_NSS 但是这里不用*/GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/*__HAL_RCC_GPIOC_CLK_ENABLE();GPIO_InitStruct.Pin = GPIO_PIN_1;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);*/ }
}

初始化SPI外设

#define SPI_CS1                        GPIO_PIN_1
#define SPI_CS1_PORT                   GPIOC
#define SPI_CS2                        GPIO_PIN_2
#define SPI_CS2_PORT                   GPIOC
#define SPI_CS3                        GPIO_PIN_3
#define SPI_CS3_PORT                   GPIOC
static void init_spi(SPI_HandleTypeDef * spi_handle)
{/* SPI1 parameter configuration*/spi_handle->Instance = SPI1;spi_handle->Init.Mode = SPI_MODE_MASTER;spi_handle->Init.Direction = SPI_DIRECTION_2LINES;spi_handle->Init.DataSize = SPI_DATASIZE_8BIT;spi_handle->Init.CLKPolarity = SPI_POLARITY_LOW;spi_handle->Init.CLKPhase = SPI_PHASE_1EDGE;spi_handle->Init.NSS = SPI_NSS_HARD_OUTPUT;spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;spi_handle->Init.FirstBit = SPI_FIRSTBIT_MSB;spi_handle->Init.TIMode = SPI_TIMODE_DISABLE;spi_handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;spi_handle->Init.CRCPolynomial = 10;ASSERT (HAL_SPI_Init(spi_handle) != HAL_OK);GPIO_InitTypeDef  GPIO_InitStructure;__HAL_RCC_GPIOC_CLK_ENABLE();GPIO_InitStructure.Pin = SPI_CS1;GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStructure.Pull = GPIO_NOPULL;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_MEDIUM;HAL_GPIO_Init(SPI_CS1_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = SPI_CS2;HAL_GPIO_Init(SPI_CS2_PORT, &GPIO_InitStructure);  GPIO_InitStructure.Pin = SPI_CS3;HAL_GPIO_Init(SPI_CS3_PORT, &GPIO_InitStructure);
}

从而原来SPI的收发函数前后加上片选信号即可:

typedef enum
{  SPI_CH_1=0,SPI_CH_2,SPI_CH_3,SPI_CH_LAST,
} SPI_CH;
static HAL_StatusTypeDef SPI_Select(SPI_CH ch)
{switch (ch){case SPI_CH_1:HAL_GPIO_WritePin(SPI_CS1_PORT,SPI_CS1,GPIO_PIN_RESET);break;case SPI_CH_2:HAL_GPIO_WritePin(SPI_CS2_PORT,SPI_CS2,GPIO_PIN_RESET);break;case SPI_CH_3:HAL_GPIO_WritePin(SPI_CS3_PORT,SPI_CS3,GPIO_PIN_RESET);break;       default:return HAL_ERROR;}  return HAL_OK;
}
static HAL_StatusTypeDef SPI_DeSelect(SPI_CH ch)
{switch (ch){case SPI_CH_1:HAL_GPIO_WritePin(SPI_CS1_PORT,SPI_CS1,GPIO_PIN_SET);break;case SPI_CH_2:HAL_GPIO_WritePin(SPI_CS2_PORT,SPI_CS2,GPIO_PIN_SET);break;case SPI_CH_3:HAL_GPIO_WritePin(SPI_CS3_PORT,SPI_CS3,GPIO_PIN_SET);break;       default:return HAL_ERROR;}return HAL_OK;
}HAL_StatusTypeDef SPI_TransmitReceive(SPI_CH ch,SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,uint32_t Timeout)
{HAL_StatusTypeDef ret; if(ch>=SPI_CH_LAST)return HAL_ERROR;  SPI_Select(ch);ret = HAL_SPI_TransmitReceive(hspi,pTxData,pRxData,Size,Timeout);SPI_DeSelect(ch);return ret;
}HAL_StatusTypeDef SPI_Transmit(SPI_CH ch,SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{HAL_StatusTypeDef ret; if(ch>=SPI_CH_LAST)return HAL_ERROR;  SPI_Select(ch);ret = HAL_SPI_Transmit(hspi,pData,Size,Timeout);SPI_DeSelect(ch);return ret;
}

如此一来,一个SPI外设就可以控制多个从芯片了。你如果有兴趣,不妨照这个思路试试看。

1.中国芯片替代方案公司名单公布(70个类别)

2.为什么原理图总画不好?这些技巧要知道

3.嵌入式设备如何显示IP属地?

4.RISC-V面向MCU/MPU、RTOS,但面临挑战。。。

5.单片机固件自更新的一个方法!

6.玄铁杯RISC-V应用创新大赛正式开赛,现开放报名!

免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。

STM32的SPI外设片选只有一个怎么破?相关推荐

  1. 关于STM32的SPI外设时钟分频对应的SCK速率

    以STM32F103为例, 经过system_stm32f10x.c文件中的SystemInit()函数之后,这里是指的默认时钟配置如下图所示: STM32F103的系统框架图如下所示: 可见:SPI ...

  2. 基于stm32、spi协议的Fatfs文件系统移植(附完整代码下载)

    开发环境:Window 7 32bit 开发工具:Keil uVision4 硬件:stm32f103vct6 目录 1.硬件设计: 2.软件设计 1.SPI收发数据 2.向SD卡发送的命令格式: 3 ...

  3. 【STM32】SPI协议通信详解

    目录 一.SPI协议简介 二.SPI物理层 三.SPI协议层 1.通讯的起始和停止信号 2.数据有效性 3.时钟信号的相位和极性(重点) 四.SPI 特性及架构(重点) 1.通信引脚 2.时钟控制逻辑 ...

  4. stm32中spi可以随便接吗_stm32之SPI通信协议实例详解

    之前一直对SPI通信一知半解,所以想抽空把它搞得明白一些.考虑到之前是结合Flash芯片来学的,十分不直观,而且主要把时间和精力都花在Flash芯片的datasheet和驱动上了,SPI通信也没学好. ...

  5. 【嵌入式】STM32实现SPI双机通信的一些细节(2)片选总结

    [嵌入式]STM32实现SPI双机通信的一些细节(2)SPI软硬件片选总结 SPI片选总结 坑爹的手册示意图 理想中的硬件片选 主机软件片选就对了 从机硬件片选 从机软件片选 代码 主机软件片选SPI ...

  6. 高通平台SPI外设的片选信号配置

    spi master 和spi device有各自的dts配置: 这是spi master的配置示例,也就是spi控制器 这是一个spi device的配置示例,也就是spi外设(从设备) 一个spi ...

  7. 【STM32】SPI 实验代码详解

    友情链接:[小项目关键技术]硬件通信三种方式.串口.IIC.SPI 文章目录 main.c spi.c spi.h SPI 是英语 Serial Peripheral interface 的缩写,顾名 ...

  8. 基于STM32的SPI基本介绍

    STM32---SPI(DMA)通信的总结(库函数操作) 本文主要由7项内容介绍SPI并会在最后附上测试源码供参考: 1.     SPI的通信协议 2.     SPI通信初始化(以STM32为从机 ...

  9. 【STM32】SPI程序示例

    00. 目录 文章目录 00. 目录 01. SPI简介 02. 功能描述 03. 硬件模块 04. 软件设计 05. 结果验证 06. 附录 07. 声明 01. SPI简介 SPI 是英语 Ser ...

最新文章

  1. Windows系统运维转linux系统运维的经历
  2. CentOS中JAVA_HOME的环境变量设置
  3. 华大单片机HC32L136J8TA读取DS18B20温度(源码+时钟配置)
  4. hdu 1806线段树 区间合并
  5. 把nc v6的源码看懂
  6. 工业交换机的定义和应用
  7. python 多线程 廖雪峰_python中多线程与多进程中的数据共享问题
  8. flask如何查询mysql_bootstrap+flask+mysql实现网站查询
  9. Google code android开源项目(五)
  10. LNK快捷方式漏洞利用方式 exp制作教程
  11. js 生成二维码(qrcodejs)
  12. 瑞星企业防毒2010网络版(二)管理及应用
  13. 电机专题2:直流有刷电机工作原理
  14. 计算机学报应用研究,组推荐系统及其应用研究-计算机学报.PDF
  15. 6s英语语法笔记(图片炸了)
  16. RT-1052学习笔记 - GPIO架构分析
  17. Win10注册表无法保存对权限所作的更改拒绝访问
  18. Excel操作技巧:三列内容合并生成到另外一列中;在判断某列里面的值在另外列中是否存在
  19. 【论文简述及翻译】PWC-Net: CNNs for Optical Flow Using Pyramid, Warping, and Cost Volume(CVPR 2018)
  20. JS身份证号码校验,JS根据身份证号码获取出生年月日,JS根据出生年月日获取年龄,JS根据身份证号码获取性别

热门文章

  1. 全网19套超热门表情包,小狗头、国王排名等我全部整理来了
  2. java case 的错误_关于java:switch case语句错误:case表达式必须是常量表达式
  3. java中一个有意思的字符串intern问题
  4. Tushare介绍、安装及使用教程
  5. WORD批量修改文献引用为上标
  6. Java SE 控制流程(今天本君不早朝)
  7. Css3学习日志 --css层叠样式表
  8. 抗疫行动题材网页设计 大学生最美逆行者感动人物网页代码 众志成城万众一心抗击疫情HTML网页设计
  9. 数学类笔试题(四分位数、数据规约和协方差)
  10. php网页可视化编辑器,在线HTML可视化编辑器KindEditor | 严佳冬