STM32 Advanced Learning (5)-SPI Protocol of Communication Protocol


Preface

Looking back at IIC, we know that IIC is a half-duplex communication, that is, reading and writing by both communicating parties cannot be performed at the same time. Therefore, each time communication is made, it is necessary to first determine whether it is reading or writing, which is more troublesome. So the current SPI is Very good solution to this problem.

1. Basic concepts of SPI

1. Introduction to SPI protocol

SPI is the abbreviation of Serial Peripheral Interface. It is a high-speed, full-duplex, synchronous communication bus, and only occupies four wires on the chip's pins, saving the chip's pins. At the same time, it saves space and provides convenience in PCB layout. It is precisely because of this simple and easy-to-use feature that more and more chips integrate this communication protocol, which is mainly used in EEPROM, FLASH, real-time clock, and AD converters. , and between the digital signal processor and the digital signal decoder.

2. SPI mode

SPI is divided into two modes: master and slave. An SPI communication system needs to contain one (and only one) master device and one or more slave devices.

The device that provides the clock is the master device (Master), and the device that receives the clock is the slave device (Slave). The read and write operations of the SPI interface are initiated by the master device. When there are multiple slave devices, they are managed through their respective chip select signals.

SPI is full-duplex and SPI has no defined speed limit. General implementations can usually reach or even exceed 10 Mbps.
insert image description here

3. SPI signal line

The SPI interface generally uses four signal lines for communication:

SDI (data input), SDO (data output), SCK (clock), CS (chip select)

MISO: Master input/slave output pin. This pin transmits data in slave mode and receives data in master mode.
MOSI: Master output/slave input pin. This pin transmits data in master mode and receives data in slave mode.
SCLK: Serial clock signal, generated by the master device.
CS/SS: Slave device chip select signal, controlled by the master device. Its function is to serve as a "chip select pin", that is, to select a specified slave device, so that the master device can communicate with a specific slave device independently to avoid conflicts on the data line.
insert image description here

4. SPI device selection

SPI is a single-master communication protocol, which means that only one central device in the bus can initiate communication.

When the SPI master device wants to read/write [slave device]:
① It first pulls the SS line corresponding to [slave device] low (SS is active low level)
② Then starts to send working pulses to the clock line
③ In the corresponding pulse In terms of time, [the master device] sends the signal to MOSI to achieve "writing", and at the same time, it can sample MISO to achieve "reading"

5. SPI data sending and receiving

Both the SPI master and slave have a serial shift register , and the master initiates a transfer by writing a byte to its SPI serial register .

① First pull the corresponding SS signal line low to indicate communication with the device
② The host tells the slave to write data or read data by sending the SCLK clock signal. (It should be noted here that the SCLK clock signal may be active at low level or at high level, because SPI has four modes) ③The
host (Master) writes the data to be sent to the sending data buffer area (Menory), and caches The area passes through the shift register (0~7). The serial shift register moves out the bytes one by one through the MOSI signal line and transmits them to the slave. At the same time, the data received by the MISO interface passes through the shift register one by one.
④The slave (Slave) also returns the contents of its own serial shift register (0~7) to the host through the MISO signal line. At the same time, the data sent by the host is received through the MOSI signal line.

In this way, the contents of the two shift registers are exchanged.

Notice:

SPI is only divided into master mode and slave mode. There is no term for reading and writing. The writing and reading operations of peripherals are completed synchronously.
If only a write operation is performed, the master only needs to ignore the received byte; conversely, if the master wants to read a byte from the slave, it must send a null byte to trigger the slave's transmission.
In other words, if you send a data, you will definitely receive a data; if you want to receive a data, you must also send a data first.

6. Four modes of SPI communication

The four modes of SPI are simply to set the signal on the SCLK clock signal line as a valid signal.

The difference between them is that they define which edge of the clock pulse toggles the output signal, which edge samples the input signal, and the stable level value of the clock pulse (that is, whether the clock signal is high or low when it is inactive). Each mode is characterized by a pair of parameters called clock polarity (CPOL) and clock phase (clock phase) CPHA.

