linux上面使用ftdi芯片模拟485串口详解

一、设备信息
cpu:AR9344
switch:QCA8337
ftdi:FT4232HL
内核版本:Linux version 2.6.31--LSDK-9.2.0_U11.14

ps:我这里使用FT4232HL芯片模拟485串口的功能

FT4232HL芯片功能介绍,这些都能在ftdi官网找到相关手册

1.单芯片USB到四串行端口与各种配置。2.整个USB协议由芯片处理,USB不需特定固件编程。3.USB 2.0高速传输(每秒480兆位)和全速(每秒12兆位)兼容。4.两个多协议同步串行引擎(MPSSE)的通道A和B,以简化同步串行协议(USB转JTAG,I2C,SPI 或 bit-bang)的设计。
独立的波特(baud)率发生器。5.RS232/RS422/RS485串口传输数据速率高达12兆波特。(RS232数据速率限制由外部电平转换器决定)。6.FTDI公司的免费虚拟COM端口(VCP)和直接(D2XX)驱动程序消除在大多数情况下的USB驱动程序开发的要求。7.可使用TX / RX流量指示灯以添加LED和外部74HC595的移位寄存器(shift register)。8.可调超时接收缓冲区9.支持USB的暂停和恢复的条件,通过PWREN#,SUSPEND#和RI#引脚。10.高度集成设计包括 +1.8V电压LDO稳压器,集成POR功能和芯片时脉倍频PLL(12MHz–480MHz)。FTDI公司FT232B方式,异步UART串行接口选项全硬件交握和调制解调器接口信号.完整的硬件交握或X-On/X-Off软件交握。UART接口支持7或8位数据,1或2位停止位,和奇/偶/标志/空间/无奇偶校验。使用TXDEN引脚做为RS485串行应用程序自动传输的启用控制。操作配置模式和USB描述字符串通过USB接口外接EEPROM配置。低操作和低USB暂停电流。可配置的IO驱动强度(4,8,12或16 mA)和压摆率(slew rate)。支持总线供电,自供电和和高功率总线供电的USB配置。UHCI/ OHCI/ EHCI主控制器兼容。USB批量数据传输模式(高速模式下512字节的数据包)。专用的Windows DLL可用于USB到JTAG,USB至SPI和USB至I2C的应用。+1.8V(芯片核心)和+3.3V的I/O接口(+5V耐压)。扩展工业工作温度范围 -40°C 到 85°C。简洁的64-LD无铅LQFP/LQFN封装和56-LD VQFN封装。+ 3.3V单电源工作电压范围。

二、.调试过程
1.首先内核里面选上ftdi模块(USB_SERIAL_FTDI_SIO)
make menuconfig->kernel module->Device Drivers ->USB support->USB Serial Converter support

将相关的基础usb.ko以及ftdi.ko 添加进去以后,

基础的usb库insmod /tmp/modules/usb/usbcore.koinsmod /tmp/modules/usb/ehci-hcd.koinsmod /tmp/modules/usb/usb-storage.koinsmod /tmp/modules/usb/usbnet.koinsmod /tmp/modules/usb/cdc_encap.koinsmod /tmp/modules/usb/cdc_ether.koinsmod /tmp/modules/usb/usbserial.ko                                    insmod /tmp/modules/usb/option.koftdi koinsmod /tmp/modules/usb/ftdi_sio.ko

设备启动以后,串口能看到识别到了ftdi芯片

usb 1-1: new high speed USB device using ath-ehci and address 2
usb 1-1: New USB device found, idVendor=0403, idProduct=6011
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1: Product: USB <-> Serial Converter
usb 1-1: SerialNumber: FT4K3SCF
usb 1-1: configuration #1 chosen from 1 choice
ftdi_sio 1-1:1.0: FTDI USB Serial Device converter detected
usb 1-1: Detected FT4232H
usb 1-1: Number of endpoints 2
usb 1-1: Endpoint 1 MaxPacketSize 2
usb 1-1: Endpoint 2 MaxPacketSize 2
usb 1-1: Setting MaxPacketSize 16384
usb 1-1: FTDI USB Serial Device converter now attached to ttyUSB0
ftdi_sio 1-1:1.1: FTDI USB Serial Device converter detected
usb 1-1: Detected FT4232H
usb 1-1: Number of endpoints 2
usb 1-1: Endpoint 1 MaxPacketSize 2
usb 1-1: Endpoint 2 MaxPacketSize 2
usb 1-1: Setting MaxPacketSize 16384
usb 1-1: FTDI USB Serial Device converter now attached to ttyUSB1
ftdi_sio 1-1:1.2: FTDI USB Serial Device converter detected
usb 1-1: Detected FT4232H
usb 1-1: Number of endpoints 2
usb 1-1: Endpoint 1 MaxPacketSize 2
usb 1-1: Endpoint 2 MaxPacketSize 2
usb 1-1: Setting MaxPacketSize 16384
usb 1-1: FTDI USB Serial Device converter now attached to ttyUSB2
ftdi_sio 1-1:1.3: FTDI USB Serial Device converter detected
usb 1-1: Detected FT4232H
usb 1-1: Number of endpoints 2
usb 1-1: Endpoint 1 MaxPacketSize 2
usb 1-1: Endpoint 2 MaxPacketSize 2
usb 1-1: Setting MaxPacketSize 16384
usb 1-1: FTDI USB Serial Device converter now attached to ttyUSB3

