收藏 分享(赏)

STM32的SPI通信总结(含DMA).docx

上传人:pw17869 文档编号:4272725 上传时间:2018-12-19 格式:DOCX 页数:15 大小:702KB
下载 相关 举报
STM32的SPI通信总结(含DMA).docx_第1页
第1页 / 共15页
STM32的SPI通信总结(含DMA).docx_第2页
第2页 / 共15页
STM32的SPI通信总结(含DMA).docx_第3页
第3页 / 共15页
STM32的SPI通信总结(含DMA).docx_第4页
第4页 / 共15页
STM32的SPI通信总结(含DMA).docx_第5页
第5页 / 共15页
点击查看更多>>
资源描述

1、STM32-SPI(DMA )通信的总结 (库函数操作)本文主要由 7 项内容介绍 SPI 并会在最后附上测试源码供参考:1. SPI 的通信协议2. SPI 通信初始化( 以 STM32 为从机,LPC1114 为主机介绍)3. SPI 的读写函数4. SPI 的中断配置5. SPI 的 SMA 操作6. 测试源码7. 易出现的问题及原因和解决方法一、 SPI 的通信协议SPI(Serial Peripheral Interface)是一种串行同步通讯协议,由一个主设备和一个或多个从设备组成,主设备启动一个与从设备的同步通讯,从而完成数据的交换。SPI 接口一般由 4 根线组成,CS 片选信

2、号(有的单片机上也称为 NSS) ,SCLK 时钟信号线, MISO 数据线(主机输入从机输出) ,MOSI 数据线(主机输出从机输入) ,CS 决定了唯一的与主设备通信的从设备,如没有 CS 信号,则只能存在一个从设备,主设备通过产生移位时钟信号来发起通讯。通讯时主机的数据由 MISO输入,由 MOSI 输出,输入的数据在时钟的上升或下降沿被采样,输出数据在紧接着的下降或上升沿被发出(具体由 SPI 的时钟相位和极性的设置而决定) 。二、 以 STM32 为例介绍 SPI 通信1. STM32f103 带有 3 个 SPI 模块其特性如下:2 SPI 初始化初始化 SPI 主要是对 SPI

3、要使用到的引脚以及 SPI 通信协议中时钟相位和极性进行设置,其实 STM32 的工程师已经帮我们做好了这些工作,调用库函数,根据自己的需要来修改其中的参量来完成自己的配置即可,主要的配置是如下几项: 引脚的配置SPI1 的 SCLK, MISO ,MOSI 分别是 PA5,PA6,PA7 引脚,这几个引脚的模式都配置成 GPIO_Mode_AF_PP 复用推挽输出(关于 GPIO 的 8种工作模式如不清楚请自己百度,在此不解释) ,如果是单主单从,CS 引脚可以不配置,都设置成软件模式即可。 通信参数的设置1. SPI_Direction_2Lines_FullDuplex 把 SPI 设置

4、成全双工通信;2. 在 SPI_Mode 里设置你的模式(主机或者从机) ,3. SPI_DataSize 是来设置数据传输的帧格式的 SPI_DataSize_8b 是指8 位数据帧格式,也可以设置为 SPI_DataSize_16b,即 16 位帧格式4. SPI_CPOL 和 SPI_CPHA 是两个很重要的参数,是设置 SPI 通信时钟的极性和相位的,一共有四种模式在库函数中 CPOL 有两个值 SPI_CPOL_High(=1)和 SPI_CPOL_Low ( =0).CPHA 有两个值 SPI_CPHA_1Edge (=0) 和 SPI_CPHA_2Edge(=1)CPOL 表示时

5、钟在空闲状态的极性是高电平还是低电平,而 CPHA 则表示数据是在什么时刻被采样的,手册中如下:我的程序中主、从机的这两位设置的相同都是设置成 1,即空闲时时钟是高电平,数据在第二个时钟沿被采样,实验显示数据收发都正常。(要特别注意极性和相位的设置否则,数据传输会出现错位的现象)一般主从机的这两个位要设置的一样,但是网上也有人说不能设置成一样的,在后文中我对主从机极性和相位的配置的 16 种情况都做了测试,结果见下文。 下图很好的描述了 4 种模式下的时序状况引用网友的一句话:“ SPI 主模块和与之通信的外设备时钟相位和极性应该一致。个人理解这句话有 2 层意思:其一,主设备 SPI 时钟和

