不同编程语言下CH347DLL的调用方法

这篇具有很好参考价值的文章主要介绍了不同编程语言下CH347DLL的调用方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

        CH347为一款USB转JTAG/SPI/IIC/GPIO/UART接口的转换芯片,此处总结一下开发时所遇到的在C/C++、Python、C#下调用CH347DLL的方法,若有其他需要补充的也可一起交流。

        基于WCH官方Demo板做的代码验证。

1、C/C++调用

        可参考WCH官网CH347EVT/Tools下工程代码,此处则不再重复

2、Python调用

        选择Python调用时,需对应上Python和DLL是否都为32或64位,否则会出现调用失败的情况,传入API参数时则只需注意一下特殊的结构体此类参函数即可。

'''
Author: OIDCAT
Date: 2022-07-13 15:22:17
LastEditTime: 2022-08-23 19:19:23
此处需注意Python版本位数与DLL是否匹配
'''

 #! /usr/bin/env python
 #coding=utf-8
import ctypes
import os
from ctypes import *

# 
print("进入程序")
CH347 = windll.LoadLibrary("./CH347DLL.DLL")
DevIndex = 0
I2C_addr = 0xA0
class spi_config(Structure):
        _fields_ = [
            ("iMode", c_ubyte),
            ("iClock", c_ubyte),
            ("iByteOrder", c_ubyte),
            ("iSpiWriteReadInterval", c_ushort),
            ("iSpiOutDefaultData",c_ubyte),
            ("iChipSelect", c_ulong),
            ("CS1Polarity",c_ubyte),  
            ("CS2Polarity", c_ubyte), 
            ("iIsAutoDeativeCS", c_ushort), 
            ("iActiveDelay", c_ushort), 
            ("iDelayDeactive", c_ulong),
        ]

def init():
    if CH347.CH347OpenDevice(DevIndex) != -1:
        print("CH347 Open succeeded")
        CH347.CH347I2C_Set(DevIndex, 3)

        CH347_SPI = spi_config()
        CH347_SPI.iMode = 0x03
        CH347_SPI.iClock = 0x01
        CH347_SPI.iByteOrder = 0x01
        CH347_SPI.iSpiOutDefaultData = 0xff 
        CH347_SPI.iChipSelect = 0x80
        CH347.CH347SPI_Init(DevIndex, CH347_SPI)
        # CH347.CH347CloseDevice(DevIndex)
    else:
        print("Open The CH347 Failed")
            
def read(addr):
    if CH347.CH347OpenDevice(DevIndex) != -1:
        oBuf = (c_byte *2)()
        iBuf = (c_byte *1)()
        oBuf[0] = 0xA0
        oBuf[1] = addr
        CH347.CH347StreamI2C(DevIndex, 2, oBuf, 1, iBuf)
        CH347.CH347CloseDevice(DevIndex)
        print("CH347 read succeeded")
        return iBuf[0] & 0xFF
    else:
        print("CH347I2C.CH347OpenDevice")
        return 0

def spi_readId(DevIndex):
    cmd_buf = (c_byte * 4)()
    len = 4
    cmd_buf[0] = 0x9F
    cmd_buf[1] = 0xFF
    cmd_buf[2] = 0xFF
    cmd_buf[3] = 0xFF
    
    CH347.CH347SPI_WriteRead(DevIndex, 0x80, len, cmd_buf)
    print("{0:x} {1:x} {2:x} {3:x}".format(cmd_buf[0], cmd_buf[1], cmd_buf[2], cmd_buf[3]))
    return cmd_buf[0] & 0xFF

if __name__ == "__main__":
    print("CH347 Test")
    init()
    read(0x02)
    spi_readId(DevIndex)

3、C#调用

        使用C#比较麻烦的就是需要将头文件重新换格式,但实际上工作量并不是太大,其中结构体需要注意其地址对齐。文章来源地址https://www.toymoban.com/news/detail-595054.html

using System;

