CH34X-MPHSI高速Master扩展应用—SPI设备调试

一、前言 

本文介绍,基于USB2.0高速USB转接芯片CH347,配合厂商提供的USB转MPHSI(Multi Protocol High-Speed Serial Interface)Master总线驱动(CH34X-MPHSI-Master)为系统扩展SPI总线的用法,除此之外,还可以扩展I2C总线和GPIO等资源。

驱动软件正常工作后,会在系统下创建新的SPI Master,拥有独立的bus num,原SPI器件的设备驱动可直接通过DTS配置文件或者sysfs节点挂载到该总线上,原有设备驱动无需任何修改。

项目地址:GitHub - WCHSoftGroup/ch34x_mphsi_master_linux

 二、应用框图

三、CH347 SPI接口特点

CH347F SPI接口

PIN脚SPI功能脚GPIO复用脚
13SCS0-
7SCS1-
14SCK-
16MOSI-
15MISO-

CH347T SPI接口

PIN脚SPI功能脚GPIO复用脚
5SCS0gpio2
9SCS1gpio5
6SCKgpio0
8MOSI-
7MISOgpio1

SPI接口特性:

  • SPI模式0/1/2/3

  • SPI时钟频率60MHz~218.75KHz

  • MSB/LSB传输

  • 8位/16位传输

  • 2路片选

  • 片选高/低有效

四、驱动使用与确认SPI总线信息

本文基于树莓派4B平台,使用CH347F/T芯片通过树莓派的USB接口扩展SPI总线接口,介绍不同SPI设备的应用实例。

驱动程序默认未开启 spidev 设备创建,如需要使用 /dev/spidev*,在 ch34x_mphsi_master_spi.c 文件中要开放 SPIDEV 宏定义,即修改成:

#define SPIDEV
//#undef SPIDEV

1. 编译驱动

root@raspberrypi:/home/wch/ch34x_mphsi_master_linux_V1.1/driver # make
make -C /lib/modules/6.1.21-v8+/build M=/home/wch/ch34x_mphsi_master_linux_V1.1/driver modules
make[1]: 进入目录“/usr/src/linux-headers-6.1.21-v8+”
  CC [M]  /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master_usb.o
  CC [M]  /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master_spi.o
  CC [M]  /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master_i2c.o
  CC [M]  /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master_gpio.o
  LD [M]  /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master.o
  MODPOST /home/wch/ch34x_mphsi_master_linux_V1.1/driver/Module.symvers
  CC [M]  /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master.mod.o
  LD [M]  /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master.ko
make[1]: 离开目录“/usr/src/linux-headers-6.1.21-v8+”

2. 加载驱动

root@raspberrypi:/home/wch/ch34x_mphsi_master_linux_V1.1/driver # make load
insmod ch34x_mphsi_master.ko

3、确认SPI总线信息

将CH347F/T 设备通过USB连接至树莓派,查看系统日志,可看到扩展的SPI总线号为SPI bus 7

[  218.193644] ch34x_mphsi_master: loading out-of-tree module taints kernel.
[  218.194619] mphsi-ch34x 1-1.2:1.2: ch34x_cfg_probe: output SPI slave with CS0
[  218.194633] mphsi-ch34x 1-1.2:1.2: ch34x_cfg_probe: output SPI slave with CS1
[  218.195050] mphsi-ch34x 1-1.2:1.2: ch34x_spi_probe: SPI master connected to SPI bus 7
[  218.195323] mphsi-ch34x 1-1.2:1.2: ch34x_mphsi_i2c_probe: I2C master connected to I2C bus 22
[  218.195645] mphsi-ch34x 1-1.2:1.2: ch34x_mphsi_gpio_probe: registered GPIOs from 501 to 503
[  218.195663] mphsi-ch34x 1-1.2:1.2: ch34x_usb_probe: USB to SPI/I2C/GPIO adapter ch34x now attached.
[  218.195778] usbcore: registered new interface driver mphsi-ch34x

五、W25Q16模块调试

