当前位置:   article > 正文

USB转I2C芯片操作EEPROM--CH347应用

usb转i2c

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包括CH347T和CH347F两款型号,CH347T芯片使用I2C功能需要额外模式选择,芯片在复位时,会根据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可使用I2C的模式有两种,其区别在Mode1需要安装厂商驱动,Mode3可以使用系统内置HID驱动无需额外安装,只需在编程时调用CH347动态库进行软件编程即可,本博客使用Mode1来进行操作。

        CH347F芯片不需要进行额外的模式选择,该型号默认支持所有接口功能。

驱动安装

window驱动安装

        从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驱动安装

        下载Linux驱动、应用库和软件包:CH341PAR_LINUX.ZIP - 南京沁恒微电子股份有限公司USB转JTAG/SPI/I2C/并口/GPIO等接口的Linux设备驱动程序,支持CH341的USB转SPI/I2C/EPP并口/MEM并口等,支持CH347的480Mbps高速USB转JTAG/SPI/I2C/GPIO等,支持32/64位操作系统。icon-default.png?t=N7T8https://www.wch.cn/downloads/CH341PAR_LINUX_ZIP.html         按照压缩包内的说明资料使用驱动和其他资料。

        1、执行 sudo make install 可自动编译与安装驱动;

        2、插入USB设备可查看到生成前缀为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】

  1. /***************插拔监测函数************/
  2. BOOL WINAPI CH347SetDeviceNotify( // 设定设备事件通知程序
  3. ULONG iIndex, // 指定设备序号,0对应第一个设备
  4. PCHAR iDeviceID, // 可选参数,指向字符串,指定被监控的设备的ID,字符串以\0终止
  5. mPCH347_NOTIFY_ROUTINE iNotifyRoutine ); // 指定设备事件回调程序,为NULL则取消事件通知,否则在检测到事件时调用该程序
  6. /********IIC接口函数通用于Mode1/2***********/
  7. // 设置串口流模式
  8. BOOL WINAPI CH347I2C_Set(ULONG iIndex, // 指定设备序号
  9. ULONG iMode ); // 指定模式,见下行
  10. // 位1-位0: I2C接口速度/SCL频率, 00=低速/20KHz,01=标准/100KHz(默认值),10=快速/400KHz,11=高速/750KHz
  11. // 其它保留,必须为0
  12. // 设置硬件异步延时,调用后很快返回,而在下一个流操作之前延时指定毫秒数
  13. BOOL WINAPI CH347I2C_SetDelaymS(ULONG iIndex, // 指定设备序号
  14. ULONG iDelay ) ; // 指定延时的毫秒数
  15. // 处理I2C数据流,2线接口,时钟线为SCL引脚,数据线为SDA引脚
  16. BOOL WINAPI CH347StreamI2C( ULONG iIndex, // 指定设备序号
  17. ULONG iWriteLength, // 准备写出的数据字节数
  18. PVOID iWriteBuffer, // 指向一个缓冲区,放置准备写出的数据,首字节通常是I2C设备地址及读写方向位
  19. ULONG iReadLength, // 准备读取的数据字节数
  20. PVOID oReadBuffer ); // 指向一个缓冲区,返回后是读入的数据
  21. #ifndef _CH341_DLL_H
  22. typedef enum _EEPROM_TYPE {// EEPROM型号
  23. ID_24C01,
  24. ID_24C02,
  25. ID_24C04,
  26. ID_24C08,
  27. ID_24C16,
  28. ID_24C32,
  29. ID_24C64,
  30. ID_24C128,
  31. ID_24C256,
  32. ID_24C512,
  33. ID_24C1024,
  34. ID_24C2048,
  35. ID_24C4096
  36. } EEPROM_TYPE;
  37. #endif
  38. // 从EEPROM中读取数据块,速度约56K字节
  39. BOOL WINAPI CH347ReadEEPROM(ULONG iIndex, // 指定设备序号
  40. EEPROM_TYPE iEepromID, // 指定EEPROM型号
  41. ULONG iAddr, // 指定数据单元的地址
  42. ULONG iLength, // 准备读取的数据字节数
  43. PUCHAR oBuffer ); // 指向一个缓冲区,返回后是读入的数据
  44. // 向EEPROM中写入数据块
  45. BOOL WINAPI CH347WriteEEPROM(ULONG iIndex, // 指定设备序号
  46. EEPROM_TYPE iEepromID, // 指定EEPROM型号
  47. ULONG iAddr, // 指定数据单元的地址
  48. ULONG iLength, // 准备写出的数据字节数
  49. PUCHAR iBuffer ); // 指向一个缓冲区,放置准备写出的数据

操作流程

代码示例

Windows例程

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

        界面读写示例如下:

Linux例程

