SPI/I2C/UART

1. 环境搭建

1.1 USB转UART

设备通过USB插入Host环境,通常可枚举出tty设备,如果没有出现,需要对模块进行驱动的安装。可通过Host代码直接访问这些设备

1.2 USB转SPI/I2C

当我们想调试一些SPI、I2C接口的传感器或者模块,可通过CH341 A/B模块作中转,它可通过USB接口将SPI/IIC数据在设备与Host之间进行传输,通过其驱动可在Host环境下注册SPI/IIC字符设备
CH341转SPI

  • 电平限制为3.3V或5V,只支持master模式
  • 速率固定为1.4MHz左右,数据长度固定8bit,模式固定为mode0,支持MSB/LSB
  • 支持最多3个从机,分别使用CS0/1/2作为片选,支持片选高/低有效
    CH341转I2C
  • 内部上拉电平可选3.3V或5V,只支持master模式
  • 速率支持20K/100K/400K/750KHz,只支持7位地址、8位数据

模块上有跳帽可以切换3.3V/5V,切换SPI+I2C/UART

USB转SPI驱动
驱动参考 https://github.com/gschorcht/spi-ch341-usb

git clone https://github.com/gschorcht/spi-ch341-usb.git
cd spi-ch341-usb
make
sudo make install

不将驱动安装到内核的话,可以在需要时手动加载驱动。
加载前先将CH341转串口和转I2C的驱动卸载,CH341转串口、转I2C、转SPI的驱动相互冲突

sudo rmmod ch341        #需要先卸载ch341,才能卸载usbserial
sudo rmmod usbserial
sudo rmmod i2c_ch341_usb

将仓库目录下的spi-ch341-usb.ko加载:

sudo insmod spi-ch341-usb.ko

设备1模块切换到SPI+I2C模式,插到主机USB上,此时通过 lsmod 可以看到spidev0.0/1/2,其中spidev0.x表示是SPI0总线上的设备,x用于区分各个从机(即通信时使能设备1上的CS0/1/2脚)。
电脑重启后需要重新加载spi-ch341-usb.ko

1.3 USB转I2C驱动

驱动参考 https://github.com/gschorcht/i2c-ch341-usb

git clone https://github.com/gschorcht/i2c-ch341-usb.git
cd i2c-ch341-usb
make
sudo make install

不将驱动安装到内核的话,可以在需要时手动加载驱动。
加载前先将CH341转串口和转SPI的驱动卸载,CH341转串口、转I2C、转SPI的驱动相互冲突:

sudo rmmod ch341        #需要先卸载ch341,才能卸载usbserial
sudo rmmod usbserial
sudo rmmod spidev
sudo rmmod spi_ch341_usb

将仓库目录下的i2c-ch341-usb.ko加载:

sudo insmod i2c-ch341-usb.ko

设备1模块切换到SPI+I2C模式,插到主机USB上,此时通过 lsmod 可以看到i2c_ch341_usb,通过 ls /dev 可以看到i2c-x,其中x根据原有的i2c设备编号而有所变化。
电脑重启后需要重新加载i2c-ch341-usb.ko。
如果insmod提示.ko文件invalid format,可能是linux内核版本更新了,需要重新编译。

2. 测试Host上可用性

2.1 UART测试

当插入的设备可接收AT命令时,可通过如下程序向tty设备发送AT\r,读取到OK。

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>

int main(int argc, char *argv[])
{
  struct termios opt;
  char cmd[] = "AT\r";
  int fd;
  int ret;

  /* Switch TTY to raw mode */
  memset(&opt, 0, sizeof(opt));
  cfmakeraw(&opt);

  errno = 0;
  fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
  if (fd < 0)
        return -1;

  tcflush(fd, TCIOFLUSH);
  tcsetattr(fd, TCSANOW, &opt);

  write(fd, cmd, strlen(cmd));
  read(fd, buf, sizeof(buf));
  close(fd);
}

2.1 SPI测试

在Linux中编写应用程序测试SPI的可用性,可以使用类似如下代码,读取一个某个开发板/器件/模块的ID等寄存器验证:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/spi/spidev.h>
......
 