本节介绍通过CH347的SPI接口操作W25Q16模块,相关资料:LibDriver W25QXX,是LibDriver推出的W25QXX全功能驱动,该驱动提供Flash读取,Flash写入等功能并且它符合MISRA标准)

GitHub - hepingood/w25qxx: W25QXX(W25Q80, W25Q16, W25Q32, W25Q64, W25Q128, W25Q256) full function driver for general MCU and Linux.

获得资料包后,进入w25qxx-master/project/raspberrypi4b目录,根据README编译得到可执行文件w25qxx.

注:

需进入w25qxx-master\project\raspberrypi4b\driver\src目录,修改raspberrypi4b_driver_w25qxx_interface.c文件,替换成CH347驱动创建的/dev/spi7.0节点设备。

#define SPI_DEVICE_NAME "/dev/spidev0.0" 修改为:

#define SPI_DEVICE_NAME "/dev/spidev7.0"

根据README运行可执行文件

寄存器测试

root@raspberrypi:/home/wch/w25qxx-master/project/raspberrypi4b/build # ./w25qxx -t reg --type=W25Q16 --interface=spi
w25qxx: chip is Winbond W25QXX.
w25qxx: manufacturer is Winbond.
w25qxx: interface is SPI QSPI.
w25qxx: driver version is 1.0.
w25qxx: min supply voltage is 2.7V.
w25qxx: max supply voltage is 3.6V.
w25qxx: max current is 25.00mA.
w25qxx: max temperature is 85.0C.
w25qxx: min temperature is -40.0C.
w25qxx: start register test.
w25qxx: w25qxx_set_type/w25qxx_get_type test.
w25qxx: set type W25Q80.
w25qxx: check chip type ok.
w25qxx: set type W25Q16.
w25qxx: check chip type ok.
w25qxx: set type W25Q32.
w25qxx: check chip type ok.
w25qxx: set type W25Q64.
w25qxx: check chip type ok.
w25qxx: set type W25Q128.
w25qxx: check chip type ok.
w25qxx: set type W25Q256.
w25qxx: check chip type ok.
w25qxx: w25qxx_set_interface/w25qxx_get_interface test.
w25qxx: set interface SPI.
w25qxx: check chip interface ok.
w25qxx: set interface QSPI.
w25qxx: check chip interface ok.
w25qxx: w25qxx_get_manufacturer_device_id test.
w25qxx: manufacturer is 0xEF, device id is 0x14.
w25qxx: w25qxx_get_jedec_id test.
w25qxx: manufacturer is 0xEF, device id is 0x40 0x15.
w25qxx: w25qxx_get_unique_id test.
w25qxx: unique id 0xE6 0x61 0x74 0xA2 0x43 0x3E 0xA0 0x2B.
w25qxx: w25qxx_set_status1/w25qxx_get_status1 test.
w25qxx: status1 is 0x00.
w25qxx: w25qxx_set_status2/w25qxx_get_status2 test.
w25qxx: status2 is 0x02.
w25qxx: w25qxx_set_status3/w25qxx_get_status3 test.
w25qxx: status3 is 0x60.
w25qxx: w25qxx_enable_write test.
w25qxx: check enable write ok.
w25qxx: w25qxx_disable_write test.
w25qxx: check disable write ok.
w25qxx: w25qxx_enable_write test.
w25qxx: check enable sr write ok.
w25qxx: w25qxx_erase_program_suspend test.
w25qxx: check erase program suspend ok.
w25qxx: w25qxx_erase_program_suspend test.
w25qxx: check erase program resume ok.
w25qxx: w25qxx_global_block_lock test.
w25qxx: check global block lock ok.
w25qxx: w25qxx_global_block_unlock test.
w25qxx: check global block unlock ok.
w25qxx: w25qxx_individual_block_lock test.
w25qxx: check individual block lock ok.
w25qxx: w25qxx_read_block_lock test.
w25qxx: check read block lock ok with 1.
w25qxx: w25qxx_individual_block_unlock test.
w25qxx: check individual block unlock ok.
w25qxx: w25qxx_set_burst_with_wrap test.
w25qxx: check set burst with wrap ok.
w25qxx: w25qxx_power_down test.
w25qxx: w25qxx_release_power_down test.
w25qxx: w25qxx_enable_reset test.
w25qxx: w25qxx_reset_device test.
w25qxx: finish register test.

