Cortex_m3_stm32 Embedded Learning Note (21): SPI Experiment (communication bus)

Source: Internet
Author: User
Tags bit set reset
SPI is the abbreviation of English Serial peripheral interface, as the name implies is the serial peripheral device interface. Motorola was first defined on its MC68HCXX series processors. SPI interface is mainly used in EEPROM, FLASH, real-time clock, AD converter, as well as digital signal processor and digital signal decoder. SPI, is a high-speed, full-duplex, synchronous communication busAnd only takes up the pins on the chip Four wires, save the chip pin, while the layout of the PCB space saving, convenient, it is for this simple and easy-to-use features, now more and more chips integrated this communication protocol, STM32 also has SPI interface.

Functions similar to the previous section of the I²c, are used to transfer data: Find an article on I²c VS SPI: Click to open the link

The SPI interface typically uses 4 lines of communication:
Miso Master device data input, from device data output.
MOSI Master device data output, input from device data.
The SCLK clock signal is generated by the main device.
CS to select the signal from the device, controlled by the main device.
SPI main features are: can send and receive serial data at the same time, can be used as a host or slave, provide frequency programmable clock, send end interrupt sign, write conflict protection, bus competition protection.

In this chapter, we will use the SPI of the STM32 to read the external SPI FLASH chip (w25q64) to achieve a function similar to the previous section.
W25q64 is a large-capacity SPI FLASH product launched by Winbond, W25q64 has a capacity of 64Mb, the series also has W25Q80/16/32 and so on. The MiniSTM32 V3.0 Development Board chooses a w25q64 capacity of 64Mb, which is 8M bytes.

The connection diagram is as follows:

We need to initialize the peripherals. PA5 6 7

Configuring the SPI and Flash files is very long.

Spi.c

#include "spi.h"///The following is the initialization code of the SPI module, configured as host mode, access to the SD card/w25x16/24l01/jf24c//SPI port initialization//Here the PIN is the initialization of SPI1 Spi_inittypedef

Spi_initstructure;
  
	void Spi1_init (void) {gpio_inittypedef gpio_initstructure; Rcc_apb2periphclockcmd (rcc_apb2periph_gpioa|	
 
	RCC_APB2PERIPH_SPI1, ENABLE); Gpio_initstructure.gpio_pin = Gpio_pin_5 | Gpio_pin_6 |
	gpio_pin_7;  Gpio_initstructure.gpio_mode = gpio_mode_af_pp;
	Multiplexing push-pull output gpio_initstructure.gpio_speed = Gpio_speed_50mhz;

 	Gpio_init (Gpioa, &gpio_initstructure); Gpio_setbits (gpioa,gpio_pin_5| gpio_pin_6|

	GPIO_PIN_7);  Spi_initstructure.spi_direction = Spi_direction_2lines_fullduplex;		Set SPI unidirectional or bidirectional data mode: SPI set to double-line bidirectional full duplex spi_initstructure.spi_mode = Spi_mode_master;		Set SPI operating mode: set to primary SPI spi_initstructure.spi_datasize = spi_datasize_8b;		Set the data size of the SPI: SPI send receive 8-bit frame structure Spi_initstructure.spi_cpol = Spi_cpol_high;	The steady state of the serial clock has been selected: clock floating high spi_initstructure.spi_cpha = Spi_cpha_2edge;		The data is captured in the second clock along spi_initstructure.spi_nss = Spi_nss_soft; NSS signals by hardware (NSSPIN) or software (using SSI bit) management: The internal NSS signal has SSI bit control Spi_initstructure.spi_baudrateprescaler = spi_baudrateprescaler_256;	Defines the value of the baud rate Prescaler: The baud rate prescaler value is Spi_initstructure.spi_firstbit = SPI_FIRSTBIT_MSB;	Specifies whether the data transfer begins with the MSB bit or the LSB bit: The data transfer begins with the MSB bit spi_initstructure.spi_crcpolynomial = 7;  Polynomial spi_init of CRC value calculation (SPI1, &spi_initstructure); Initializes the peripheral Spix register spi_cmd (SPI1, ENABLE) based on the parameters specified in the spi_initstruct; Enable SPI peripheral spi1_readwritebyte (0xff);//start transfer}//SPI speed setting function//speedset://spi_baudrateprescaler_2 2 divide (SPI 36m@s Ys 72M)//spi_baudrateprescaler_8 8 frequency (SPI 9m@sys 72M)//spi_baudrateprescaler_16 16 (SPI 4.5m@sys 72M)//spi_baud RATEPRESCALER_256 256 frequency (SPI 281.25k@sys 72M) void Spi1_setspeed (U8 speedset) {Spi_initstructure.spi_baudrateprescale
  	R = Speedset;
	Spi_init (SPI1, &spi_initstructure);
Spi_cmd (spi1,enable);				 	
	}//spix reads and writes a byte//txdata: bytes to write//return value: bytes read to U8 spi1_readwritebyte (U8 txdata) {U8 retry=0; while (Spi_i2s_getflagstatus (SPI1, spi_i2s_flag_txe) = = RESET)//Check the specified SPI labelLog bit set or not: Send cache null flag bit {retry++;
		if (retry>200) return 0; } spi_i2s_senddata (SPI1, TxData);

	Send a data retry=0 via peripheral Spix;
		while (Spi_i2s_getflagstatus (SPI1, spi_i2s_flag_rxne) = = RESET)//Check the specified SPI flag bit setting or not: Accept cache non-null flag bit {retry++;
		if (retry>200) return 0; } return Spi_i2s_receivedata (SPI1); Returns the most recently received data through Spix}
