ftdi_sio应用学习笔记 5 - SPI

ops/2024/11/25 7:39:31/

目录

1. 查找设备

2. 打开设备

3. 验证

3.1 遍历设备

3.2 打开关闭设备

3.3 读flash id


SPI的SCK/MOSI/MISO分别对应(A/B)D0/D1/D2,其他IO作为CS。和I2C一样,最大支持2路MPSSE通道,一路MPSSE最大13路SPI。

#define FTDI_DEVICE_MAX_INTEFACE_SPI    2
#define FTDI_DEVICE_MAX_SPI             13

定义spi设备的信息结构体

struct ftdi_spi_info {struct ftdi_spi_info *next;int spi_master[FTDI_DEVICE_MAX_INTEFACE_SPI];//int spi_index[FTDI_DEVICE_MAX_INTEFACE_SPI][FTDI_DEVICE_MAX_SPI]; char tty_name[FTDI_DEVICE_MAX_INTEFACE_SPI][10];int pid;int vid;char serial_number[64];
};

1. 查找设备

spi设备的编号可以在ttyUSBn的spi_master目录下找到,例如

:/sys/bus/usb/devices/2-1/2-1:1.0/ttyUSB0/spi_master/spi0$ ls
device  spi0.0  spi0.2  spi0.4      subsystem
power   spi0.1  spi0.3  statistics  uevent

对于MPSSE设备,一路MPSSE只会有一个spi master,所以只需要找到"spi0"这里面的编号0。

DIR *spi_dir;
struct dirent *spi_entry;
int spi_index = 0;sprintf(dev_list->tty_name[interface], "%s", tty_entry->d_name);
sprintf(name_path, "/sys/bus/usb/devices/%s:1.%d/%s/spi_master", entry->d_name, interface, tty_entry->d_name);
spi_dir = opendir(name_path);
if (spi_dir == NULL) {  break;
}
while ((spi_entry = readdir(spi_dir)) != NULL) {if (strstr(spi_entry->d_name, "spi") != NULL) {  printf("Found:%s\n", spi_entry->d_name);sscanf(spi_entry->d_name, "spi%d", &dev_list->spi_master[interface]);break;} 
}
closedir(spi_dir);

将这个编号保存起来,至于下一级的编号,肯定是固定的从0开始计数,直到最大12(对于FT4232H最大直到5)。

2. 打开设备

打开设备和i2c设备一样分2种情况

int open_spi(int pid, int n, int interface, int num, int freq);
int open_spi(char *serial_number, int interface, int num, int freq);

参数:

pid - FTDI设备的PID号

n - 需要打开的同PID号的第n个设备

num - 该设备的第num个spi设备

freq - 设置该设备的频率,Hz为单位

返回spi设备的设备句柄。

找到对应的设备号后打开文件即可。

char dev_path[PATH_MAX];
int fd;
sprintf(dev_path, "/dev/spidev%d.%d", dev_list->spi_master[interface], num);
printf("open:%s\n", dev_path);
if ((fd = open(dev_path, O_RDWR)) < 0) {perror("Failed to open the spi bus\n");
}
return fd;  

3. 验证

通过FT4232H验证,将BD0/BD1/BD2/BD3接入spi nor flash,即spidev1.0。

3.1 遍历设备

ftdi_sio_spi spi;
spi.find_devices();spi.free_devices();

打印结果:

serial number:FT9PQ9R2
Found:spi0
Found:spi1

3.2 打开关闭设备

int fd;spi.find_devices();
fd = spi.open_spi((char *)"FT9PQ9R2", 1, 0);
if(fd < 0) {printf("open spi device fail %d\n", fd);
}spi.close_spi(fd);

打印结果:

open:/dev/spidev1.0

3.3 读flash id

flash_id = sflashReadJedecID(fd);
printf("flash id: 0x%x\n", flash_id);

打印结果:

sflash Winbond
sflash size 16MB, 24bits address
flash id: 0xef4018

http://www.ppmy.cn/ops/136513.html

相关文章

Perforce《2024游戏技术现状报告》Part3:生成式AI、版本控制、CI/CD等游戏技术的未来趋势与应用

游戏开发者一直处于创新前沿。他们的实践、工具和技术受到各行各业的广泛关注&#xff0c;正在改变着组织进行数字创作的方式。 近期&#xff0c;Perforce发布了《2024游戏技术现状报告》&#xff0c;通过收集来自游戏、媒体与娱乐、汽车和制造业等高增长行业的从业者、管理人…

二.LoadBalancer负载均衡服务调用(1)

1.spring-cloud-loadbalancer概述 (1)官网 2.客户端负载VS服务器端负载 loadbalancer本地负载均衡客户端VSNginx服务端负载均衡区别 Nginx是服务器端负载均衡,客户端所有请求都会交给nignx,然后由nginx实现转发请求,即负载均衡是由服务端实现的 loadbalancer本地负载均衡,在…

使用var/let/const的选择

对于var的使用 1、需要明白一个事实&#xff0c;var所表现出来的特殊性:比如作用域提升、window全局对象、没有块级作用域等都是一些历史遗留问题&#xff1b; 2、其实是JavaScript在设计之初的一种语言缺陷&#xff1b; 3、在实际工作中&#xff0c;我们可以使用最新的规范来…

HashMap的寻址算法(源码分析)

建议先看完我这篇文章HashMap底层原理-CSDN博客 hashmap插入值的时候&#xff0c;是如何找到数组索引位置的呢&#xff1f; 例如下图左边四个连续红点&#xff0c;是如何在插入的时候定位到了数组下标为3的位置&#xff1f; 来看看put方法的源码&#xff0c;里面有个hash&…

洛谷 B2038:奇偶 ASCII 值判断

【题目来源】https://www.luogu.com.cn/problem/B2038http://shnoip.openjudge.cn/level1/39/【题目描述】 任意输入一个字符&#xff0c;判断其 ASCII 是否是奇数&#xff0c;若是&#xff0c;输出 YES&#xff0c;否则&#xff0c;输出 NO。 例如&#xff0c;字符 A 的 ASCII…

MQ重复消费与消息顺序

如何避免消息重复消费 RocketMQ&#xff1a;给每个消息分配了一个MessageID。这个MessageID就可以作为消费者判断幂等的依据。这种方式不太建议&#xff0c;原因是在高并发场景下这个MessageID不保证全局唯一性。 最好由业务方创建一个与业务相关的全局唯一的ID来区分消息&am…

springboot实战(17)(“大事件“——新增文章主体逻辑)

目录 一、新增文章涉及的数据表、实体类。 &#xff08;1&#xff09;表结构。 &#xff08;2&#xff09;实体类&#xff08;Article&#xff09; 二、接口文档分析。 &#xff08;1&#xff09;请求方式与请求路径。 &#xff08;2&#xff09;请求参数。 &#xff08;3&…

RabbitMQ简单应用

概念 RabbitMQ 是一种流行的开源消息代理&#xff08;Message Broker&#xff09;软件&#xff0c;它实现了高级消息队列协议&#xff08;AMQP - Advanced Message Queuing Protocol&#xff09;。RabbitMQ 通过高效的消息传递机制&#xff0c;主要应用于分布式系统中解耦应用…