namespace CH347T_Develop
{
    using System.Runtime.InteropServices;
    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Size = 8)]
    public struct mUSB_SETUP_PKT
    {// USB控制传输的建立阶段的数据请求包结构
        [FieldOffset(0)]
        public byte mUspReqType;                // 00H 请求类型
        [FieldOffset(1)]
        public byte mUspRequest;                // 01H 请求代码

        [FieldOffset(2)]
        public byte mUspValueLow;// 02H 值参数低字节
        [FieldOffset(3)]
        public byte mUspValueHigh;              // 03H 值参数高字节
        [FieldOffset(2)]
        public UInt16 mUspValue;                // 02H-03H 值参数

        [FieldOffset(4)]
        public byte mUspIndexLow;// 04H 索引参数低字节
        [FieldOffset(5)]
        public byte mUspIndexHigh;              // 05H 索引参数高字节
        [FieldOffset(4)]
        public UInt16 mUspIndex;                    // 04H-05H 索引参数
        [FieldOffset(6)]
        public UInt16 mLength;// 06H-07H 数据阶段的数据长度
    }

    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
    public struct mWIN32_COMMAND_USB_SETUP_PKT
    {               // 定义WIN32命令接口结构
        [FieldOffset(0)]
        public UInt32 mFunction; // 输入时指定功能代码或者管道号
        [FieldOffset(0)]
        public Int32 mStatus;                    // 输出时返回操作状态
        [FieldOffset(4)]
        public UInt32 mLength;                   // 存取长度,返回后续数据的长度
        [FieldOffset(8)]
        public mUSB_SETUP_PKT mSetupPkt;         // USB控制传输的建立阶段的数据请求
    }

    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
    public struct mWIN32_COMMAND_mBuffer
    {// 定义WIN32命令接口结构
        [FieldOffset(0)]
        public UInt32 mFunction;// 输入时指定功能代码或者管道号
        [FieldOffset(0)]
        public Int32 mStatus;// 输出时返回操作状态
        [FieldOffset(4)]
        public UInt32 mLength;// 存取长度,返回后续数据的长度

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = CH347DLL.mCH341_PACKET_LENGTH), FieldOffset(8)]
        public byte[] mBuffer;                // 数据缓冲区,长度为0至255B
    }
    // 此处可能存在问题,待修改

    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
    public struct DEV_INFOR
    {
        [FieldOffset(0)]
        public byte iIndex;                 // 当前打开序号

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64), FieldOffset(16)]
        public byte[] DevicePath;           // 设备链接名,用于CreateFile

        [FieldOffset(18)]
        public byte UsbClass;               // 0:CH347_USB_CH341, 2:CH347_USB_HID,3:CH347_USB_VCP

        [FieldOffset(19)]
        public byte FuncType;               // 0:CH347_FUNC_UART,1:CH347_FUNC_SPI_I2C,2:CH347_FUNC_JTAG_I2C

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64), FieldOffset(35)]
        public byte[] DeviceID;             // USB\VID_xxxx&PID_xxxx

        [FieldOffset(36)]
        public byte ChipMode;               // 芯片模式,0:Mode0(UART0/1); 1:Mode1(Uart1+SPI+I2C); 2:Mode2(HID Uart1+SPI+I2C) 3:Mode3(Uart1+Jtag+IIC)

        [FieldOffset(0)]
        IntPtr DevHandle;                   // 设备句柄

        [FieldOffset(0)]
        public UInt16 BulkOutEndpMaxSize;     // 上传端点大小

        [FieldOffset(2)]
        public UInt16 BulkInEndpMaxSize;      // 下传端点大小

        [FieldOffset(37)]
        public byte UsbSpeedType;           // USB速度类型,0:FS,1:HS,2:SS

        [FieldOffset(38)]
        public byte CH347IfNum;             // 设备接口号: 0:UART,1:SPI/IIC/JTAG/GPIO

        [FieldOffset(39)]
        public byte DataUpEndp;             // 端点地址

        [FieldOffset(40)]
        public byte DataDnEndp;             // 端点地址

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64), FieldOffset(56)]
        public byte[] ProductString;      // USB产品字符串

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64), FieldOffset(72)]
        public byte[] ManufacturerString; // USB厂商字符串

        [FieldOffset(0)]
        public UInt32 WriteTimeout;           // USB写超时

        [FieldOffset(4)]
        public UInt32 ReadTimeout;            // USB读超时

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64), FieldOffset(88)]
        public byte[] FuncDescStr;        // 接口功能描述符

        [FieldOffset(89)]
        public byte FirewareVer;            // 固件版本
    }

    class CH347DLL
    {
        public const int mCH341_PACKET_LENGTH = 64;

        public byte Index;

        // CH341端点地址
        public const int mCH347_ENDP_DATA_UP = 0x86;// CH347的数据块上传端点的地址
        public const int mCH347_ENDP_DATA_DOWN = 0x06;      // CH347的数据块下传端点的地址

        // 设备层接口提供的管道操作命令
        public const int mPipeDeviceCtrl = 0x00000004;      // CH347的综合控制管道
        public const int mPipeDataUp = 0x00000006;          // CH347的数据块上传管道
        public const int mPipeDataDown = 0x00000007;        // CH347的数据块下传管道

        // 应用层接口的功能代码
        public const int mFuncNoOperation = 0x00000000;     // 无操作
        public const int mFuncGetVersion = 0x00000001;      // 获取驱动程序版本号
        public const int mFuncGetConfig = 0x00000002;       // 获取USB设备配置描述符
        public const int mFuncSetTimeout = 0x00000009;      // 设置USB通讯超时
        public const int mFuncSetExclusive = 0x0000000b;    // 设置独占使用
        public const int mFuncResetDevice = 0x0000000c;     // 复位USB设备
        public const int mFuncResetPipe = 0x0000000d;       // 复位USB管道
        public const int mFuncAbortPipe = 0x0000000e;       // 取消USB管道的数据请求
        public const int mFuncBufferMode = 0x00000020;      // 设定缓冲上传模式及查询缓冲区中的数据长度
        public const int mFuncBufferModeDn = 0x00000021;    // 设定缓冲下传模式及查询缓冲区中的数据长度
        public const int mFuncGetVersionEx = 0x00000022;    // 获取驱动程序版本号及芯片型号
                                                            // USB设备标准请求代码
        public const int mUSB_CLR_FEATURE = 0x01;
        public const int mUSB_SET_FEATURE = 0x03;
        public const int mUSB_GET_STATUS = 0x00;
        public const int mUSB_SET_ADDRESS = 0x05;
        public const int mUSB_GET_DESCR = 0x06;
        public const int mUSB_SET_DESCR = 0x07;
        public const int mUSB_GET_CONFIG = 0x08;
        public const int mUSB_SET_CONFIG = 0x09;
        public const int mUSB_GET_INTERF = 0x0a;
        public const int mUSB_SET_INTERF = 0x0b;
        public const int mUSB_SYNC_FRAME = 0x0c;

        // CH341控制传输的厂商专用请求类型
        public const int mCH341_VENDOR_READ = 0xC0;         // 通过控制传输实现的CH341厂商专用读操作
        public const int mCH341_VENDOR_WRITE = 0x40;        // 通过控制传输实现的CH341厂商专用写操作
        public const int mCH341A_CMD_I2C_STREAM = 0xAA;     // I2C接口的命令包,从次字节开始为I2C命令流
        public const int mCH341A_CMD_UIO_STREAM = 0xAB;     // UIO接口的命令包,从次字节开始为命令流
        public const int mCH341A_CMD_PIO_STREAM = 0xAE;     // PIO接口的命令包,从次字节开始为数据流
                                                            // CH341A控制传输的厂商专用请求代码
        public const int mCH341A_BUF_CLEAR = 0xB2;          // 清除未完成的数据
        public const int mCH341A_I2C_CMD_X = 0x54;          // 发出I2C接口的命令,立即执行
        public const int mCH341A_DELAY_MS = 0x5E;           // 以亳秒为单位延时指定时间
        public const int mCH341A_GET_VER = 0x5F;            // 获取芯片版本

        public const int mCH341A_CMD_I2C_STM_STA = 0x74;    // I2C接口的命令流:产生起始位
        public const int mCH341A_CMD_I2C_STM_STO = 0x75;    // I2C接口的命令流:产生停止位
        public const int mCH341A_CMD_I2C_STM_OUT = 0x80;    // I2C接口的命令流:输出数据,位5-位0为长度,后续字节为数据,0长度则只发送一个字节并返回应答
        public const int mCH341A_CMD_I2C_STM_IN = 0xC0;     // I2C接口的命令流:输入数据,位5-位0为长度,0长度则只接收一个字节并发送无应答
        public const int mCH341A_CMD_I2C_STM_MAX = ((0x3F < mCH341_PACKET_LENGTH) ? 0x3F : mCH341_PACKET_LENGTH);// I2C接口的命令流单个命令输入输出数据的最大长度
        public const int mCH341A_CMD_I2C_STM_SET = 0x60;    // I2C接口的命令流:设置参数,位2=SPI的I/O数(0=单入单出,1=双入双出),位1位0=I2C速度(00=低速,01=标准,10=快速,11=高速)
        public const int mCH341A_CMD_I2C_STM_US = 0x40;     // I2C接口的命令流:以微秒为单位延时,位3-位0为延时值
        public const int mCH341A_CMD_I2C_STM_MS = 0x50;     // I2C接口的命令流:以亳秒为单位延时,位3-位0为延时值
        public const int mCH341A_CMD_I2C_STM_DLY = 0x0F;    // I2C接口的命令流单个命令延时的最大值
        public const int mCH341A_CMD_I2C_STM_END = 0x00;    // I2C接口的命令流:命令包提前结束

        public const int mCH341A_CMD_UIO_STM_IN = 0x00;     // UIO接口的命令流:输入数据D7-D0
        public const int mCH341A_CMD_UIO_STM_DIR = 0x40;    // UIO接口的命令流:设定I/O方向D5-D0,位5-位0为方向数据
        public const int mCH341A_CMD_UIO_STM_OUT = 0x80;    // UIO接口的命令流:输出数据D5-D0,位5-位0为数据
        public const int mCH341A_CMD_UIO_STM_US = 0xC0;     // UIO接口的命令流:以微秒为单位延时,位5-位0为延时值
        public const int mCH341A_CMD_UIO_STM_END = 0x20;    // UIO接口的命令流:命令包提前结束

        public const int MAX_DEVICE_PATH_SIZE = 128;        // 设备名称的最大字符数
        public const int MAX_DEVICE_ID_SIZE = 64;           // 设备ID的最大字符数

        //驱动接口
        public const int CH347_USB_VENDOR = 0;
        public const int CH347_USB_HID = 2;
        public const int CH347_USB_VCP = 3;

        //CH347_USB_VENDOR支持CH341/7
        public const int CHIP_TYPE_CH341 = 0;
        public const int CHIP_TYPE_CH347 = 1;

        //芯片功能接口号
        public const int CH347_FUNC_UART = 0;
        public const int CH347_FUNC_SPI_IIC = 1;
        public const int CH347_FUNC_JTAG_IIC = 2;

        public const int DEFAULT_READ_TIMEOUT = 500;        //默认读超时毫秒数
        public const int DEFAULT_WRITE_TIMEOUT = 500;       //默认写超时毫秒数

        public const int mCH347_PACKET_LENGTH = 512;    // CH347支持的数据包的长度

        private const string CH347_DLL = "CH347DLL.DLL";
        /// <summary>
        /// HANDLE WINAPI CH347OpenDevice(ULONG DevI);
        /// </summary>
        /// <param name="Index"></param>
        /// <returns></returns>
        [DllImport("CH347DLL.DLL", EntryPoint = "CH347OpenDevice")]
        public static extern IntPtr CH347OpenDevice(UInt32 Index);

        [DllImport("CH347DLL.DLL", EntryPoint = "CH347CloseDevice")]
        public static extern IntPtr CH347CloseDevice(UInt32 Index);

        [DllImport("CH347DLL.DLL", EntryPoint = "CH347Uart_Open")]
        public static extern IntPtr CH347Uart_Open(UInt32 Index);

        [DllImport("CH347DLL.DLL", EntryPoint = "CH347Uart_Close")]
        public static extern IntPtr CH347Uart_Close(UInt32 Index);

        [DllImport("CH347DLL.DLL", EntryPoint = "CH347GetDeviceInfor")]
        public static extern IntPtr CH347GetDeviceInfor(UInt32 Index,
            ref DEV_INFOR info);

        [DllImport("CH347DLL.DLL", EntryPoint = "CH347GPIO_Get")]
        public static extern IntPtr CH347GPIO_Get(UInt32 Index,
            ref UInt16 iDir,
            ref UInt16 iData);

        [DllImport("CH347DLL.DLL", EntryPoint = "CH347GPIO_Set")]
        public static extern IntPtr CH347GPIO_Set(UInt32 Index,
            UInt32 iEnable,
            UInt32 iSetDirOut,
            UInt32 iSetDataOut);
    }
}

