单片机
返回首页

STM32 SPI W25X16驱动

2015-10-30 来源:eefocus

    前面说了STM32的I2C,作为STM32的另外一个串行接口就不得不提到了——SPI。与I2C差不多,同样有硬件接口,有库函数支持,我们要做的就是结合SPI接口芯片调用库函数,就能实现SPI驱动了。一切看代码,你会懂的,注释非常详细的,很适合初学者。代码能够直接用到实际项目工程里面去的。SPI芯片选用W25X系列。。。

    演示效果使用超级终端或者SecureCRT 5.5(这货真的不错)

    工程结构图:

  STM32 <wbr>SPI <wbr>W25X16驱动

    1、工程里面的beep.c led.c usart1.c 与《STM32 基于库函数控制按键&nb… 》《STM32 串口例程之查询收》里面完全一样,这里就不在上代码。

    2、main.c

//程序功能:主要用于测试SPI W25X16驱动是否正常


#include'stm32f10x.h'
#include'user_usart1.h'
#include'user_led.h'
#include'user_beep.h'
#include'user_spi_w25x16.h'
#include


#define  FLASH_ID1              0xef3015
#define  FLASH_ID2              0xef4015
#define  FLASH_WriteAddress     0x000000
#define  FLASH_ReadAddress      FLASH_WriteAddress
#define  FLASH_SectorErase      FLASH_WriteAddress

#define CountOf(a)          (sizeof(a)/sizeof(*(a)))
#define DataSize    (CountOf(TxDataTable)-1)

u8 TxDataTable[]=' Hello,I am wgchnln,我 爱 ARM,I will persist in learning ARM,坚决不放弃 ';
u8 RxDataTable[DataSize];


//=============================================
#ifdef __GNUC__
 
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
//=============================================



TestStatus User_SPI_DataCompare(u8 *TxData,u8 *RxData,u8 Num)
{
  while(Num--)
  {
   if(*TxData!=*RxData)
   {
    return Failed;
   }
   RxData++;
   TxData++;
  }

  return Successed;
}


