当前位置: 首页 > news >正文

FPGA—ZYNQ学习spi(六)

完成对SPiflash的读写

功能:1.flash初始化2.flash擦除3.flash写入数据4.flash读数据

1可以选择是ps的mio引脚也可以是emio的PL侧引出来的引脚

1.1mio

1.2emio

2综合完后,分配引脚

还是一样的需要导出然后设置顶层,最后进行综合,分配引脚,生成bit打开SDK

3打开SDK,在进行创建工层

4.打开示例工程发现一些指令

指令

基本读写操作指令

这是最核心、最常用的一组指令。

指令宏

操作码

功能描述

READ_CMD

0x03

​读取数据​​。主控制器发送此命令后,再发送要读取的内存地址,Flash芯片就会从该地址开始返回数据。

FAST_READ_CMD

0x08

​快速读取​​。比普通读取更快,通常在命令和地址后会有一个“哑元”字节,以支持更高的SPI时钟频率。

WRITE_CMD

0x02

​页编程​​。用于向Flash​​写入数据​​。主控制器先发送此命令,再发送目标地址,然后是待写入的数据。​​写入前必须先擦除​​。

AAI_WRITE_CMD

0xAD

​自动地址增量写入​​。某些品牌(如SST)Flash的特色功能,可以连续写入多个字而无需重复发送写命令和地址,提高了写入效率。

🗑️ 擦除操作指令

Flash存储器的重要特性是:在写入(编程)之前,必须先进行擦除(将位从“0”变为“1”)。擦除操作的单位不同。

指令宏

操作码

功能描述

CHIP_ERASE_CMD

0x60或 0xC7

​整片擦除​​。擦除整个Flash芯片的所有数据,​​操作需极其谨慎​​,因为会清空所有内容。

BULK_ERASE_CMD

0xC7

​批量擦除​​,通常是CHIP_ERASE_CMD的另一个别名。

BLOCK_ERASE_64K_CMD

0xD8

​块擦除​​。擦除一个指定地址开始的、大小为64KB的存储块。这是更精细的擦除操作。

⚙️ 状态与控制指令

用于管理写操作、查询芯片状态和配置。

指令宏

操作码

功能描述

WRITE_ENABLE_CMD

0x06

​写使能​​。​​在执行任何写或擦除操作前,必须首先发送此命令​​,将芯片置为可写状态。

WRITE_DISABLE_CMD

0x04

​写禁止​​。用于取消写使能状态,保护数据。

READ_STATUS_CMD

0x05

​读状态寄存器​​。Flash芯片内部有一个状态寄存器,通过此命令可以读取其值,关键目的是​​检查bit0的“忙”位​​,以判断写/擦除操作是否完成。

WRITE_STATUS_CMD

0x01

​写状态寄存器​​。用于配置写保护区域等参数。

🔍 识别与保护指令

用于识别芯片型号和管理硬件保护功能。

指令宏

操作码

功能描述

READ_ID

0x90

​读ID​​。读取制造商标识和设备标识。

SST_READ_ID

0x9F

​SST读ID​​。另一种标准的读ID命令,JEDEC标准命令,绝大多数SPI Flash都支持。

SST_FLUSH_ID

0xBF

注释说明是SST闪存的ID值,可能用于识别。

GLOBAL_BLK_PROT_UNLK

0x98

​全局块保护解锁​​。用于解除SST Flash的硬件写保护功能。

💎 总结与工作流程

这些指令共同构成了操作SPI Flash的完整流程。一个典型的​​写入流程​​如下:

  1.  

    发送 WRITE_ENABLE_CMD

  2.  

    发送擦除指令(如 BLOCK_ERASE_64K_CMD)擦除目标区域。

  3.  

    轮询 READ_STATUS_CMD直到芯片就绪。

  4.  

    再次发送 WRITE_ENABLE_CMD

  5.  

    发送 WRITE_CMD或 AAI_WRITE_CMD进行数据写入。

  6.  

    轮询 READ_STATUS_CMD直到写入完成。

4找到spi.h库文件看看函数有哪些


4.2模式函数作用

 根据是哪个spi进行操作

XSpiPs Setoptlons(SpiInstancePtr, XSPIPS MANUAL START OPTION
XSPIPS MASTER OPTIONXSPIPS FORCE SSELECT OPTION);

XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MANUAL_START_OPTION | XSPIPS_MASTER_OPTION | XSPIPS_FORCE_SSELECT_OPTION);

这行代码的意思是:​​对 SpiInstancePtr所指向的SPI控制器实例,同时启用“手动启动”、“主模式”和“强制片选”这三个选项。​

🔧 三种模式详解

下面的表格清晰地展示了代码中设置的三种模式及其作用:

模式选项(宏定义)

含义

作用与解释

XSPIPS_MASTER_OPTION

​主模式​

将当前SPI设备设置为​​主设备​​。​​主设备​​控制通信,提供时钟信号(SCLK),并决定何时开始和结束传输。这是最常见的设置,因为CPU/FPGA通常作为主设备去控制Flash、传感器等从设备。

XSPIPS_FORCE_SSELECT_OPTION

​强制片选模式​