/* path of spi dev,
   note the x of spidev0.x, must correspond to the CSx */
#define SPI_DEV "/dev/spidev0.1"
......

int main( int argc, char *argv[] )
{
    ......
    
    /* open the spi device */
    int handle_spi = 0;
    handle_spi = open(SPI_DEV, O_RDWR);

    /* since tx and rx will complete at the same time,
       one may use 1 message (the struct below) with rxbuf and txbuf,
       or may use 2 messages with txbuf and rxbuf respectively -- message 1 for tx first and message 2 for rx later, with a interval between 2 messages */
    struct spi_ioc_transfer spi_trans = {
        .tx_buf = (unsigned long)txbuf,
        .rx_buf = (unsigned long)rxbuf,
        .len = len,                        /* length of transmitted data */
        .delay_usecs = 0,                  /* interval between SPI_IOC_MESSAGEs */ */ 
        .speed_hz = 1400000,               /* unavailable for CH341 */
        .bits_per_word = 8,                /* unavailabel for CH341 */
        };
 
    /* set SPI mode, unavailable for CH341*/     
    unsigned char mode = SPI_MODE_0;
    ret = ioctl(handle_spi, SPI_IOC_WR_MODE, &mode);

    /* transmit data through SPI device. 
       The desired data is ready to read in rxbuf when transmitting completed*/
    ret = ioctl(handle_spi, SPI_IOC_MESSAGE(1), &spi_trans);
    
    /* close the spi device*/
    close(handle_spi);
    
    ......
}

2.1 I2C测试

在Linux中编写应用程序测试I2C的可用性,可以使用类似如下代码,读取一个某个开发板/器件/模块的ID等寄存器验证

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
......

/* path of i2c device */
#define I2C_DEV "/dev/i2c-7"

/* address of the slave to communicate, in 7bit format, not left-shifted*/
#define SLAVE_ADDR  0x6C
......

int main( int argc, char *argv[] )
{
    ......
    
    /* open i2c device */
    int handle_i2c = 0;
    handle_i2c = open(I2C_DEV, O_RDWR);

    /* config the slave address */
    ret = ioctl(handle_i2c, I2C_SLAVE, SLAVE_ADDR);

    /* transmit data through i2c,
       slave addr and nW bit will be send first automatically */
    ret = write(i2c_fd, txbuf, tx_count);
    
    /* read data from i2c,
       slave addr and R bit will be send first automatically */   
    ret = read(i2c_fd, rxbuf, rx_count);
    
    /* close i2c device */
    close(handle_i2c);
    
    ......
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UARTSPII2C(也称为IIC)、IIS(也称为I2S)是一些常见的串行通信接口标准,用于在电子设备之间传输数据。 1. UART(通用异步收发器):UART是一种常见的串行通信接口,用于通过异步方式传输数据。它通常用于连接计算机和外部设备,如调制解调器、GPS模块、传感器等。UART使用TX(发送)和RX(接收)线来进行数据传输。 2. SPI(串行外围接口):SPI是一种全双工的串行通信接口,用于在微控制器和外部设备之间传输数据。SPI使用主从模式,其中一个设备充当主设备,控制通信的时序和数据传输。它使用多个线(如SCLK、MISO、MOSI)进行通信,并支持高速数据传输。 3. I2C(双线串行接口):I2C是一种双线制的串行通信接口,用于在芯片之间进行通信。它使用两根线(SDA和SCL)进行数据和时钟传输。I2C支持多主从模式,允许多个设备在同一总线上进行通信。 4. IIS(集成电路音频总线)/I2S(Inter-IC Sound):IIS或I2S是一种用于音频数据传输的串行接口。它通常用于数字音频设备之间的连接,如音频编解码器、数字信号处理器等。I2S使用多个线(如数据线、时钟线、帧同步线)来传输音频数据。 这些接口标准在电子设备中广泛应用,每种接口都有其独特的特点和应用场景。具体使用哪种接口取决于设备之间的通信需求和硬件支持。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值