CH347--USB转I2C芯片操作EEPROM

发布于:2022-10-14 ⋅ 阅读:(1601) ⋅ 点赞:(1)

USB转I2C芯片简介

        高速USB转接芯片CH347是一款集成480Mbps高速USB接口、JTAG接口、SPI接口、I2C接口、异步UART串口、GPIO接口等多种硬件接口的转换芯片。

接口示意图:

CH347-I2C接口特点

  • USB传输采用USB2.0高速(480Mbps)
  • 工作在 Host/Master主机模式;
  • 硬件信号:SCL、SDA;
  • 支持4种传输速度:低速20KHz、标准100KHz、快速400KHz、高速750KHz;
  • 支持I2C时序参数调节;
  • 提供计算机端驱动程序和USB转I2C函数库,支持二次开发

使用芯片准备工作

选择CH347工作模式

        CH347芯片在复位时,会根据DTR1(CFG0)和RTS1(CFG1)引脚的电平状态配置其工作模式,各工作模式及功能说明如下

工作模式

模式说明

CFG0

CFG1

Mode0

480Mbps高速USB转双UART(Baudrate最高9Mbps)

1

1

Mode1

480Mbps高速USB转UART+SPI+I2C(厂商驱动模式)

0

1

Mode2

480Mbps高速USB转UART+SPI+I2C(系统HID驱动模式)

1

0

Mode3

480Mbps高速USB转UART+JTAG(厂商驱动模式)

0

0

        CH347可使用SPI的模式有两种,其区别在Mode1需要安装厂商驱动,Mode3可以使用系统内置HID驱动无需额外安装,只需在编程时调用CH347动态库进行软件编程即可,此处我们使用Mode1来进行操作。

驱动安装

windows驱动安装

        从WCH官网下载CH347转SPI/I2C/JTAG/GPIO驱动:CH341PAR.EXE - 南京沁恒微电子股份有限公司

        驱动下载后进行一次安装,后续即可实现系统“免驱”效果无需二次安装。未插入设备时安装会显示“驱动预安装成功”,此时驱动已经正常安装,硬件即插即用。

        Windows驱动通过微软数字签名认证,支持32/64位 Windows 11/10/8.1/8/7/VISTA/XP/2000,SERVER 2019/2016/2012/2008/2003等系统,无需担心Windows不同系统兼容性问题。

        官方同时提供驱动资源包CH341PAR.ZIP - 南京沁恒微电子股份有限公司,可将驱动安装文件打包至成熟产品一齐发布,且支持无界面安装操作,可通过软件编程调用命令行操作,只需执行“SETUP /S”命令即可静默驱动安装。

        点击安装之后,等待弹出安装成功窗口后点击确定即可。

Linux驱动安装

        联系WCH技术支持获取到CH347-Linux驱动,然后进行安装

        1、执行make编译驱动;

        2、执行make load动态加载驱动,或执行make install后可实现重新启动自动检测硬件并加载驱动;

        3、插入设备可查看到生成前缀为ch34x_pis的设备节点。

使用USB操作EEPROM

        本次操作CH347开发板板载EEPROM:24LC515H。

        除此之外,CH347也可操作AT24xxx、M24xxx等等EEPROM

调用函数

        WCH提供了一套公用的库函数接口,即Windows&Linux平台接口函数名称与参数一致,其库函数接口特性如下:

        操作SPI、I2C、GPIO等的接口在任何工作模式下都可使用同一API,在进行软件编写时,只需调用接口完成代码操作逻辑而不用关注当前硬件工作模式。提供插拔检测函数可动态监测设备插拔信息,更方便进行设备管理。

        具体详细内容可参考官方开发手册:CH347EVT.ZIP - 南京沁恒微电子股份有限公司 【目录:CH347EVT\EVT\PUB\CH347应用开发手册.PDF】

/***************插拔监测函数************/
BOOL    WINAPI  CH347SetDeviceNotify(                                           // 设定设备事件通知程序
                                     ULONG                  iIndex,             // 指定设备序号,0对应第一个设备
                                     PCHAR                  iDeviceID,          // 可选参数,指向字符串,指定被监控的设备的ID,字符串以\0终止
                                     mPCH347_NOTIFY_ROUTINE iNotifyRoutine );   // 指定设备事件回调程序,为NULL则取消事件通知,否则在检测到事件时调用该程序
/********IIC接口函数通用于Mode1/2***********/
// 设置串口流模式
BOOL    WINAPI  CH347I2C_Set(ULONG          iIndex,  // 指定设备序号
                             ULONG          iMode );  // 指定模式,见下行
// 位1-位0: I2C接口速度/SCL频率, 00=低速/20KHz,01=标准/100KHz(默认值),10=快速/400KHz,11=高速/750KHz
// 其它保留,必须为0

// 设置硬件异步延时,调用后很快返回,而在下一个流操作之前延时指定毫秒数
BOOL    WINAPI  CH347I2C_SetDelaymS(ULONG           iIndex,       // 指定设备序号
                                    ULONG           iDelay ) ;    // 指定延时的毫秒数

 // 处理I2C数据流,2线接口,时钟线为SCL引脚,数据线为SDA引脚
