草庐IT

STM32 SPI硬件NSS

小蜗牛,呵呵呵 2023-03-28 原文

STM32 SPI硬件NSS

STM32F1的SPI NSS引脚并不是通常认为的,打开硬件NSS后在发送数据的时候NSS输出低,去片选从设备,在发送完成后释放从设备,硬件NSS而是用来实现多主机模式的。

当时我还以为买到了假STM32了呢。


在我们配置SPI为硬件NSS之后,配置代码如下,发现不论发不发数据NSS都为0V;

//SPI Pins SCK MOSI
GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AF_PP;//注意这里
GPIO_Init(GPIOB,&GPIO_InitStructure);

SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
SPI_InitStructure.SPI_Mode      = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize  = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL      = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA      = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS       = SPI_NSS_Hard;//注意这里
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit  = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2,&SPI_InitStructure);
SPI_SSOutputCmd(SPI2,ENABLE);//注意这里
SPI_Cmd(SPI2,ENABLE);

在阅读Reference Manual时发现这么一句话

This configuration is used only when the device operates in master mode. The NSS signal is driven low when the master starts the communication and is kept low until the SPI is disabled.

大概意思是:在disable SPI之后NSS才会不被拉低。于是我就这样:

SPI_Cmd(SPI2,DISABLE);

发现NSS是0.5V左右,注意是0.5V,这里像是开漏输出的样子;为什么没有输出3.3V,于是在NSS上加了一个10K上拉电阻,结果NSS输出了3.3V,这不就是开漏吗?这也是为了能够线与,实现多主机模式吧。

加了上拉电阻之后SPI的NSS功能就算正常啦。


Reference Manual写到

When configured in master mode with NSS configured as an input (MSTR=1 and SSOE=0) and if NSS is pulled low, the SPI enters the master mode fault state: the MSTR bit is automatically cleared and the device is configured in slave mode

其中说到SSOE = 0,NSS配置为输入,当NSS为低电平时,SPI 进入从机模式,也就下边的代码,注意这里使用的SPI_NSS_Hard。

SPI_SSOutputCmd(SPI2,DISABLE);

在NSS未接上拉电阻的时候,NSS为逻辑0 ,那么SPI就会进入从机模式,SCK和MOSI上无数据;接上拉电阻之后,这下就变正常啦,在NSS为高时SPI是主机模式SCK和MOSI可以输出数据,当外部把NSS拉低后SPI就进入了从机模式。


那可不可以这样

//SPI Pin NSS
GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_Out_PP;//注意这里
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET);//注意这里

SPI_InitStructure.SPI_NSS       = SPI_NSS_Hard;
SPI_SSOutputCmd(SPI2,ENABLE);//注意这里

NSS引脚不用复用推挽输出 ,而是用推挽输出,也就是PB12不接入SPI,这样NSS可以通过软件的控制输出高电平和低电平,也许可以省略一个上拉电阻(别问我为什么这么扣,为了省去一个上拉电阻大费周章,因为我的板子没有设计上拉电阻,测试的上拉电阻是从外部接的),结论是否定的,因为推挽输出 是这样的

两个SPI的NSS引脚都是推挽输出,当一个输出高,一个输出低,那么他们会各自分得1.6V的电压,也就是逻辑1,若设置了SSOE = 0,SPI 也不会 从主机自动变成从机。


那么可不可以这样

//SPI Pin NSS
GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_Out_OD;//注意这里
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET);//注意这里

SPI_InitStructure.SPI_NSS       = SPI_NSS_Hard;
SPI_SSOutputCmd(SPI2,ENABLE);//注意这里

PB12开漏输出,然后在外部上拉一个大电阻。哈哈,这次答案是肯定的,NSS有高有低,SPI也可以进入从机模式,但是上拉电阻还是不能省啊。


PB12没有设置成复用功能,为什么SPI还会检测到NSS引脚的低电平,而后进入从机模式呢?

看上面STM32 GPIO的图,会发现不管输出设为那种模式,输入是一直连接到STM32 内部的,这也就是为什么 STM32 固件库里输入模式只有这几种模式,而没有复用输入的原因。

GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,

那怎么才能使用多主机模式呢?

  1. NSS设置成复用功能,加上拉电阻,SPI_NSS_Hard,且在不发送数据时失能NSS输出,在要发送数据时使能NSS输出。

  2. NSS设置成开漏输出,加上拉电阻,SPI_NSS_Hard,且在不发送数据时失能NSS输出,在要发送数据时使能NSS输出。

  3. 第2种方法真鸡肋


如果只是单主机模式,那么配置模式就比较的随意啦。

  1. NSS设置成复用功能,加上拉电阻,SPI_NSS_Hard,SPI_SSOutputCmd(SPI2,ENABLE),软件去控制NSS。

  2. NSS设置成开漏输出,加上拉电阻或者推挽输出,SPI_NSS_Hard,SPI_SSOutputCmd(SPI2,ENABLE),软件去控制NSS。

  3. 直接NSS设置成推挽输出,SPI_NSS_Soft,软件去控制NSS。

  4. 还是第3种方法最实用。