Spi.h

#ifndef __spi_h
#define __SPI_H
#include "sys.h" 				  	    													  
void Spi1_init (void);			 Initialize SPI port
void Spi1_setspeed (U8 speedset);//Set SPI speed   
U8 spi1_readwritebyte (U8 txdata);//spi bus reads and writes a byte 
# endif
Flash.c

#include "flash.h" #include "spi.h" #include "delay.h" U16 spi_flash_type=w25q64;//default is 25q64//4kbytes for a sector//16 Fans Zone is 1 blocks//w25x16//capacity is 2M bytes, total 32 block,512 sector//Initialize SPI Flash io port void spi_flash_init (void) {Gpio_inittypedef GPI

  O_initstructure;

	Rcc_apb2periphclockcmd (Rcc_apb2periph_gpioa, ENABLE); Gpio_initstructure.gpio_pin = gpio_pin_2| gpio_pin_3|  Gpio_pin_4;  SPI CS gpio_initstructure.gpio_mode = gpio_mode_out_pp;
 	Multiplexing push-pull output gpio_initstructure.gpio_speed=gpio_speed_50mhz;
 	Gpio_init (Gpioa, &gpio_initstructure); Gpio_setbits (gpioa,gpio_pin_2| gpio_pin_3|
	Gpio_pin_4);		   Spi1_init ();	Initialize SPI spi1_setspeed (spi_baudrateprescaler_4);
Set to 18M clock, high-speed mode spi_flash_type=spi_flash_readid ();//Read FLASH ID. }//Read Spi_flash status Register//BIT7 6 5 4 3 2 1 0//spr RV TB BP2 BP1 BP0 WEL BUSY//SPR: default 0, Status register protection bit, with WP use/   
	/tb,bp2,bp1,bp0:flash Zone write protection settings//wel: Write enable lock//busy: Busy Mark Bit (1, busy; 0, idle)//default: 0x00 U8 spi_flash_readsr (void) {U8 byte=0; spi_flash_cs=0;                           Enable Device Spi1_readwritebyte (W25x_readstatusreg);             Send read Status register command Byte=spi1_readwritebyte (0XFF);                            Reads a byte of Spi_flash_cs=1;   