6、极性的配置应该由外设的从设备来决定;其二,二者的配置应该保持一致,即主设备的 SDO 同从设备的 SDO 配置一致,主设备的 SDI 同从设备的 SDI 配置一致。因为主从设备是在 SCLK 的控制下,同时发送和接收数据,并通过 2 个双向移位寄存器来交换数据。 ”5. SPI_BaudRatePrescaler 波特率的设置这在主机模式中,这一位的设置直接决定了通信的传输速率,而从机的设置不会影响数据传输的速率,手册中有这样一句话:(实际测试中发现:当 STM32 作为从机时,它对波特率的设置会影响数据的通信,特别是在大数据两传输时,当主机 SPI 时钟设置为 15M 时,STM32 从机如

7、果是 2 分频即 18M 则会在多次传输时出现错误,我记得在资料中看到过有前辈的经验贴说 SPI 从机的时钟设置不能高于 SPI 主机的时钟设置,虽然理论上从机的时钟设置不影响 SPI 通信,但是在试验中我也验证,当 STM32 从机时钟设为 4 分频 9M,低于 15M 时,通信就不会出现问题。所以 SPI 从机波特率的设置最好低于 SPI 主机波特率的设置。)6. SPI_FirstBit 这一位是设置首先传输的高字节还是低字节SPI_FirstBit_MSB 是先传输高字节,SPI_FirstBit_LSB 是先传输低字节注意在初始化函数里还有两项重要的内容就是在初始化之前先使能 SPI

8、 的时钟和在初始化配置完成后使能 SPI。(初始化配置)三、 SPI 的读写函数SPI 有一个 16 位的数据寄存器 SPI_DR,它对应两个缓冲区,1 个发送缓冲区,1 个接收缓冲区,当在控制寄存器里 SPI_CR1 里对 DFF 位设置数据帧格式为 8 位时, 发送和接收只用到 SPI_DR7:0这 8 位,15-8 位被强制为 0,帧格式设置成 16 位时全用。读写过程在手册中是这样描述的:简而言之,发送时,可以通过检测 SPI_SR 中的 TXE 位,当数据寄存器里有数据时,TXE 位是 0,当数据全部从数据寄存器的发送缓冲区传输到移位寄存器时TXE 位被置 1,这时候可以再往数据寄存

9、器里写入数据。可以通过while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) = RESET) 来检测。SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) 是库函数,可以检测 SPI 的一些状态位。接收时,可以通过检测 SPI_SR 中的 RXNE 位,当数据寄存器里有数据时,RXNE 位是 0,当数据全部从数据寄存器的接收缓冲区传输到移位寄存器时RXNE 位被置 1,这时候可以从数据寄存器里读出数据。可以通过while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_