到了这里,关于不同编程语言下CH347DLL的调用方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python环境解析任意编程语言 tree-sitter使用方法(1)

    我个人目前仍在研究代码有关的知识。目前基于深度学习表征代码的论文越来越卷了,用到的工具越来越高级了。目前有一个开源项目tree-sitter,专门用于解析 具体语法树 ,声称: 足够通用 ,能用于任何编程语言 足够迅速 ,能在文本编辑器中响应每一个用户输入 足够鲁棒

    2024年02月09日
    浏览(32)
  • 对比编程语言的四种错误处理方法,哪种才是最优方案?

    作者:Andrea Bergia 译者:豌豆花下猫@Python猫 英文:Error handling patterns 转载请保留作者及译者信息! 错误处理是编程的一个基本要素。除非你写的是“hello world”,否则就必须处理代码中的错误。在本文中,我将讨论各种编程语言在处理错误时使用的最常见的四种方法,并分析

    2024年02月03日
    浏览(63)
  • C语言编程技巧 全局变量在多个c文件中公用的方法

    在使用C语言编写程序时,经常会遇到这样的情况:我们希望在头文件中定义一个全局变量,并将其包含在两个不同的C文件中,以便这个全局变量可以在这两个文件中共享。举个例子,假设项目文件夹\\\"project\\\"下有三个文件:main.c、common.c和common.h。在这种情况下,我们希望声明

    2024年02月14日
    浏览(26)
  • CH342/CH343/CH344/CH347/CH9101/CH9102/CH9103/CH9104 Linux串口驱动使用教程

    CH343 Linux串口驱动 ch343ser_linux 支持USB转串口芯片 ch342/ch343/ch344/ch347/ch9101/ch9102/ch9103/ch9104等 ,同时该驱动配合ch343_lib库还提供了芯片GPIO接口的读写功能,内部EEPROM的信息配置和读取功能等。 芯片型号 串口数量 GPIO数量 CH342F/K 2 CH342F:12 CH343G/P/K 1 — CH344Q/L 4 CH344Q:16 CH344L:

    2024年02月13日
    浏览(24)
  • XILINX-FPGA下载工具--CH347FPGADownloader

            CH347FPGADownloader是一款专用于CH347的FPGA下载软件,结合OpenOCD开源项目实现。         当前支持FPGA型号主要以xilinx为主,其中具体型号如下: ​         使用中若遇到问题,可邮件咨询:tech@wch.cn ​ ​         1.“选择FPGA型号”:选择本次进行操作的FPGA型

    2024年02月07日
    浏览(21)
  • GO编程语言:简洁、高效、强大的开源编程语言

    在现代软件开发领域,随着应用复杂度的不断提升,开发人员对编程语言的需求也日益增长。GO编程语言,作为一种简洁、高效且具备强大并发能力的新型开源编程语言,逐渐成为了许多开发者的首选。本文将详细介绍GO语言在哪些项目开发中表现出色,以及为什么许多开发者

    2024年02月02日
    浏览(67)
  • 一起来做个CH347的项目(应用于FPGA、CPLD、MCU)

            国产CH347芯片自从出现在大众视野,就展开了很多讨论。四种工作模式,多接口可同时使用,如下表: 接口模式 接口功能 Mode-0 480Mbps高速USB转双UART(Baudrate最高9Mbps) Mode-1 480Mbps高速USB转UART+SPI+I2C(厂商驱动模式) Mode-2 480Mbps高速USB转UART+SPI+I2C(系统HID驱动模式)

    2024年02月09日
    浏览(28)
  • 【编程语言 · C语言 · 函数指针】

    由于指针可以指向任何存储器位置中的地址,因此它们也可以指向可执行代码的开头。 函数指针或函数指针指向内存中函数的可执行代码。函数指针可以存储在数组中,也可以作为参数传递给其他函数。 函数指针声明使用 * 就像使用任何指针一样: (*func_name)  周围的括号很

    2024年02月10日
    浏览(42)
  • 介绍一些编程语言—C语言

    C 语言是一门 面向过程 的计算机编程语言,与 C++、C#、Java 等面向对象编程语言有所不同。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、仅产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。 C语言描述问题比汇编语言迅速、工作量小

    2024年02月13日
    浏览(39)
  • 介绍一些编程语言— Perl 语言

    Perl 是一种动态解释型的脚本语言。 最初的设计者为拉里・沃尔,它于 1987 1987 1987 年 12 12 12 月 18 18 18 日发表。Perl 借取了 C、sed、awk、shell scripting 以及很多其他编程语言的特性。其中最重要的特性是他内部集成了正则表达式的功能,以及巨大的第三方代码库 CPAN。 1987 1987

    2024年02月12日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包