Cancels the chip selection return byte;
}//write Spi_flash status Register//only spr,tb,bp2,bp1,bp0 (bit 7,5,4,3,2) can write!!!                            void Spi_flash_write_sr (U8 SR) {spi_flash_cs=0;   Enable Device Spi1_readwritebyte (W25x_writestatusreg);               Send write Status Register command Spi1_readwritebyte (SR);                            Writes a byte Spi_flash_cs=1;                            Cancel the chip select}//spi_flash write enable//set wel void spi_flash_write_enable (void) {spi_flash_cs=0;      Enable Device Spi1_readwritebyte (w25x_writeenable);                            Send write enable to Spi_flash_cs=1;                            Cancel the chip select}//spi_flash write Forbidden//will wel clear 0 void spi_flash_write_disable (void) {spi_flash_cs=0;     Enable Device Spi1_readwritebyte (w25x_writedisable); Send write Forbidden Command SPI_FLAsh_cs=1;	  
	Cancel the chip Select}//read the chip ID w25x16 id:0xef14 U16 spi_flash_readid (void) {u16 Temp = 0;				    
	spi_flash_cs=0; 	    
	Spi1_readwritebyte (0x90);//Send Read ID command spi1_readwritebyte (0x00); 	    
	Spi1_readwritebyte (0x00); 	 			   
	Spi1_readwritebyte (0x00);  
	Temp|=spi1_readwritebyte (0xFF) <<8;	 
	Temp|=spi1_readwritebyte (0xFF);				    
	Spi_flash_cs=1;
return Temp; }//Read SPI FLASH//start reading the specified length of data at the specified address//pbuffer: Data store//readaddr: Start read address (24bit)//numbytetoread: Number of bytes to read (max 65535) v    												    
	OID Spi_flash_read (u8* pbuffer,u32 readaddr,u16 numbytetoread) {U16 i;                            spi_flash_cs=0;         Enable Device Spi1_readwritebyte (W25x_readdata);  Send Read command Spi1_readwritebyte ((U8) ((READADDR) >>16));   
    Send 24bit address Spi1_readwritebyte ((U8) ((READADDR) >>8));   
    Spi1_readwritebyte ((U8) readaddr); for (i=0;i<numbytetoread;i++) {Pbuffer[i]=spi1_readwritebyte(0XFF);                            Cyclic reading} Spi_flash_cs=1; Cancel Slice}//spi writes less than 256 bytes of data in a page (0~65535)//writes up to 256 bytes of data at the specified address//pbuffer: Data store//writeaddr: Address to start writing (24bit)//	 
Numbytetowrite: The number of bytes to write (max 256), which should not exceed the number of bytes remaining on the page!!!  
    void Spi_flash_write_page (u8* pbuffer,u32 writeaddr,u16 numbytetowrite) {U16 i;                  Spi_flash_write_enable ();                            SET WEL spi_flash_cs=0;      Enable Device Spi1_readwritebyte (W25x_pageprogram); Send the Write Page command Spi1_readwritebyte ((U8) ((WRITEADDR) >>16));   
    Send 24bit address Spi1_readwritebyte ((U8) ((WRITEADDR) >>8));   
    Spi1_readwritebyte ((U8) writeaddr);                            for (i=0;i<numbytetowrite;i++) Spi1_readwritebyte (Pbuffer[i]);//loop write number Spi_flash_cs=1;					   Remove the spi_flash_wait_busy ();
Wait for write to end}//No Test write SPI FLASH//must make sure that the data in the range of addresses written is all 0XFF, otherwise the data written at non-0XFF will fail!
have auto-paging function//start writing to the specified length of data at the specified address, but make sure the address does not cross the line! Pbuffer: Data store//WRITEADDR: Address to begin writing (24bit)//numbytetowrite: ToNumber of bytes written (max 65535)//check OK void Spi_flash_write_nocheck (u8* pbuffer,u32 writeaddr,u16 numbytetowrite) {U16 PA	   
	Geremain; pageremain=256-writeaddr%256; The number of bytes remaining in a single page if (Numbytetowrite<=pageremain) pageremain=numbytetowrite;//is not greater than 256 bytes while (1) {SPI_FLASH_WR
		Ite_page (Pbuffer,writeaddr,pageremain);
			if (Numbytetowrite==pageremain) break;//write ends the else//numbytetowrite>pageremain {pbuffer+=pageremain;	

			Writeaddr+=pageremain;			  Numbytetowrite-=pageremain; Subtract the number of bytes already written if (numbytetowrite>256) pageremain=256; 	  Can write 256 bytes at a time else pageremain=numbytetowrite;	    