可参考如下代码,链接地址:CH341PAR_LINUX.ZIP - 南京沁恒微电子股份有限公司USB转JTAG/SPI/I2C/并口/GPIO等接口的Linux设备驱动程序,支持CH341的USB转SPI/I2C/EPP并口/MEM并口等,支持CH347的480Mbps高速USB转JTAG/SPI/I2C/GPIO等,支持32/64位操作系统。icon-default.png?t=N7T8https://www.wch.cn/downloads/CH341PAR_LINUX_ZIP.html

  1. /*
  2. * ch347 application demo
  3. *
  4. * Copyright (C) 2023 Nanjing Qinheng Microelectronics Co., Ltd.
  5. * Web: http://wch.cn
  6. * Author: WCH <tech@wch.cn>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * Cross-compile with cross-gcc -I /path/to/cross-kernel/include
  14. *
  15. * V1.0 - initial version
  16. * V1.1 - add operation for HID mode
  17. * V1.2 - add serial port operation in HID and TTY mode
  18. * V1.3 - update with new library
  19. * V1.4 - add gpio interrupt funciton, update with new library,
  20. * - support more SPI and I2C stretching
  21. * - support I2C clock stretch
  22. */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <stdbool.h>
  27. #include <stdint.h>
  28. #include <unistd.h>
  29. #include <sys/ioctl.h>
  30. #include <sys/types.h>
  31. #include <sys/time.h>
  32. #include <sys/stat.h>
  33. #include <fcntl.h>
  34. #include <time.h>
  35. #include <endian.h>
  36. #include <linux/hidraw.h>
  37. #include "ch347_lib.h"
  38. #define CMD_FLASH_SECTOR_ERASE 0x20
  39. #define CMD_FLASH_BYTE_PROG 0x02
  40. #define CMD_FLASH_READ 0x03
  41. #define CMD_FLASH_RDSR 0x05
  42. #define CMD_FLASH_WREN 0x06
  43. #define CMD_FLASH_JEDEC_ID 0x9F
  44. #define SPI_FLASH_PerWritePageSize 256
  45. typedef enum _CH347FUNCTYPE {
  46. FUNC_UART = 0,
  47. FUNC_SPI_I2C_GPIO,
  48. FUNC_JTAG_GPIO,
  49. FUNC_SPI_I2C_JTAG_GPIO,
  50. } CH347FUNCTYPE;
  51. struct ch34x {
  52. int fd;
  53. char version[100];
  54. CHIP_TYPE chiptype;
  55. uint32_t dev_id;
  56. CH347FUNCTYPE functype;
  57. };
  58. static struct ch34x ch347device;
  59. bool CH347_SPI_Init()
  60. {
  61. bool ret;
  62. mSpiCfgS SpiCfg = { 0 };
  63. /* set spi interface in [mode3] & [15MHz] & [MSB] & output [0xFF] by default */
  64. SpiCfg.iMode = 3;
  65. SpiCfg.iSpiSpeedHz = 30e6;
  66. SpiCfg.iByteOrder = 1;
  67. SpiCfg.iSpiOutDefaultData = 0xFF;
  68. SpiCfg.iChipSelect = 0x80;
  69. /* init spi interface */
  70. ret = CH347SPI_Init(ch347device.fd, &SpiCfg);
  71. if (!ret) {
  72. printf("Failed to init SPI interface.\n");
  73. return false;
  74. }
  75. return true;
  76. }
  77. bool CH347_I2C_Init()
  78. {
  79. bool ret;
  80. int iMode;
  81. /* set i2c interface in 750KHZ */
  82. iMode = 0x03;
  83. /* init i2c interface */
  84. ret = CH347I2C_Set(ch347device.fd, iMode);
  85. if (!ret) {
  86. printf("Failed to init I2C interface.\n");
  87. return false;
  88. }
  89. return true;
  90. }
  91. bool Flash_ID_Read()
  92. {
  93. int iChipSelect;
  94. int iLength;
  95. uint8_t ioBuffer[4] = { 0 };
  96. uint32_t Flash_ID;
  97. iChipSelect = 0x80;
  98. iLength = 4;
  99. ioBuffer[0] = CMD_FLASH_JEDEC_ID;
  100. memset(ioBuffer + 1, 0xFF, 3);
  101. if (CH347SPI_WriteRead(ch347device.fd, false, iChipSelect, iLength, ioBuffer) == false)
  102. return false;
  103. else {
  104. ioBuffer[0] = 0x00;
  105. memcpy(&Flash_ID, ioBuffer, 4);
  106. }
  107. Flash_ID = htole32(Flash_ID);
  108. printf("Read flash ID: 0x%x.\n", Flash_ID);
  109. if (Flash_ID == 0x000000 || Flash_ID == 0xffffff00) {
  110. printf("Read flash ID error.\n");
  111. return false;
  112. }
  113. return true;
  114. }
  115. unsigned int Flash_Block_Read(unsigned int address, uint8_t *pbuf, unsigned int len)
  116. {
  117. int iChipSelect;
  118. int iLength;
  119. int oLength;
  120. uint8_t ioBuffer[8192] = { 0 };
  121. iChipSelect = 0x80;
  122. iLength = 0x04;
  123. oLength = len;
  124. ioBuffer[0] = CMD_FLASH_READ;
  125. ioBuffer[1] = (uint8_t)(address >> 16);
  126. ioBuffer[2] = (uint8_t)(address >> 8);
  127. ioBuffer[3] = (uint8_t)(address);
  128. if (!CH347SPI_Read(ch347device.fd, false, iChipSelect, iLength, &oLength, ioBuffer)) {
  129. printf("Flash_Block_Read read %d bytes failed.\n", len);
  130. return 0;
  131. } else
  132. memcpy(pbuf, ioBuffer, oLength);
  133. return oLength;
  134. }
  135. bool Flash_Block_Read_Test()
  136. {
  137. double UseT;
  138. uint32_t DataLen, FlashAddr, i;
  139. uint8_t ioBuffer[8192] = { 0 };
  140. char FmtStr1[8 * 1024 * 3 + 16] = "";
  141. static struct timeval t1, t2;
  142. int delta_sec, delta_usec;
  143. FlashAddr = 0x00;
  144. DataLen = 0x500;
  145. gettimeofday(&t1, NULL);
  146. DataLen = Flash_Block_Read(FlashAddr, ioBuffer, DataLen);
  147. if (DataLen <= 0) {
  148. printf("\tFlash Read: Addr[0x%x] read %d bytes failed.\n", FlashAddr, DataLen);
  149. return false;
  150. }
  151. gettimeofday(&t2, NULL);
  152. delta_sec = t2.tv_sec - t1.tv_sec;
  153. delta_usec = t2.tv_usec - t1.tv_usec;
  154. UseT = (float)delta_sec + (float)delta_usec / 1000000;
  155. printf("\tFlash Read: Addr[0x%x] read %d bytes in %.3f seconds.\n", FlashAddr, DataLen, UseT);
  156. for (i = 0; i < DataLen; i++)
  157. sprintf(&FmtStr1[strlen(FmtStr1)], "%02x ", ioBuffer[i]);
  158. printf("\nRead: \n%s\n\n", FmtStr1);
  159. return true;
  160. }
  161. bool Flash_Write_Enable()
  162. {
  163. int iChipSelect;
  164. int iLength;
  165. uint8_t ioBuffer;
  166. iChipSelect = 0x80;
  167. iLength = 1;
  168. ioBuffer = CMD_FLASH_WREN;
  169. return CH347SPI_WriteRead(ch347device.fd, false, iChipSelect, iLength, &ioBuffer);
  170. }
  171. bool Flash_Wait()
  172. {
  173. int iChipSelect;
  174. int iLength;
  175. uint8_t ioBuffer[2];
  176. uint8_t status;
  177. int retry_times = 1000;
  178. iChipSelect = 0x80;
  179. iLength = 2;
  180. do {
  181. ioBuffer[0] = CMD_FLASH_RDSR;
  182. if (CH347SPI_WriteRead(ch347device.fd, false, iChipSelect, iLength, ioBuffer) == false)
  183. return false;
  184. status = ioBuffer[1];
  185. usleep(100);
  186. } while ((status & 0x01) && (retry_times--));
  187. if ((status & 0x01) == 0)
  188. return true;
  189. else
  190. return false;
  191. }
  192. bool Flash_Sector_Erase(uint32_t StartAddr)
  193. {
  194. int iChipSelect;
  195. int iLength;
  196. uint8_t ioBuffer[4];
  197. if (Flash_Write_Enable() == false)
  198. return false;
  199. iChipSelect = 0x80;
  200. iLength = 4;
  201. ioBuffer[0] = CMD_FLASH_SECTOR_ERASE;
  202. ioBuffer[1] = (uint8_t)(StartAddr >> 16 & 0xff);
  203. ioBuffer[2] = (uint8_t)(StartAddr >> 8 & 0xf0);
  204. ioBuffer[3] = 0x00;
  205. if (CH347SPI_WriteRead(ch347device.fd, false, iChipSelect, iLength, ioBuffer) == false)
  206. return false;
  207. if (Flash_Wait() == false)
  208. return false;
  209. return true;
  210. }
  211. bool W25X_Flash_Write_Page(uint8_t *pBuf, uint32_t address, uint32_t len)
  212. {
  213. int iChipSelect;
  214. int iLength;
  215. uint8_t ioBuffer[8192];
  216. if (!Flash_Write_Enable())
  217. return false;
  218. iChipSelect = 0x80;
  219. iLength = len + 4;
  220. ioBuffer[0] = CMD_FLASH_BYTE_PROG;
  221. ioBuffer[1] = (uint8_t)(address >> 16);
  222. ioBuffer[2] = (uint8_t)(address >> 8);
  223. ioBuffer[3] = (uint8_t)address;
  224. memcpy(&ioBuffer[4], pBuf, len);
  225. if (CH347SPI_Write(ch347device.fd, false, iChipSelect, iLength, SPI_FLASH_PerWritePageSize + 4, ioBuffer) ==
  226. false)
  227. return false;
  228. memset(ioBuffer, 0, sizeof(uint8_t) * len);
  229. if (!Flash_Wait())
  230. return false;
  231. return true;
  232. }
  233. bool Flash_Block_Write()
  234. {
  235. int ret;
  236. int i = 0;
  237. uint32_t DataLen, FlashAddr, BeginAddr, NumOfPage, NumOfSingle;
  238. uint8_t ioBuffer[0x500] = { 0 };
  239. uint8_t *pbuf = ioBuffer;
  240. double UseT;
  241. static struct timeval t1, t2;
  242. int delta_sec, delta_usec;
  243. /* write flash from addr 0 */
  244. FlashAddr = 0x00;
  245. BeginAddr = FlashAddr;
  246. DataLen = 0x500;
  247. for (i = 0; i < DataLen; i++)
  248. ioBuffer[i] = i;
  249. NumOfPage = DataLen / SPI_FLASH_PerWritePageSize;
  250. NumOfSingle = DataLen % SPI_FLASH_PerWritePageSize;
  251. /* caculate flash write time */
  252. gettimeofday(&t1, NULL);
  253. while (NumOfPage--) {
  254. ret = W25X_Flash_Write_Page(pbuf, FlashAddr, SPI_FLASH_PerWritePageSize);
  255. if (ret == false)
  256. goto exit;
  257. pbuf += SPI_FLASH_PerWritePageSize;
  258. FlashAddr += SPI_FLASH_PerWritePageSize;
  259. }
  260. if (NumOfSingle) {
  261. ret = W25X_Flash_Write_Page(pbuf, FlashAddr, NumOfSingle);
  262. if (ret == false)
  263. goto exit;
  264. }
  265. gettimeofday(&t2, NULL);
  266. delta_sec = t2.tv_sec - t1.tv_sec;
  267. delta_usec = t2.tv_usec - t1.tv_usec;
  268. UseT = ((float)delta_sec + (float)delta_usec / 1000000);
  269. printf("\tFlash Write: Addr[0x%x] write %d bytes in %.3f seconds.\n", BeginAddr, DataLen, UseT / 1000);
  270. return true;
  271. exit:
  272. printf("\tFlash Write: Addr [0x%x] write %d bytes failed.\n", BeginAddr, DataLen);
  273. return false;
  274. }
  275. bool EEPROM_Read()
  276. {
  277. bool ret = false;
  278. EEPROM_TYPE eeprom;
  279. int iAddr;
  280. int iLength;
  281. int i;
  282. uint8_t oBuffer[256] = { 0 };
  283. eeprom = ID_24C02;
  284. iAddr = 0;
  285. iLength = 256;
  286. ret = CH347ReadEEPROM(ch347device.fd, eeprom, 0, iLength, oBuffer);
  287. if (ret == false)
  288. goto exit;
  289. printf("\nRead EEPROM data:\n");
  290. for (i = 0; i < iLength; i++) {
  291. printf("%02x ", oBuffer[i]);
  292. if (((i + 1) % 10) == 0)
  293. putchar(10);
  294. }
  295. putchar(10);
  296. exit:
  297. return ret;
  298. }
  299. bool EEPROM_Write()
  300. {
  301. bool ret = false;
  302. EEPROM_TYPE eeprom;
  303. int iAddr;
  304. int iLength;
  305. int i;
  306. uint8_t iBuffer[256] = { 0 };
  307. eeprom = ID_24C02;
  308. iAddr = 0;
  309. iLength = 256;
  310. for (i = 0; i < 256; i++)
  311. iBuffer[i] = i;
  312. printf("\nWrite EEPROM data:\n");
  313. ret = CH347WriteEEPROM(ch347device.fd, eeprom, iAddr, iLength, iBuffer);
  314. if (ret == false)
  315. goto exit;
  316. for (i = 0; i < iLength; i++) {
  317. printf("%02x ", iBuffer[i]);
  318. if (((i + 1) % 10) == 0)
  319. putchar(10);
  320. }
  321. putchar(10);
  322. exit:
  323. return ret;
  324. }
  325. void ch34x_demo_flash_operate()
  326. {
  327. bool ret = false;
  328. ret = CH347_SPI_Init();
  329. if (ret == false) {
  330. printf("Failed to init CH347 SPI interface.\n");
  331. return;
  332. }
  333. printf("CH347 SPI interface init succeed.\n");
  334. /* read flash ID */
  335. ret = Flash_ID_Read();
  336. if (!ret) {
  337. printf("Failed to read flash ID.\n");
  338. return;
  339. }
  340. /* read flash block data */
  341. ret = Flash_Block_Read_Test();
  342. if (!ret) {
  343. printf("Failed to read flash.\n");
  344. return;
  345. }
  346. /* erase flash sector data */
  347. ret = Flash_Sector_Erase(0x00);
  348. if (!ret) {
  349. printf("Failed to erase flash.\n");
  350. return;
  351. }
  352. printf("Erase one sector from Addr[0x%x] of flash succeed.\n", 0x00);
  353. /* write flash block data */
  354. ret = Flash_Block_Write();
  355. if (!ret) {
  356. printf("Failed to write flash.\n");
  357. return;
  358. }
  359. /* read flash block data */
  360. ret = Flash_Block_Read_Test();
  361. if (!ret) {
  362. printf("Failed to read flash.\n");
  363. return;
  364. }
  365. }
  366. void ch34x_demo_eeprom_operate()
  367. {
  368. bool ret = false;
  369. ret = CH347_I2C_Init();
  370. if (!ret) {
  371. printf("Failed to init CH347 I2C.\n");
  372. return;
  373. }
  374. printf("CH347 I2C interface init succeed.\n");
  375. ret = EEPROM_Read();
  376. if (!ret) {
  377. printf("Failed to read eeprom.\n");
  378. return;
  379. }
  380. ret = EEPROM_Write();
  381. if (!ret) {
  382. printf("Failed to write eeprom.\n");
  383. return;
  384. }
  385. ret = EEPROM_Read();
  386. if (!ret) {
  387. printf("Failed to read eeprom.\n");
  388. return;
  389. }
  390. }
  391. void ch34x_demo_jtag_operate()
  392. {
  393. int i;
  394. int oReadLength;
  395. uint8_t retue[32] = { 0 };
  396. uint8_t IDCODE[4096] = { 0 };
  397. oReadLength = 32;
  398. /* init jtag tck clock */
  399. CH347Jtag_INIT(ch347device.fd, 4);
  400. /* reset target jtag device */
  401. CH347Jtag_SwitchTapState(ch347device.fd, 0);
  402. /* SHIFT-DR Read the Target IDCODE */
  403. CH347Jtag_ByteReadDR(ch347device.fd, &oReadLength, &retue);
  404. printf("Target IDCODE: \n");
  405. for (i = 0; i < 4; i++) {
  406. printf("0x%2x", retue[3 - i]);
  407. }
  408. puts("");
  409. return;
  410. }
  411. bool CH347_SPI_Slave_Init()
  412. {
  413. bool ret;
  414. mSpiCfgS SpiCfg = { 0 };
  415. /* set spi interface in spi slave mode, [mode3] & [MSB] & output [0xFF] by default */
  416. SpiCfg.iByteOrder = 1;
  417. SpiCfg.iSpiOutDefaultData = 0xFF;
  418. SpiCfg.iMode = 0x83;
  419. /* init spi interface */
  420. ret = CH347SPI_Init(ch347device.fd, &SpiCfg);
  421. if (!ret) {
  422. printf("Failed to init SPI interface.\n");
  423. return false;
  424. } else {
  425. printf("SPI init slave ok.\n");
  426. }
  427. return true;
  428. }
  429. void ch34x_demo_spi_slave_operate(bool enable)
  430. {
  431. bool ret = false;
  432. uint8_t oBuffer[SPI_SLAVE_MAX_LENGTH];
  433. uint32_t oLength;
  434. int i;
  435. if (enable) {
  436. ret = CH347_SPI_Slave_Init();
  437. if (ret == false) {
  438. printf("Failed to init CH347 SPI interface.\n");
  439. return;
  440. }
  441. printf("CH347 SPI interface init succeed.\n");
  442. ret = CH347SPI_Slave_Control(ch347device.fd, true);
  443. if (!ret)
  444. return;
  445. printf("Begin read data in slave mode.\n");
  446. while (1) {
  447. ret = CH347SPI_Slave_QweryData(ch347device.fd, &oLength);
  448. if (!ret) {
  449. printf("CH347SPI_Slave_QweryData failed.\n");
  450. goto exit;
  451. }
  452. if (oLength == 0) {
  453. usleep(10 * 1000);
  454. continue;
  455. }
  456. ret = CH347SPI_Slave_ReadData(ch347device.fd, oBuffer, &oLength);
  457. if (!ret) {
  458. printf("CH347SPI_Slave_ReadData failed.\n");
  459. goto exit;
  460. }
  461. printf("\nRead Slave data, len: %d, contents:\n", oLength);
  462. for (i = 0; i < oLength; i++) {
  463. printf("%02x ", oBuffer[i]);
  464. if (((i + 1) % 20) == 0)
  465. putchar(20);
  466. }
  467. putchar(20);
  468. }
  469. } else
  470. ret = CH347SPI_Slave_Control(ch347device.fd, false);
  471. return;
  472. exit:
  473. CH347SPI_Slave_Control(ch347device.fd, false);
  474. }
  475. static void ch34x_demo_gpio_input_operate()
  476. {
  477. bool ret;
  478. int i, j;
  479. int gpiocount = 8;
  480. uint8_t iDir = 0xff;
  481. uint8_t iData = 0x00;
  482. ret = CH347GPIO_Get(ch347device.fd, &iDir, &iData);
  483. if (ret == false) {
  484. printf("CH347GPIO_Set error.\n");
  485. return;
  486. }
  487. printf("\n********** GPIO Input Start **********\n\n");
  488. for (i = 0; i < gpiocount; i++) {
  489. if ((iData & (1 << i)))
  490. printf("H");
  491. else
  492. printf("L");
  493. }
  494. printf("\n");
  495. printf("\n********** GPIO Input End **********\n\n");
  496. }
  497. static void ch34x_demo_gpio_output_operate()
  498. {
  499. bool ret;
  500. int i, j;
  501. int gpiocount = 8;
  502. uint8_t iEnable = 0xff;
  503. uint8_t iSetDirOut = 0xff;
  504. uint8_t iSetDataOut = 0x00;
  505. /* analog leds here */
  506. CH347GPIO_Set(ch347device.fd, iEnable, iSetDirOut, iSetDataOut);
  507. printf("\n********** GPIO Output Start **********\n");
  508. for (i = 0; i < gpiocount; i++) {
  509. iSetDataOut = 1 << i;
  510. ret = CH347GPIO_Set(ch347device.fd, iEnable, iSetDirOut, iSetDataOut);
  511. if (ret == false) {
  512. printf("CH347GPIO_Set error.\n");
  513. return;
  514. }
  515. printf("\n");
  516. for (j = 0; j < gpiocount; j++) {
  517. if (j == i)
  518. printf("H");
  519. else
  520. printf("L");
  521. }
  522. printf("\n");
  523. usleep(200 * 1000);
  524. }
  525. iSetDataOut = 0x00;
  526. CH347GPIO_Set(ch347device.fd, iEnable, iSetDirOut, iSetDataOut);
  527. printf("\n********** GPIO Output End **********\n\n");
  528. }
  529. static void ch34x_demo_isr_handler(int signo)
  530. {
  531. static int int_times = 0;
  532. printf("ch34x interrupt times: %d\n", int_times++);
  533. }
  534. static void ch34x_demo_irq_operate(bool enable)
  535. {
  536. bool ret;
  537. int gpioindex = 6;
  538. ret = CH347GPIO_IRQ_Set(ch347device.fd, gpioindex, enable, IRQ_TYPE_EDGE_BOTH, ch34x_demo_isr_handler);
  539. if (!ret) {
  540. printf("Failed to set CH347 irq function.");
  541. return;
  542. }
  543. }
  544. void ch34x_demo_uart_operate()
  545. {
  546. bool ret = false;
  547. uint8_t iBuffer[256];
  548. uint8_t oBuffer[256];
  549. uint32_t ioLength;
  550. int i;
  551. ioLength = 256;
  552. for (i = 0; i < 256; i++)
  553. iBuffer[i] = i;
  554. ret = CH347Uart_Init(ch347device.fd, 115200, 3, 0, 0, 1);
  555. if (!ret) {
  556. printf("Failed to init CH347 UART interface.\n");
  557. return;
  558. }
  559. printf("CH347 UART interface init succeed.\n");
  560. ret = CH347Uart_Write(ch347device.fd, iBuffer, &ioLength);
  561. if (ret == false) {
  562. printf("CH347Uart_Write failed.\n");
  563. return;
  564. }
  565. printf("Uart wrote %d bytes already.\n", ioLength);
  566. ret = CH347Uart_Read(ch347device.fd, oBuffer, &ioLength);
  567. if (ret == false) {
  568. printf("CH347Uart_Read failed.\n");
  569. return;
  570. }
  571. printf("\nRead Uart data:\n");
  572. for (i = 0; i < ioLength; i++) {
  573. printf("%02x ", oBuffer[i]);
  574. if (((i + 1) % 10) == 0)
  575. putchar(10);
  576. }
  577. putchar(10);
  578. }
  579. bool Show_DevMsg(char *pathname)
  580. {
  581. unsigned char buf[256];
  582. int ret;
  583. int i;
  584. struct hidraw_devinfo info;
  585. uint16_t vendor, product;
  586. CHIP_TYPE chiptype;
  587. if (strstr(pathname, "tty")) {
  588. printf("Device operating has function [UART].\n");
  589. ch347device.functype = FUNC_UART;
  590. } else if (strstr(pathname, "hidraw")) {
  591. /* Get Raw Name */
  592. ret = ioctl(ch347device.fd, HIDIOCGRAWNAME(256), buf);
  593. if (ret < 0) {
  594. perror("HIDIOCGRAWNAME");
  595. goto exit;
  596. } else
  597. printf("Raw Name: %s\n", buf);
  598. /* Get Raw Info */
  599. ret = ioctl(ch347device.fd, HIDIOCGRAWINFO, &info);
  600. if (ret < 0) {
  601. perror("HIDIOCGRAWINFO");
  602. goto exit;
  603. } else {
  604. printf("Raw Info:\n");
  605. printf("\tvendor: 0x%04hx\n", info.vendor);
  606. printf("\tproduct: 0x%04hx\n", info.product);
  607. }
  608. if (info.vendor == 0x1a86) {
  609. if (info.product == 0x55dc)
  610. ch347device.chiptype = CHIP_CH347T;
  611. else if (info.product == 0x55e5)
  612. ch347device.chiptype = CHIP_CH347F;
  613. else {
  614. printf("Current HID device PID is not CH347.\n");
  615. return -1;
  616. }
  617. } else {
  618. printf("Current HID device VID is not CH347.\n");
  619. return -1;
  620. }
  621. /* Get Physical Location */
  622. ret = ioctl(ch347device.fd, HIDIOCGRAWPHYS(256), buf);
  623. if (ret < 0) {
  624. perror("HIDIOCGRAWPHYS");
  625. goto exit;
  626. } else
  627. printf("Raw Phys: %s\n", buf);
  628. if (ch347device.chiptype == CHIP_CH347T) {
  629. if (strstr(buf, "input0")) {
  630. ch347device.functype = FUNC_UART;
  631. printf("Device operating has function [UART].\n");
  632. } else {
  633. ch347device.functype = FUNC_SPI_I2C_GPIO;
  634. printf("Device operating has function [SPI+I2C+GPIO].\n");
  635. }
  636. } else {
  637. if (strstr(buf, "input0")) {
  638. ch347device.functype = FUNC_UART;
  639. printf("Device operating has function [UART].\n");
  640. } else if (strstr(buf, "input2")) {
  641. ch347device.functype = FUNC_UART;
  642. printf("Device operating has function [UART].\n");
  643. } else {
  644. ch347device.functype = FUNC_SPI_I2C_GPIO;
  645. printf("Device operating has function [SPI+I2C+JTAG+GPIO].\n");
  646. }
  647. }
  648. } else if (strstr(pathname, "ch34x_pis")) {
  649. /* Get Driver Version */
  650. ret = CH34x_GetDriverVersion(ch347device.fd, ch347device.version);
  651. if (ret == false) {
  652. printf("CH34x_GetDriverVersion error.\n");
  653. goto exit;
  654. }
  655. printf("Driver version: %s\n", ch347device.version);
  656. /* Get Chip Type */
  657. ret = CH34x_GetChipType(ch347device.fd, &ch347device.chiptype);
  658. if (ret == false) {
  659. printf("CH34x_GetChipType error.\n");
  660. goto exit;
  661. }
  662. if (ch347device.chiptype == CHIP_CH341) {
  663. printf("Current chip operating is CH341, please use ch341_demo.\n");
  664. goto exit;
  665. }
  666. /* Get Device ID */
  667. ret = CH34X_GetDeviceID(ch347device.fd, &ch347device.dev_id);
  668. if (ret == false) {
  669. printf("CH34X_GetDeviceID error.\n");
  670. goto exit;
  671. }
  672. vendor = ch347device.dev_id;
  673. product = ch347device.dev_id >> 16;
  674. printf("Vendor ID: 0x%4x, Product ID: 0x%4x\n", vendor, product);
  675. if (product == 0x55db) {
  676. ch347device.functype = FUNC_SPI_I2C_GPIO;
  677. printf("Device operating has function [SPI+I2C+GPIO].\n");
  678. } else if (product == 0x55dd) {
  679. ch347device.functype = FUNC_JTAG_GPIO;
  680. printf("Device operating has function [JTAG+GPIO].\n");
  681. } else if (product == 0x55de) {
  682. ch347device.functype = FUNC_SPI_I2C_JTAG_GPIO;
  683. printf("Device operating has function [SPI+I2C+JTAG+GPIO].\n");
  684. }
  685. }
  686. return true;
  687. exit:
  688. return false;
  689. }
  690. int main(int argc, char *argv[])
  691. {
  692. bool ret;
  693. char choice, ch;
  694. if (argc != 2) {
  695. printf("Usage: sudo %s [device]\n", argv[0]);
  696. return -1;
  697. }
  698. /* open device */
  699. ch347device.fd = CH347OpenDevice(argv[1]);
  700. if (ch347device.fd < 0) {
  701. printf("CH347OpenDevice false.\n");
  702. return -1;
  703. }
  704. printf("Open device %s succeed, fd: %d\n", argv[1], ch347device.fd);
  705. ret = Show_DevMsg(argv[1]);
  706. if (ret == false)
  707. return -1;
  708. sleep(1);
  709. if (strstr(argv[1], "ch34x_pis")) {
  710. ret = CH34xSetTimeout(ch347device.fd, 2000, 2000);
  711. if (ret == false) {
  712. printf("CH34xSetTimeout false.\n");
  713. return -1;
  714. }
  715. }
  716. switch (ch347device.functype) {
  717. case FUNC_UART:
  718. while (1) {
  719. printf("\npress u to operate uart, q to quit.\n");
  720. scanf("%c", &choice);
  721. while ((ch = getchar()) != EOF && ch != '\n')
  722. ;
  723. if (choice == 'q')
  724. break;
  725. switch (choice) {
  726. case 'u':
  727. ch34x_demo_uart_operate();
  728. break;
  729. default:
  730. break;
  731. }
  732. }
  733. break;
  734. case FUNC_SPI_I2C_GPIO:
  735. case FUNC_SPI_I2C_JTAG_GPIO:
  736. while (1) {
  737. printf("\npress f to operate spi flash, e to operate eeprom,\n"
  738. "a to get gpio status, g to gpio output test, j to operate jtag interface,\n"
  739. "s to enable spi slave mode, o to disable spi slave mode,\n"
  740. "i to enable interrupt, d to disable interrupt, q to quit.\n");
  741. scanf("%c", &choice);
  742. while ((ch = getchar()) != EOF && ch != '\n')
  743. ;
  744. if (choice == 'q')
  745. break;
  746. switch (choice) {
  747. case 'f':
  748. printf("FLASH Test begin.\n");
  749. ch34x_demo_flash_operate();
  750. break;
  751. case 'e':
  752. printf("EEPROM Test begin.\n");
  753. ch34x_demo_eeprom_operate();
  754. break;
  755. case 'a':
  756. printf("GPIO Input Test Begin.\n");
  757. ch34x_demo_gpio_input_operate();
  758. break;
  759. case 'g':
  760. printf("GPIO Output Test Begin.\n");
  761. ch34x_demo_gpio_output_operate();
  762. break;
  763. case 'i':
  764. printf("IRQ Test Begin.");
  765. ch34x_demo_irq_operate(true);
  766. break;
  767. case 'd':
  768. printf("IRQ Test Over.\n");
  769. ch34x_demo_irq_operate(false);
  770. break;
  771. case 'j':
  772. if (ch347device.functype == FUNC_SPI_I2C_JTAG_GPIO) {
  773. printf("JTAG Test begin.\n");
  774. ch34x_demo_jtag_operate();
  775. } else {
  776. printf("Chip is not CH347F.\n");
  777. }
  778. break;
  779. case 's':
  780. if (ch347device.chiptype == CHIP_CH347F) {
  781. printf("SPI Slave Test Begin.\n");
  782. ch34x_demo_spi_slave_operate(true);
  783. } else {
  784. printf("Chip is not CH347F.\n");
  785. }
  786. break;
  787. case 'o':
  788. if (ch347device.chiptype == CHIP_CH347F) {
  789. printf("SPI Slave Test Over.\n");
  790. ch34x_demo_spi_slave_operate(false);
  791. } else {
  792. printf("Chip is not CH347F.\n");
  793. }
  794. break;
  795. default:
  796. printf("Bad choice, please input again.\n");
  797. break;
  798. }
  799. }
  800. break;
  801. case FUNC_JTAG_GPIO:
  802. while (1) {
  803. printf("\npress j to operate jtag interface, a to get gpio status,\n"
  804. "g to gpio output test q to quit.\n");
  805. scanf("%c", &choice);
  806. while ((ch = getchar()) != EOF && ch != '\n')
  807. ;
  808. if (choice == 'q')
  809. break;
  810. switch (choice) {
  811. case 'j':
  812. printf("JTAG Test begin.\n");
  813. ch34x_demo_jtag_operate();
  814. break;
  815. case 'a':
  816. printf("GPIO Input Test Begin.\n");
  817. ch34x_demo_gpio_input_operate();
  818. break;
  819. case 'g':
  820. printf("GPIO Test begin.\n");
  821. ch34x_demo_gpio_output_operate();
  822. default:
  823. printf("Bad choice, please input again.\n");
  824. break;
  825. }
  826. }
  827. break;
  828. default:
  829. break;
  830. }
  831. /* close the device */
  832. if (CH347CloseDevice(ch347device.fd)) {
  833. printf("Close device succeed.\n");
  834. }
  835. return 0;
  836. }

执行截图:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/81668
推荐阅读
相关标签
  

闽ICP备14008679号