SPI communication has 4 different operating modes. Different slave devices may be configured in a certain mode at the factory, which cannot be changed. But our communication parties must work in the same mode,
so we can configure the SPI mode of our main device and control the communication mode of our main device through CPOL (clock polarity) and CPHA (clock phase). The details are as follows
:

  1. Clock polarity (CPOL) defines the clock idle state level:

CPOL=0, means that it is in the idle state when SCLK=0, so the effective state is when SCLK is at high level ** (high effective)**
CPOL=1, means that it is in the idle state when SCLK=1, so the effective state is SCLK When low **(active low)**

  1. Clock phase (CPHA) defines the time at which data is collected.

CPHA=0, data sampling is performed on the first transition edge of the clock (rising edge or falling edge). Send data on the second edge** (1 sampling, 2 sending)**
CPHA=1, perform data sampling on the second transition edge of the clock (rising edge or falling edge). Send data on the 1st edge** (1 send, 2 picks)**

For example:

Mode0: CPOL=0, CPHA=0: In the idle state at this time, SCLK is at low level; data sampling is on the first edge, which is the transition of SCLK from low level to high level; so the data sampling is On the rising edge, data is sent on the falling edge.

Mode1: CPOL=0, CPHA=1: In the idle state at this time, SCLK is at low level; data is sent on the first edge, which is the transition of SCLK from low level to high level; so the data sampling is On the falling edge, data is sent on the rising edge.

Mode2: CPOL=1, CPHA=0: In the idle state at this time, SCLK is at high level; data sampling is on the first edge, which is the transition of SCLK from high level to low level; so the data collection is On the falling edge, data is sent on the rising edge.

Mode3: CPOL=1, CPHA=1: In the idle state at this time, SCLK is at high level; data is sent on the first edge, which is the transition of SCLK from high level to low level; so the data acquisition is On the rising edge, data is sent on the falling edge.

Note: Data sampling = preparing data

CPOL=0: High effective, 0 to 1, that is, the rising edge is the first edge

CPOL=1: Active low, 1 to 0, that is, the falling edge is the first edge

7. SPI communication protocol

The master and slave devices must use the same operating mode - SCLK, CPOL and CPHA to work properly.

If there are multiple slave devices and they use different working modes, the master device must re-modify the mode of the corresponding slave device when reading and writing different slave devices.

This is the case with SPI. It does not specify the maximum transmission rate, address scheme, communication response mechanism, or flow control rules.

As long as the four signal lines are connected correctly and the SPI mode is the same, pull the CS/SS signal line low, you can communicate directly, transmit one byte at a time, read and write data simultaneously, this is SPI

SPI does not care about the electrical characteristics of the physical interface, such as the standard voltage of the signal.

This is also a shortcoming of the SPI interface: there is no specified flow control and no response mechanism to confirm whether data has been received.

8. Three modes of SPI

SPI works in three modes: running, waiting and stopping.

1. Run Mode (Run Mode)
This is the basic operating mode

2. Wait Mode (Wait Mode)
SPI works in wait mode, which is a configurable low-power consumption mode that can be controlled through the SPISWAI bit of the SPICR2 register. In wait mode, if the SPISWAI bit is cleared to 0, SPI operation is similar to run mode. If the SPISWAI bit is set, the SPI enters a low power state and the SPI clock will be turned off. If the SPI is configured as master, all transfers will stop, but will be restarted after the CPU enters run mode. If SPI is configured as a slave, it will continue to receive and transmit one byte, thus ensuring that the slave is synchronized with the master.

3. Stop Mode (Stop Mode)
In order to reduce power consumption, SPI is inactive in stop mode. If the SPI is configured as master, ongoing transfers will stop, but will restart after the CPU enters run mode. If SPI is configured as a slave, it will continue to receive and send one byte, thus ensuring that the slave is synchronized with the master.

2. Understand the SPI communication process with the help of punctual atomic SPI routines

