[DemoCode下载] N76E003 软SPI 驱动 W25X大容量EEPROM,附全部源文件

[复制链接]
2441|7
 楼主| tianxj01 发表于 2018-7-29 09:56 | 显示全部楼层 |阅读模式
本帖最后由 tianxj01 于 2018-7-29 10:09 编辑

因为003芯片硬件SPI已经被单独占用,而外部W25X64使用频率不高,因此用IO模拟SPI进行驱动是一个很好的方法。硬件连接:由于W25X64 是3.3V,而我的003用的是5V,所以这里全部采用外接3.3K电阻上拉3.3V,003端口输入采用高阻外部上拉,输出采用开漏,上拉。

下面给出全部源代码:(SPI_Flash_cmd.h)
  1. #ifndef __SPI_FLASH_CMD_H__
  2. #define __SPI_FLASH_CMD_H__

  3. #define W25X_BUSY       0
  4. #define W25X_NotBUSY    1   
  5. #define Dummy_Byte1     0xFF

  6. /*********************************************
  7. - W25X的操作指令表,MCU通过向W25X
  8.   发送以下指令就可以对W25X进行以下的操作
  9. *********************************************/
  10. #define W25X_WriteEnable            0x06    //Write Enable
  11. #define W25X_WriteEnableVSR         0x50    //Write Enable for Volatile Status Register
  12. #define W25X_WriteDisable           0x04    //Write Disable
  13. #define W25X_ReadStatusReg1         0x05    //读状态寄存器1:S7~S0
  14. #define W25X_ReadStatusReg2         0x35    //读状态寄存器2:S15~S8
  15. #define W25X_WriteStatusReg         0x01    //写读状态寄存器:BYTE1:S7~S0  BYTE2:S15~S8
  16. #define W25X_PageProgram            0x02    //单页编程:BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0  BYTE4:D7~D0
  17. #define W25X_SectorErase            0x20    //扇区擦除:4K  BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0
  18. #define W25X_BlockErase32K          0x52    //块擦除:32K  BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0
  19. #define W25X_BlockErase64K          0xD8    //块擦除:64K  BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0
  20. #define W25X_ChipErase              0xC7    //芯片擦除
  21. #define W25X_EraseSuspend           0x75    //暂停擦除
  22. #define W25X_EraseResume            0x7A    //恢复擦除
  23. #define W25X_PowerDown              0xB9    //掉电
  24. #define W25X_ContinuousReadMode     0xFF    //连续读模式
  25. #define W25X_ReadData               0x03    //读数据:BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0  BYTE4:D7~D0
  26. #define W25X_FastReadData           0x0B    //快速读取:BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0  BYTE4:dummy  BYTE5:D7~D0
  27. #define W25X_FastReadDual           0x3B    //快速双读取:BYTE1:A23~A16  BYTE2:A15~A8  BYTE3:A7~A0  BYTE4:dummy  BYTE5:D7~D0
  28. #define W25X_ReleasePowerDown       0xAB   
  29. #define W25X_DeviceID               0xAB
  30. #define W25X_ManufactDeviceID       0x90
  31. #define W25X_JedecDeviceID          0x9F

  32. #endif
SPI_Flash_reg.h:
  1. /**************************************
  2. 软SPI端口连接
  3. P16  -- spi cs
  4. P15  -- spi clock
  5. P14  -- spi MOSI
  6. P13  -- spi MISO   
  7. ***************************************/
  8. #define SPI_CS                P16
  9. #define SPI_CLK                P15
  10. #define SPI_MOSI        P14
  11. #define SPI_MISO        P13

  12. void SPI_Flash_Init_IO (void);
  13. void SPI_Flash_WriteEnable  (void);
  14. void SPI_Flash_WriteDisable (void);
  15. void SPI_Flash_Wait_Busy (void);
  16. void SPI_Flash_Read ( u32 ReadAddr , u8* pBuffer , u16 NumByteToRead );
  17. void SPI_Flash_Write_Page (u32 WriteAddr, u8* pBuffer , u16 NumByteToWrite);
  18. void SPI_Flash_Erase_Block( u32 Erase_Addr ,u8 mode );

  19. unsigned int  SPI_Flash_ReadID(void);
  20. unsigned char SPI_Flash_Read_Busy(void);
  21. unsigned char SPI_Flash_Write_Byte(unsigned char Data);





 楼主| tianxj01 发表于 2018-7-29 09:58 | 显示全部楼层
什么情况,怎么没有发完整,晕
 楼主| tianxj01 发表于 2018-7-29 10:02 | 显示全部楼层
本帖最后由 tianxj01 于 2018-7-29 10:05 编辑

