【嵌入式】STM32实现SPI双机通信的一些细节(2)SPI软硬件片选总结
SPI片选总结
本文基于STM32F4系列。
虽然说一主一从好像和片选没什么关系但是不搞清楚总觉得心里发慌,但是不搞不知道,一搞折腾了我好几天。目前我接触到的很多示例代码包括正点原子的教学视频中,对于软件片选的选择显得理所当然,几乎没有设置为硬件片选的情况。《STM32中文参考手册》中关于软硬件片选讲的很混乱,看了好几遍也摸不着头脑。下面我就按照自己目前理解到的内容进行一些总结吧,如果有不对的地方请大家指正。
坑爹的手册示意图
关于SPI软硬件片选,最开始思考方式完全是错误的,就是由于看不懂一张示意图,我的妈耶也不知道怎么搜索,直到这两天看了一篇博客才真正了解了它的含义。
这张图在SPI的原理框图中很容易找到,下面就对它进行一个解释。对于从机SPI寄存器CR1中的SSM位,置1时代表软件片选,置0时代表硬件片选。上图的意思是,如果SSM置0,则内部NSS由外部NSS引脚电平确定;如果SSM置1,则外部NSS引脚无效了,随你怎么用,哪怕是复用为SPI_CS也起不到任何作用,因为内部的NSS电平是由SSI位决定的。天哪!这么简单的一个含义!折腾了我那么久,哪些仁兄能告诉我这种示意图叫什么?我以后要是遇到其他的也好去查查含义,我最开始竟然以为是个“与”门,日。
理想中的硬件片选
按照手册上的说法,如果选择了硬件片选,那么对于从机而言,就要将PA4即默认的片选引脚与主机片选信号相连,来作为从机片选信号的来源,低电平代表被选中,高电平代表未被选中。我在测试的过程中发现,如果将从机设置为硬件片选模式,无论主机电平是高还是低,都能接收到数据。这就和手册上说的有出入了,就在写这篇文章的时候我突然想起来,丫的我从机代码最开始是在主机代码的基础上改的,没有使能复用PA4引脚当然没用啦!加了两条语句果然,硬件片选模式下的从机,PA4接收到高电平时是不会触发中断即不会接收数据的,拉低则可以,完美解决。
也就是说,硬件模式对从机是非常友好的,没有任何问题。当然啦,什么SSOE支持多主或者动态切换这方面的问题我还没有去好好研究,后面有机会再看!虽然应该是不会再看了。。
问题出在主机上。如果主机选择了硬件模式,一般都会以为片选引脚会在发送时自动拉低,在结束发送时自动拉高,但是实际上,手册上的说法是:使能SPI后片选引脚就会输出低直到关闭SPI(对于我的使用场景,就算你一直拉低也没什么哈)。具体的内容可以参看如下博客:这篇博客相比我看过的大量垃圾复制粘贴博客好很多,让我一下子解决了问题:https://www.cnblogs.com/shangdawei/p/4756415.html
主机软件片选就对了
主机选择软件片选后,内部NSS会自动保持高电平(也就是SSI),好像是为了维持自己的主机状态,这个可以去看初始化函数定义以及SPI寄存器定义,就可以知道了。如下图:
左侧是SPI_Init函数内部,可以看到CR1寄存器是一堆参数的或运算;
右上角是软硬件片选模式选择,可以看到软件模式是将CR1寄存器的SSM位置1即使能软件片选;
右中是主从机模式选择,可以看到当选择主机模式时,实际上是将CR1的SSI和MSTR位置1;
记住一句话,选择了软件片选以后,原先的SPI_CS引脚就可以随便用了,你甚至可以直接不复用PA4为SPI_CS,可以把它配置成普通GPIO口输出高低电平来控制一个从机。 当然,选择主机的其他任何一个GPIO口都是可以的。软件片选意味着,选谁已经完全由代码来决定了,有几个从机就要使用几个GPIO口来对应从机,当然可以使用一个扩展器来节约GPIO口(类似编码解码的功能),给谁输出低电平就是和谁交换数据。这样多方便啊。
从机硬件片选
实际上先前已经提到过,从机的硬件片选比较简单,使用默认的SPI_CS引脚作为片选信号的来源就可以了。因为硬件模式下时,SPI的内部NSS电平由外部NSS控制,所以从机的配置会很简单。最开始我以为主从机的软硬件片选应当保持一致,但是现在我的观点是:主机选择软件片选对于一主多从很方便,从机选择硬件片选配合,这样比较好。
从机软件片选
从机的软件片选是比较麻烦的。因为,从机的内部NSS电平是由从机CR1寄存器的SSI位决定的。同时,如果从机选择了软件片选,那么原本可以复用成SPI_CS的引脚也和普通引脚没有区别了。在标准库中,有一个函数是:SPI_NSSInternalSoftwareConfig(User_SPI,SPI_NSSInternalSoft_Reset)。这个函数就是用来控制CR1寄存器的SSI位的。这就很明显了,我们可以随便指定从机的一个GPIO口与主机的片选引脚连接,使能外部边沿中断,在中断中判断如果拉低就调用上述函数将从机内部NSS拉低以片选,反之则取消片选。
这么做不是绕了很大的一圈么?为什么不直接用硬件片选呢?我没有意识到软件片选对于从机有什么其他的好处,如果有我没考虑到的请大家指点一下哈。
代码
主机软件片选SPI初始化
void SPI_INIT()
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(</