有关STM32 SPI硬件NSS的更多相关文章

  1. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  2. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

  3. STM32的HAL和LL库区别和性能对比 - 2

    LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L

  4. ESP32学习入门:WiFi连接网络 - 2

    目录一、ESP32简单介绍二、ESP32Wi-Fi模块介绍三、ESP32Wi-Fi编程模型四、ESP32Wi-Fi事件处理流程 五、ESP32Wi-Fi开发环境六、ESP32Wi-Fi具体代码七、ESP32Wi-Fi代码解读6.1主程序app_main7.2自定义代码wifi_init_sta()八、ESP32Wi-Fi连接验证8.1测试方法8.2服务器模拟工具sscom58.3测试代码8.4测试结果前言为了开发一款亚马逊物联网产品,开始入手ESP32模块。为了能够记录自己的学习过程,特记录如下操作过程。一、ESP32简单介绍ESP32是一套Wi-Fi(2.4GHz)和蓝牙(4.2)双模解决方

  5. Spring Security 6.0系列【32】授权服务器篇之默认过滤器 - 2

    有道无术,术尚可求,有术无道,止于术。本系列SpringBoot版本3.0.4本系列SpringSecurity版本6.0.2本系列SpringAuthorizationServer版本1.0.2源码地址:https://gitee.com/pearl-organization/study-spring-security-demo文章目录前言1.OAuth2AuthorizationServerMetadataEndpointFilter2.OAuth2AuthorizationEndpointFilter3.OidcProviderConfigurationEndpointFilter4.N

  6. ruby - 摘要::CRC32 与 Zlib - 2

    在我的代码中,我需要使用各种算法(包括CRC32)对文件进行哈希处理。因为我还在Digest系列中使用其他加密哈希函数,所以我认为为它们维护一个一致的接口(interface)会很好。为了记录,我确实找到了digest-crc,一颗完全符合我要求的gem。问题是,Zlib是标准库的一部分,并且有一个我想重用的CRC32工作实现。此外,它是用C编写的,因此它应该提供与digest-crc相关的卓越性能,后者是纯ruby​​实现。实现Digest::CRC32一开始看起来非常简单:%w(digestzlib).each{|f|requiref}classDigest::CRC32一切正常:

  7. ruby - 安装gem : Couldn't reserve space for cygwin's heap, Win32错误487错误 - 2

    我正在尝试在我的机器上安装win32-apigem,但在构建native扩展时我遇到了一些问题:$geminstallwin32-api--no-ri--rdocTemporarilyenhancingPATHtoincludeDevKit...Buildingnativeextensions.Thiscouldtakeawhile...C:\Programs\dev_kit\bin\make.exe:***Couldn'treservespaceforcygwin'sheap,Win32error0ERROR:Errorinstallingwin32-api:ERROR:Failed

  8. Ruby 1.9 - 没有这样的文件可以加载 'win32/open3' - 2

    我在Windows上运行ruby​​1.9.2并试图移植在Ruby1.8中工作的代码。该代码使用以前运行良好的Open4.popen4。对于1.9.2,我做了以下事情:通过geminstallPOpen4安装了POpen4需要POpen4通过require'popen4'尝试像这样使用POpen4:Open4.popen4("cmd"){|io_in,io_out,io_er|...}当我这样做时,我得到了错误:nosuchfiletoload--win32/open3如果我尝试安装win32-open3(geminstallwin32-open3),我会收到错误消息:win32-op

  9. Dell Inspiron 5488加内存32G - 2

    DellInspiron5488加内存32G 原装内置内存仅仅8G,目前看,真的太小了! 1.内存型号Dell5488内存型号:DDR42666。笔记本有两个内存插槽,原装占了一个,还能扩展一个。 2.买内存如果买Dell原装笔记本内存,8G就得500块左右。 我咨询了一下,三星的笔记本内存,可以兼容。16G,299块(2023年2月23日,京东价) Dell5488内存组合,最多只能插两根16G内存。 我于是买了两根三星16G内存。装上,很爽😄 跑国产系统统信UOS,再也看不到用交换区了,32G内存,爽!  

  10. MicroBlaze在纯FPGA下 Xilinx SDK固化程序到外部SPI FLASH - 2

    外部SPIFLASH:MicronN25Q128A13ESE40G(128Mbit(16MByte))FPGA:XC7A100T CPU:Microblaze第一种情况:Microblaze在简单的应用,比如运行LED,IIC,SPI,UART之类的低俗接口驱动,或做一些简单的辅助型工作时,一般生成的applicationelf文件都不大,在10几KB或者几十,百几KB,此时使用FPGA内部的BRAM资源已经足够。XC7A100T本身就有600几KB的BRAM资源。这种情况下直接将硬件流文件和elf文件合并为download.bit文件,在直接烧录到外部SPIFLAH即可。1.Xilinx--

随机推荐