官方提供的58x的spi例程,spi主机模式下的发送方式有三种单字节发送,FIFO连续发送,DMA连续发送。本文分别对SPI0主机模式下三种发送模式进行使用。

本次使用的是CH582m做为主机,W25Q64FV作为从机。

一、单字节发送

本次调试中实现对W25Q64FVflas进行读id,擦除,写入,读取。

在进行主要操作的时候先理清代码逻辑。主机先将SCS总线拉低,保证能够开始接收数据。再通过W25Q64FV的手册我们知道在进行操作之前要判断当前是否在

忙碌状态。如果不在忙碌状态将进行下一步。通过手册我们可以知道通过发送对应的地址(0x05or0x35)进行判忙。

程序中实现判断忙碌的操作可见如下:

void SPI_Flash_Wait_Busy(void)
{
uint8_t busy;
do
{
GPIOA_ResetBits(GPIO_Pin_12);
SPI0_MasterSendByte(0x05); busy=SPI0_MasterRecvByte();
GPIOA_SetBits(GPIO_Pin_12); PRINT("busy%02x\r\n",busy);
}
while((busy&0x01)==0x01); }

接下来基本就按照需要使用的器件的手册进行读写等操作:

(1)、读ID:

读ID看是否能够读到正确的设备ID:

#define W25Q80 0XEF13
#define W25Q16 0XEF14
#define W25Q32 0XEF15
#define W25Q64 0XEF16
#define W25Q128 0XEF17

我们读ID根据手册的提示需要对就相应的寄存器地址进行操作;程序演示如下所示:

void read_wq64_id(void)
{
uint8_t ID1,ID2;
GPIOA_ResetBits(GPIO_Pin_12);
SPI0_MasterSendByte(0x90);
SPI0_MasterSendByte(0x00);
SPI0_MasterSendByte(0x00);
SPI0_MasterSendByte(0x00);
ID1=SPI0_MasterRecvByte();
ID2=SPI0_MasterRecvByte();
GPIOA_SetBits(GPIO_Pin_12); PRINT("%02x\r\n %02x\r\n ",ID1,ID2); }

读取到的数据是EF16证明读取的ID没有问题。如果是其他的值可以在程序加判断直到是自己使用器件的ID再在进行下面的操作;

(2)、擦除扇区

在写之前要对对应的扇区进行擦除,

从手册上可以看出是4k擦除,还要注意在指令之后有24bit地址的操作,写入20h后需要进行移位操作,详情可见程序

手册中有这样一句话:A Write Enable instruction must be executed before the device will accept the Sector Erase Instruction (Status Register bit WEL must equal 1)。在进行擦除操作之前需要写使能:

所以擦除之前需要进行写使能:对应时序操作如下

代码实现:

void SPI_Write_Enable(void)
{
GPIOA_ResetBits(GPIO_Pin_12);
SPI0_MasterSendByte(0x06);
GPIOA_SetBits(GPIO_Pin_12); }

下面的则是擦除部分的代码:

void erase_sector(uint32_t SectorAddress)
{
SectorAddress *= 4096;
SPI_Write_Enable();
SPI_Flash_Wait_Busy();
GPIOA_ResetBits(GPIO_Pin_12);
SPI0_MasterSendByte(0x20); SPI0_MasterSendByte((uint8_t)(SectorAddress>>16));
SPI0_MasterSendByte((uint8_t)(SectorAddress>>8));
SPI0_MasterSendByte((uint8_t)SectorAddress);
GPIOA_SetBits(GPIO_Pin_12); }

(3)读操作,

进行读操作的情况下;读的操作稍微方便一些不需要进行判忙写使能等操作

在进行读操作的时,注意时序图中有一个Data Out 1,此时会有输出