​强制SPI控制器的片选信号(SS或CS)在整个数据传输期间始终保持有效(低电平)​​。这确保了从设备在接收一整个完整的数据帧期间不会被意外中断,是通信稳定性的关键。

XSPIPS_MANUAL_START_OPTION

​手动启动模式​

将传输的控制权交给程序员。启用后,​​调用XSpiPs_Transfer函数不会立即开始传输​​,而是需要再调用XSpiPs_Start函数来真正启动SPI传输。这提供了对传输时序的精确控制。

4.3时钟分频函数作用

spi控制器是连接总线的,axi总线的时钟比较快,所以必须进行分频一般在25mhz以下

分频的参数

4.4FLASH读ID 指令

在手册中找到读ID指令

需要给FLASH写入一个字节的90h,然后在发送三个字节,

 第五个字节返回厂商的字节以及他的设备id

根据自己的设备ID 读出来了进行核对

根据自己的器件手册把指令定义

根据是对读id进行6个字节的操作

设置6个字节的写操作

4.5传输指令

spi控制器以及发送的地址和接收的地址,没有接收就不接收等等spi是包括读和写的

byteconunt是写和读的总共字节数

在传输的时候,如果对设备进行读ID,需要先发送4个字节,然后接收的是2个字节,就是得从第5个字节和第6个字节进行接收

4.6片擦除指令

spi控制器最少发送两个字节

查看状态寄存器的busy最低位是不是0 0 表示擦除结束

int FlashChipErase(XSpiPs *SpiPs)
{u8 WriteBuf[2];u8 ReadBuf[2];WriteBuf[0] = ChipEraseCmd;WriteBuf[1] = 0;XSpiPs_PolledTransfer(SpiPs,WriteBuf,NULL,2); 不关心接收数据可以填写null空指针while(1)  //判断擦除有没有结束查看状态寄存器的busy最低位是不是0 0 表示擦除结束{WriteBuf[0] = ReadStatus1Cmd;WriteBuf[1] = 0;XSpiPs_PolledTransfer(SpiPs,WriteBuf,ReadBuf,2);//if(ReadBuf[1]&0x01 == 0)break; //如果最低位是1与0x01就是看最低位 是否为10}return XST_SUCCESS;
}

4.7FLASH写操作

因为是32位的地址只用了24为 在给地址的时候需要把第三位与ff相与 在左移16位放在最低位。以此类推

4.8FLASH读操作