void User_SPI_Test(void)
{
  vu32 ID,DeviceID;
  u8 Buffer;
  volatile TestStatus Test1=Failed;
  volatile TestStatus Test2=Successed;        //存放两次测试的结果
 
 
  printf(' 正在努力读取ID号.....');
  User_LedSpark(Led1,2);
  ID=User_SPI_W25X16_ReadID();
  printf('flashID:%x ',ID);

  printf(' 正在努力读取DeviceID号......');
  User_LedSpark(Led1,2);
  DeviceID=User_SPI_W25X16_ReadDeviceID();
  printf('flashDeviceID:%x ',DeviceID);
 
 
 
  if((ID==FLASH_ID1)||(ID==FLASH_ID2))
  {
 
   printf(' ARM在芯片擦除......');
 User_LedSpark(Led1,2);
 User_SPI_W25X16_SectorErase(FLASH_SectorErase);
 printf('完成 ');

 
 printf(' 你要写入的数据:%s ',TxDataTable);
 printf(' 努力为你芯片写入中......');
 User_LedSpark(Led1,2);
 User_SPI_W25X16_ChipWrite(TxDataTable,FLASH_WriteAddress,DataSize);
 printf('完成 ');

 
 printf(' 芯片数据读取......');
 User_LedSpark(Led1,2);
 User_SPI_W25X16_ChipRead(RxDataTable,FLASH_ReadAddress,DataSize);
 printf('完成 ');
 User_LedSpark(Led1,2);
 printf(' 为您读取的数据:%s ',RxDataTable);

 
 printf(' 为您做数据比较中......');
 User_LedSpark(Led1,2);
 Test1=User_SPI_DataCompare(RxDataTable,TxDataTable,DataSize);
 if(Test1==Successed)
 {
   printf('数据相同 ');
 }
 else
 {
   printf('数据不相同 ');
   User_LedSpark(Led2,2);
   printf('为您分析可能原因:数据未写入、读取错误、或者两者同时存在 ');
 }

 
 printf(' 再一次芯片擦除......');
 User_LedSpark(Led1,2);
 User_SPI_W25X16_SectorErase(FLASH_SectorErase);
 printf('完成 ');

 
 printf(' 又一次芯片读取......');
 User_LedSpark(Led1,2);
 User_SPI_W25X16_ChipRead(RxDataTable,FLASH_ReadAddress,DataSize);
 printf('完成 ');

 
 printf(' 判断是否擦除掉......');
 User_LedSpark(Led1,1);
 for(Buffer=0;Buffer
 {
   if(RxDataTable[Buffer]!=0xff)
   {
    Test2=Failed;
   }
 }
 if(Test2==Failed)
 {
   printf('失败 ');
   printf('为您分析的可能原因:读取错误、擦除失败、或者两者同时存在 ');
 }
 else
 {
   printf('擦除OK ');
 }

 
 printf(' ------------为您展示此次测试结果------------ ');
 if((Test1==Successed)&&((Test2==Successed)))
 {
   User_LedSpark(Led1,2);
   printf(' 恭喜你,SPI W25X16驱动测试通过啦 ');
 }
 else
 {
   User_LedSpark(Led2,2);
   printf(' 糟糕,SPI功能演示失败了......原因可能是读写数据不一致、软件擦除失败 ');
 }
  }
 
 
  else
  {
   User_LedSpark(Led2,2);
 printf(' 悲剧了,SPI功能演示失败啦.....原因是芯片ID号码读取出错哦 ');
  }
}


int main(void)
{
  User_USART1Config();
  printf(' 串口1配置......');
  printf('完成 ');

  printf(' 蜂鸣器初始化...');
  User_BeepConfig();
  printf(' 蜂鸣器测试......');
  User_BeepStatus(BeepStatus_TurnOn);
  printf('完成 ');

  printf(' LED初始化...');
  User_LedConfig();
  printf(' LED测试......');
  User_LedSpark(Led0,2);
  printf('完成 ');

  printf(' SPI初始化...');
  User_SPI_Config();
  User_LedSpark(Led0,2);
  printf('完成 ');

  User_SPI_Test();

  while(1);
}

//==================================================
PUTCHAR_PROTOTYPE
{
 
 
  USART_SendData(USART1, (uint8_t) ch);

 
  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
  {}

  return ch;
}
//==================================================

  3、user_spi_w25x16.c

//program function:SPI1 Init &&  FLASF Chip W25X16 driver


#include'stm32f10x.h'
#include'user_spi_w25x16.h'
#include



#define WriteEnable    0x06
#define WriteDisable   0x04
#define ReadStatusRegister  0x05
#define WriteStatusRegister  0x01
#define ReadData    0x03
#define FastRead    0x0b
#define FsatReadDualOutput  0x3b
#define PageProgram    0x02
#define BlukErase    0xd8
#define SectorErase    0x20
#define ChipErase    0xc7
#define PowerDown    0xb9
#define WakeUp     0xab
#define DeviceID    0xab
#define ManufatureID   0x90
#define JedecID     0x9f

#define JudgeCode    0x01           //用于判断通讯是否结束用
#define NoneCode    0xa5           //无意义的指令,用于:接收数据时,发送这个质量来产生接收时候的时钟



void User_SPI_Config(void)
{
 
 
  SPI_InitTypeDef           SPI_InitStructure;
 
  GPIO_InitTypeDef           GPIO_InitStructure;

 
 
  RCC_APB2PeriphClockCmd(SPI_24G_CS_Clock,ENABLE);
  GPIO_InitStructure.GPIO_Pin        =SPI_24G_CS_Pin;
  GPIO_InitStructure.GPIO_Mode        =GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed        =GPIO_Speed_50MHz;
  GPIO_Init(SPI_24G_CS_Port,&GPIO_InitStructure);
  GPIO_SetBits(SPI_24G_CS_Port,SPI_24G_CS_Pin);

 
  RCC_APB2PeriphClockCmd(SPI_VS1003B_CS_Clock,ENABLE);
  GPIO_InitStructure.GPIO_Pin        =SPI_VS1003B_CS_Pin;
  GPIO_InitStructure.GPIO_Mode        =GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed        =GPIO_Speed_50MHz;
  GPIO_Init(SPI_VS1003B_CS_Port,&GPIO_InitStructure);
  GPIO_SetBits(SPI_VS1003B_CS_Port,SPI_VS1003B_CS_Pin);

 
 
  RCC_APB2PeriphClockCmd(SPI_W25X16_Clock,ENABLE);
 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

 
 
  RCC_APB2PeriphClockCmd(SPI_W25X16_CS_Clock,ENABLE);
  GPIO_InitStructure.GPIO_Pin        =SPI_W25X16_CS_Pin;
  GPIO_InitStructure.GPIO_Mode        =GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed        =GPIO_Speed_50MHz;
  GPIO_Init(SPI_W25X16_CS_Port,&GPIO_InitStructure);
  SPI_W25X16_CS_DisSelect;

 
  RCC_APB2PeriphClockCmd(SPI_W25X16_SCK_Clock,ENABLE);
  GPIO_InitStructure.GPIO_Pin        =SPI_W25X16_SCK_Pin;
  GPIO_InitStructure.GPIO_Mode        =GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed        =GPIO_Speed_50MHz;
  GPIO_Init(SPI_W25X16_SCK_Port,&GPIO_InitStructure);

 
  RCC_APB2PeriphClockCmd(SPI_W25X16_MISO_Clock,ENABLE);
  GPIO_InitStructure.GPIO_Pin        =SPI_W25X16_MISO_Pin;
  GPIO_Init(SPI_W25X16_MISO_Port,&GPIO_InitStructure);

 
  RCC_APB2PeriphClockCmd(SPI_W25X16_MOSI_Clock,ENABLE);
  GPIO_InitStructure.GPIO_Pin        =SPI_W25X16_MOSI_Pin;
  GPIO_Init(SPI_W25X16_MOSI_Port,&GPIO_InitStructure);

 
 
  SPI_InitStructure.SPI_Direction       =SPI_Direction_2Lines_FullDuplex;      //通讯模式:双向全双工模式
  SPI_InitStructure.SPI_Mode        =SPI_Mode_Master;       //主从:主模式
  SPI_InitStructure.SPI_DataSize       =SPI_DataSize_8b;       //数据帧长度:8bits
  SPI_InitStructure.SPI_CPOL        =SPI_CPOL_High;        //空闲时置高
  SPI_InitStructure.SPI_CPHA        =SPI_CPHA_2Edge;        //第二个时钟采样
  SPI_InitStructure.SPI_NSS         =SPI_NSS_Soft;        //NSS控制选择:软件控制
  SPI_InitStructure.SPI_BaudRatePrescaler     =SPI_BaudRatePrescaler_2;     //波特率分配系数:2分频
  SPI_InitStructure.SPI_FirstBit       =SPI_FirstBit_MSB;       //数据帧格式:MSB在前
  SPI_InitStructure.SPI_CRCPolynomial      =7;           //CRC效验多项式
 
  SPI_Init(SPI1,&SPI_InitStructure);
 
  SPI_Cmd(SPI1,ENABLE);
}


u8 User_SPI_W25X16_SendByte(u8 SendByteData)
{
  u8 ReceiveData;
 
 
  while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);
 
  SPI_I2S_SendData(SPI1,SendByteData);

 
  while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);
 
  ReceiveData=SPI_I2S_ReceiveData(SPI1);

  return ReceiveData;
}

         
u8 User_SPI_W25X16_ReadByte(void)
{
  u8 ReceiveData;
 
  ReceiveData=User_SPI_W25X16_SendByte(NoneCode);

  return ReceiveData;
}

                       
vu16 User_SPI_W25X16_SendHalfWord(u16 HalfWord)
{
  vu16 ReceiveData;

 
  while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);
 
  SPI_I2S_SendData(SPI1,HalfWord);

 
  while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);
 
  ReceiveData=SPI_I2S_ReceiveData(SPI1);
 
  return ReceiveData;
}

        
void User_SPI_W25X16_WriteEnable(void)
{
 
  SPI_W25X16_CS_Select;

 
  User_SPI_W25X16_SendByte(WriteEnable);

 
  SPI_W25X16_CS_DisSelect;
}

            
void User_SPI_W25X16_WaitForWriteEnd(void)
{
  u8 ReceiveStatus;                     //用于存放W25X16返回的状态非零就是操作结束
 
  SPI_W25X16_CS_Select;                    
 
  User_SPI_W25X16_SendByte(ReadStatusRegister);
 
  do
  {
   ReceiveStatus=User_SPI_W25X16_SendByte(NoneCode);
  }
  while(ReceiveStatus & JudgeCode==SET);
 
  SPI_W25X16_CS_DisSelect;
        

                       
void User_SPI_W25X16_SectorErase(vu32 SectorAddress)
{
 
  User_SPI_W25X16_WriteEnable();
 
  SPI_W25X16_CS_Select;

 
  User_SPI_W25X16_SendByte(SectorErase);
 
  User_SPI_W25X16_SendByte((SectorAddress & 0xff0000)>>16);       //发送最高8位
  User_SPI_W25X16_SendByte((SectorAddress & 0xff00)>>8);       // 中间8位
  User_SPI_W25X16_SendByte(SectorAddress & 0xff);         //发送最低8位
 

 
  SPI_W25X16_CS_DisSelect;

 
  User_SPI_W25X16_WaitForWriteEnd();
}


void User_SPI_W25X16_BulkErase(void)
{
 
  User_SPI_W25X16_WriteEnable();
 
  SPI_W25X16_CS_Select;

 
  User_SPI_W25X16_SendByte(ChipErase);

 
  SPI_W25X16_CS_DisSelect;

 
  User_SPI_W25X16_WaitForWriteEnd();
}


void User_SPI_W25X16_PageWrite(u8 *DataTable,vu32 WriteAddress,vu16 NumberOfWrite)
{
 
  User_SPI_W25X16_WriteEnable();
 
  SPI_W25X16_CS_Select;

 
  User_SPI_W25X16_SendByte(PageProgram);

 
  User_SPI_W25X16_SendByte((WriteAddress & 0xff0000)>>16);     //最高8位地址
  User_SPI_W25X16_SendByte((WriteAddress & 0xff00)>>8);      //中间8位地址
  User_SPI_W25X16_SendByte(WriteAddress & 0xff);       //最低8位地址

 
  if(NumberOfWrite > SPI_W25X16_PerPageWriteSize)       //W25X16采用的是页写入方式,最多一次性写入256个数据,然后内部地址指针归零
  {
   NumberOfWrite=SPI_W25X16_PerPageWriteSize;
 printf(' 哦偶,一次性写入的数据太多,不能超过256的啦,ARM将为你写入前256个数据 ');
  }

 
  while(NumberOfWrite--)
  {
   User_SPI_W25X16_SendByte(*DataTable);
 DataTable++;               //数组指针 +1
  }

  SPI_W25X16_CS_DisSelect;

 
  User_SPI_W25X16_WaitForWriteEnd();
}


void User_SPI_W25X16_ChipWrite(u8 *DataTable,vu32 WriteAddress,vu16 NumberOfWrite)
{
  u8 AddressRemainder    =0;
  u8 NumberOfPage     =0;
  u8 Count       =0;                        //存放地址所在页需要写入的最多数据
  u8 NumberOfSingle     =0;                        //写入数据的最后一些需要写入的数据个数
  u8 Buffer       =0;            //保留

  AddressRemainder     =WriteAddress % SPI_W25X16_PageSize;
  Count        =SPI_W25X16_PageSize - AddressRemainder;
  NumberOfPage      =NumberOfWrite / SPI_W25X16_PageSize;
  NumberOfSingle     =NumberOfWrite % SPI_W25X16_PageSize;

 
  if(AddressRemainder==0)
  {
   
 if(NumberOfPage==0)                //NumberOfWrite < SPI_W25X16_PageSize
 {
   User_SPI_W25X16_PageWrite(DataTable,WriteAddress,NumberOfWrite);
 }
 
 else
 {
  
   while(NumberOfPage--)
   {
     User_SPI_W25X16_PageWrite(DataTable,WriteAddress,SPI_W25X16_PageSize);  //一次性写入256个
  DataTable+=SPI_W25X16_PageSize;          //接着写下一个256数据
  WriteAddress+=SPI_W25X16_PageSize;          //地址就移到下一页(256为单位)
   }
  
   User_SPI_W25X16_PageWrite(DataTable,WriteAddress,NumberOfSingle);
 }
  }
 
  else
  {
   
 if(NumberOfPage==0)
 {
  
   if(NumberOfWrite < Count)
   {
     User_SPI_W25X16_PageWrite(DataTable,WriteAddress,NumberOfWrite);
   }
  
   else
   {
  
  User_SPI_W25X16_PageWrite(DataTable,WriteAddress,Count);     //起始地址所在页只需要写入Count个
  Buffer=NumberOfWrite-Count;          //计算出下一页要写入的数据数量
  DataTable+=Count;
  WriteAddress+=Count;

  
  User_SPI_W25X16_PageWrite(DataTable,WriteAddress,Buffer);
   }
 }
 
 else
 {
  
   User_SPI_W25X16_PageWrite(DataTable,WriteAddress,Count);

   //之后需要重新计算以下参数  原因:数据量超过一页分两种情况:1、数据量不会覆盖完起始地址下一页;2、数据量会完全覆盖起始地址下一页
   //重新计算就是看是否会覆盖掉下一页,如果会就进入while()循环,否则就不进入
   DataTable+=Count;
   WriteAddress+=Count;
   NumberOfWrite-=Count;
   NumberOfPage=NumberOfWrite / SPI_W25X16_PageSize;
   NumberOfSingle=NumberOfWrite % SPI_W25X16_PageSize;

  
   while(NumberOfPage--)
   {
    User_SPI_W25X16_PageWrite(DataTable,WriteAddress,SPI_W25X16_PageSize);
  DataTable+=SPI_W25X16_PageSize;
  WriteAddress+=SPI_W25X16_PageSize;
   }

  
   if(NumberOfSingle != 0)
   {
    User_SPI_W25X16_PageWrite(DataTable,WriteAddress,NumberOfSingle);
   }
 }
  }
}


void User_SPI_W25X16_ChipRead(u8 *DataTable,vu32 ReadAddress,vu16 NumberOfRead)
{
                   //虽然要发送地址,但是不需要说明有个写操作(I2C才是这样的时序)
  SPI_W25X16_CS_Select;

 
  User_SPI_W25X16_SendByte(ReadData);

 
  User_SPI_W25X16_SendByte((ReadAddress & 0xff0000) >> 16);       //最高8位地址
  User_SPI_W25X16_SendByte((ReadAddress & 0xff00) >> 8);       //中间8位
  User_SPI_W25X16_SendByte(ReadAddress & 0xff);                   //最低8位

 
  while(NumberOfRead--)
  {
   *DataTable = User_SPI_W25X16_SendByte(NoneCode);
 DataTable++;
  }

 
  SPI_W25X16_CS_DisSelect;
}


vu32 User_SPI_W25X16_ReadID(void)
{
  vu32 ID      =0;
  vu32 IDBuffer1 =0;
  vu32 IDBuffer2 =0;
  vu32 IDBuffer3 =0;
                  
  SPI_W25X16_CS_Select;
 
  User_SPI_W25X16_SendByte(JedecID);

 
  IDBuffer1   =User_SPI_W25X16_SendByte(NoneCode);     //读取高位
  IDBuffer2   =User_SPI_W25X16_SendByte(NoneCode);     //读取中位
  IDBuffer3   =User_SPI_W25X16_SendByte(NoneCode);     //读取低位

  SPI_W25X16_CS_DisSelect;

  ID=(IDBuffer1<<16)|(IDBuffer2<<8)|IDBuffer3;
 
  return ID;
}


vu32 User_SPI_W25X16_ReadDeviceID(void)
{
  vu32 ID      =0;
  vu32 IDBuffer1 =0;
  vu32 IDBuffer2 =0;
  vu32 IDBuffer3 =0;
                  
  SPI_W25X16_CS_Select;
 
  User_SPI_W25X16_SendByte(ManufatureID);

 
  IDBuffer1   =User_SPI_W25X16_SendByte(NoneCode);     //读取高位
  IDBuffer2   =User_SPI_W25X16_SendByte(NoneCode);     //读取中位
  IDBuffer3   =User_SPI_W25X16_SendByte(NoneCode);     //读取低位

  SPI_W25X16_CS_DisSelect;

  ID=(IDBuffer1<<16)|(IDBuffer2<<8)|IDBuffer3;
 
  return ID;
}


void User_SPI_W25X16_StartReadSequence(vu32 ReadAddress)
{
  SPI_W25X16_CS_Select;

  User_SPI_W25X16_SendByte(ReadData);

  User_SPI_W25X16_SendByte((ReadAddress & 0xff0000) >> 16);       //最高8位地址
  User_SPI_W25X16_SendByte((ReadAddress & 0xff00) >> 8);       //中间8位
  User_SPI_W25X16_SendByte(ReadAddress & 0xff);                   //最低8位

  //SPI_W25X16_DisSelect;
}


void User_SPI_W25X16_PowerDown(void)
{
  SPI_W25X16_CS_Select;

  User_SPI_W25X16_SendByte(PowerDown);

  SPI_W25X16_CS_DisSelect;
}


void User_SPI_W25X16_WakeUp(void)
{
  SPI_W25X16_CS_Select;

  User_SPI_W25X16_SendByte(WakeUp);

  SPI_W25X16_CS_DisSelect;
}

user_spi_w25x16.h

//SPI FLASH chip W25X16 头文件

#ifndef _USER_SPI_W25X16_H
#define _USER_SPI_W25X16_H

#include'stm32f10x.h'

typedef enum{Failed=0,Successed=!Failed}TestStatus;                         //声明定义枚举型变量 用于表示测试失败与成功

#define SPI_W25X16_SectorSize      4096
#define SPI_W25X16_PageSize       256      //W25X16每页数据长度
#define SPI_W25X16_PerPageWriteSize     256      //每页最多写入的数据个数


#define SPI_W25X16         SPI1
#define SPI_W25X16_Clock       RCC_APB2Periph_SPI1


#define SPI_W25X16_CS_Clock       RCC_APB2Periph_GPIOC
#define SPI_W25X16_CS_Port       GPIOC
#define SPI_W25X16_CS_Pin       GPIO_Pin_4


#define SPI_W25X16_SCK_Clock      RCC_APB2Periph_GPIOA
#define SPI_W25X16_SCK_Port       GPIOA
#define SPI_W25X16_SCK_Pin       GPIO_Pin_5


#define SPI_W25X16_MISO_Clock         RCC_APB2Periph_GPIOA
#define SPI_W25X16_MISO_Port      GPIOA
#define SPI_W25X16_MISO_Pin       GPIO_Pin_6


#define SPI_W25X16_MOSI_Clock      RCC_APB2Periph_GPIOA
#define SPI_W25X16_MOSI_Port      GPIOA
#define SPI_W25X16_MOSI_Pin       GPIO_Pin_7


#define SPI_24G_CS_Clock       RCC_APB2Periph_GPIOB
#define SPI_24G_CS_Port        GPIOB
#define SPI_24G_CS_Pin        GPIO_Pin_2


#define SPI_VS1003B_CS_Clock      RCC_APB2Periph_GPIOB
#define SPI_VS1003B_CS_Port       GPIOB
#define SPI_VS1003B_CS_Pin       GPIO_Pin_0


#define SPI_W25X16_CS_Select      GPIO_ResetBits(SPI_W25X16_CS_Port,SPI_W25X16_CS_Pin)

#define SPI_W25X16_CS_DisSelect      GPIO_SetBits(SPI_W25X16_CS_Port,SPI_W25X16_CS_Pin)



u8   User_SPI_W25X16_SendByte(u8 SendByteData)         //send data that is byte
u8   User_SPI_W25X16_ReadByte(void);                        //Read ByteData from chip W25X16
vu16  User_SPI_W25X16_SendHalfWord(u16 HalfWord) ;         //send data ,is halfword
void User_SPI_W25X16_WriteEnable(void);                     //write enable for W25X16
void User_SPI_W25X16_WaitForWriteEnd(void);                 //wait the end about write for chip W25X16


void User_SPI_Config(void);                         //SPI1 init configuration
void User_SPI_W25X16_SectorErase(vu32 SectorAddress);       
void User_SPI_W25X16_BulkErase(void);            //erase the W25X16
void User_SPI_W25X16_PageWrite(u8 *DataTable,vu32 WriteAddress,vu16 NumberOfWrite);
void User_SPI_W25X16_ChipWrite(u8 *DataTable,vu32 WriteAddress,vu16 NumberOfWrite);
void User_SPI_W25X16_ChipRead(u8 *DataTable,vu32 ReadAddress,vu16 NumberOfRead);
vu32 User_SPI_W25X16_ReadID(void);             //read chip ID
vu32 User_SPI_W25X16_ReadDeviceID(void);           //read manufacture device ID
void User_SPI_W25X16_StartReadSequence(vu32 ReadAddress);
void User_SPI_W25X16_PowerDown(void);
void User_SPI_W25X16_WakeUp(void);

 


#endif

 

以上,结束。

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 用NE555制作定时器

  • 带有短路保护系统的5V直流稳压电源电路图

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章