[How to set the polarity and phase of SPI in software] SPI is divided into master and slave devices, and the two communicate through the SPI protocol. The mode of SPI is set by the slave device, which determines the mode of the master device. Therefore, you must first understand the SPI mode of the slave device, and then set the SPI mode of the master device to the same mode as the slave device, so that normal communication can be achieved. There are two types of SPI modes for slave devices: (1) Fixed, determined by the SPI slave device hardware. The specific mode of the SPI slave device will be described in the relevant datasheet. You need to find the relevant description in the datasheet yourself, namely: Regarding the SPI slave device, when it is idle, is it high or low, which determines whether CPOL is 0 or 1; Then find out whether the device samples data on the rising edge or the falling edge. In this way, under the premise of determining the value of CPOL, it can be inferred whether CPHA is 0 or 1. Example 1: The SPI timing diagram in the datasheet of CC2500 - Low-Cost Low-Power 2.4 GHz RF Transceiver is:
From the figure, we can see that the initial SCLK and the SCLK at the end, that is, the SCLK at the idle time, are low levels, and CPOL=0 is deduced. Then we can see that when the data is sampled, that is, the point in the middle of the data, it corresponds to the first edge of SCLK, so CPHA=0 (this corresponds to the rising edge). Example 2: The datasheet of SSD1289 - 240 RGB x 320 TFT LCD Controller Driver mentions: "SDI is shifted into 8-bit shift register on every rising edge of SCK in the order of data bit 7, data bit 6 … data bit 0." This means that the data is sampled on the rising edge, so it can be determined that it is CPOL=0, CPHA=0, or CPOL=1, CPHA=1, but as to which mode it is. Logically, we should then determine whether SCLK is high or low when idle to determine whether CPOL is 0 or 1, but the datasheet does not mention this. Therefore, we are not sure whether both modes are supported or whether we need to find additional evidence to determine whether CPOL is 0 or 1. (2) Configurable, set by the software The slave device is also a SPI controller that supports all four modes. In this case, you only need to set it to a certain mode. After knowing the mode of the slave device, set the mode of the SPI master device to the same as the slave device mode. As for how to configure SPI's CPOL and CPHA, I will not go into details. Most people directly write the two bits CPOL and CPHA in the corresponding register of the corresponding SPI controller, writing 0 or 1. For example: The SPI in C8051F347 is an SPI controller, which supports software configuration of CPOL and CPHA values and supports four modes. Here, C8051F347 is used as a SPI slave device and the mode of CPOL=1, CPHA=0 is set. Therefore, the SPI controller in the main chip here, as a Master device, also needs to set its SPI mode to CPOL=1, CPHA=0.
[SPI read and write program design] The parts marked in red in the text are especially important to read. You should be familiar with the instruction set of the flash chip and the understanding of the sectors and blocks of the storage chip. The most important thing is that erasing is done in the form of sector erasing.
This section will use SPI to read and write external FLASH (W25X16) and display the results on the TFTLCD module. This section is divided into the following parts:
3.17.1 Introduction to SPI
3.17.2 Hardware Design
3.17.3 Software Design
3.17.4 Download and test
1 Introduction to SPI
SPI is the abbreviation of Serial Peripheral interface, which means serial peripheral interface. It was first defined by Motorola on its MC68HCXX series processors. The SPI interface is mainly used in EEPROM, FLASH, real-time clock, AD converter, and between digital signal processor and digital signal decoder. SPI is a high-speed, full-duplex, synchronous communication bus, and only occupies four wires on the chip pins, which saves the chip pins and saves space on the PCB layout, providing convenience. It is precisely because of this simple and easy-to-use feature that more and more chips are now integrated with this communication protocol, and STM32 also has a SPI interface.
The SPI interface generally uses 4 lines:
MISO Master device data input, slave device data output.
MOSI Master device data output, slave device data input.
SCLK clock signal, generated by the master device.
CS is the chip select signal from the device and is controlled by the master device.
The main features of SPI are: it can send and receive serial data at the same time; it can work as a master or a slave; it provides a frequency-programmable clock; it has a send end interrupt flag; it has write conflict protection; it has bus contention protection, etc.
Four working modes of SPI bus In order to exchange data with peripherals, the SPI module can configure the polarity and phase of its output serial synchronous clock according to the working requirements of the peripherals. The clock polarity (CPOL) has no significant impact on the transmission protocol. If CPOL=0, the idle state of the serial synchronous clock is low; if CPOL=1, the idle state of the serial synchronous clock is high. The clock phase (CPHA) can be configured to select one of two different transmission protocols for data transmission. If CPHA=0, the data is sampled at the first transition edge (rising or falling) of the serial synchronous clock; if CPHA=1, the data is sampled at the second transition edge (rising or falling) of the serial synchronous clock. The clock phase and polarity of the SPI master module and the peripheral device communicating with it should be consistent.
The bus data transmission timing under different clock phases is shown in the figure below:
Figure 3.17.1.1 Bus transfer timing under different clock phases (CPHA=0/1)
The SPI function of STM32 is very powerful. The SPI clock can reach up to 18Mhz, supports DMA, and can be configured as SPI protocol or I2S protocol.
In this section, we will use the STM32 SPI to read the external SPIFLASH chip (W25X16) to achieve similar functions as in the previous section. Here we will only briefly introduce the use of SPI. For a detailed introduction to the STM32 SPI, please refer to page 422, section 22 of the "STM32 Reference Manual". Then we will introduce the SPIFLASH chip.
In this section, we use the master mode of SPI1 of STM32. Let's take a look at the setting steps of SPI1. The master mode configuration steps of STM32 are as follows:
1) Configure the multiplexing function of the relevant pins and enable the SPI1 clock.
We want to use SPI1, the first step is to enable the clock of SPI1, which is set by the 12th bit of APB2ENR. Secondly, the relevant pins of SPI1 should be set as multiplexed outputs, so that they can be connected to SPI1. Otherwise, these IO ports are still in the default state, that is, standard input and output ports. Here we use PA5, 6, and 7 (SCK., MISO, MOSI, CS uses software management), so these three are set as multiplexed IO.
2) Set the SPI1 working mode.
This step is all set up through SPI1_CR1. We set SPI1 to master mode, set the data format to 8 bits, and then set the SCK clock polarity and sampling mode through the CPOL and CPHA bits. And set the SPI1 clock frequency (maximum 18Mhz) and the data format (MSB first or LSB first).
3) Enable SPI1.
This step is to set bit6 of SPI1_CR1 to start SPI1. After starting, we can start SPI communication.
The use of SPI1 is introduced here. Next, let's introduce W25X16. W25X16 is a FLASH product with larger capacity after W25X10/20/40/80 (from 1Mb to 8Mb) launched by Winbond. The capacity of W25X16 is 16Mb. There is also W25X32/64 with even larger capacity. The capacity of W25X16 selected by ALIENTEK is 16Mb, that is, 2M bytes, which is the same size as AT45DB161.
W25X16 divides 2M capacity into 32 blocks, each block is 64K bytes, each block is divided into 16 sectors, each sector is 4K bytes. The minimum erase unit of W25X16 is one sector, which means 4K bytes must be erased each time. So we need to open up a cache area of at least 4K for W25X16, which has higher requirements on SRAM (compared to AT45DB161), but it has advantages in price and supply.
The W25X16 has a minimum cycle of 10,000 times, a data retention period of 20 years, and a supported voltage of 2.7~3.6V. The W25X16 supports standard SPI and dual-output SPI. The maximum SPI clock can reach 75Mhz (equivalent to 150Mhz when dual output). For more information about the W25X16, please refer to the W25X16 DATASHEET.
2 Hardware Design
Brief introduction of the experimental functions in this section: When starting up, first check whether W25X16 exists, then use one button in the main loop to write into W25X16, and another button to read out, and display the relevant information on the TFTLCD module. At the same time, use DS0 to indicate that the program is running.
The hardware resources to be used are as follows:
1) STM32F103RBT6.
2) DS0 (External LED0).
3) KEY0 and KEY2.
4) TFTLCD liquid crystal module.
5)W25X16.
We have already introduced the resources in the first four parts, please refer to the relevant chapters. Here we only introduce the connection between W25X16 and STM32. The W25X16 on the board is directly connected to the STM32F103RBT6. The connection relationship is as follows:
Figure 3.17.2.1 STM32F103RBT6 and W25X16 connection circuit diagram
3 Software Design
Open the project in the previous section, first create a FLASH folder and a SPI folder in the HARDWARE folder. Then create a flash.c and flash.h file and save them in the FLASH folder, create spi.c and spi.h files and save them in the SPI folder, and add these two folders to the header file include path.
Open the spi.c file and enter the following code:
#include "spi.h"
//SPI port initialization
//This is the initialization of SPI1
voidSPIx_Init(void)
{
RCC->APB2ENR|=1<<2; //PORTA clock enable
RCC->APB2ENR|=1<<12; //SPI1 clock enable
//Here is only for SPI port initialization
GPIOA->CRL&=0X000FFFFF;
GPIOA->CRL|=0XBBB00000; //PA5.6.7 multiplexing
GPIOA->ODR|=0X7<<5; //PA5.6.7 pull-up
SPI1->CR1|=0<<10; //Full-duplex mode
SPI1->CR1|=1<<9; //Software nss management
SPI1->CR1|=1<<8;
SPI1->CR1|=1<<2; //SPI master
SPI1->CR1|=0<<11; //8bit data format
SPI1->CR1|=1<<1; //SCK is 1 in idle mode CPOL=1
SPI1->CR1|=1<<0; //Data sampling starts from the second time edge, CPHA=1
SPI1->CR1|=7<<3; //Fsck=Fcpu/256
SPI1->CR1|=0<<7; //MSBfirst
SPI1->CR1|=1<<6; //SPI device enable
SPIx_ReadWriteByte(0xff); //Start transmission
}
//SPI speed setting function
//SpeedSet:
//SPI_SPEED_2 2-division (SPI 36M@sys 72M)
//SPI_SPEED_8 8-division (SPI 9M@sys 72M)
//SPI_SPEED_16 16-division (SPI 4.5M@sys 72M)
//SPI_SPEED_256256 division (SPI281.25K@sys 72M)
voidSPIx_SetSpeed(u8 SpeedSet)
{
SPI1->CR1&=0XFFC7;//Fsck=Fcpu/256
if(SpeedSet==SPI_SPEED_2)//Divided by two
{
SPI1->CR1|=0<<3;//Fsck=Fpclk/2=36Mhz
}else if(SpeedSet==SPI_SPEED_8)//eighth frequency division
{
SPI1->CR1|=2<<3;//Fsck=Fpclk/8=9Mhz
}else if(SpeedSet==SPI_SPEED_16)//16th frequency division
{
SPI1->CR1|=3<<3;//Fsck=Fpclk/16=4.5Mhz
}else //256 division
{
SPI1->CR1|=7<<3; //Fsck=Fpclk/256=281.25Khz low speed mode
}
SPI1->CR1|=1<<6; //SPI device enable
}
//SPIx read and write a byte
//TxData: Bytes to be written
//Return value: the bytes read
u8SPIx_ReadWriteByte(u8 TxData)
{ u8 retry=0;
while((SPI1->SR&1<<1)==0)//Wait for the send area to be empty
{ retry++;
if(retry>200)return 0;
}
SPI1->DR=TxData; //Send a byte
retry=0;
while((SPI1->SR&1<<0)==0) //Wait for receiving a byte
{ retry++;
if(retry>200)return 0;
}
return SPI1->DR; //Return received data
}
This part of the code mainly initializes SPI. Here we choose SPI1, so in the SPIx_Init function, the related operations are for SPI1, and its initialization steps are the same as we introduced above. After initialization, we can start using SPI1. In the SPIx_Init function, the baud rate of SPI1 is set to the lowest (281.25Khz). In the external function, we use SPIx_SetSpeed to set the speed of SPI1, and our data transmission and reception are realized through the SPIx_ReadWriteByte function.
Save spi.c and add the file to the RDWARE group. Then open spi.h and enter the following code:
#ifndef __SPI_H
#define __SPI_H
#include "sys.h"
//SPI bus speed setting
#define SPI_SPEED_2 0
#define SPI_SPEED_8 1
#define SPI_SPEED_16 2
#define SPI_SPEED_256 3
void SPIx_Init(void); //Initialize SPI port
void SPIx_SetSpeed(u8 SpeedSet); //Set SPI speed
u8 SPIx_ReadWriteByte(u8 TxData); //SPI bus reads and writes a byte
#endif
We will not introduce this part of the code in detail. Save spi.h, then open flash.c and enter the following code in it:
#include "flash.h"
#include "spi.h"
#include "delay.h"
//4Kbytes is a Sector
//16 sectors make up 1 Block
//W25X16
//The capacity is 2M bytes, with a total of 32 blocks and 512 sectors
//Initialize SPI FLASH IO
void SPI_Flash_Init(void)
{
RCC->APB2ENR|=1<<2; //PORTA clock enable
//here
GPIOA->CRL&=0XFFF000FF;
GPIOA->CRL|=0X00033300; //PA2.3.4 push-pull
GPIOA->ODR|=0X7<<2; //PA2.3.4 pull-up
SPIx_Init(); //Initialize SPI
}
//Read the status register of SPI_FLASH
//BIT7 6 5 4 3 2 1 0
//SPR RV TB BP2 BP1 BP0 WEL BUSY
//SPR: default 0, status register protection bit, used with WP
//TB,BP2,BP1,BP0: FLASH area write protection setting
//WEL: Write Enable Lock
//BUSY: busy flag (1, busy; 0, idle)
//Default: 0x00
u8 SPI_Flash_ReadSR(void)
{
u8byte=0;
SPI_FLASH_CS=0; //Enable device
SPIx_ReadWriteByte(W25X_ReadStatusReg); //Send the read status register command
byte=SPIx_ReadWriteByte(0Xff); //Read a byte
SPI_FLASH_CS=1; //Cancel chip select
returnbyte;
}
//Write SPI_FLASH status register
//Only SPR, TB, BP2, BP1, BP0 (bit7, 5, 4, 3, 2) can be written!!!
void SPI_FLASH_Write_SR(u8 sr)
{ SPI_FLASH_CS=0; //Enable device
SPIx_ReadWriteByte(W25X_WriteStatusReg); //Send write status register command
SPIx_ReadWriteByte(sr); //Write a byte
SPI_FLASH_CS=1; //Cancel chip select
}
//SPI_FLASH write enable
//Set WEL
void SPI_FLASH_Write_Enable(void)
{
SPI_FLASH_CS=0; //Enable device
SPIx_ReadWriteByte(W25X_WriteEnable); //Send write enable
SPI_FLASH_CS=1; //Cancel chip select
}
//SPI_FLASH write disabled
// Clear WEL
void SPI_FLASH_Write_Disable(void)
{ SPI_FLASH_CS=0; //Enable device
SPIx_ReadWriteByte(W25X_WriteDisable); //Send write disable command
SPI_FLASH_CS=1; //Cancel chip select
}
//Read chip ID W25X16 ID: 0XEF14
u16 SPI_Flash_ReadID(void)
{u16Temp = 0;
SPI_FLASH_CS=0;
SPIx_ReadWriteByte(0x90); //Send read ID command
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
Temp|=SPIx_ReadWriteByte(0xFF)<<8;
Temp|=SPIx_ReadWriteByte(0xFF);
SPI_FLASH_CS=1;
returnTemp;
}
//Read SPI FLASH
//Start reading data of the specified length at the specified address
//pBuffer: data storage area
//ReadAddr: start reading address (24bit)
//NumByteToRead: the number of bytes to read (maximum 65535)
void SPI_Flash_Read(u8* pBuffer,u32ReadAddr,u16 NumByteToRead)
{ u16 i;
SPI_FLASH_CS=0; //Enable device
SPIx_ReadWriteByte(W25X_ReadData); //Send read command
SPIx_ReadWriteByte((u8)((ReadAddr)>>16)); //Send 24-bit address
SPIx_ReadWriteByte((u8)((ReadAddr)>>8));
SPIx_ReadWriteByte((u8)ReadAddr);
for(i=0;i { pBuffer=SPIx_ReadWriteByte(0XFF); //Loop reading } SPI_FLASH_CS=1; //Cancel chip select } //SPI writes less than 256 bytes of data in one page (0~65535) //Start writing data up to 256 bytes at the specified address //pBuffer: data storage area //WriteAddr: start writing address (24bit) //NumByteToWrite: The number of bytes to be written (maximum 256), this number should not exceed the remaining bytes of the page!!! void SPI_Flash_Write_Page(u8* pBuffer,u32WriteAddr,u16 NumByteToWrite) { u16 i; SPI_FLASH_Write_Enable(); //SET WEL SPI_FLASH_CS=0; //Enable device SPIx_ReadWriteByte(W25X_PageProgram); //Send page write command SPIx_ReadWriteByte((u8)((WriteAddr)>>16)); //Send 24-bit address SPIx_ReadWriteByte((u8)((WriteAddr)>>8)); SPIx_ReadWriteByte((u8)WriteAddr); for(i=0;i SPI_FLASH_CS=1; //Cancel chip select SPI_Flash_Wait_Busy(); //Wait for writing to end } //Write SPI FLASH without checking // Make sure that all data in the address range you write is 0XFF, otherwise data written at non-0XFF will fail! //With automatic page change function //Start writing data of the specified length at the specified address, but make sure the address does not cross the boundary! //pBuffer: data storage area //WriteAddr: start writing address (24bit) //NumByteToWrite: the number of bytes to be written (maximum 65535) //CHECK OK void SPI_Flash_Write_NoCheck(u8*pBuffer,u32 WriteAddr,u16 NumByteToWrite) { u16pageremain; pageremain=256-WriteAddr%256; //Number of bytes remaining in a single page if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite; //No more than 256 bytes while(1) { SPI_Flash_Write_Page(pBuffer,WriteAddr,pageremain); if(NumByteToWrite==pageremain)break;//Writing is finished else//NumByteToWrite>pageremain { pBuffer+=pageremain; WriteAddr+=pageremain; NumByteToWrite-=pageremain; //Subtract the number of bytes already written if(NumByteToWrite>256)pageremain=256; //256 bytes can be written at a time elsepageremain=NumByteToWrite; //Not enough 256 bytes } }; } //Write SPI FLASH //Start writing data of the specified length at the specified address //This function has erase operation! //pBuffer: data storage area //WriteAddr: start writing address (24bit) //NumByteToWrite: the number of bytes to be written (maximum 65535) u8 SPI_FLASH_BUF[4096]; void SPI_Flash_Write(u8* pBuffer,u32WriteAddr,u16 NumByteToWrite) { u32secpos; u16secoff; u16secremain; u16 i; secpos=WriteAddr/4096; //sector address 0~511 for w25x16 secoff=WriteAddr%4096; //Offset within the sector secremain=4096-secoff; //Sector remaining space size if(NumByteToWrite<=secremain)secremain=NumByteToWrite; //No more than 4096 bytes while(1) { SPI_Flash_Read(SPI_FLASH_BUF,secpos*4096,4096);//Read the contents of the entire sector for(i=0;i { if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//need to erase } if(i { SPI_Flash_Erase_Sector(secpos); //Erase this sector for(i=0;i { SPI_FLASH_BUF[i+secoff]=pBuffer; } SPI_Flash_Write_NoCheck(SPI_FLASH_BUF,secpos*4096,4096);//Write the entire sector }elseSPI_Flash_Write_NoCheck(pBuffer,WriteAddr,secremain);//Write the erased content and directly write to the remaining area of the sector. if(NumByteToWrite==secremain)break;//Writing is finished else //Writing is not finished { secpos++; //sector address increment by 1 secoff=0; //Offset position is 0 pBuffer+=secremain; //Pointer offset WriteAddr+=secremain; //write address offset NumByteToWrite-=secremain; //Number of bytes decreases if(NumByteToWrite>4096)secremain=4096; //The next sector still cannot be written elsesecremain=NumByteToWrite; //The next sector can be written } }; } // Erase the entire chip //Whole chip erase time: //W25X16:25s //W25X32:40s //W25X64:40s //Waiting time is too long... void SPI_Flash_Erase_Chip(void) { SPI_FLASH_Write_Enable(); //SET WEL SPI_Flash_Wait_Busy(); SPI_FLASH_CS=0; //Enable device SPIx_ReadWriteByte(W25X_ChipErase); //Send chip erase command SPI_FLASH_CS=1; //Cancel chip select SPI_Flash_Wait_Busy(); //Wait for chip erasure to end } // Erase a sector //Dst_Addr: sector address 0~511 for w25x16 //Minimum time to erase a mountain area: 150ms void SPI_Flash_Erase_Sector(u32Dst_Addr) { Dst_Addr*=4096; SPI_FLASH_Write_Enable(); //SET WEL SPI_Flash_Wait_Busy(); SPI_FLASH_CS=0; //Enable device SPIx_ReadWriteByte(W25X_SectorErase); //Send sector erase command SPIx_ReadWriteByte((u8)((Dst_Addr)>>16)); //Send 24-bit address SPIx_ReadWriteByte((u8)((Dst_Addr)>>8)); SPIx_ReadWriteByte((u8)Dst_Addr); SPI_FLASH_CS=1; //Cancel chip select SPI_Flash_Wait_Busy(); //Wait for erasing to complete } //Wait for free time void SPI_Flash_Wait_Busy(void) { while((SPI_Flash_ReadSR()&0x01)==0x01); // Wait for BUSY bit to clear } //Enter power-down mode void SPI_Flash_PowerDown(void) { SPI_FLASH_CS=0; //Enable device SPIx_ReadWriteByte(W25X_PowerDown); //Send power-down command SPI_FLASH_CS=1; //Cancel chip select delay_us(3); //Wait for TPD } //wake void SPI_Flash_WAKEUP(void) { SPI_FLASH_CS=0; //Enable device SPIx_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB SPI_FLASH_CS=1; //Cancel chip select delay_us(3); //Wait for TRES1 } One of the most critical functions in this part of the code is voidSPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite), which can start writing data of any length (must not exceed the capacity of W25X16) from any address of W25X16. Here we briefly introduce the idea: first obtain the sector where the first address (WriteAddr) is located, and calculate the offset in the sector, and then determine whether the length of the data to be written exceeds the remaining length of this sector. If not, check whether to delete it first. If not, just write the data directly. If you want to, read the entire sector, start writing data of the specified length at the offset, then erase this sector, and write it all at once. When the length of the data to be written exceeds the length of a sector, we first write the remaining part of the sector according to the previous steps, and then perform the same operation in the new sector, and repeat this cycle until the writing is completed. The rest of the code is relatively simple, so we won't introduce it here. Save falsh.c, add it to the HARDWARE group, then open falshs.h and enter the following code in the file: #ifndef __FLASH_H #define __FLASH_H #include "sys.h" //Mini STM32 development board //W25X16 driver function //Atom on point @ALIENTEK //2010/6/13 //V1.0 #define SPI_FLASH_CSPAout(2) //Select FLASH ///////////////////////////////////////////////////// ///////////////////////////// //W25X16 read and write #define FLASH_ID 0XEF14 //Instruction table #define W25X_WriteEnable 0x06 #define W25X_WriteDisable 0x04 #define W25X_ReadStatusReg 0x05 #define W25X_WriteStatusReg 0x01 #define W25X_ReadData 0x03 #define W25X_FastReadData 0x0B #define W25X_FastReadDual 0x3B #define W25X_PageProgram 0x02 #define W25X_BlockErase 0xD8 #define W25X_SectorErase 0x20 #define W25X_ChipErase 0xC7 #define W25X_PowerDown 0xB9 #define W25X_ReleasePowerDown 0xAB #define W25X_DeviceID 0xAB #define W25X_ManufactDeviceID 0x90 #define W25X_JedecDeviceID 0x9F void SPI_Flash_Init(void); u16 SPI_Flash_ReadID(void); //Read FLASH ID u8 SPI_Flash_ReadSR(void); //Read status register void SPI_FLASH_Write_SR(u8 sr); //Write status register void SPI_FLASH_Write_Enable(void); //Write enable void SPI_FLASH_Write_Disable(void); //Write protection void SPI_Flash_Read(u8* pBuffer,u32ReadAddr,u16 NumByteToRead); //Read flash void SPI_Flash_Write(u8* pBuffer,u32WriteAddr,u16 NumByteToWrite);//Write to flash void SPI_Flash_Erase_Chip(void); // Erase the entire chip void SPI_Flash_Erase_Sector(u32Dst_Addr); // sector erase void SPI_Flash_Wait_Busy(void); //Wait for idle void SPI_Flash_PowerDown(void); //Enter power-down mode void SPI_Flash_WAKEUP(void); //Wake up #endif Here, some commands related to W25X16 operation are defined. These commands are described in detail in the W25X16 data sheet. Those who are interested can refer to the data sheet. There is nothing else to say. Save this part of the code. Finally, we modify the main function in test.c as follows: //To write to the string array of W25X16 const u8 TEXT_Buffer[]={"MiniSTM32SPI TEST"}; #define SIZE sizeof(TEXT_Buffer) int main(void) { u8key; u16i=0; u8datatemp[SIZE]; Stm32_Clock_Init(9); //System clock settings delay_init(72); //delay initialization uart_init(72,9600); //Serial port 1 initialization LED_Init(); //LED initialization KEY_Init(); //Key initialization LCD_Init(); //TFTLCD liquid crystal initialization SPI_Flash_Init(); //SPI FLASH initialization POINT_COLOR=RED; //Set the font to blue LCD_ShowString(60,50,"MiniSTM32"); LCD_ShowString(60,70,"SPITEST"); LCD_ShowString(60,90,"ATOM@ALIENTEK"); LCD_ShowString(60,110,"2010/6/11"); while(SPI_Flash_ReadID()!=FLASH_ID) //Cannot detect W25X16 { i=SPI_Flash_ReadID(); printf("ID:%d",i); LCD_ShowString(60,130,"W25X16Check Failed!"); delay_ms(500); LCD_ShowString(60,130," Please Check! "); delay_ms(500); LED0=!LED0; //DS0 flashes } LCD_ShowString(60,130,"W25X16Ready!"); //Display prompt information LCD_ShowString(60,150,"KEY0:WriteKEY2:Read"); POINT_COLOR=BLUE; //Set the font to blue while(1) { key=KEY_Scan(); if(key==1)//KEY0 is pressed, write to SPIFLASH { LCD_Fill(0,170,239,319,WHITE); //Clear half screen LCD_ShowString(60,170,"StartWrite W25X16...."); SPI_Flash_Write((u8*)TEXT_Buffer,1000,SIZE);//Starting from 1000 bytes, write data of SIZE length LCD_ShowString(60,170,"W25X16Write Finished!");//Prompt that the transfer is completed } if(key==3) //KEY1 is pressed, read the written character string and display it { LCD_ShowString(60,170,"StartRead W25X16.... "); SPI_Flash_Read(datatemp,1000,SIZE); //Start from address 1000 and read SIZE bytes LCD_ShowString(60,170,"TheData Readed Is: ");//Prompt that the transmission is completed LCD_ShowString(60,190,datatemp);//Display the read string } i++; delay_ms(1); if(i==200) { LED0=!LED0; //Prompt that the system is running i=0; } } }
Previous article:STM32 study notes stack space
Next article:STM32 study notes: the production and application of Keil project Lib library files
Recommended ReadingLatest update time:2024-11-15 15:39
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- EEWORLD University - From entry to mastery of Huawei IoT technology
- 【Silicon Labs BG22-EK4108A Bluetooth Development Review】 IV. Create a project: Control a DC motor via Bluetooth
- A First Look at TouchGFX
- Introduce some basic knowledge of MSP430 microcontroller
- 16 Altera SOC examples (ARM part)
- Methods for controlling stepper motors using microcontrollers or DSP
- 【mpy】STM32 supports using HSI as the main clock
- dsp bootloader c5000
- Will SiC replace IGBT? Let's discuss it together.
- Arduino is about to release the Portenta H7 development board