CH347读写SPI Flash

CH347读写SPI Flash

前面耽搁了几天,今天终于把CH347 SPI接口调试好了。

CH347动态库中SPI接口函数如下:

typedef struct _SPI_CONFIG{UCHAR           iMode;                 // 0-3:SPI Mode0/1/2/3UCHAR           iClock;                // 0=60MHz, 1=30MHz, 2=15MHz, 3=7.5MHz, 4=3.75MHz, 5=1.875MHz, 6=937.5KHz,7=468.75KHzUCHAR			iByteOrder;            // 0=LSB first(LSB), 1=MSB first(MSB)USHORT          iSpiWriteReadInterval; // The SPI interface routinely reads and writes data command, the unit is uSUCHAR           iSpiOutDefaultData;    // SPI prints data by default when it reads dataULONG			iChipSelect;           // Piece of selected control, if bit 7 is 0, slice selection control is ignored, if bit 7 is 1, the parameter is valid: bit 1 bit 0 is 00/01 and CS1/CS2 pins are selected as low level active chip options respectivelyUCHAR           CS1Polarity;           // Bit 0: CS1 polarity control: 0: effective low level; 1: effective lhigh level;UCHAR           CS2Polarity;           // Bit 0: CS2 polarity control: 0: effective low level; 1: effective lhigh level;USHORT          iIsAutoDeativeCS;      // Whether to undo slice selection automatically after the operation is completeUSHORT          iActiveDelay;          // Set the latency for read/write operations after slice selection,the unit is usULONG           iDelayDeactive;        // Delay time for read and write operations after slice selection is unselected,the unit is us
}mSpiCfgS,*mPSpiCfgS;/***************SPI********************/
// SPI Controller Initialization
BOOL	WINAPI	CH347SPI_Init(ULONG iIndex,mSpiCfgS *SpiCfg);// Get SPI controller configuration information
BOOL    WINAPI  CH347SPI_GetCfg(ULONG iIndex,mSpiCfgS *SpiCfg);// Before setting the chip selection status, call CH347SPI_Init to set CS
BOOL	WINAPI	CH347SPI_ChangeCS(ULONG			iIndex,         // Specify device number	UCHAR         iStatus);       // 0=Cancel the piece to choose,1=Set piece selected// Set SPI slice selection
BOOL	WINAPI	CH347SPI_SetChipSelect(ULONG			iIndex,            // Specify device numberUSHORT           iEnableSelect,     // The lower octet is CS1 and the higher octet is CS2. A byte value of 1= sets CS, 0= ignores this CS settingUSHORT           iChipSelect,       // The lower octet is CS1 and the higher octet is CS2. A byte value of 1= sets CS, 0= ignores this CS settingULONG            iIsAutoDeativeCS,  // The lower 16 bits are CS1 and the higher 16 bits are CS2. Whether to undo slice selection automatically after the operation is completeULONG            iActiveDelay,      // The lower 16 bits are CS1 and the higher 16 bits are CS2. Set the latency of read/write operations after chip selection, the unit is usULONG            iDelayDeactive);   // The lower 16 bits are CS1 and the higher 16 bits are CS2. Delay time for read and write operations after slice selection the unit is us//SPI4 write data
BOOL	WINAPI	CH347SPI_Write(ULONG			iIndex,          // Specify device number	ULONG			iChipSelect,     // Slice selection control, when bit 7 is 0, slice selection control is ignored, and when bit 7 is 1, slice selection operation is performedULONG			iLength,         // Number of bytes of data to be transferred	ULONG			iWriteStep,      // The length of a single block to be readPVOID			ioBuffer);       // Point to a buffer to place the data to be written out from MOSI//SPI4 read data. No need to write data first, the efficiency is higher than that of the CH347SPI_WriteRead
BOOL	WINAPI	CH347SPI_Read(ULONG			iIndex,           // Specify device numberULONG			iChipSelect,      // Slice selection control, when bit 7 is 0, slice selection control is ignored, and when bit 7 is 1, slice selection operation is performedULONG         oLength,          // Number of bytes to sendPULONG		iLength,          // Number of bytes of data to be read inPVOID			ioBuffer);        // Points to a buffer that place the data to be written out from DOUT, return the data read in from DIN// Handle SPI data stream 4-wire interface
BOOL	WINAPI	CH347SPI_WriteRead(ULONG			iIndex,       // Specify the device numberULONG			iChipSelect,  // Selection control, if the film selection control bit 7 is 0, ignore the film selection control bit 7 is 1 and operate the film selectionULONG			iLength,      // Number of bytes of data to be transferredPVOID			ioBuffer );   // Points to a buffer that place the data to be written out from DOUT, return the data read in from DIN//place the data to be written from MOSI, return the data read in from MISO
BOOL	WINAPI	CH347StreamSPI4(ULONG			iIndex,       // Specify the device numberULONG			iChipSelect,  // Film selection control, if bit 7 is 0, slice selection control is ignored.If bit 7 is 1, the parameter is valid:Bit 1 bit 0 is 00/01/10. Select D0/D1/D2 pins as low level active chip options respectivelyULONG			iLength,      // Number of bytes of data to be transferredPVOID			ioBuffer );   // Points to a buffer, places data to be written out from DOUT, and returns data to be read in from DIN

要实现SPI通信,至少要用到CH347SPI_Init(ULONG iIndex,mSpiCfgS *SpiCfg) CH347SPI_Write(ULONG iIndex, ULONG iChipSelect, ULONG iLength, ULONG iWriteStep, PVOID ioBuffer) CH347SPI_Read(ULONG iIndex, ULONG iChipSelect, ULONG oLength, PULONG iLength, PVOID ioBuffer)这3个函数。

对这3个函数进行封装:

class SPIConfig(ctypes.Structure):_fields_ = [("iMode", ctypes.c_ubyte),                      # 0-3: SPI Mode0/1/2/3("iClock", ctypes.c_ubyte),                     # 0=60MHz, 1=30MHz, 2=15MHz, 3=7.5MHz,("iByteOrder", ctypes.c_ubyte),                 # 4=3.75MHz, 5=1.875MHz, 6=937.5KHz, 7=468.75KHz("iSpiWriteReadInterval", ctypes.c_ushort),     # Regular interval for SPI read/write commands, in microseconds("iSpiOutDefaultData", ctypes.c_ubyte),         # Default output data when reading from SPI("iChipSelect", ctypes.c_ulong),                # Chip select control. Bit 7 as 0 ignores chip select control,# Bit 7 as 1 makes the parameters valid:# Bit 1 and Bit 0 as 00/01 selects CS1/CS2 pin as the active low chip select.("CS1Polarity", ctypes.c_ubyte),                # Bit 0: CS1 polarity control, 0: active low, 1: active high("CS2Polarity", ctypes.c_ubyte),                # Bit 0: CS2 polarity control, 0: active low, 1: active high("iIsAutoDeativeCS", ctypes.c_ushort),          # Automatically de-assert chip select after the operation is completed("iActiveDelay", ctypes.c_ushort),              # Delay time for executing read/write operations after chip select is set, in microseconds("iDelayDeactive", ctypes.c_ulong)              # Delay time for executing read/write operations after chip select is de-asserted, in microseconds]def spi_init(self, device_index: int, spi_config: SPIConfig) -> bool:"""Initialize the SPI Controller.Args:device_index (int): The device number.spi_config (SPIConfig): The configuration for the SPI controller.Returns:bool: True if initialization is successful, False otherwise."""result = self.ch347dll.CH347SPI_Init(device_index, ctypes.byref(spi_config))return resultdef spi_write(self, device_index: int, chip_select: int, write_data: bytes, write_step: int = 512) -> bool:"""SPI write data.Args:device_index (int): Device number.chip_select (int): Chip selection control. When bit 7 is 0, chip selection control is ignored.When bit 7 is 1, chip selection operation is performed.write_data (bytes): Data to write.write_step (int, optional): The length of a single block to be read. Default is 512.Returns:bool: True if successful, False otherwise."""write_length = len(write_data)write_buffer = ctypes.create_string_buffer(write_data)result = self.ch347dll.CH347SPI_Write(device_index, chip_select, write_length, write_step, write_buffer)return resultdef spi_read(self, device_index: int, chip_select: int, write_data: bytes, read_length: int) -> bytes:"""SPI read data.Args:device_index (int): Device number.chip_select (int): Chip selection control. When bit 7 is 0, chip selection control is ignored.When bit 7 is 1, chip selection operation is performed.write_data (bytes): Data to write.read_length (int): Number of bytes to read.Returns:bytes: Data read in from the SPI stream if successful, None otherwise."""write_length = len(write_data)# Create ctypes buffer for write datawrite_buffer = ctypes.create_string_buffer(write_data)# Create ctypes buffer for read dataread_buffer = ctypes.create_string_buffer(read_length)# Create combined buffer for read and write datacombined_buffer = ctypes.create_string_buffer(write_buffer.raw[:write_length] + read_buffer.raw)result = self.ch347dll.CH347SPI_Read(device_index, chip_select, write_length, ctypes.byref(ctypes.c_ulong(read_length)), combined_buffer)if result:# Extract the read data from the combined bufferread_data = combined_buffer[:read_length]return bytes(read_data)else:return None

连接CH347和SPI Flash模块:

连接CH347和SPI Flash模块

上图中,红色LED的是W25Q32FV SPI Flash模块,绿色LED的是MPU6050。

编写测试代码:

import ch347dll_path = "ch347dlla64.dll"  # Replace with the actual path to the DLL
device_index = 0  # Set the device index according to your requirementsch347_driver = ch347.CH347Driver(dll_path)result = ch347_driver.open_device(device_index)
if result:print(f"Successfully opened device index: {device_index}")
else:print(f"Failed to close device index: {device_index}")spi_config = ch347.SPIConfig(iMode = 0,iClock = 0,iByteOrder = 1,iSpiWriteReadInterval = 0,iSpiOutDefaultData = 0,iChipSelect = 0x80,CS1Polarity = 0,CS2Polarity = 0,iIsAutoDeative = 1,iActiveDelay = 0,iDelayDeactive = 0
)
result = ch347_driver.spi_init(device_index, spi_config)
if result:print("Success to init SPI.")
else:print("Failed to init SPI.")# 读制造商数据
read_data = ch347_driver.spi_read(device_index, 0x80, b"\x90\x00\x00\x00", 2)
print(read_data)# 读 0x000000 4个字节
read_data = ch347_driver.spi_read(device_index, 0x80, b"\x03\x00\x00\x00", 4)
print(read_data)# 写 0x000000 2个字节 0x01 0x02
ch347_driver.spi_write(device_index, 0x80, b'\x06')
ch347_driver.spi_write(device_index, 0x80, b'\x02\x00\x00\x00\x01\x02')# 读 0x000000 4个字节
read_data = ch347_driver.spi_read(device_index, 0x80, b"\x03\x00\x00\x00", 4)
print(read_data)# Example usage of CH347CloseDevice
result = ch347_driver.close_device(device_index)
if result:print(f"Successfully closed device index: {device_index}")
else:print(f"Failed to close device index: {device_index}")

运行一下:

❯ python testSPI.py
Successfully opened device index: 0
Success to init SPI.
b'\xef\x15'
b'\xff\xff\xff\xff'
b'\x01\x02\xff\xff'
Successfully closed device index: 0

至此就可以读写SPI Flash了。

公众号 | FunIO
微信搜一搜 “funio”,发现更多精彩内容。
个人博客 | blog.boringhex.top

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/91081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据库】形式化关系查询语言(一):关系代数Relational Algebra

目录 一、关系代数Relational Algebra 1. 基本运算 a. 选择运算(Select Operation) b. 投影运算(Project Operation) 组合 c. 并运算(Union Operation) d. 集合差运算(Set Difference Op…

python: 用百度API读取增值税发票信息

# encoding: utf-8 # 版权所有 2023 涂聚文有限公司 # 许可信息查看: # 描述: # Author : geovindu,Geovin Du 涂聚文. # IDE : PyCharm 2023.1 python 311 # Datetime : 2023/9/30 6:56 # User : geovindu # Product : PyCharm # Proj…

机器学习笔记 - 基于强化学习的贪吃蛇玩游戏

一、关于深度强化学习 如果不了解深度强化学习的一般流程的可以考虑看一下下面的链接。因为这里的示例因为在PyTorch 之上实现深度强化学习算法。 机器学习笔记 - Deep Q-Learning算法概览深度Q学习是一种强化学习算法,它使用深度神经网络来逼近Q函数,用于确定在给定状态下采…

架构设计第七讲:数据巡检系统之daily线上表结构自动化比对

架构设计第七讲:数据巡检系统之daily&线上表结构自动化比对 本文是架构设计第七讲,数据巡检系统之daily&线上表结构自动化比对,避免正式环境与测试环境数据库/表、列结构不一致带来问题。 文章目录 架构设计第七讲:数据巡…

193419-86-2,用于蛋白电泳检测的Fluorescein o-acrylate

产品简介:Fluorescein o-acrylate 中FITC具有荧光素衍生物的普遍特性,FITC也经常被用于蛋白电泳检测和荧光能量激发转移测试。 荧光染料及其荧光标记技术一直是生物领域常用的产品和技术,荧光物质是指具有共轭双键体系化学结构的化合物&…

LabVIEW开发实时自动化多物镜云计算全玻片成像装置

LabVIEW开发实时自动化多物镜云计算全玻片成像装置 数字病理学领域正在迅速发展,这主要是由于计算机处理能力、数据传输速度、软件创新和云存储解决方案方面的技术进步。因此,病理科室不仅将数字成像用于图像存档等简单任务,还用于远程病理学…

monkeyrunner录制脚本和回放

Monkeyrunner关于使用录制、生成脚本、编译脚本及执行脚本。 首先在计算机上下载和安装SDK、python 2.将recorder.py文件放置SDK文件夹里tools文件夹下 3.USB连接手机,手机端,开启USB调试,并在计算机DOS中输入adb devices命令,查看…

XXE 漏洞及案例实战

文章目录 XXE 漏洞1. 基础概念1.1 XML基础概念1.2 XML与HTML的主要差异1.3 xml示例 2. 演示案例2.1 pikachu靶场XML2.1.1 文件读取2.1.2 内网探针或者攻击内网应用(触发漏洞地址)2.1.4 RCE2.1.5 引入外部实体DTD2.1.6 无回显读取文件 3. XXE 绕过3.1 dat…

网络爬虫--伪装浏览器

从用户请求的Headers反反爬 在访问某些网站的时候,网站通常会用判断访问是否带有头文件来鉴别该访问是否为爬虫,用来作为反爬取的一种策略。很多网站都会对Headers的User-Agent进行检测,还有一部分网站会对Referer进行检测(一些资…

【Leetcode】 501. 二叉搜索树中的众数

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。 如果树中有不止一个众数,可以按 任意顺序 返回。 假定 BST 满足如下定义&#xf…

【图论C++】树的重心——教父POJ 3107(链式前向星的使用)

》》》算法竞赛 /*** file * author jUicE_g2R(qq:3406291309)————彬(bin-必应)* 一个某双流一大学通信与信息专业大二在读 * * brief 一直在竞赛算法学习的路上* * copyright 2023.9* COPYRIGHT 原创技术笔记:转载…

K8S:pod控制器详解

文章目录 一.pod控制器的基础1.pod概念及分类2.什么是Pod控制器及其功用3.pod控制器有多种类型(1)ReplicaSet(2)Deployment(3)DaemonSet(4)Statef…

python time和datetime的常用转换处理

嗨喽,大家好呀~这里是爱看美女的茜茜呐 👇 👇 👇 更多精彩机密、教程,尽在下方,赶紧点击了解吧~ python源码、视频教程、插件安装教程、资料我都准备好了,直接在文末名片自取就可 一、time 1、…

第一部分:HTML5

目录 一:网页 1.1:什么是网页? 1.2:什么是HTML? 1.3:网页的形成 二:常用浏览器 三:Web标准 3.1:为什么需要Web标准? 3.2:Web标准的构成 四&a…

自动群发节日祝福,1 行 Python 代码搞定,小白可用

想了解更多精彩内容,快来关注程序员晚枫 大家节日快乐,这里是程序员晚枫,小红薯也叫这个名字。 今天给大家分享一个实用功能:自动群发祝福消息。 我相信社会人都体会过,过年过节给别人群发祝福消息的无奈&#xff0…

Cloudflare进阶技巧:缓存利用最大化

1. 引言 cloudflare我想你应该知道是什么,一家真正意义上免费无限量的CDN,至今未曾有哥们喷它的。当然,在国内的速度确实比较一般,不过这也不能怪它。 CDN最大的特色,我想就是它的缓存功能,达到防攻击&am…

C#解析JSON详解

C#解析Json详解 文章目录 C#解析Json详解什么是Json?Json的特点 常用的Json库Json.NET (Newtonsoft.Json)System.Text.Json 实例序列化反序列化 总结 什么是Json? JSON的全称是JavaScript Object Notation,是一种轻量级的数据交换格式&#…

抖音短视频seo矩阵系统源代码开发系统架构及功能解析

短视频seo源码,短视频seo矩阵系统底层框架上支持了从ai视频混剪,视频批量原创产出,云存储批量视频制作,账号矩阵,视频一键分发,站内实现关键词、短视频批量搜索排名,数据统计分类多功能细节深度…

spark Structured报错解决

报错,不想看原因的直接去解决方案试试 Exception in thread "main" java.lang.IllegalArgumentException: Pathname /C:/Users/Administrator/AppData/Local/Temp/1/temporary-611514af-8dc5-4b20-9237-e5f2d21fdf88/metadata from hdfs://master:8020/C…

我的国庆回家之路

文章目录 回家的计划假期的礼物学习新技术与家人团聚遇到的趣事总结 🎉欢迎来到IT陈寒的博客空间~我的国庆回家之路 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:IT陈寒的博客🎈该系列文章专栏:Java学习路线&#x1…