Not enough for 256 bytes}};
}//write SPI FLASH//start writing to the specified length of data at the specified address//The function with erase operation!
Pbuffer: Data store//writeaddr: Start write Address (24bit)//numbytetowrite: Number of bytes to write (max 65535) U8 spi_flash_buf[4096];
	void Spi_flash_write (u8* pbuffer,u32 writeaddr,u16 numbytetowrite) {u32 secpos;
	U16 Secoff;	   
 	U16 Secremain;    

	U16 I; secpos=writeaddr/4096;//sector address 0~511 for w25x16 secoff=writeaddr%4096;//offset within sector secremain=4096-secoff;//sector remaining space size if (Numbytetowrite<=secremain) secremain=numbytetowrite;// 
		Not greater than 4,096 bytes while (1) {spi_flash_read (spi_flash_buf,secpos*4096,4096);//read out the contents of the entire sector for (i=0;i<secremain;i++)//checksum data {if (SPI_FLASH_BUF[SECOFF+I]!=0XFF) break;//need to erase} if (I<secremain)//need to erase {spi_flash_erase_sector (SE	  
			CPOs);//Erase this sector for (i=0;i<secremain;i++)//copy {spi_flash_buf[i+secoff]=pbuffer[i]; } spi_flash_write_nocheck (spi_flash_buf,secpos*4096,4096);//write entire sector}else Spi_flash_write_nocheck (PBUFFER,WRITEADD 				   
		R,secremain);//write to the remaining interval of the sector that has been erased directly. if (Numbytetowrite==secremain) break;//write ends else//write not ended {secpos++;//sector address increased 1 secoff=0;//offset position is 0 pbuffer+=  Secremain;				Pointer offset writeaddr+=secremain;//write address offset numbytetowrite-=secremain;	Decreasing number of bytes if (numbytetowrite>4096) secremain=4096;			The next sector is still not finished writing else secremain=numbytetowrite;	 	 
The next sector can be finished.}}; }//Erase entire chip//erase time://w25x16:25s
w25x32:40s//w25x64:40s//wait time extra long ... void spi_flash_erase_chip (void) {                  Spi_flash_write_enable ();   
  	SET WEL spi_flash_wait_busy ();                            spi_flash_cs=0;        Enable Device Spi1_readwritebyte (w25x_chiperase);                            Send slice erase command spi_flash_cs=1;   				   Remove the spi_flash_wait_busy ();   
Wait for chip erase to end}//Erase a Sector//DST_ADDR: Sector address 0~511 for w25x16//erase a mountain minimum time: 150ms void Spi_flash_erase_sector (U32 dst_addr)
    {dst_addr*=4096;                  Spi_flash_write_enable ();   
  	SET WEL spi_flash_wait_busy ();                            spi_flash_cs=0;      Enable Device Spi1_readwritebyte (w25x_sectorerase);  Send sector erase instruction Spi1_readwritebyte ((U8) ((DST_ADDR) >>16));   
    Send 24bit address Spi1_readwritebyte ((U8) ((DST_ADDR) >>8));  
	Spi1_readwritebyte ((U8) dst_addr);                            Spi_flash_cs=1;     	      
  Cancel the chip selection  Spi_flash_wait_busy ();   Wait for erase to complete}//wait for free void spi_flash_wait_busy (void) {while ((SPI_FLASH_READSR () &0x01) ==0x01);                            Wait for the busy bit to clear}//Enter the power-down mode void Spi_flash_powerdown (void) {spi_flash_cs=0;        Enable Device Spi1_readwritebyte (W25x_powerdown);                            Send power off command Spi_flash_cs=1;                               Remove the Delay_us (3);                            Wait for TPD}//wake void Spi_flash_wakeup (void) {spi_flash_cs=0;   Enable Device Spi1_readwritebyte (W25x_releasepowerdown);                            Send W25x_powerdown command 0xAB Spi_flash_cs=1;                               Remove the Delay_us (3);    Wait TRES1}

Flash.h

