linux里面使用ftdi芯片模拟485并口解读
一、设备信息
cpu:AR9344
switch:QCA8337
ftdi:FT4232HL
内核版本:Linuxversion2.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)
makemenuconfig->kernelmodule->DeviceDrivers->USBsupport->USBSerialConvertersupport
将相关的基础usb.ko以及ftdi.ko添加进去之后,
基础的usb库
insmod /tmp/modules/usb/usbcore.ko
insmod /tmp/modules/usb/ehci-hcd.ko
insmod /tmp/modules/usb/usb-storage.ko
insmod /tmp/modules/usb/usbnet.ko
insmod /tmp/modules/usb/cdc_encap.ko
insmod /tmp/modules/usb/cdc_ether.ko
insmod /tmp/modules/usb/usbserial.ko
insmod /tmp/modules/usb/option.ko
ftdi ko
insmod /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芯片问题马哥linux,
跟踪FTDI的驱动,将FTDI驱动上面接收数据函数(ftdi_process_read)添加一些复印,将收到的数据,以及数据宽度复印下来,
need_flip = 0;
for (packet_offset = priv->rx_processed;
packet_offset 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 differences
are 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或者-1
if (length dev, "%s - bad packet length: %dn",
__func__, length+2);
length = 0;
}
if(0)
{
for(i=0;idev,"data[%d]=x ",i,data[i]);
}
dev_err(&port->dev,"length=%dn",length);
dev_err(&port->dev,"max_packet_size=%dn",priv->max_packet_size);
dev_err(&port->dev,"actual_length=%dn",urb->actual_length);
}
在源码上面查找max_packet_sizelinux系统日志,发觉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 %dn", 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 dev, "Endpoint %d MaxPacketSize %dn", 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 %dn", 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 %dn", 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的
这儿选上RIasRS485Enable就可以。
点击ProgramDevices按键会将你的配置生成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能收到数据了,而且自己发送的数据ftdi usb转串口驱动 linux,自己也会收到!
对比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里面打开早已被打开过并口的时侯ftdi usb转串口驱动 linux,会提示并口被占用。
linux多次打开并口(ttyUSB0),系统不会有任何提示,只能由程序员自己控制了!
***并口插口编程还是要当心一些,不能打开多次,要不然就出现我里面的乌龙风波了!