I2C的实例位于:
STM32Cube_FW_U3_V1.2.0\Projects\NUCLEO-U385RG-Q\Examples\I2C
其中I2C_TwoBoards_MultiMasterIT_Master,I2C_TwoBoards_MultiMasterIT_Slave可以实现一对开发板进行I2C发送接收演示。
如果没有2个STM32U385RG开发板,可以用其他的STM32开发板代替,其他开发板也有这个2个示例,可以和STM32U385RG进行I2C通讯。

我将STM32U385RG做Slave,STM32H533RE做Master发现可以很容易实现两者的I2C通信实验。


于是想如果用CH347做Master,是否也可以和做为Slave的STM32U385RG进行I2C通信呢?

一、尝试HAL_I2C_Slave_Receive_IT失败了
然后发现竟然不行,也许是认知有限吧。

在I2C_TwoBoards_MultiMasterIT_Slave中采用的HAL_I2C_Slave_Receive_IT做为接收函数。
HAL_I2C_Slave_Receive_IT 设计用于简单的单次传输(主机发送数据后结束通信)。可能 CH347 的通信协议中包含了重复起始条件(Repeated Start)或连续传输(如先写后读),此函数无法自动处理,导致 Slave 无响应。

试了很多次,没有成功,还是放弃了。

二、使用HAL_I2C_Master_Seq_Receive_IT成功了
后来看了I2C_TwoBoards_RestartComIT这个示例,这个例子使用HAL_I2C_Master_Seq_Receive_IT做为接收函数,经过尝试发现可以实现和CH347通信。

1、CH347简介
CH347 是南京沁恒微电子(WCH)推出的一款高速USB总线转接芯片,支持 USB 转多协议串行接口,包括:
USB 转 I2C(主/从模式)、USB 转 SPI(主模式)、USB 转 异步串口(UART)、GPIO 控制
其中,
I2C 支持        - 主模式(Master)- 速率:标准模式(100kHz)、快速模式(400kHz)、高速模式(1MHz)


从已知的资料上看CH347支持I2C Master模式,所以STM32U385RG只能做为Slave
 



2、STM32U385RG软件部分

1)I2C初始化
速率:100khz

复制

 
  1. hi2c2.Instance = I2C2;
  2.   hi2c2.Init.Timing = 0x0070123C;
  3.   hi2c2.Init.OwnAddress1 = I2C_ADDRESS;
  4.   hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  5.   hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  6.   hi2c2.Init.OwnAddress2 = 0;
  7.   hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  8.   hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  9.   hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  10.   if (HAL_I2C_Init(&hi2c2) != HAL_OK)
  11.   {
  12.     Error_Handler();
  13.   }



2)启用监听模式

复制

 
  1. int main(void)
  2. {
  3. ...
  4. if(HAL_I2C_EnableListen_IT(&hi2c2) != HAL_OK)
  5.     {
  6.         Error_Handler();
  7.     }
  8. while(1)
  9. {
  10. }



3)地址匹配回调

复制

 
  1. void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
  2. {
  3.         HAL_I2C_Slave_Seq_Receive_IT(&hi2c2, aRxBuffer, 10, I2C_FIRST_FRAME);
  4. }



4)接收完成回调

复制

 
  1. void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
  2. {
  3.         printf("Received data: [%s]\r\n", aRxBuffer);
  4.         
  5.         if (hi2c2.State != HAL_I2C_STATE_READY) {
  6.         HAL_I2C_DeInit(&hi2c2);
  7.         HAL_I2C_Init(&hi2c2);
  8.     }
  9.         HAL_I2C_EnableListen_IT(&hi2c2);
  10. }

在 RxCpltCallback 中强制复位 I2C,并重启监听模式

3、ch347 I2C Master发送部分
 

复制

 
  1. #! /usr/bin/env python
  2. #coding=utf-8
  3. import os
  4. import time
  5. from ctypes import *
  6. class USBI2C():
  7.     ch347 = windll.LoadLibrary("./CH347DLLA64.dll")
  8.     def __init__(self, usb_dev = 0, i2c_dev = 0x30):
  9.         self.usb_id   = usb_dev
  10.         self.dev_addr = i2c_dev
  11.         USBI2C.ch347.CH347I2C_Set(self.usb_id,4)
  12.         if USBI2C.ch347.CH347OpenDevice(self.usb_id) != -1:
  13.             USBI2C.ch347.CH347CloseDevice(self.usb_id)
  14.         else:
  15.             print("USB CH347 Open Failed!")
  16.         
  17.     def read(self):
  18.         if USBI2C.ch347.CH347OpenDevice(self.usb_id) != -1:
  19.             
  20.             rec  = (c_byte * 1)()
  21.             ibuf = (c_byte * 9)()
  22.             rec[0] = self.dev_addr
  23.             
  24.             USBI2C.ch347.CH347StreamI2C(self.usb_id, 1, rec, 9, ibuf)
  25.             USBI2C.ch347.CH347CloseDevice(self.usb_id)
  26.             
  27.             return ibuf
  28.         else:
  29.             print("USB CH347 Open Failed!")
  30.             return 0
  31.     def write(self,cmd,size):
  32.         if USBI2C.ch347.CH347OpenDevice(self.usb_id) != -1:
  33.             tcmd = (c_byte * (size + 1))()
  34.             ibuf = (c_byte * 1)()
  35.             tcmd[0] = self.dev_addr
  36.             for i in range (size):
  37.                 tcmd[i+1] = cmd[i] & 0xff
  38.                 print(tcmd[i+1])
  39.             
  40.             USBI2C.ch347.CH347StreamI2C(self.usb_id,11,tcmd,1,ibuf)
  41.             USBI2C.ch347.CH347CloseDevice(self.usb_id)
  42.         else:
  43.             print("USB CH347 Open Failed!")
  44. if __name__ == "__main__":
  45.     cmd = (c_byte * 10)(0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39)
  46.     size = sizeof(cmd)
  47.     q = USBI2C()
  48.     while True:
  49.         q.write(cmd,size)
  50.         time.sleep(1) #1s

也可以利用沁恒提供的上位机
 



三、运行效果

1、使用PYTHON脚本
 



2、使用CH347上位机
 


 


---------------------
作者:sujingliang
链接:https://bbs.21ic.com/icview-3471916-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