int FlashRead(XSpiPs *SpiPs,u32 Address,u8 *ReadBuf,u32 Readlen)
{u8 *WriteBuf = (u8 *)malloc(Readlen * sizeof(u8));WriteBuf[0] = ReadDataCmd;WriteBuf[1] = (Address & 0xFF0000) >> 16;WriteBuf[2] = (Address & 0xFF00) >> 8;WriteBuf[3] = (Address & 0xFF);XSpiPs_PolledTransfer(SpiPs,WriteBuf,ReadBuf,Readlen);return XST_SUCCESS;

5,完整代码

5.1 flash.driver.c

/** flash_drive.c*  功能:1.flash初始化 2.flash擦除 3.flash写入数据 4.flash读数据*/#include "flash_drive.h"int FlashInit(XSpiPs *SpiPs,u16 DeviceId)
{int Status;XSpiPs_Config *SpiConfig;u8 ManID;u8 DeviceID;SpiConfig = XSpiPs_LookupConfig(DeviceId);if (NULL == SpiConfig) {return XST_FAILURE;}Status = XSpiPs_CfgInitialize(SpiPs, SpiConfig,SpiConfig->BaseAddress);if (Status != XST_SUCCESS) {return XST_FAILURE;}XSpiPs_SetOptions(SpiPs, XSPIPS_MASTER_OPTION | XSPIPS_FORCE_SSELECT_OPTION);XSpiPs_SetClkPrescaler(SpiPs,XSPIPS_CLK_PRESCALE_32);if(FlashID(SpiPs,&ManID,&DeviceID) == XST_FAILURE)return XST_FAILURE;return XST_SUCCESS;
}int FlashID(XSpiPs *SpiPs,u8 *ManID,u8 *DeviceID)
{u8 WriteBuf[6];u8 ReadBuf[6];WriteBuf[0] = ReadIDCmd;WriteBuf[1] = 0;WriteBuf[2] = 0;WriteBuf[3] = 0;if(XSpiPs_PolledTransfer(SpiPs,WriteBuf,ReadBuf,6) == XST_FAILURE)return XST_FAILURE;//ReadBuf[5] Man ID//ReadBuf[6] Device ID*ManID = ReadBuf[5];*DeviceID = ReadBuf[6];return XST_SUCCESS;
}int FlashChipErase(XSpiPs *SpiPs)
{u8 WriteBuf[2];u8 ReadBuf[2];WriteBuf[0] = ChipEraseCmd;WriteBuf[1] = 0;XSpiPs_PolledTransfer(SpiPs,WriteBuf,NULL,2);while(1){WriteBuf[0] = ReadStatus1Cmd;WriteBuf[1] = 0;XSpiPs_PolledTransfer(SpiPs,WriteBuf,ReadBuf,2);if(ReadBuf[1]&0x01 == 0)break;}return XST_SUCCESS;
}int FlashWrite(XSpiPs *SpiPs,u32 Address,u8 *Num,u32 Numlen)
{u8 WriteDataBuf[5];u32 i;for(i  = 0 ;i < Numlen ;i++){WriteDataBuf[0] = WriteDataCmd;WriteDataBuf[1] = (Address & 0xFF0000) >> 16;WriteDataBuf[2] = (Address & 0xFF00) >> 8;WriteDataBuf[3] = (Address & 0xFF);WriteDataBuf[4] = *(Num + i);XSpiPs_PolledTransfer(SpiPs,WriteDataBuf,NULL,5);}return XST_SUCCESS;
}int FlashRead(XSpiPs *SpiPs,u32 Address,u8 *ReadBuf,u32 Readlen)
{u8 *WriteBuf = (u8 *)malloc(Readlen * sizeof(u8));WriteBuf[0] = ReadDataCmd;WriteBuf[1] = (Address & 0xFF0000) >> 16;WriteBuf[2] = (Address & 0xFF00) >> 8;WriteBuf[3] = (Address & 0xFF);XSpiPs_PolledTransfer(SpiPs,WriteBuf,ReadBuf,Readlen);return XST_SUCCESS;
}

5.2 .h

/**/#ifndef SRC_FLASH_DRIVE_H_
#define SRC_FLASH_DRIVE_H_#include "xparameters.h"	/* SDK generated parameters */
#include "xplatform_info.h"
#include "xspips.h"		/* SPI device driver */
#include "xil_printf.h"
#include "xstatus.h"
#include "stdlib.h"#define WriteEnableCmd 		0x16
#define WriteDisEnableCmd 	0x04
#define ReadStatus1Cmd 		0x05
#define ReadStatus2Cmd 		0x35
#define WriteStatusCmd 		0x01
#define WriteDataCmd		0x02
#define BlockErase64Cmd 	0xd8
#define BlockErase32Cmd 	0x52
#define SectorEraseCmd 		0x20
#define ChipEraseCmd 		0xc7
#define ReadIDCmd 			0x90
#define ReadDataCmd 		0x03#endif /* SRC_FLASH_DRIVE_H_ */

遗漏问题:

1.对spi的写id时候为什么写3个字节,读的字节是要跟写字节后面的

2.对于写操作怎么计算和读操作    u8 *WriteBuf = (u8 *)malloc(Readlen * sizeof(u8));

WriteDataBuf[1] = (Address & 0xFF0000) >> 16;
WriteDataBuf[2] = (Address & 0xFF00) >> 8;
WriteDataBuf[3] = (Address & 0xFF);
WriteDataBuf[4] = *(Num + i);
XSpiPs_PolledTransfer(SpiPs,WriteDataBuf,NULL,5);

这两个为什么放到的是最低位发送流程是什么

http://www.dtcms.com/a/577139.html

相关文章:

  • 多智能体医疗会诊系统
  • ETCD 压力测试脚本
  • kali的下载和安装【ISO安装】
  • 从标签到数据流:BarTender让“可追溯”更简单
  • 零基础学AI大模型之Embedding与LLM大模型对比全解析
  • 7.游戏逆向-pxxx-TUObjectArray分析
  • web214-web220
  • 通州北苑网站建设程序开发的基本步骤是什么?
  • 专题:2025中国制造业出海与出海品牌社媒影响力洞察报告|附300+份报告PDF、数据、绘图模板汇总下载
  • 【 C/C++ 算法】入门动态规划 ----- 简单多状态 dp 问题》打家劫舍 和 股票买卖问题
  • (114页PPT)华为FusionCloud私有云最佳实践RegionTypeII(附下载方式)
  • 赤壁专业建站公司学做卤味视频网站
  • 3d光学轮廓仪如何局部测量标准台阶?
  • 【数据集+完整源码】水稻病害数据集,yolov8水稻病害检测数据集 6715 张,目标检测水稻识别算法实战训推教程
  • 3D Gaussian Splatting:渲染流程
  • 云原生LVS+Keepalived高可用方案(二)
  • IBM VO 面试经验分享|一场更像“聊天”的正式考核
  • 用单位的服务器做网站关键词优化网站
  • C语言基础开发入门系列(八)C语言指针的理解与实战
  • 如何绑定网站域名解析电商网站模板html
  • 【机器视觉通用检测框架】基于VS2019 C#+VisionPro9.0开发的视觉框架软件,全套源码,开箱即用
  • 智慧交通管理新范式 基于深度学习的城市交通车型识别AI监控系统 车型识别 停车场车型分类系统 高速路车型识别算法
  • pnpm 安装依赖后 仍然启动报的问题
  • 【河北政务服务网-注册_登录安全分析报告】
  • 深入理解 package.json:前端项目的 “身份证“
  • 【辽宁政务服务网-注册_登录安全分析报告】
  • 免费正能量励志网站建设网站要多久到账
  • 新乡市红旗区建设局网站网页制作素材网有哪些
  • 用车申请车辆管理小程序开发
  • 单片机.RS485