继续:
SPI_Flash_reg.c:
  1. #include <stdio.h>
  2. #include "N76E003.h"
  3. #include "Common.h"
  4. #include "SFR_Macro.h"
  5. #include "Function_define.h"
  6. #include "SPI_Flash_reg.h"
  7. #include "SPI_Flash_cmd.h"

  8. #define NOP()                _nop_();
  9. /**************************************
  10. 软SPI端口连接
  11. P16  -- spi cs
  12. P15  -- spi clock
  13. P14  -- spi MOSI
  14. P13  -- spi MISO   
  15. ***************************************/

  16. void SPI_Flash_Init_IO(void)
  17.         {
  18.                
  19. P13_Input_Mode;
  20. P14_OpenDrain_Mode;P14=0;
  21. P15_OpenDrain_Mode;P15=0;
  22. P16_OpenDrain_Mode;P16=1;
  23. }
  24. /***************************************************************************
  25. 函 数 名:SPI_Flash_Write_Byte
  26. 功    能:软SPI_Flash 总线驱动基础函数,发送单个字节到MOSI,并同时接受MISO数据
  27. 参    数:unsigned char Data MOSI数据线上发送的数据
  28. 返    回:unsigned char Out         MISO数据线上接受的数据
  29. ****************************************************************************/
  30. unsigned char SPI_Flash_Write_Byte(unsigned char Data)
  31.         {
  32.                 unsigned char Out = 0;
  33.                 unsigned char i;// = 0;
  34.                 //SPI_CLK = 0;
  35.                 for(i = 8; i > 0; i--)
  36.                         {
  37.                                 SPI_CLK = 0;
  38.                                 SPI_MOSI=Data>>7;
  39.                                 Data <<= 1;
  40.                                 NOP();
  41.                                 NOP();
  42.                                 NOP();
  43.                                 NOP();
  44.                                 NOP();
  45.                                 Out<<=1;
  46.                                 SPI_CLK = 1;
  47.                                 Out|=SPI_MISO;
  48.                         }
  49.                 SPI_CLK = 0;
  50.                 return Out;
  51.         }
  52. //*************** 写使能 ****************************  OK
  53. void SPI_Flash_WriteEnable  (void)
  54.         {
  55.                 SPI_CS = 0;
  56.                 NOP();
  57.                 NOP();
  58.                 SPI_Flash_Write_Byte(W25X_WriteEnable);
  59.                 NOP();
  60.                 NOP();
  61.                 SPI_CS = 1;
  62.         }

  63. //*************** 写禁止 ****************************    OK
  64. void SPI_Flash_WriteDisable (void)
  65.         {
  66.                 SPI_CS = 0;
  67.                 NOP();
  68.                 NOP();
  69.                 SPI_Flash_Write_Byte(W25X_WriteDisable);
  70.                 NOP();
  71.                 NOP();
  72.                 SPI_CS = 1;
  73.         }

  74. /***************BUSY等待*********************************************
  75. 函 数 名:SPI_Flash_Wait_Busy
  76. 功    能:读FLASH的BUSY,如果忙就等待。BUSY的原因是擦除,或是连续读写
  77. *********************************************************************/
  78. void SPI_Flash_Wait_Busy(void)
  79.         {                                
  80.                 unsigned char test;        
  81.                 SPI_CS = 0;
  82.             do
  83.                         {
  84.                                 SPI_Flash_Write_Byte(W25X_ReadStatusReg1);
  85.                                 test = SPI_Flash_Write_Byte(Dummy_Byte1);
  86.                                 //  连续读StatusReg1,不影响总操作时间,也就是芯片不会添忙
  87.                         }
  88.                 while ((test&0x01)==0x01);
  89.                 SPI_CS = 1;
  90.         }
  91. /***************读BUSY*********************************************
  92. 函 数 名:SPI_Flash_Read_Busy
  93. 功    能:读FLASH的BUSY
  94. 返    回:空返回NotBUSY,忙返回BUSY
  95. *********************************************************************/
  96. unsigned char SPI_Flash_Read_Busy(void)
  97.         {                                
  98.                 unsigned char test;        
  99.                 SPI_CS = 0;
  100.             SPI_Flash_Write_Byte(W25X_ReadStatusReg1);
  101.                 test = SPI_Flash_Write_Byte(Dummy_Byte1);
  102.                 SPI_CS = 1;
  103.                 if(test&0x01)return (W25X_BUSY);
  104.                 else return (W25X_NotBUSY);
  105.         }
  106. /************************************************************************
  107. 函 数 名:SPI_Flash_Erase_Block
  108. 功能描述: 擦除一个32K or 64K 块
  109. 输入参数: u32 Data_Addr 开始擦除的块首地址
  110. mode        擦除模式 1=32K 其他=64K
  111. ************************************************************************/
  112. void SPI_Flash_Erase_Block( u32 Erase_Addr ,u8 mode )
  113.         {
  114.                 SPI_Flash_WriteEnable();
  115.                 SPI_Flash_Wait_Busy();
  116.                 SPI_CS = 0;
  117.                 if(mode==1){SPI_Flash_Write_Byte(W25X_BlockErase32K);}  //根据定义,发送32K或64K擦除指令
  118.                 else {SPI_Flash_Write_Byte(W25X_BlockErase64K);}
  119.                 SPI_Flash_Write_Byte(Erase_Addr >> 16);
  120.             SPI_Flash_Write_Byte(Erase_Addr >> 8);
  121.             SPI_Flash_Write_Byte(Erase_Addr);
  122.                 SPI_CS = 1;
  123.                 SPI_Flash_Wait_Busy();                //等待擦除完成
  124.         }

  125. /************************************************************************
  126. 函 数 名  : SPI_Flash_Read
  127. 功能描述  : 在指定地址开始读取指定长度的数据
  128. 输入参数  : u32 ReadAddr       开始读取的地址(24bit)
  129. u8* pBuffer        数据存储区
  130. u16 NumByteToRead  要读取的字节数(最大65535)
  131. *****************************************************************************/
  132. void SPI_Flash_Read ( u32 ReadAddr , u8* pBuffer , u16 NumByteToRead )
  133.         {
  134.                 u16 i;
  135.                 SPI_CS = 0;/* Enable chip select */
  136.                 SPI_Flash_Write_Byte(W25X_ReadData);
  137.                 SPI_Flash_Write_Byte(ReadAddr >> 16);
  138.                 SPI_Flash_Write_Byte(ReadAddr >> 8);
  139.                 SPI_Flash_Write_Byte(ReadAddr);
  140.                 for(i=0;i<NumByteToRead;i++)
  141.                         {
  142.                                 pBuffer[i] = SPI_Flash_Write_Byte(Dummy_Byte1); //Read one byte
  143.                         }
  144.                 SPI_CS = 1;/* Disable chip select */
  145.         }
  146. /*************************************************************************
  147. 函 数 名:SPI_Flash_Write_Page
  148. 功    能:SPI在一页(0~65535)的指定地址开始写入最大256字节的数据
  149. 输入参数:pBuffer:数据存储区
  150. WriteAddr:开始写入的地址(24bit)
  151. NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!
  152. ***************************************************************************/
  153. void SPI_Flash_Write_Page (u32 WriteAddr, u8* pBuffer , u16 NumByteToWrite)
  154.         {
  155.                 u16 i;  
  156.                 SPI_Flash_WriteEnable();                  //SET WEL
  157.                 SPI_CS = 0;
  158.                 SPI_Flash_Write_Byte(W25X_PageProgram);      //发送写页命令   
  159.                 SPI_Flash_Write_Byte((u8)((WriteAddr)>>16)); //发送24bit地址   
  160.                 SPI_Flash_Write_Byte((u8)((WriteAddr)>>8));   
  161.                 SPI_Flash_Write_Byte((u8)WriteAddr);   
  162.                 for(i=0;i<NumByteToWrite;i++)SPI_Flash_Write_Byte(pBuffer[i]);//循环写数  
  163.                 SPI_CS = 1;                                          //取消片选
  164.         SPI_Flash_Wait_Busy();                  //等待写入结束
  165.                 SPI_Flash_WriteDisable();
  166.         }

  167. /*******************************************************************************
  168. * Function Name  : SPI_FLASH_ReadID
  169. * Description    : Reads FLASH identification.
  170. * Input          : None
  171. * Output         : None
  172. * Return         : FLASH identification
  173. *******************************************************************************/
  174. unsigned int SPI_Flash_ReadID(void)
  175.         {
  176.                 u16        Temp = 0;
  177.                 /* Enable chip select */
  178.                 SPI_CS = 0;
  179.                 /* Send "RDID " instruction */
  180.                 SPI_Flash_Write_Byte(W25X_ManufactDeviceID);
  181.                 SPI_Flash_Write_Byte(0x00);
  182.                 SPI_Flash_Write_Byte(0x00);
  183.                 SPI_Flash_Write_Byte(0x00);
  184.                 /* Read a byte from the FLASH */
  185.                 Temp|= SPI_Flash_Write_Byte(Dummy_Byte1)<<8;
  186.                 Temp|= SPI_Flash_Write_Byte(Dummy_Byte1);
  187.                 /* Disable chip select */
  188.                 SPI_CS = 1;
  189.                 return Temp;
  190.         }

xuanhuanzi 发表于 2018-7-29 12:57 | 显示全部楼层
不错,好资料,注释的完整啊。
xixi2017 发表于 2018-7-29 16:21 | 显示全部楼层
楼主这个掌握的不错。
xinxianshi 发表于 2018-7-29 19:05 | 显示全部楼层
51内核的跑模拟通信接口最合适了。
21mengnan 发表于 2018-7-29 19:29 | 显示全部楼层
不错,这个宏替换搞的好,可以随意修改IO。
mintspring 发表于 2018-7-29 20:16 | 显示全部楼层
我擦,给力,我要保存下来。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

3211

帖子

93

粉丝
快速回复 在线客服 返回列表 返回顶部
0