1.W25Q128 introduction

W25Q128 is a large-capacity SPI FLASH product launched by Winbond . The capacity of W25Q128 is 128Mb. This series also includes W25Q80/16/32/64, etc.
The capacity of W25Q128 selected by ALIENTEK is 128Mb, which is 16M bytes.
W25Q128 divides the 16M capacity into 256 blocks (Block), each block is 64K bytes in size, and each block is divided into 16 sectors (Sector), each sector is 4K bytes. The minimum erasing unit of W25Q128 is one sector, that is, 4K bytes must be erased each time. In this way, we need to open a cache area of ​​at least 4K for W25Q128, which has relatively high requirements on SRAM. The chip must have more than 4K SRAM to operate well.
W25Q128 has an erase and write cycle of up to 10W times, has a data retention period of 20 years, and supports a voltage of 2.7~3.6V. W25Q128 supports standard SPI and also supports dual-output/quad-output SPI. The maximum SPI clock can reach 80Mhz (dual Equivalent to 160Mhz when output, equivalent to 320M when using four outputs). For more introduction to W25Q128, please refer to the DATASHEET of W25Q128.

2.SPI initialization program

①SPI.h

#ifndef __SPI_H
#define __SPI_H
#include "sys.h"
	  	    													  
void SPI2_Init(void);			 //初始化SPI口
void SPI2_SetSpeed(u8 SpeedSet); //设置SPI速度   
u8 SPI2_ReadWriteByte(u8 TxData);//SPI总线读写一个字节 
#endif

Compared with IIC, it is still very simple, with only three functions.

②SPI2_Init(void) function

void SPI2_Init(void)
{
    
    
 	GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;

	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 
	RCC_APB1PeriphClockCmd(	RCC_APB1Periph_SPI2,  ENABLE );//SPI2时钟使能 	
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB

 	GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15上拉

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;		//串行同步时钟的空闲状态为高电平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;	//串行同步时钟的第二个跳变沿(上升或下降)数据被采样
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;		//定义波特率预分频的值:波特率预分频值为256
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRC值计算的多项式
	SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
 
	SPI_Cmd(SPI2, ENABLE); //使能SPI外设
	SPI2_ReadWriteByte(0xff);//启动传输,这句话最大的作用就是维持 MOSI
//为高电平,而且这句话也不是必须的,可以去掉。		 
}   

First, configure the IO port, check the manual:
insert image description here
PB13, 14, and 15 correspond to (SCK., MISO, MOSI), while the CS chip select uses software management.

Here comes the point: What do these parameters of SPI mean?

typedef struct
{
    
    
  uint16_t SPI_Direction;          
  uint16_t SPI_Mode;               
  uint16_t SPI_DataSize;         
  uint16_t SPI_CPOL;              
  uint16_t SPI_CPHA;              
  uint16_t SPI_NSS;                
  uint16_t SPI_BaudRatePrescaler;  
  uint16_t SPI_FirstBit;            
  uint16_t SPI_CRCPolynomial;     
}SPI_InitTypeDef;

Borrowing the picture from this boss to explain:
insert image description here
The first parameter SPI_Direction is used to set the SPI communication method. It can be selected as half-duplex, full-duplex, and serial transmission and serial reception. Here we choose full-duplex SPI_Direction_2Lines_FullDuplex.
The second parameter SPI_Mode is used to set the master-slave mode of SPI. Here we set it to the master mode SPI_Mode_Master . If necessary, you can also choose the slave SPI_Mode_Slave.
The third parameter SPI_DataSiz is the 8-bit or 16-bit frame format selection. Here we are 8-bit transmission, select SPI_DataSize_8b.
The fourth parameter SPI_CPOL is used to set the clock polarity. We set the idle state of the serial synchronization clock to high level so we choose SPI_CPOL_High.
The fifth parameter SPI_CPHA is used to set the clock phase, that is, to select which edge (rising or falling) of the serial synchronization clock the data is sampled on. It can be collected for the first or second edge. Here we Select the second transition edge, so select
the sixth parameter SPI_NSS of SPI_CPHA_2Edge to set whether the NSS signal is controlled by hardware (NSS pin) or software. Here we control the NSS key through software instead of automatic hardware control, so select SPI_NSS_Soft.
The seventh parameter SPI_BaudRatePrescaler is very critical, that isSetting the SPI baud rate prescaler value is the parameter that determines the SPI clock. There are 8 optional values ​​from the channel 256 divider. During initialization, we choose the 256 divider value SPI_BaudRatePrescaler_256, and the transmission speed is 36M/256=140.625 KHz.
The eighth parameter SPI_FirstBit sets the data transmission order whether MSB bit first or LSB bit first. Here we choose SPI_FirstBit_MSB high bit first.
The ninth parameter SPI_CRCPolynomial is used to set the CRC check polynomial to improve communication reliability. It can be greater than 1. After setting the above 9 parameters, we can initialize the SPI peripherals.