10、RXNE) = RESET); 来检测。源程序如下,SPI 读写一个字节,读写一体当能成功发送和接收一个字节时,发送数组数据就变的简单了,只需要一个 for 循环,和指针变量的递增即可。以下仅为参考:(有一点特别注意,从机数据传输时要依赖主机的时钟,所以主机在接收从机发送的数据时要往从机发送哑巴字节,这个字节可以自己定义 0xff,0xfe 等什么字节都可以)读写分开的函数:/*Description:spi1 通信发送数据*/void SPI_Ecah_Buffer_Send(u8* pBuffer, u16 NumByteToRead)for(int i = 0; i TXE 为 1 时,

11、会向对应的 DMA 通道发出请求,DMA 通道会发出应答信号, SPI 收到应答信号后撤销请求信号,DMA撤销应答信号,并把内存值装入 SPI_DR 的发送缓区,SPI 的传送开始。DMA 的初始化DMA_PeripheralBaseAddr 是值外设数据的地址,用 SPI1 故 DMA 外设地址对应的是 SPI1_DR_Addr,DMA_MemoryBaseAddr 是内存地址,它的值可以使,你要发送的数据所存放的数组的名,因为数组名代表的是数组数据存放的首地址,在 SPI-DMA的发送中可以理解为把 DMATX数组里的数据传送到 SPI1_DR_AddrDMA_DIR 是指数据传输的方向,

12、其值发送时其值为DMA_DIR_PeripheralDST 即外设是目的地,方向是 DMATX SPI1_DR_Addr,在接受收时其值为 DMA_DIR_PeripheralSRC,即外设是数据的来源,传输方向是 SPI1_DR_Addr用户指定的数据存储数组。DMA_BufferSize 用来设置传输数据的个数,在 STM32 的 DMA 中其值的范围是 065536.DMA_Mode 指 DMA 的传输模式 DMA_Mode_Normal 为正常工作模式DMA_Mode_Circular 是循环工作模式,这里对循环模式的解释我认为有位网友解释的很不错如下:“循环的意思是指 DMA 的传输

13、数量计数器会重置初值,由于 DMA 每传一个数据,传输数量计数器减一,只有在传输数量计数器的值不为零时,才会响应请求。在循环模式下,当传输计数器的值减为 0 后,会重新装载;而内存(缓存)地址则不管循环非循环模式,都会在每次传输完成后重置为基地址。所以,如果我们把 DMA 设置会正常模式,那么在下次传输前,只需对 DMA 的传输数量计数器重新写入就行。循环模式一般用于数据更新,比如 ADC 采用需要不停更新数据。 ”在初始化完成之后要开启 DMA 的中断,在我的程序中开启的是 DMA 传输完成中断。DMA 传输有 3 个中断标志位,常用的是传输完成的中断。如下:这样在传输完设定的数据个数之后就

14、会触发传输完成的中断,用户可以再中断服务函数中,进行相应的操作,有一点特别注意,就是要及时清除中断标志位,为下次能够正常触发中断做准备。在我的中断服务函数中有一个标志位 SpiCommon,被置 1 后再中断之外进行其他的处理,同时调用 DMA_ClearITPendingBit(DMA1_IT_TC2)来及时清除中断标志。在进行 DMA 的数据传输时要先禁能 DMA 的通道,重置传输数据个数的值,数据的存储位置等,再使能 DMA 的通道,等待 DMA 的传输完成。我的操作时这样的,先往 DMATX里写入相应的数据,然后如下这样可能有一点不好的地方,因为只改变了 SpiTXSize 的值,却又

15、重新执行了 DMATXInit() 函数,可能此处能够再改善一下。六 测试中出现的问题及原因和解决方法 示波器观察主机能够产生正确的时钟,主机输出引脚也能产生正确的数据,但是从机不能接受数据。可能原因:1. 从机的接收中断配置不正确,或者没有打开相应的中断。2. 在从机中 TXEIE 的中断和 TXDMAEN 的中断都被使能,手册中说,这两个中断只能使能 1 个. 从机能接收数据,但是接收的数据乱码可能原因:1. 主从机的时钟相位和极性的配置导致的,关于这一点想做一下说明,网上有人说,主从机时钟的相位和极性要配置的一样,也有人说不能配置的一样,而我对于主从机的相位和极性的 16 种组合情况全做

16、了试验,结果如下:(主机 LPC1114 的 SPI1 从机 STM32 的 SPI1) (表示能正常通信)主 从 通信CPOL CPHA CPOL CPHA0 0 0 0 0 0 0 1 乱码(左移 1 位)0 0 1 0 乱码0 0 1 1 乱码0 1 0 0 乱码0 1 0 1 乱码0 1 1 0 0 1 1 1 乱码1 0 0 0 1 0 0 1 1 0 1 0 乱码1 0 1 1 乱码1 1 0 0 乱码1 1 0 1 乱码1 1 1 0 1 1 1 1 (当然可能上述的结果也跟测试环境有关,当对其有所怀疑时,读者不妨自己实验看一下。 )2. 乱码的第二个原因可能是两个设备没有共地而

17、造成的,在出现问题时一定要先检查一下硬件的连接是否正确,是否有虚焊接触不好的地方而导致通讯不正常。 (在信号要求高的电路里一定单独用一根线把主从机的地连接在一起) ,关于共地,不仅是要在电源接通时用万用表测试两点共地,在切断电源后用万用表测试,连点依然共地才是真正的共地。3. 乱码还有一个很重要的原因,就是主机能发出时钟,但是时钟的高电平不到 3.3V,我在调试中就出现过主机时钟和数据看波形正常,但是高电平只有 2.3V 左右,但从机的数据波形的高电平为 3.3V 左右,收发数据乱码,一直没找到原因,后来发现主机的高电平较低,怀疑是硬件的问题,更换主机后,SPI 通信正常了,所以出现了问题一定要先检查硬件是否合格,在保证硬件无误的情况下再分析软件程序的问题。 从机能接收数据,但接收的数据不全,又丢字节的现象发生。可能原因:1. 如果是通过串口打印来观察接收数据,那要看一下数据中是否有 0,结合自己的串口函数分析一下,因为打印数组或者字符串时遇 0 会截止。2. 看一下接收的数组中,其指针是否是递增的。3. 如果使用了 CS 片选信号,看一下主机发出的数据是否都在 CS 拉低的范围内。4. 在使用 DMA 的传输时一定要注意传输的数据个数一定要和 DMA 初始化中设置的传输个数相同否则,收到的数据可能会出现字节丢失的现象。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 实用文档 > 工作总结

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报