读写FLASH测试

root@raspberrypi:/home/wch/w25qxx-master/project/raspberrypi4b/build # ./w25qxx -e write --type=W25Q16 --interface=spi --addr=0x000000 --data=0x08
w25qxx: addr 0 write data 8.
root@raspberrypi:/home/wch/w25qxx-master/project/raspberrypi4b/build # ./w25qxx -e read --type=W25Q16 --interface=spi --addr=0x000000
w25qxx: addr 0 is 8.

六、SSD1306模块调试

SSD1306是一款带控制器的用于OLED点阵图形显示系统的单片CMOS OLED/PLED驱动器。它由128个SEG(列输出)和64个COM(行输出)组成。该芯片专为共阴极OLED面板设计。

参考资料链接:

GitHub - rm-hull/luma.oled: Python module to drive a SSD1306 / SSD1309 / SSD1322 / SSD1325 / SSD1327 / SSD1331 / SSD1351 / SH1106 OLED

加载OLED驱动程序

root@raspberrypi:~ # insmod oled_drv.ko

使用sysfs或dts绑定将此spi设备驱动挂载到ch347创建的spi总线

  • 配置driver_override,用于匹配设备和驱动

root@raspberrypi:~ # echo oled_drv > /sys/class/spi_master/spi7/spi7.0/driver_override
  • 此处echo的名称应与驱动中name一致,示例:

static struct spi_driver spidev_spi_driver = {
    .driver = {
        .name = "oled_drv",
        ...
    }
    ...
}
  • 解除spidev7.0与原有spidev驱动的绑定

root@raspberrypi:~ # echo spi7.0 > /sys/bus/spi/drivers/spidev/unbind
  • 进行spi7.0和oled驱动的绑定

root@raspberrypi:~ # echo spi7.0 > /sys/bus/spi/drivers/oled_drv/bind

进入/sys/bus/spi/drivers/oled_drv目录,可以看到driver指向了对应的device

root@raspberrypi:/sys/bus/spi/drivers/oled_drv # ls -l spi7.0
lrwxrwxrwx 1 root root 0  7月 24 16:56 spi7.0 -> ../../../../devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.1/1-1.1:1.2/spi_master/spi7/spi7.0

或进入/sys/bus/spi/devices/spi7.0目录。可以看到device和driver匹配成功

root@raspberrypi:/sys/bus/spi/devices/spi7.0 # ls -l driver
lrwxrwxrwx 1 root root 0  7月 24 17:02 driver -> ../../../../../../../../../../../../../../bus/spi/drivers/oled_drv

运行应用程序

./test_app /dev/spi_oled

查看OLED模块显示内容

七、TLC5615模块调试

TLC5615 为德州仪器公司推出的具有串行接口的数模转换器,输入采用三线SPI串行信号,其输出为电压模拟信号,最大输出电压是基准电压值的两倍,配置简单不需要配置过多的寄存器,仅需使用单5V的电源即可工作。

参考资料 TLC5615 数据表、产品信息和支持 | 德州仪器 TI.com.cn

引脚如图

CH347模块的MOSI连接DIN,作为串行信号输入;OUT脚用于输出模拟电压信号;REFIN为外接参考电压2.048V。

加载TLC5615驱动程序

root@raspberrypi:~ # insmod tlc5615_drv.ko

配置driver_override,用于匹配设备和驱动

root@raspberrypi:~ # echo tlc5615_drv > /sys/class/spi_master/spi7/spi7.0/driver_override

解除spidev7.0与原有spidev驱动的绑定

root@raspberrypi:~ # echo spi7.0 > /sys/bus/spi/drivers/spidev/unbind

进行spi7.0和tlc5615驱动的绑定

root@raspberrypi:~ # echo spi7.0 > /sys/bus/spi/drivers/tlc5615_drv/bind

分别查看/sys/bus/spi/drivers/tlc5615_drv/spi7.0文件和/sys/bus/spi/devices/spi7.0/driver文件,可以看到device和driver匹配成功。