③SPI read and write byte function

//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI2_ReadWriteByte(u8 TxData)
{
    
    		
	u8 retry=0;				 	
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
		{
    
    
		retry++;
		if(retry>200)return 0;
		}			  
	SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
	retry=0;

	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
		{
    
    
		retry++;
		if(retry>200)return 0;
		}	  						    
	return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据					    
}

(1) It should be known that once the master and the slave communicate in SP, for the master, when it sends a byte to the slave, it will also receive a byte of data from the slave at the same time. Same reason.
(2) Loop waiting for the send buffer empty flag bit to be set and retry a maximum of 200 times; send one byte of data to SPI2 through the SPI_I2S_SendData function; loop wait for the receive buffer non-empty flag bit to be set and retry a maximum of 200 times; Returns the most recent data received via SPI2.

3. Main programs related to W25Q128

Here we first introduce a question: SPI has four lines, SCK, MISO, and MOSI have been initialized. What about the chip select CS?
In the software, the corresponding slave can be selected by controlling the output level of the GPIO port of the NSS signal . When communicating with a slave, pull the NSS port of the slave low, and keep the NSS ports of other slaves high. When the communication is completed, the NSS port of the slave is pulled high to release the bus control of the slave to communicate with other slaves.
Therefore, it is necessary for us to set the port of the slave device as a chip select port.

①Initialize chip select port

void W25QXX_Init(void)
{
    
    	
  GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;  // PB12 推挽 
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
 	GPIO_SetBits(GPIOB,GPIO_Pin_12);
 
        W25QXX_CS=1;				//SPI FLASH不选中
	SPI2_Init();		   	//初始化SPI
	SPI2_SetSpeed(SPI_BaudRatePrescaler_2);//设置为18M时钟,高速模式
	W25QXX_TYPE=W25QXX_ReadID();//读取FLASH ID.  

}  

②W25QXX_Read function: used to read data of specified length from the specified address of W25Q128

//读取SPI FLASH  
//在指定地址开始读取指定长度的数据
//pBuffer:数据存储区
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节数(最大65535)
void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)   
{
    
     
 	u16 i;   										    
	W25QXX_CS=0;                            	//使能器件   
    SPI2_ReadWriteByte(W25X_ReadData);         	//发送读取命令   
    SPI2_ReadWriteByte((u8)((ReadAddr)>>16));  	//发送24bit地址    
    SPI2_ReadWriteByte((u8)((ReadAddr)>>8));   
    SPI2_ReadWriteByte((u8)ReadAddr);   
    for(i=0;i<NumByteToRead;i++)
	{
    
     
        pBuffer[i]=SPI2_ReadWriteByte(0XFF);   	//循环读数  
    }
	W25QXX_CS=1;  				    	      
}  

Since W25Q128 supports reading data starting from any address (but not exceeding the address range of W25Q128), this code is relatively simple. After sending the 24-bit address, the program can start reading data in a loop, and its address It will be added automatically, but please note that the data that cannot be read exceeds the address range of W25Q128! Otherwise, the data read out will not be the data you want.