void read_wq64_data(uint8_t instruction,uint32_t ReadAddr,uint16_t ReadByteNum,uint8_t *p_Buffer)
{
uint16_t i;
GPIOA_ResetBits(GPIO_Pin_12);
SPI0_MasterSendByte(instruction);
SPI0_MasterSendByte((uint8_t)(ReadAddr>>16));
SPI0_MasterSendByte((uint8_t)(ReadAddr>>8));
SPI0_MasterSendByte((uint8_t)ReadAddr); for(i = 0; i < ReadByteNum; i++)
{
p_Buffer[i] = SPI0_MasterRecvByte(); }
GPIOA_SetBits(GPIO_Pin_12); }

(5)写操作;

本次写入是按页写入,写之前先看手册注意手册中需要操作的部分

对应程序如下所示:

void  write_wq64_page_data(uint8_t *p_Buffer,uint32_t PageAddress,uint16_t WriteByteNum)
{
SPI_Write_Enable(); GPIOA_ResetBits(GPIO_Pin_12);
SPI0_MasterSendByte(0x02);
SPI0_MasterSendByte((uint8_t)(PageAddress>>16));
SPI0_MasterSendByte((uint8_t)(PageAddress>>8));
SPI0_MasterSendByte((uint8_t)PageAddress);
if(WriteByteNum > 256)
{
WriteByteNum=256;
PRINT("\r\n Err");
}
while(WriteByteNum--)
{
SPI0_MasterSendByte(*p_Buffer);
p_Buffer++;
}
GPIOA_SetBits(GPIO_Pin_12);
SPI_Flash_Wait_Busy();
}

差不多一个流程就是如此;可以在程序中加入打印或者使用逻辑分析仪等辅助工具对现象进行查看。

准备写入的数据__attribute__((aligned(4))) UINT8 spiBuff[] = {2, 2, 3, 3, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6};读出的结果如下

本次操作关键是对片选信号线的操作与对不同指令的读写操作,具体按照手册的时序的操作来即可。

仅是个人学习分享;如有任何错漏敬请留言指正。