root@raspberrypi:~ # ls /sys/bus/spi/drivers/tlc5615_drv/spi7.0 -l
lrwxrwxrwx 1 root root 0  7月 25 19:01 /sys/bus/spi/drivers/tlc5615_drv/spi7.0 -> ../../../../devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.1/1-1.1:1.2/spi_master/spi7/spi7.0
root@raspberrypi:~ #
root@raspberrypi:~ #
root@raspberrypi:~ # ls /sys/bus/spi/devices/spi7.0/driver -l
lrwxrwxrwx 1 root root 0  7月 25 19:02 /sys/bus/spi/devices/spi7.0/driver -> ../../../../../../../../../../../../../../bus/spi/drivers/tlc5615_drv
root@raspberrypi:~ #

驱动加载成功后运行应用程序测量OUT引脚输出电压,OUT脚输出电压 = 2 * VREFIN * n / 1024 = 2 * 2.048 * n / 1024,其中,n为DIN输入的原始值。

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以给你提供一个基本的参考程序,你可以根据自己的需要进行修改和完善。以下是一个简单的示例程序,用于实现ESP32-C3作为SPI Master控制ch623芯片: ```c #include "driver/spi_master.h" #include "esp_err.h" // SPI总线配置参数 #define SPI_BUS HSPI_HOST #define SPI_FREQ 1000000 #define SPI_MODE 0 #define SPI_MSBFIRST 1 // ch623芯片控制命令 #define CMD_RESET 0x01 #define CMD_VOLUME 0x02 // ch623芯片音量控制参数 #define VOL_LEFT 0x3f #define VOL_RIGHT 0x3f // SPI总线句柄 spi_device_handle_t spi_dev; // 初始化SPI总线 void spi_master_init(void) { esp_err_t ret; spi_bus_config_t buscfg = { .miso_io_num = -1, .mosi_io_num = 23, .sclk_io_num = 18, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = 0, }; spi_device_interface_config_t devcfg = { .command_bits = 8, .address_bits = 0, .dummy_bits = 0, .mode = SPI_MODE, .duty_cycle_pos = 128, .cs_ena_posttrans = 3, .cs_ena_pretrans = 0, .clock_speed_hz = SPI_FREQ, .input_delay_ns = 0, .spics_io_num = 5, .flags = 0, .queue_size = 1, .pre_cb = NULL, .post_cb = NULL, .tx_buffer = NULL, .rx_buffer = NULL, }; ret = spi_bus_initialize(SPI_BUS, &buscfg, 1); ESP_ERROR_CHECK(ret); ret = spi_bus_add_device(SPI_BUS, &devcfg, &spi_dev); ESP_ERROR_CHECK(ret); } // ch623芯片复位 void ch623_reset(void) { esp_err_t ret; uint8_t cmd = CMD_RESET; spi_transaction_t t = { .length = 8, .tx_buffer = &cmd, }; ret = spi_device_transmit(spi_dev, &t); ESP_ERROR_CHECK(ret); } // ch623芯片音量控制 void ch623_volume(uint8_t left, uint8_t right) { esp_err_t ret; uint8_t cmd = CMD_VOLUME; uint8_t data[2] = {left, right}; spi_transaction_t t = { .length = 24, .tx_data = &cmd, .rx_data = NULL, .flags = SPI_TRANS_USE_RXDATA, }; ret = spi_device_transmit(spi_dev, &t); ESP_ERROR_CHECK(ret); t.length = 16; t.tx_data = data; ret = spi_device_transmit(spi_dev, &t); ESP_ERROR_CHECK(ret); } void app_main(void) { spi_master_init(); ch623_reset(); ch623_volume(VOL_LEFT, VOL_RIGHT); } ``` 以上代码中,`spi_master_init()`函数用于初始化SPI总线,并创建一个SPI设备句柄;`ch623_reset()`函数用于向ch623芯片发送复位命令;`ch623_volume()`函数用于向ch623芯片发送音量控制命令和参数。你可以根据自己的需要修改这些函数的参数和实现细节,以满足具体的应用需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PC技术小能手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值