CH347读写SPI Flash

2023-11-19

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

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

typedef struct _SPI_CONFIG{
	UCHAR           iMode;                 // 0-3:SPI Mode0/1/2/3
	UCHAR           iClock;                // 0=60MHz, 1=30MHz, 2=15MHz, 3=7.5MHz, 4=3.75MHz, 5=1.875MHz, 6=937.5KHz,7=468.75KHz
	UCHAR			iByteOrder;            // 0=LSB first(LSB), 1=MSB first(MSB)
	USHORT          iSpiWriteReadInterval; // The SPI interface routinely reads and writes data command, the unit is uS
	UCHAR           iSpiOutDefaultData;    // SPI prints data by default when it reads data
	ULONG			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 respectively
	UCHAR           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 complete
	USHORT          iActiveDelay;          // Set the latency for read/write operations after slice selection,the unit is us
	ULONG           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 number
									   USHORT           iEnableSelect,     // The lower octet is CS1 and the higher octet is CS2. A byte value of 1= sets CS, 0= ignores this CS setting
									   USHORT           iChipSelect,       // The lower octet is CS1 and the higher octet is CS2. A byte value of 1= sets CS, 0= ignores this CS setting
									   ULONG            iIsAutoDeativeCS,  // The lower 16 bits are CS1 and the higher 16 bits are CS2. Whether to undo slice selection automatically after the operation is complete
									   ULONG            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 us
									   ULONG            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 performed
							   ULONG			iLength,         // Number of bytes of data to be transferred	
							   ULONG			iWriteStep,      // The length of a single block to be read
							   PVOID			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 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 performed
							  ULONG         oLength,          // Number of bytes to send
							  PULONG		iLength,          // Number of bytes of data to be read in
							  PVOID			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 number
								   ULONG			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 selection
								   ULONG			iLength,      // Number of bytes of data to be transferred
								   PVOID			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 number
								ULONG			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 respectively
								ULONG			iLength,      // Number of bytes of data to be transferred
								PVOID			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 result

def 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 result

def 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 data
	write_buffer = ctypes.create_string_buffer(write_data)

	# Create ctypes buffer for read data
	read_buffer = ctypes.create_string_buffer(read_length)

	# Create combined buffer for read and write data
	combined_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 buffer
		read_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 ch347

dll_path = "ch347dlla64.dll"  # Replace with the actual path to the DLL
device_index = 0  # Set the device index according to your requirements

ch347_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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CH347读写SPI Flash 的相关文章

随机推荐

  • non-protected broadcast场景分析及解决

    non protected broadcast场景分析及解决 在两个app之间互相送消息使用BroadcastReceiver 有时在运行过程中在logcat工具中会发现大片的飘红消息 要消除这些错误信息 需要在广播的 Sender 和 R
  • WSL和VMware不兼容,安装了WSL之后VMware启动不起来

    WSL依赖于hyper v必须开启 而VMware不依赖这个 必须关闭 CMD管理员模式启动 输入bcdedit set hypervisorlaunchtype auto开启 则可以使用WSL CMD管理员模式启动 输入bcdedit s
  • ubuntn 下安装nginx 报错 ./configure: error: C compiler cc is not found

    原因是 error C compiler cc is not found c编译器没有安装 解决办法 需要安装编译工具及库文件 网址很多文章没有详细写nginx 安装教程 跟着教程敲命令然后出错了 安装nginx需要安装编译工具及库文件参考
  • 分布式锁解决方案_Zookeeper分布式锁原理

    通过召zk实现分布式锁可靠性时最高的 公平锁和可重入锁的原理 取水秩序 1 取水之前 先取号 2 号排在前面的 就可以先取水 3 先到的排在前面 那些后到的 一个一个挨着 在井边排成一队 公平锁 这种排队取水模型 就是一种锁的模型 什么是可
  • docker遇到问题集合

    1 docker images下删除镜像提示image is being used by stopped container 1b817324f96a 依次执行下面命令 docker ps a grep Exited awk print 1
  • 爬虫实例十一 全国城市房价排行

    目标网址 https www creprice cn rank index html 这一看就是个静态页面 没有用任何反爬措施所以很好爬 直接发送请求解析数据就可以了 完整代码 import requests from lxml impor
  • 睿智的目标检测54——Tensorflow2 搭建YoloX目标检测平台

    睿智的目标检测54 Tensorflow2 搭建YoloX目标检测平台 学习前言 源码下载 YoloX改进的部分 不完全 YoloX实现思路 一 整体结构解析 二 网络结构解析 1 主干网络CSPDarknet介绍 2 构建FPN特征金字塔
  • ElementUI浅尝辄止26:Notification 通知

    悬浮出现在页面角落 显示全局的通知提醒消息 1 如何使用 适用性广泛的通知栏 Notification 组件提供通知功能 Element 注册了 notify方法 接收一个options字面量参数 在最简单的情况下 你可以设置title字段
  • 资源路径嵌套异常,检测不到:IOException parsing XML document from class path resource [applicationContext.xml]

    org springframework beans factory BeanDefinitionStoreException IOException parsing XML document from class path resource
  • ARP与ARP代理的理解

    1 ARP 首先讲到ARP ARP是地址解析协议 它的作用是在以太网环境下 通过第3层的网络层IP地址来找寻2层数据链路层的MAC地址 得到一张ARP缓存表 转发数据的时候根据ARP缓存表来进行传输 下图详细说明数据传输时ARP是如何一步步
  • TVP新书上架

    新书速递 近期 在腾讯云 TVP 联合出书计划中 腾讯云 TVP 山金孝老师推出了新书 融合 产业数字化转型的十大关键技术 融合 产业数字化转型的十大关键技术 作者 山金孝 李琦 中译出版社 内容简介 数字经济已成为高质量发展的新引擎 数字
  • [Django基础06]模型和数据库交互

    2 数据库配置 MySQL 通常情况下 如果你只是做测试使用 可以使用Django内置的数据库SQLite就完全可以满足需要了 我们在本次教程中 通过使用MySQL这个数据库来完成后续的功能操作 我们首先要做的是 在配置文件中指定数据库的配
  • Densely Connected Convolutional Networks 密集连接卷积网络

    什么是DenseNet DenseNet是由清华大学的Zhuang Liu 康奈尔大学的Gao Huang和Kilian Q Weinberger 以及Facebook研究员Laurens van der Maaten在CVPR 2017所
  • 5.13 综合案例2.0-火焰检测系统(2.2版本接口有更新)

    综合案例2 0 火焰检测系统 简介 火焰传感器 准备 硬件连接图 代码流程 功能实现 1 物联网平台开发 2 设备端开发 调试 3 物联网应用开发 4 1新建 普通项目 4 2创建 Web应用 4 3页面设计 4 4关联产品 4 5关联数据
  • 蓝桥杯C/C++百校真题赛(3期)Day3(考勤刷卡、最大和)

    Day3 Q1 考勤刷卡 Q2 最大和 Q1 考勤刷卡 问题描述 小蓝负责一个公司的考勤系统 他每天都需要根据员工刷卡的情况来确定 每个员工是否到岗 当员工刷卡时 会在后台留下一条记录 包括刷卡的时间和员工编号 只 要在一天中员工刷过一次卡
  • 【反向工程】从科研文献表格,反向还原数据

    很多时候会遇到这样一个问题 有一些文章在chart中汇报了实验结果 但是并没有标注上具体的实验数值 如果逍遥获得具体数值 就得用尺子去量 这里推荐一个网站 能够帮助你估计一张chart中 每个数据点对应的横纵坐标 在某些情况下很有用处 至少
  • 数据仓库灵魂30问之数仓基础理念理解

    主题 主题是一个抽象概念 是在较高层次上将数据综合 归类并进行分析利用的抽象 每一个主题都对应一个宏观的分析领域 在实际上 每一个主题对应这个分析领域的所有的分析对象 比如销售主题对应所有和销售这个领域有关的数据 主题域 主题域通常是联系较
  • 效果奇特的HTML5动画,12个效果奇特的HTML5动画赏析

    本文将为大家分享12个效果奇特的HTML5动画 HTML5强大的动画特性可以让你的网页变得更加生动和富有活力 交互性也会进一步得到提高 一起来看看下面的这些HTML5动画案例 没个案例都提供源代码下载 1 HTML5 Canvas瀑布动画
  • KVM源代码分析1:基本工作原理

    http www oenhan com kvm src 1 13年的时候准备挖 KVM源代码分析 的坑 陆陆续续2年过去了 坑也没有填上 当时是因为对KVM了解的肤浅 真正的理解必然要深入到代码级别 所谓 摈弃皮毛 看到血肉 看到真相 当时
  • CH347读写SPI Flash

    前面耽搁了几天 今天终于把CH347 SPI接口调试好了 CH347动态库中SPI接口函数如下 typedef struct SPI CONFIG UCHAR iMode 0 3 SPI Mode0 1 2 3 UCHAR iClock 0