模拟SPI

本文介绍了SPI通信协议的优势,如避免IIC的“死锁”问题和更高的通信速率,并提供了SPI模拟读写操作的C代码实现,包括初始化、读写单字节、读取ID和擦除芯片等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值