IIC相对而言硬件设计较为简单,两线总线可以直接挂载很多芯片,但通信受干扰,容易进入“死锁”状态,需要软件处理。SPI相对而言需要的硬线更多,但不存在出现“死锁”的问题,另外通信速率也更高。
死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
那么为什么会产生死锁呢?
1.因为系统资源不足。
2.进程运行推进的顺序不合适。
3.资源分配不当。
产生死锁的四个必要条件:
互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。
#ifndef _USER_SPI_FLASH_H_
#define _USER_SPI_FLASH_H_#include "nrf_gpio.h"
#include <stdint.h>
//SPI hardware gpio config
#define SPI_FLASH_CS 14
#define SPI_FLASH_CLK 11
#define SPI_FLASH_MOSI 12
#define SPI_FLASH_MISO 13
//#define SPI_FLASH_WP25
//SPI hardware fuction
#define SPIFlash_Enable_CS nrf_gpio_pin_clear(SPI_FLASH_CS)
#define SPIFlash_Disable_CS nrf_gpio_pin_set(SPI_FLASH_CS)
#define SPIFlash_Set_SCLK nrf_gpio_pin_set(SPI_FLASH_CLK)
#define SPIFlash_Clr_SCLK nrf_gpio_pin_clear(SPI_FLASH_CLK)
#define SPIFlash_Set_DO nrf_gpio_pin_set(SPI_FLASH_MOSI)
#define SPIFlash_Clr_DO nrf_gpio_pin_clear(SPI_FLASH_MOSI)
#define SPIFlash_Get_DI nrf_gpio_pin_read(SPI_FLASH_MISO)
#define W25Q80 0XEF13
#define W25Q16 0XEF14
#define W25Q32 0XEF15
#define W25Q64 0XEF16
#define FLASH_ID 0XEF14
//指令表
#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
//page --256bytes
//1 Sector = 4Kbytes
//16 Sector = 1 Block = 64Kbytes
//W25X16
//size = 2M BYTE= 32 Block = 512 Sector
void USER_SPI_Init(void);
//uint8_t SPI_Flash_ReadWriteByte(uint8_t dat);//
uint8_t SpiFlash_ReadOneByte(void);//read byte
void SpiFlash_WriteOneByte(uint8_t DataBuffer);//wirte byte
uint16_t SPI_Flash_ReadID(void); //read ID ,W25X16 is 0xEF14
void SPI_Flash_ReadUID(uint8_t* TAB);
uint8_t SpiFlash_ReadSR(void);//
void SPI_FLASH_Write_SR(uint8_t sr);
void SPI_FLASH_Write_Enable(void);
void SPI_FLASH_Write_Disable(void);
void SPI_Flash_Wait_Busy(void);
void SPI_Flash_Erase_Sector(uint32_t Dst_Addr);
void SPI_Flash_Erase_Chip(void);
void SPI_Flash_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead);
void SPI_Flash_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
uint8_t SPI_Flash_Test(void);
#endif /*_USER_SPI_FLASH_H_*/
-------------------------------------------------------------------------------------------------------------------------------
#include "user_spi_flash.h"
//SPI hardware gpio config
void USER_SPI_Init(void)
{
nrf_gpio_cfg_output(SPI_FLASH_CS);
nrf_gpio_cfg_output(SPI_FLASH_CLK);
nrf_gpio_cfg_output(SPI_FLASH_MOSI);
nrf_gpio_cfg_input(SPI_FLASH_MISO,NRF_GPIO_PIN_NOPULL);
}
uint8_t SpiFlash_ReadOneByte(void)
{
uint8_t BitCount = 0;
uint8_t retValue = 0;
SPIFlash_Set_SCLK; //clK=Hight
for(BitCount = 0;BitCount < 8; BitCount++)
{
retValue <<= 1;
SPIFlash_Set_SCLK; //clK=Hight
if(SPIFlash_Get_DI)
{
retValue |= 0x01;
}
else
{
retValue &= 0xFE;
}
SPIFlash_Clr_SCLK; //clK=Hight failling edge read one bit
}
SPIFlash_Set_SCLK;
return (retValue);
}
void SpiFlash_WriteOneByte(uint8_t DataBuffer)
{
uint8_t BitCount = 0;
SPIFlash_Clr_SCLK; //clK=Low
for(BitCount = 0;BitCount < 8; BitCount++)
{
SPIFlash_Clr_SCLK; //clK=Low
if(DataBuffer & 0x80)
{
SPIFlash_Set_DO;
}
else
{
SPIFlash_Clr_DO;
}
DataBuffer <<= 1;
SPIFlash_Set_SCLK; //clK=Hight rising edge werite one bit
}
SPIFlash_Clr_SCLK;
SPIFlash_Set_DO; // ont byte have send, MOSI line = Hight means is free
}
uint16_t SPI_Flash_ReadID(void)
{
uint16_t Temp = 0;
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(0x90);
SpiFlash_WriteOneByte(0x00);
SpiFlash_WriteOneByte(0x00);
SpiFlash_WriteOneByte(0x00);
Temp |= SpiFlash_ReadOneByte()<<8;
Temp |= SpiFlash_ReadOneByte();
SPIFlash_Disable_CS;
return Temp;
}
void SPI_Flash_ReadUID(uint8_t* TAB)
{
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(0x4B);
SpiFlash_WriteOneByte(0x00);
SpiFlash_WriteOneByte(0x00);
SpiFlash_WriteOneByte(0x00);
SpiFlash_WriteOneByte(0x00);
TAB[0] = SpiFlash_ReadOneByte();
TAB[1] = SpiFlash_ReadOneByte();
TAB[2] = SpiFlash_ReadOneByte();
TAB[3] = SpiFlash_ReadOneByte();
TAB[4] = SpiFlash_ReadOneByte();
TAB[5] = SpiFlash_ReadOneByte();
TAB[6] = SpiFlash_ReadOneByte();
TAB[7] = SpiFlash_ReadOneByte();
SPIFlash_Disable_CS;
}
uint8_t SpiFlash_ReadSR(void)
{
uint8_t retValue = 0;
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(W25X_ReadStatusReg);
retValue = SpiFlash_ReadOneByte();
SPIFlash_Disable_CS;
return retValue;
}
void SPI_FLASH_Write_SR(uint8_t sr)
{
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(W25X_WriteStatusReg);
SpiFlash_WriteOneByte(sr);
SPIFlash_Disable_CS;
}
void SPI_FLASH_Write_Enable(void)
{
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(W25X_WriteEnable);
SPIFlash_Disable_CS;
}
void SPI_FLASH_Write_Disable(void)
{
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(W25X_WriteDisable);
SPIFlash_Disable_CS;
}
void SPI_Flash_Wait_Busy(void)
{
while ((SpiFlash_ReadSR()&0x01)==0x01);
}
void SPI_Flash_Erase_Sector(uint32_t Dst_Addr)
{
Dst_Addr*=4096;
SPI_FLASH_Write_Enable();
SPI_Flash_Wait_Busy();
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(W25X_SectorErase);
SpiFlash_WriteOneByte((uint8_t)((Dst_Addr)>>16));
SpiFlash_WriteOneByte((uint8_t)((Dst_Addr)>>8));
SpiFlash_WriteOneByte((uint8_t)Dst_Addr);
SPIFlash_Disable_CS;
SPI_Flash_Wait_Busy();
}
void SPI_Flash_Erase_Chip(void)
{
SPI_FLASH_Write_Enable();//SET WEL
SPI_Flash_Wait_Busy();
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(W25X_ChipErase);
SPIFlash_Disable_CS;
SPI_Flash_Wait_Busy();
}
void SPI_Flash_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)
{
uint16_t i;
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(W25X_ReadData);
SpiFlash_WriteOneByte((uint8_t)((ReadAddr)>>16));
SpiFlash_WriteOneByte((uint8_t)((ReadAddr)>>8));
SpiFlash_WriteOneByte((uint8_t)ReadAddr);
for(i=0;i<NumByteToRead;i++)
{
pBuffer[i]=SpiFlash_ReadOneByte();
}
SPIFlash_Disable_CS;
}
void SPI_Flash_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
uint16_t i;
SPI_FLASH_Write_Enable();
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(W25X_PageProgram);
SpiFlash_WriteOneByte((uint8_t)((WriteAddr)>>16));
SpiFlash_WriteOneByte((uint8_t)((WriteAddr)>>8));
SpiFlash_WriteOneByte((uint8_t)WriteAddr);
for(i=0;i<NumByteToWrite;i++) SpiFlash_WriteOneByte(pBuffer[i]);
SPIFlash_Disable_CS;
SPI_Flash_Wait_Busy();
}
uint8_t SPI_Flash_Test(void)
{
uint16_t id;
uint8_t w_tab[5]={0x01,0x02,0x03,0x04,0x05};
uint8_t r_tab[5]={0};
uint8_t UID_tab[8];
SPI_Flash_ReadUID(UID_tab);
SPI_Flash_Erase_Sector(1);
//SPI_Flash_Erase_Chip();
SPI_Flash_Write_Page(w_tab,4096,5);
SPI_Flash_Read(r_tab,4096,5);
id=SPI_Flash_ReadID();
if(id==0xEF15)
{
return 0;
}
else
{
return 1;
}
}