1、SPI简介
?
2、函数配置
1、SPI简介
SPI通信是一种高速的,全双工的同步通信总线,通讯时,只占用四条线:MISO MOSI CS SCLK,其中cs为片选线,sclk为时钟线(一般同步通讯带有时钟线,像uart异步通信的就不带),miso和mosi这个就是主入从出和主出从入的信号线。下面看下spi的工作过程。
?这边在主机和从机都会有一个移位寄存器,spi的数据是如何传输的呢,从图中可知,spi是全双工,那么在我们读取一个字节的时候,也会写一个字节进去,这样就相当于两个移位寄存器的内容进行了交换。一般开始的时候,主机都会向从机写入一个字节来开始spi的传输,所以后面的代码段我们会看见主机向从机写一个0xff作为spi的开始,实际上这个值可以取任何值,都可以作为spi的开始信号。如果我们只进行写操作,那么我们可以忽略读进来的内容,同理,如果我们进行读操作,那么我们就可以随便写一个内容(但是为了麻烦通常都写0xff)。
2、函数配置
这边我们选取的是W25Q128,这边给128除以8,可以看出这个flash可以存储16m的字节。下面我们开始函数的配置。这边选取的stm32f103zet6的spi2作为实验接口。
1、spi2的初始化,初始化spi的话肯定要先初始化gpio口时。这边由硬件连我们去查芯片手册,我们可以得到各个引脚的模式,这边mosi选择的是推挽输出,miso芯片手册上显示的是配置成上拉输入和浮空输入(这边选择配置为推挽输出,也能工作),还有一个sclk的时钟信号输入,这边选择也是推挽输出。初始化gpio后,需要初始化spi2,这边需要注意几个个参数,一个是CPOL和CPHA,这两个参数一个是配置spi空闲时是高电平还是低电平,一个是配置spi通信是是第一个时钟沿还是第二个时钟沿开始数据捕获.这边我们选择空闲时电平为高电平,选择在第二个时钟沿开始数据捕获。还有这边cs引脚选择软件控制,其中的一个参数crc需要大于1,这里选择7,这里的预分频系数由于是初始化,所以选择的频率可以很低,这边选择预分频系数为256,后面开始传输的时候我们再提高spi的频率,我们的片选引脚是我们给定的io控制的,所以我们选择软件控制。
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置 SPI 全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置 SPI 工作模式:设置为主 SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 8 位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//选择了串行时钟的稳态:时钟悬空高?
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //数据捕获于第二个时钟沿?
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS 信号由硬件管理 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //预分频 256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从 MSB 位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC 值计算的多项式
2、spi的速率设置。这里主要操作的spi2的CR1寄存器,这里主要是判断spi的预分频系数是否是给定的几个数字,如果是的话,就操作CR1寄存器修改spi的速率。
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler) { assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler)); SPI2->CR1&=0XFFC7; SPI2->CR1|=SPI_BaudRatePrescaler; //设置 SPI2 速度 SPI_Cmd(SPI2,ENABLE); }
3、spi的读写一个字节
在我们使用spi发送和接收数据的时候,一般我们都需要等待spi忙完,这时我们可以去获取spi2的状态,我们发送数据的时候,我们去获取?SPI_I2S_FLAG_TXE这个状态,如果这个状态是0,说明此时spi2处于发送状态,那么就等待发送完成,发送之后,由于spi是发送的同时在接收,紧接著我们获取spi的接收状态?SPI_I2S_FLAG_RXNE,所以这边我们等待spi接收完成,然后返回我们接收的值。这就是一个spi的接收和发送数据的过程。
4、在使用W25QXX的时候,由于我们使用的是软件片选在,在初始化flash时,我们要初始化我们的片选io口。
5、下面说一下W25QXX的读写过程,读操作相对于写操作简单一点。读操作:首先我们拉低片选引脚,然后我们向flash发送读命令,紧接着我们向flash发送我们读取的地址,flash在收到我们的地址之后就会把相应位置的数据发送过来,发送完一个字节之后,地址会自动加一,这样我们通过这一个命令就可以读取flash的全部数据或者指定长度的数据(不受扇区等的限制)。而写操作相对于读操作就相对来说复杂一点,一部分原因是因为向W25QXX写入数据时需要保证我们写入的扇区是擦除过的,另一方面是我们每写完一个扇区(256个字节)的时候,我们必须把地址给清零,否则的话,你这个地址就会作为扇区地址,那样256个字节之后的内容就会写到其他的扇区而不是下一个扇区了。所以我们综上两点,写操作就比读操作麻烦。
|