CH58x/CH57x硬件SPI操作外部flash学习记录的更多相关文章

  1. STM32学习笔记(八) SPI总线(操作外部flash)

    1. SPI总线简介 SPI全称串行外设接口,是一种高速,全双工,同步的外设总线:它工作在主从方式,常规需要至少4根线才能够正常工作.SPI作为基本的外设接口,在FLASH,EPPROM和一些数字通讯 ...

  2. KL25用SPI操作nor flash

    KL25的SPI连接一个nor flash.该flash型号为FM25F04,支持SPI的模式0和模式3,要求高位先发送,在上升沿采集数据. 通常,SPI有4种模式,取决于CPOL与CPHA如何配置. ...

  3. spi数据KL25用SPI操作nor flash

    最近研究spi数据,稍微总结一下,以后继续补充: KL25的SPI连接一个nor flash.该flash型号为FM25F04,支撑SPI的模式0和模式3,要求高位先发送,在上升沿采集数据. 通常,S ...

  4. ESP8266清理flash学习记录

    学习来源:http://bbs.eeworld.com.cn/thread-497588-1-1.html 还稍看了电子产品世界 主要内容 1在windows 上通过 命令行 安装  Python环境 ...

  5. php 链式操作的实现 学习记录

    php 面向对象中实现链式操作的关键部分:调用的方法中返回当前对象 ,从而实现链式操作: <?php namespace commom; class db { public function w ...

  6. ElasticSearch 学习记录之ES几种常见的聚合操作

    ES几种常见的聚合操作 普通聚合 POST /product/_search { "size": 0, "aggs": { "agg_city&quo ...

  7. ElasticSearch 学习记录之 分布式文档存储往ES中存数据和取数据的原理

    分布式文档存储 ES分布式特性 屏蔽了分布式系统的复杂性 集群内的原理 垂直扩容和水平扩容 真正的扩容能力是来自于水平扩容–为集群添加更多的节点,并且将负载压力和稳定性分散到这些节点中 ES集群特点 ...

  8. ElasticSearch 学习记录之ES短语匹配基本用法

    短语匹配 短语匹配故名思意就是对分词后的短语就是匹配,而不是仅仅对单独的单词进行匹配 下面就是根据下面的脚本例子来看整个短语匹配的有哪些作用和优点 GET /my_index/my_type/_sea ...

  9. ElasticSearch 学习记录之如任何设计可扩容的索引结构

    扩容设计 扩容的单元 一个分片即一个 Lucene 索引 ,一个 Elasticsearch 索引即一系列分片的集合 一个分片即为 扩容的单元 . 一个最小的索引拥有一个分片. 一个只有一个分片的索引 ...

  10. ElasticSearch 学习记录之ES高亮搜索

    高亮搜索 ES 通过在查询的时候可以在查询之后的字段数据加上html 标签字段,使文档在在web 界面上显示的时候是由颜色或者字体格式的 GET /product/_search { "si ...

随机推荐

  1. 牛客 | 小G的约数引起的对于 整数分块 学习

    整除分块是个啥:要求\(∑_{i = 1}^n{n/i}\) 的值,这时候暴力需要O(n)的时间.由于这个区间是连续的,且'/'是向下取整,当i不能整除k时,n/i会等于最小的i(也就是区间最左边的值 ...

  2. 淘宝flexible.js源码分析

    下面三种情况都会刷新页面,都会触发load事件. 1.a标签的超链接. 2.F5或者刷新按钮(强制刷新) 3.前进后退按钮 但是火狐中,有个特点,有个"往返缓存",这个缓存中不仅保 ...

  3. HTTP协议六种请求:GET,HEAD,PUT,DELETE,POST

    Http定义了与服务器交互的不同方法,标准Http协议支持六种请求方法,即: 1.GET 2.POST 3.PUT 4.Delete 5.HEAD 6.Options 最基本的方法有4种,分别是GET ...

  4. NLP复习之神经网络

    NLP复习之神经网络 前言 tips: 设计神经网络时,输入层与输出层节点数往往固定,中间层可以自由指定: 神经网络中的拓扑与箭头代表预测过程数据流向,与训练的数据流有一定区别: 我们不妨重点关注连接 ...

  5. 一文搞清楚Java中的方法、常量、变量、参数

    写在开头 在上一篇文章:一文搞清楚Java中的包.类.接口 中我们讲了Java中的包.类和接口,今天继续将剩下的方法.常量.变量以及参数梳理完. Java中的变量与常量 在JVM的运转中,承载的是数据 ...

  6. 完美:C# Blazor中显示Markdown并添加代码高亮

    昨天发了一篇介绍这个库:C# Blazor中显示Markdown文件,介绍怎么在Blazor中显示Markdown内容的文章,文章内的代码是没有高亮的,思来相去,还是要做好,于是百度到这篇文章.NET ...

  7. Go-错误栈信息

    Go中错误栈信息 .\main.go:22:2: number1 declared but not used .\main.go 错误发生的文件 22:2 文件的22行第2列 number1 decl ...

  8. 【OpenVINO】基于 OpenVINO Python API 部署 RT-DETR 模型

    目录 1. RT-DETR 2. OpenVINO 3. 环境配置 3.1 模型下载环境 3.2 模型部署环境 4. 模型下载与转换 4.1 PaddlePaddle模型下载 4.2 IR模型转换 5 ...

  9. [转帖]Oracle Exadata X10M 数据库一体机发布,树立 OLTP 数据库性能新标杆

    https://www.modb.pro/db/653936 2023年6月25日消息,Oracle 公司继续以其专用的 Exadata 平台重新定义 OLTP 数据库性能.上周,该公司延续了这一传统 ...

  10. [转帖]数据库连接池选型 Druid vs HikariCP性能对比

    这里主要比较HikariCP 和阿里的Druid springboot 现在官方默认的数据库连接池是 HikariCP,HikariCP的性能从测试的数据上来看也是最高的. 先来看下这个著名的issu ...