看到上面这些信息的话,列出来的设备ttyUSB0,ttyUSB1,ttyUSB2,ttyUSB3,就能通过串口程序打开进行读写了!

2.遇到的问题以及解决过程
第一个问题:添加了ftdi的ko以后,模拟485串口发送数据正常,无法接收数据。
通过RS232转RS485线,将电脑和设备的ttyUSB2连接起来,、
设备里面运行程序打开ttyUSB2,开启发送和接收程序,
电脑上面开启串口调试工具SSCOM或者USR-TCP232-Test.exe等
***发现设备端发送的数据,电脑上面的串口调试工具能正确收到数据*******
***电脑上面的串口调试工具发送的数据,设备端无法接收到数据************

调试过程:
一开始以为是ftdi转RS485有问题,就跳线改为ftdi直接出RS232,调试以后发现问题还是一样!这样就排除了FTDI芯片问题,

跟踪FTDI的驱动,将FTDI驱动里面接收数据函数(ftdi_process_read)添加一些打印,将收到的数据,以及数据长度打印出来,

need_flip = 0;for (packet_offset = priv->rx_processed;packet_offset < urb->actual_length; packet_offset += priv->max_packet_size) {int length;/* Compare new line status to the old one, signal if different/N.B. packet may be processed more than once, but differencesare only processed once.  */char new_status = data[packet_offset + 0] &FTDI_STATUS_B0_MASK;if (new_status != priv->prev_status) {priv->diff_status |=new_status ^ priv->prev_status;wake_up_interruptible(&priv->delta_msr_wait);priv->prev_status = new_status;}length = min_t(u32, priv->max_packet_size, urb->actual_length-packet_offset)-2; //这里发现priv->max_packet_size为2,导致length一直为0或者-1if (length < 0) {dev_err(&port->dev, "%s - bad packet length: %d\n",__func__, length+2);length = 0;}if(0){for(i=0;i<length+2;i++){dev_err(&port->dev,"data[%d]=%02x ",i,data[i]);}dev_err(&port->dev,"length=%d\n",length);dev_err(&port->dev,"max_packet_size=%d\n",priv->max_packet_size);dev_err(&port->dev,"actual_length=%d\n",urb->actual_length);}

在源码里面查找max_packet_size,发现max_packet_size这个表示串口接收buff的长度。
有一个函数(ftdi_set_max_packet_size)是专门用来设置这个max_packet_size的

static void ftdi_set_max_packet_size(struct usb_serial_port *port)
{struct ftdi_private *priv = usb_get_serial_port_data(port);struct usb_serial *serial = port->serial;struct usb_device *udev = serial->dev;struct usb_interface *interface = serial->interface;struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;unsigned num_endpoints;int i = 0;num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);/* NOTE: some customers have programmed FT232R/FT245R devices* with an endpoint size of 0 - not good.  In this case, we* want to override the endpoint descriptor setting and use a* value of 64 for wMaxPacketSize */for (i = 0; i < num_endpoints; i++) {
dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
ep_desc = &interface->cur_altsetting->endpoint[i].desc;
if (ep_desc->wMaxPacketSize == 0) {ep_desc->wMaxPacketSize = cpu_to_le16(0x40);dev_info(&udev->dev, "Overriding wMaxPacketSize on endpoint %d\n", i);
}ep_desc->wMaxPacketSize = cpu_to_le16(0x40);//*****这里将wMaxPacketSize 设置为cpu_to_le16(0x40),实际值为0x4000}/* set max packet size based on descriptor */priv->max_packet_size = ep_desc->wMaxPacketSize;dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
}

修改ftdi的驱动,将wMaxPacketSize 改为cpu_to_le16(0x40)以后,RS232串口接收以及发送都正常了!

第二个遇到的问题:RS232接收和发送都正常了,但是RS485发送正常,接收还是有问题(收不到数据)。
解决办法,查看FTDI的芯片手册发现,如果需要使用FTDI转RS485的话,需要添加一个eeprom来控制

第三个问题:eeprom固件编程
ftdi官方提供了一个软件FT_Prog来对eeprom编程
ps:只能通过usb将FTDI芯片跟电脑连接起来,FT_Prog才能烧写eeprom,一开始是通过手动编程器烧写eeprom的

这里选上RI as RS485 Enable就可以。

点击Program Devices按钮会将你的配置生成16进制

这里发现生成的bin文件是2k大小的!一开始我是将16进制拷贝出来,然后自己制作(使用winhex软件)一个2k的二进制文件,
然后用编程器将2k的固件烧录到1k的eeprom里面去,发现只烧录了前半部1k。

这个时候才发现对eeprom的大小也有要求,没办法只能再采购几个2k的eeprom。
等2k的eeprom到了以后,直接用编程器烧写发现RS485工作也不正常。
最后只能外接usb连接电脑,通过FT_Prog对eeprom烧写,再接上烧写好的eeprom,RS485能收到数据了,但是自己发送的数据,自己也会收到!

后续其他的eeprom烧写,将一个正常的eeprom读取出来做原始固件应该就可以了!因为接usb烧写太麻烦了!
ps:在FTDI的芯片手册里面只发现了eeprom的说明(说可用1k,2k,4k),没有强调大小。
所以后面又用1k的eeprom接usb通过FT_Prog烧写了一次。发现RS485能收到数据了,但是自己发送的数据,自己也会收到!

对比16进制的数据发现,FT_Prog程序将eeprom中间的一些没用的00去去掉了!

第四个问题:RS485会收到自己发送的数据。
解决办法:查看FT4232芯片手册发现

这里对RS485收到自己发送数据做了说明,解决办法有2个
一个是软件自己解决,后面跟其他同事讨论以后发现可行性以及稳定性不好控制,容易出错误
第二个是硬件电路控制.
最后只能等硬件工程师改好了,再验证了!

第四个问题:关于RS485串口的波特率问题。
我验证了9600,115200,以及230400,RS485接收和发送都正常。

但是波特率设置为460800以后,设备发送出来的数据,电脑上的串口调试工具收到的数据不对
电脑上串口调试工具发送的数据,设备端RS485能正常使用!!
对比了AR9344直接接出来的高速串口,现象是一样的!

####所以我不太明白,是不是硬件已经不支持了460800的波特率了,还是软件配置波特率的地方有问题!!!
目前RS485使用的波特率是只有9600和115200.所以460800波特率问题就暂时不深究了!

PS后续乌龙事件补充
RS485功能都正常以后,想长时间测试一些RS485的发送和接收功能。发现RS485会定时发送一些数据,当电脑收到这些异常数据以后,RS485工作就不正常了。而且一打开RS485调试,就发现RS485会先设置921600的波特率,再改为我设置好的波特率

后面跟踪ftdi驱动,发现发送异常数据的时候,会修改RS485的波特率为921600。
查找源码发现只有在打开RS485的时候,才会设置RS485的波特率。

这个时候就发现可能有其他程序在打开相同的RS485,去操作它!
后续跟踪发现,是自己上次做的上报GPS信息的模块引起的!
上报GPS信息的模块里面将ttyUSB2接口当成了龙尚U9300C模块生成设备,去打开,并且发送AT指令了!

windows上面打开已经被打开过串口的时候,会提示串口被占用。

linux多次打开串口(ttyUSB0),系统不会有任何提示,只能由程序员自己控制了!

***串口接口编程还是要小心一些,不能打开多次,要不然就出现我上面的乌龙事件了!

linux上面使用ftdi芯片模拟485串口详解相关推荐

  1. 单片机电流检测电路图大全(四款模拟电路设计原理图详解) - 信号处理电子电路图

    电路图简介: 本文主要介绍了单片机电流检测电路图大全(四款模拟电路设计原理图详解).它的主要功能是完成对过电压的瞬时值和峰值的检测.过电压次数的检测.电源输出电压和电流的检测,并通过键盘的操作显示出各 ...

  2. 详解FTP服务完成Linux和WIN10之间的信息传输(实验详解)

    详解FTP服务完成Linux和WIN10之间的信息传输(实验详解) 一.FTP简介 1. FTP服务--用来传输文件的协议 2.端口 3.数据连接模式 二.相关配置 1.安装FTP服务 2.设置匿名用 ...

  3. 芯片常用协议种类详解,含多协议转换器

    题目:芯片常用协议种类详解,含多协议转换器 目录 1. 引言 1.1常用通信样式 1.2 FPGA芯片上的UART也是一样的 1.3 FPGA用verilog实现UART 1.4基于FPGA的SPI协 ...

  4. Linux系统多网卡绑定各配置模式详解

    Linux系统多网卡绑定各配置模式详解 1. 配置多网卡bond 1.1. mode=0 模式 1.2. mode=1 模式 1.2.1. 关闭NetworkManager服务 1.2.2. 网卡配置 ...

  5. Linux下boost库的编译、安装详解

    1.下载源文件 去官网下载:http://www.boost.org/ 这里下载最新版本 wget https://dl.bintray.com/boostorg/release/1.64.0/sou ...

  6. Linux下的tar归档及解压缩功能详解

    Linux下的tar归档及解压缩功能详解 一.Linux下解压缩工具 二.gzip工具的使用方法 三.其他解压缩工具 一.Linux下解压缩工具 二.gzip工具的使用方法 三.其他解压缩工具 一.L ...

  7. 【Linux】19.Linux环境变量名LD_LIBRARY_PATH 和 ldd命令详解

    Linux环境变量名LD_LIBRARY_PATH 和 ldd命令详解 参考链接: https://www.jianshu.com/p/a62e1d327023 LD_LIBRARY_PATH中的LD ...

  8. 【转载】Linux命令-自动挂载文件/etc/fstab功能详解[转]

    博客园 首页 新随笔 联系 订阅 管理 随笔 - 322  文章 - 0  评论 - 19 Linux命令-自动挂载文件/etc/fstab功能详解[转]     一./etc/fstab文件的作用 ...

  9. linux为什么用tar压缩,linux下tar压缩和解压命令用法详解

    linux下tar压缩和解压命令用法详解 2017-03-25 14:06 分享人:老牛 将/usr/local/test目录下所有文件仅打包,不压缩到 /usr/local/auto_bak/目下 ...

  10. linux mk创建文件,Linux运维知识之Linux mkkickstart建立安装的组态文件命令详解

    本文主要向大家介绍了Linux运维知识之Linux mkkickstart建立安装的组态文件命令详解,通过具体的内容向大家展现,希望对大家学习Linux运维知识有所帮助. 功能说明:建立安装的组态文件 ...

最新文章

  1. 数据科学中的强大思维
  2. 皮一皮:如何将紫薯变成绿薯?
  3. 在Delphi程序中应用IE浏览器控件
  4. mime设置 压缩html,MIME设置功能
  5. 无符号数的算术四则运算中的各类单词的识别_文本反垃圾在花椒直播中的应用概述...
  6. PMP-PMBOK-培训(3)Introduction to Project Process Groups and Initiating a Project
  7. 内置的常用协议实现模版
  8. 关卡 动画 蓝图 运行_UE4无缝过场动画
  9. Python二级笔记(6)
  10. mybatis(数据库增删改查)
  11. HashMap 底层
  12. mysql提现_MYSQL事务教程之Yii2.0商户提现功能
  13. Python小项目(学生成绩管理系统)7.排序、显示部分
  14. seo秘籍,seo秘籍-自学seo零基础知识入门优化教程
  15. 安卓软件开发需要学什么软件?Android开发最佳实践手册全网独一份,面试必问
  16. 针对中亚地区政府部门的攻击:通过Office漏洞传播新型Hawkball后门
  17. Web上的推箱子游戏Sokoban
  18. 汤小丹计算机操作系统慕课版课后题答案第五章:储存器管理
  19. 【LeGO-LOAM论文阅读(二)--特征提取(二)】
  20. Linux云服务器VPS一键数据盘和系统盘合并磁盘方法

热门文章

  1. 职称论文发表教育期刊《中小学教育》杂志简介及投稿须知
  2. 电脑端/手机端获取京东pt_key和pt_pin的几种方式
  3. 【转】Knowledge-Distillation 知识蒸馏论文集合
  4. 企业微信机器人python脚本执行报错-‘errcode‘: 40008, ‘errmsg‘: ‘Warning: wrong json format. invalid message type
  5. 玩转群晖NAS套件系列七:File Station的安装与使用保姆级教程!
  6. 物联网是什么意思?物联网概念是什么?
  7. Linux--DNS域名解析
  8. MIPI归纳---为什么阻抗为100欧姆
  9. 如何理解海森堡的「不确定性原理」?
  10. c语言向量乘法,运用C语言实现向量积