#ifndef __flash_h #define __FLASH_H #include "sys.h" #define W25Q80 0xef13 #define W25Q16 0xef14 #define W25Q3					 
2 0xef15 #define W25Q64 0xef16 extern U16 spi_flash_type;//defines the Flash chip model we use #define SPI_FLASH_CS paout (2)//select Flash
extern U8 spi_flash_buf[4096]; w25x16 read-write #define FLASH_ID 0XEF14//instruction table #define W25X_WRITEENABLE 0x06 #define W25X_WRITEDISABLE 0x04 #define W25x_rea Dstatusreg 0x05 #define W25X_WRITESTATUSREG 0x01 #define W25X_READDATA 0x03 #define W25X_FASTREADDATA 0x0B #defin 
E 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,u32 readaddr,u16 numbytetoread); Read Flash void Spi_flash_write (u8* pbuffer,u32 writeaddr,u16 numbytetowrite);//write Flash void spi_flash_erase_chip (void    	  );           erase void Spi_flash_erase_sector (u32 dst_addr);//Sector erase void spi_flash_wait_busy (void);           Wait for free void spi_flash_powerdown (void);			  Enter the power-down mode void spi_flash_wakeup (void);
 Wake-Up #endif

There are many functions. In fact, usually only read and write

Write:

/write SPI FLASH  
//start writing to the specified length of data at the specified address
//The function with erase operation!
Pbuffer: Data store
//WRITEADDR: Address to begin writing (24bit)
//numbytetowrite: Number of bytes to write (max 65535)  		   
U8 spi_flash_buf[4096] ;

Read

Read SPI FLASH  
//Start reading the specified length of data at the specified address
//pbuffer: Data store
//READADDR: Start read address (24bit)
//numbytetoread: Number of bytes to read (max 65535)
void Spi_flash_read (u8* pbuffer,u32 readaddr,u16 numbytetoread)


The functions implemented by the main function are similar to those of i²c.

#include "led.h" #include "delay.h" #include "sys.h" #include "usart.h" #include "lcd.h" #include "key.h" #include "spi.h"
#include "flash.h"//string array to write to w25q64 const U8 text_buffer[]={"MY SPI TEST"};
U32 flash_size;	    	 #define SIZE sizeof (text_buffer) void init (void) {delay_init ();	 	The delay function initializes the uart_init (9600);		  		The serial port is initialized to 9600 led_init ();
	Initialize the hardware interface with the LED connection lcd_init ();				Key_init ();  		Press the key to initialize the Spi_flash_init ();	
	SPI FLASH initialization point_color=red;//set the font to Red lcd_showstring (60,50,200,16,16, "Mini STM32");	
	Lcd_showstring (60,70,200,16,16, "SPI TEST");
	Lcd_showstring (60,90,200,16,16, "atom@yh");	
	Lcd_showstring (60,110,200,16,16, "2015/1/26");	Lcd_showstring (60,130,200,16,16, "Wk_up:write key0:read"); Displays the prompt message while (Spi_flash_readid ()!=w25q64)//detects w25q64 {lcd_showstring (60,150,200,16,16, 25q64 check failed!
		");
		Delay_ms (500);      Lcd_showstring (60,150,200,16,16, "please check!
		");
		Delay_ms (500); led0=! Led0;//ds0 blinking} lcd_showstring (60,150,200,16,16, "25q64 ready!");	flash_size=8*1024*1024;		FLASH size is 8M bytes point_color=blue;
	Sets the font to blue} int main (void) {U8 key;
	U16 I=0;
	
	U8 Datatemp[size];
	Init ();
		while (1) {key=key_scan (0); if (key==wkup_pres)//wk_up pressed, write w25q64 {lcd_fill (0,170,239,319,white);//Clear Half screen lcd_showstring (60,170,200,16,16
			, "Start Write w25q64 ....");		Spi_flash_write ((u8*) text_buffer,flash_size-100,size);	Starting at the bottom 100th address, write data lcd_showstring of size length (60,170,200,16,16, "w25q64 write finished!"); Prompt transfer Complete} if (Key==key0_pres)//key0 Press to read the string and display {lcd_showstring (60,170,200,16,16, "Start read w25q64 ....
			");				Spi_flash_read (datatemp,flash_size-100,size);	Starting at the bottom 100th address, read out size byte lcd_showstring (60,170,200,16,16, "The Data readed is:");					Prompt delivery complete lcd_showstring (60,190,200,16,16,DATATEMP);
		Displays the read string} i++;
		Delay_ms (10); if (i==20) {led0=!
		led0;//prompt system is running i=0; }		   
	}
}



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.