BOOL    WINAPI  CH347StreamI2C( ULONG           iIndex,        // 指定设备序号
                                ULONG           iWriteLength,  // 准备写出的数据字节数
                                PVOID           iWriteBuffer,  // 指向一个缓冲区,放置准备写出的数据,首字节通常是I2C设备地址及读写方向位
                                ULONG           iReadLength,   // 准备读取的数据字节数
                                PVOID           oReadBuffer ); // 指向一个缓冲区,返回后是读入的数据
#ifndef _CH341_DLL_H
typedef enum    _EEPROM_TYPE {// EEPROM型号
    ID_24C01,
    ID_24C02,
    ID_24C04,
    ID_24C08,
    ID_24C16,
    ID_24C32,
    ID_24C64,
    ID_24C128,
    ID_24C256,
    ID_24C512,
    ID_24C1024,
    ID_24C2048,
    ID_24C4096
} EEPROM_TYPE;
#endif

// 从EEPROM中读取数据块,速度约56K字节
BOOL    WINAPI  CH347ReadEEPROM(ULONG           iIndex,     // 指定设备序号
                                EEPROM_TYPE     iEepromID,  // 指定EEPROM型号
                                ULONG           iAddr,      // 指定数据单元的地址
                                ULONG           iLength,    // 准备读取的数据字节数
                                PUCHAR          oBuffer );  // 指向一个缓冲区,返回后是读入的数据
// 向EEPROM中写入数据块
BOOL    WINAPI  CH347WriteEEPROM(ULONG          iIndex,     // 指定设备序号
                                 EEPROM_TYPE    iEepromID,  // 指定EEPROM型号
                                 ULONG          iAddr,      // 指定数据单元的地址
                                 ULONG          iLength,    // 准备写出的数据字节数
                                 PUCHAR         iBuffer );  // 指向一个缓冲区,放置准备写出的数据

操作流程

代码示例

Windows例程

        可参考官方开发资料:CH347EVT.ZIP - 南京沁恒微电子股份有限公司 【目录:CH347EVT\EVT\TOOLS\CH347Demo】

        界面读写示例如下:

Linux例程

        可参考如下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include "CH347LIB.h"

#define CMD_FLASH_SECTOR_ERASE 0x20
#define CMD_FLASH_BYTE_PROG    0x02
#define CMD_FLASH_READ         0x03
#define CMD_FLASH_RDSR         0x05
#define CMD_FLASH_WREN         0x06

#define CMD_FLASH_JEDEC_ID     0x9F

#define SPI_FLASH_PerWritePageSize 256

#ifndef CH34x_DEBUG
#define CH34x_DEBUG
#endif

#ifdef CH34x_DEBUG
#define dbg( format, arg...)printf( format "\n", ##arg );
#endif
#define err( format, arg... )\
printf( "error %d: " format "\n", __LINE__, ##arg )

int mindex = -1;

BOOL CH347_I2C_Init()
{
    int ret = -1;
    // Init CH347 I2C
    ret = CH347I2C_Set(mindex, 3);// The IIC speed set 750K
    if (!ret) {
        err("Failed to init I2C");
        return false;
    }

    return true;
}

BOOL EEPROM_Write()
{
    ULONG i = 0;
    ULONG DataLen = 0;
    UCHAR DBuf[8 * 1024 + 16] = {0};

    BOOL RetVal = false;

    printf("Ready to write.\n");
    for (i = 0; i <= 255; i++)
    {
        DBuf[i] = 255-i;
        DataLen++;
    }

    printf("Write EEPROM data:\n");
    RetVal = CH347WriteEEPROM(mindex,ID_24C02,0x00,DataLen,DBuf);

    for (i = 0; i <= 255; i++)
    {
        printf("%02x ", DBuf[i]);
        if (((i+1) % 20) == 0) 
                putchar(10);
    }

    putchar(10);

    return RetVal;
}

BOOL EEPROM_Read()
{
    ULONG i = 0;
    ULONG DataLen = 256;
    UCHAR DBuf[8 * 1024 + 16] = {0};

    BOOL RetVal = false;

    RetVal = CH347ReadEEPROM(mindex,ID_24C02,0,DataLen,DBuf);

    printf("Read EEPROM data:\n");
    for (i = 0; i <= 255; i++)
    {
        printf("%02x ", DBuf[i]);
        if (((i+1) % 20) == 0) 
                putchar(10);
    }

    putchar(10);

    return RetVal;
}

int main()
{
        BOOL ret = false;

        // Open the device
        mindex = CH347OpenDevice(0);

        if (mindex < 0) {
            printf("Failed to open device.\n");
            return -1;
        }

        ret = CH347_I2C_Init();
        if (!ret) {
            err("Failed to init CH347 I2C.");
            exit(-1);
        }

        printf("Enter EEPROM Test,EEPROM Type:24C02\n");
        ret = EEPROM_Read();
        if (!ret) {
            err("Failed to read eeprom");
            exit(-1);
        }

        ret = EEPROM_Write();
        if (!ret) {
            err("Failed to write eeprom");
            exit(-1);
        }

        ret = EEPROM_Read();
        if (!ret) {
            err("Failed to read eeprom");
            exit(-1);
        }

        // Close the CH347 Device
        if (CH347CloseDevice(mindex))
        {
            printf("Close device succesed\n");
        }

        return 0;
}

执行截图:

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到