STM32 learning notes hardware SPI reading and writing and polarity setting

Publisher:温柔心情Latest update time:2017-09-09 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

[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;

                 }                        

     }

}


Keywords:STM32 Reference address:STM32 learning notes hardware SPI reading and writing and polarity setting

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

STM32 Light up LED
When learning a new processor, the first program must be to light up the LED. It allows us to quickly and clearly understand the program structure of a processor. Learning 32 is no exception. First, the first program is to light up the LED. There are many kinds of programs to light up the LED. Here we use the library
[Microcontroller]
STM32 Light up LED
How to deal with STM32 entering HardFault_Handler
How to deal with STM32 entering HardFault_Handler There are generally two situations in which HardFault_Handler appears:  one is: array out of bounds,  the other is: stack overflow, program pointer out of bounds method one Set a breakpoint at while() in the HardFault_Handler interrupt to stop the program executio
[Microcontroller]
How to deal with STM32 entering HardFault_Handler
AnalogML vendor Aspinity joins ST Partner Program
Aspinity joins STMicroelectronics (ST) Partner Program to deliver complete AnalogML solution for always-on edge processing. Analog machine learning pioneer teams up with leader in high-performance microcontrollers to extend battery life of IoT devices. Aspinity has joined the ST Partner Program, accelerating the int
[Microcontroller]
STM32 USART library function introduction 2
The function of USART_Cmd is to enable or disable the USART serial port peripheral. Example: Enable USART1 USART_Cmd(USART1,ENABLE); The function of USART_ITConfig is to enable or disable the specified USART serial port interrupt. USART_IT_PE Parity Error Interrupt USART_IT_TXE Transmit interrupt USART_IT_
[Microcontroller]
STM32 USB clock configuration
1. First, configure the system clock as follows: RCC_DeInit(); //Reset the peripheral RCC register to the default value     /* Enable HSE */     RCC_HSEConfig(RCC_HSE_ON); //Set external high speed crystal oscillator (HSE)     /* Wait till HSE is ready */     HSEStartUpStatus = RCC_WaitForHSEStartUp(); //Wait f
[Microcontroller]
STM32 RTC crystal oscillator problem
I searched the entire Internet for the RTC crystal oscillator of STM32 and summarized it as follows Software: In many programs in the past, there was no RTC_WaitForLastTask(); statement in the RTC interrupt. Just add it. Hardware: Conventional configuration 6p crystal oscillator plus two 10p capacitors. Do not connect
[Microcontroller]
Solve the burning problem: Jlink's three-wire SWD method connected to the STM32 chip cannot be recognized
I found this article online that solved the problem that j-flash can only be connected but not burned. I hope that friends who encounter the same problem can use the same method to solve it: Some time ago, I made a board, and the debugging interface only had three ports, SWD, SWCLK, and GND. When I used Jlink's SWD
[Microcontroller]
Solve the burning problem: Jlink's three-wire SWD method connected to the STM32 chip cannot be recognized
STM32 SysTick based on 3.5 library function
#include "stm32f10x.h" #include "led.h" #include stdio.h /*********************************************************************** ***********************************************************************/ static __IO uint32_t TimingDelay; /*********************************************************************** *
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号