③W25QXX_Write

u8 W25QXX_BUFFER[4096];		 
void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)   
{
    
     
	u32 secpos;
	u16 secoff;
	u16 secremain;	   
 	u16 i;    
	u8 * W25QXX_BUF;	  
   	W25QXX_BUF=W25QXX_BUFFER;	     
 	secpos=WriteAddr/4096;//扇区地址  
	secoff=WriteAddr%4096;//在扇区内的偏移
	secremain=4096-secoff;//扇区剩余空间大小   
 	//printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
 	if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节
	while(1) 
	{
    
    	
		W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容
		for(i=0;i<secremain;i++)//校验数据
		{
    
    
			if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除  	  
		}
		if(i<secremain)//需要擦除
		{
    
    
			W25QXX_Erase_Sector(secpos);		//擦除这个扇区
			for(i=0;i<secremain;i++)	   		//复制
			{
    
    
				W25QXX_BUF[i+secoff]=pBuffer[i];	  
			}
			W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区  

		}else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间. 				   
		if(NumByteToWrite==secremain)break;//写入结束了
		else//写入未结束
		{
    
    
			secpos++;//扇区地址增1
			secoff=0;//偏移位置为0 	 

		   	pBuffer+=secremain;  				//指针偏移
			WriteAddr+=secremain;				//写地址偏移	   
		   	NumByteToWrite-=secremain;			//字节数递减
			if(NumByteToWrite>4096)secremain=4096;//下一个扇区还是写不完
			else secremain=NumByteToWrite;		//下一个扇区可以写完了
		}	 
	};	 
}

This code snippet is used to write data to the W25QXX flash memory chip.

Function W25QXX_Write accepts three parameters: pBuffer, WriteAddr and NumByteToWrite.

pBuffer is a pointer to the buffer containing the data to be written.
WriteAddr is the starting address within the flash memory to which data is to be written.
NumByteToWrite is the number of bytes to write.
This function first calculates the sector address (secpos) and the offset within the sector (secoff) based on WriteAddr, and then calculates the remaining space in the sector (secremain) based on WriteAddr.

The function then enters a loop where it reads the entire sector into the W25QXX_BUF buffer and checks if any data needs to be erased. If data needs to be erased, the function calls the W25QXX_Erase_Sector function to erase the sector, copies the data from pBuffer to W25QXX_BUF, and uses the W25QXX_Write_NoCheck function to write the entire sector back to the flash memory.

If the data does not need to be erased, the function directly uses the W25QXX_Write_NoCheck function to write the data directly from the pBuffer to the remaining space in the sector.

The function then updates the sector address, offset, pBuffer, WriteAddr, and NumByteToWrite to continue writing the remaining data in subsequent sectors. The loop continues until all data has been written.

Summarize

To use SPI to allow STM32 to act as a master and slave for data interaction, the following steps need to be performed:
Configure the SPI bus:
First, configure the SPI peripherals of STM32, including setting the communication mode (full duplex, half duplex, etc.), data bit width , clock polarity and phase and other parameters.
Then, configure the SPI pins and connect the SPI SCLK, MISO, MOSI and chip select signal (CS) pins to the slave.

Initialize the slave:
According to the requirements of the slave, select the appropriate SPI mode (master mode or slave mode) and initialize.
If the slave has a specific initialization sequence or configuration register, it needs to be set according to the slave's specification manual.
Data interaction:

On the master, use the SPI send data function to send the data to the slave.
On the slave machine, use the SPI data receiving function to receive the data sent by the master.
The slave device communicating with the host is selected through the SPI chip select signal (CS).

Process data:
On the host, process the data returned from the slave as needed. Data can be saved to a buffer for calculation, display, or other operations.
On the slave machine, the corresponding operation is performed according to the data sent by the master machine, and the result is returned to the master machine.
End communication:
When the required data exchange is completed, SPI communication can be closed or the SPI peripheral disabled.

Guess you like

Origin blog.csdn.net/qq_53092944/article/details/132250947