2019-08-02 11:12:40 wuwuhuizheyisheng 阅读数 646
  • 嵌入式Linux文件与串口编程

    本课程介绍Linux环境下shell编程,普通文件与设备文件的编程方法,串口介绍与应用编程。 学习条件: 1.C语言编程基础 2.嵌入式Linux开发基础

    7357 人正在学习 去看看 沈寒

1、下载socat源码,并安装

2、执行如下命令,创建两个虚拟串口

#socat  -d  -d  PTY  PTY

该命令的回复提示如下:

若是虚拟的串口一直有效,必须使socat一直运行。当前产生的虚拟串口为"/dev/pts/9"和"/dev/pts/10"。这两个串口可互相通信了。

3、测试

     使用"minicom  -D   /dev/pts/10    -b    9600",打开一个串口终端,在使用"minicom  -D   /dev/pts/9    -b    9600", 打开另一个串口终端。在minicom命令中输入指令,在另一个minicom终端就能接收到了。

2020-03-15 21:36:35 u013836909 阅读数 24
  • 嵌入式Linux文件与串口编程

    本课程介绍Linux环境下shell编程,普通文件与设备文件的编程方法,串口介绍与应用编程。 学习条件: 1.C语言编程基础 2.嵌入式Linux开发基础

    7357 人正在学习 去看看 沈寒

Linux USB基础之虚拟串口枚举流程(三)

1 USB检测与枚举过程

1.1 USB插拔检测

USB集线器的每个下游端口的D+和D-上,分别接了一个15K的下拉电阻到低。当集线器的端口悬空(即没有设备插入)时,输入端就被此两个下拉电阻拉到低电平。在USB设备端,在D+或D-上接入1.5K的上拉电阻到3.3V的电源。1.5K的上拉电阻接在D+或D-上,由设备的速度决定。对于全速设备和高速设备,上拉电阻接在D+上,而低速设备的上拉电阻则是接在D-上。可简单记为:速度快的,上拉电阻接正;速度慢的,上拉电阻接负的。

当设备插入到集线器时,接了上拉电阻的数据线的电压由1.5K的上拉电阻和15K的下拉电阻分压决定,结果大概为3V。在集线器的接收端来说,是一个高电平信号。集线器检测到此状态后,就报告给USB主控制器,此时就检测到设备的插入。USB高速设备先是识别成全速设备,然后在通过集线器和设备两者的确认,在切换到高速模式下。在高速模式下,是电流传输模式,此时需要将D+上的上拉电阻断开。

1.2 USB枚举过程

1) USB主机检测到USB设备插入后,会先对设备进行复位。
USB设备在总线复位后其地址为0,此时主机可通过地址0和该设备进行通信。USB主机往地址0的设备的端点0发送获取设备描述符的标准请求(这是控制传输的建立过程)。设备收到该请求后,会按主机请求的参数,在数据过程将设备描述符返回给主机。主机在成功获取到该数据包的设备描述符并且确认没有错误后,就会返回一个0长度的确认数据包(状态过程)给设备,从而进入到接下来的设置地址阶段。注意:第一次主机只会读取一个数据包的设备描述符,标准的设备描述符有18byte,有些USB设备的端点0大小不足18byte(但至少具有8byte),这种情况下,USB主机也只发送一次数据输入请求,多余的数据将不会再次请求。因此,如果当设备断电0大小不足18字节时,就需要注意该问题,也就是说在第一次获取设备描述符时,只需要返回一次数据即可,不需要再等主句继续获取剩余数据(如果还有),因为主机不会这么干的。房主急成功获取到设备描述符的前8byte之后,他就知道端点0的最大包长度了,因为端点0最大包长度刚好在设备描述符的第八字节处。

2) USB主机对设备又一次复位,开始设置地址阶段。
USB主机往地址为0的设备的端点0发出一个设置地址的请求(控制传输的建立过程),新的设备地址包含在建立过程的数据包中。具体的地址有USB主机负责管理,主机会分配一个唯一的地址给刚接入的设备。USB设备在收到这个建立过程之后,就直接进入到状态过程,因为此控制传输没有数据过程。设备等待主机请求状态返回(一个输入令牌包),收到输入令牌包后,设备就返回0长度的状态数据包。如果主机确认该状态包已经正确收到,就会发送应答包ACK给设备,设备在收到这个ACK之后,就要启用新的设备地址了。这样设备就分配到了一个唯一的设备地址,以后主机就通过他来访问该设备。

3) USB主机重新发送获取设备描述符的命令,读取完整设备描述符。
主机向新地址重新发送Get_Device_Descriptor命令,此次读取其设备描述符的全部字段,以了解该设备的总体信息,如VID,PID。

4) USB主机获取配置描述符。
配置描述符总共9byte。主机在获取到配置描述符之后,根据配置描述符中描述的配置集合总长度,获取配置集合。获取配置描述符和获取配置描述符集合的请求是差不多的,只是指定的长度不一样。

5) USB主机获取设备字符串,获得描述字符集。
描述字符集包括了产商、产品描述、型号等信息。

6) USB主机展示新设备信息。
此时主机将会弹出窗口,展示发现新设备的信息、产商、产品描述、型号等。

7) PC判断能够提供该类USB的驱动。
根据设备描述符和配置描述符,PC判断是否能够提供USB的Driver,一般能提供几大类的设备,如游戏操作杆、存储、打印机、扫描仪等。

8) USB主机发送配置命令,请求为设备选择一个配置
加载USB设备驱动以后,主机发送Set_Configuration(x)命令请求为该设备选择一个合适的配置。如果配置成功,USB设备进入“配置”状态,并可以和客户软件进行数据传输。

1.3 虚拟串口枚举流程

1.3.1 第一次获取设备描述符

struct usb_ctrlrequest {
__u8 bRequestType		= 0x80;// 这是一个主机发给设备(bit0~bit4)的一个标准(bit5~bit6)的请求命令,请求的结果是要求设备给Host返回(bit7 == 1)
__u8 bRequest			= 0x06;// 是一个GET_DESCRIPTOR,即获取描述符的请求
__le16 wValue		= 0x0100;// 高字节表示描述符类型,01表示设备,02表示配置;低字节表示索引。
__le16 wIndex			= 0x0000;
__le16 wLength		= 0x0040;
} __attribute__ ((packed));
struct usb_device_descriptor {
    __u8  bLength 			=  0x12; ///长度
    __u8  bDescriptorType		=  0x01; ///描述符类型

    __le16 bcdUSB			= 0x0200; //该位表示版本号,使用BCD码表示,即USB2.0版本
    __u8  bDeviceClass		= 0x02;///设备类信息	
    __u8  bDeviceSubClass	= 0x00;///设备子类型
    __u8  bDeviceProtocol		= 0x00;///协议	码,0表示没指定任何协议
    __u8  bMaxPacketSize0	= 0x40;///端点0最大传输大小	
    __le16 idVendor			= 0x0525;///厂商 ID
    __le16 idProduct			= 0xa4a7;///设备 ID
    __le16 bcdDevice			= 0x0414;/// 设备版本号
    __u8  iManufacturer		= 0x01; ///描述厂商信息的字符串描述符的索引值
    __u8  iProduct			= 0x02;///描述产品信息的字串描述符的索引值
    __u8  iSerialNumber		= 0x00;///描述设备序列号信息的字串描述符的索引值-03
    __u8  bNumConfigurations	= 0x01;///设备当前速度模式下支持的配置数量。有的设备可以在多个速度模式下操作,这里包括的只是当前速度模式下的配置数目,不是总的配置数目 
} __attribute__ ((packed));

1.3.2 第二次设备复位

host通过驱动数据线到复位状态(D+和D-全为低电平 ),并持续至少10ms。

1.3.3 分配设备地址

struct usb_ctrlrequest {
__u8 bRequestType		= 0x00;// 这是一个主机发给设备(bit0~bit4)的一个标准(bit5~bit6)的请求命令,请求的结果是要求设备给Host返回(bit7 == 1)
__u8 bRequest			= 0x05;// 是一个SET_ADDRESS,即配置设备地址描述符
__le16 wValue		= 0x0025;// 表示设备地址为0x25。
__le16 wIndex			= 0x0000;
__le16 wLength		= 0x0000;
} __attribute__ ((packed));

1.3.4 第二次获取设备描述符

这次要注意,这里以及使用新分配的设备地址3了,而不是默认地址0。同时后面也都会使用新分配的地址来通信。

1.3.5 第一次获取设备配置

struct usb_ctrlrequest {
__u8 bRequestType		= 0x80;// 这是一个主机发给设备(bit0~bit4)的一个标准(bit5~bit6)的请求命令,请求的结果是要求设备给Host返回(bit7 == 1)
__u8 bRequest			= 0x06;// 是一个GET_DESCRIPTOR,即获取描述符的请求
__le16 wValue		= 0x0002;// 高字节表示描述符类型,01表示设备,02表示配置。
__le16 wIndex			= 0x0000;
__le16 wLength		= 0x00FF;
} __attribute__ ((packed));
1.3.5.1 获取配置描述符
struct usb_config_descriptor {
	__u8  bLength      		= 0x09;    	//此描述符长度为9
	__u8  bDescriptorType    	= 0x02;    	// 2代表的配置描述符 
 
	__le16 wTotalLength      	= 0x4b;    	//此配置信息的总长为34字节(包括配置,接口,端点和设备类及厂商定义的描述符)
	__u8  bNumInterfaces     = 0x02;    	//表示有一个接口描述符
	__u8  bConfigurationValue	= 0x02;    	//在SetConfiguration()请求中用2作参数来选定此配置-0x01
	__u8  iConfiguration     	= 0x04;    	//描述此配置的字串描述表索引-0x00
	__u8  bmAttributes       = 0xC0;    	//D7: 保留(设为一)D6: 自给电源 D5: 远程唤醒 D4..0:保留(设为一)   表示这是一个由总线供电,并支持远程唤醒功能(可以睡眠节约电)
	__u8  bMaxPower          = 0x64; 	//在此配置下的总线电源耗费量。以 2mA 为一个单位 即2 * 50 = 100ms
} __attribute__ ((packed));
1.3.5.2 获取接口关联描述符
struct usb_interface_assoc_descriptor {
	__u8  bLength			= 0x08;
	__u8  bDescriptorType		= 0x0b;	//IAD描述符类型

	__u8  bFirstInterface		= 0x00;	//起始接口
	__u8  bInterfaceCount		= 0x02;	//接口数量
	__u8  bFunctionClass		= 0x02;	//类型代码
	__u8  bFunctionSubClass	= 0x02;	//子类型代码
	__u8  bFunctionProtocol	= 0x01;	//协议代码
	__u8  iFunction			= 0x07;	//描述字符串索引
} __attribute__ ((packed));
1.3.5.3 获取设备接口描述符
struct usb_interface_descriptor {
	__u8  bLength        	= 0x09;    //该描述符的字节数
	__u8  bDescriptorType  	= 0x04;    //描述符类型,4代表接口描述符
 
	__u8  bInterfaceNumber	= 0x00;     //接口号,当前配置支持的接口数组索引(从零开始)
	__u8  bAlternateSetting 	= 0x00;     //可选设置的索引值,这里无
	__u8  bNumEndpoints  	= 0x01;    //端点描述符数量,1个    
	__u8  bInterfaceClass    	= 0x02;    //接口所属的类值,由USB说明保留, 2代表CDC contrl
	__u8  bInterfaceSubClass 	= 0x02;    //子类码 这些值的定义视bInterfaceClass域而定
	__u8  bInterfaceProtocol   = 0x01;    //协议码:bInterfaceClass 和bInterfaceSubClass 域的值而定
	__u8  iInterface        	= 0x05;    //描述此接口的字串描述表的索引值
} __attribute__ ((packed));
1.3.5.4 Header Functional Descriptor
/* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
struct usb_cdc_header_desc {
	__u8	bLength				= 0x05;
	__u8	bDescriptorType		= 0x24;	/* bDescriptorType: CS_INTERFACE */
	__u8	bDescriptorSubType	= 0x00; 	/* bDescriptorSubtype: Header Func Desc */

	__le16	bcdCDC				= 0x0110; /* bcdCDC: spec release number */
} __attribute__ ((packed));
1.3.5.5 Abstract Control Management Descriptor
/* "Abstract Control Management Descriptor" from CDC spec  5.2.3.3 */
struct usb_cdc_acm_descriptor {
	__u8	bLength				= 0x04;
	__u8	bDescriptorType		= 0x24;
	__u8	bDescriptorSubType	= 0x02; /* bDescriptorSubtype: Abstract Control Management desc */

	__u8	bmCapabilities		0x02;
} __attribute__ ((packed));
1.3.5.6 Union Functional Descriptor
/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
struct usb_cdc_union_desc {
	__u8	bLength				= 0x05;
	__u8	bDescriptorType		= 0x24;
	__u8	bDescriptorSubType	= 0x06; /* bDescriptorSubtype: Union func desc */

	__u8	bMasterInterface0		= 0x00;
	__u8	bSlaveInterface0		= 0x01;
	/* ... and there could be other slave interfaces */
} __attribute__ ((packed));
1.3.5.7 Call Management Descriptor
/* "Call Management Descriptor" from CDC spec  5.2.3.2 */
struct usb_cdc_call_mgmt_descriptor {
	__u8	bLength				= 0x05;
	__u8	bDescriptorType		= 0x24; /* bDescriptorType: CS_INTERFACE */
	__u8	bDescriptorSubType	= 0x01; /* bDescriptorSubtype: Call Management Func Desc */

	__u8	bmCapabilities		= 0x00; /* bmCapabilities: D0+D1 */
	__u8	bDataInterface			= 0x01; /* bDataInterface: 1 *
} __attribute__ ((packed));
1.3.5.8 获取notify端点描述符
/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {   ///USB 端点描述符(每个USB设备最多有16个端点)
     __u8  bLength			= 0x07; ///描述符的字节长度
     __u8  bDescriptorType	= 0x05;///描述符类型,对于端点就是USB_DT_ENDPOINT
     __u8  bEndpointAddress	= 0x83;///bit0~3表示端点地址,bit8 表示方向,输入还是输出
     __u8  bmAttributes		= 0x03;///属性(bit0、bit1构成传输类型,00--控制,01--等时,10--批量,11--中断)
    __le16 wMaxPacketSize	= 0x000a;///端点一次可以处理的最大字节数
    __u8  bInterval			= 0x20;///希望主机轮询自己的时间间隔
 
     /* NOTE:  these two are _only_ in audio endpoints. */
     /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
     __u8  bRefresh;
     __u8  bSynchAddress;
} __attribute__ ((packed));
1.3.5.9 获取数据类接口描述符
struct usb_interface_descriptor {
	__u8  bLength        	= 0x09;    //该描述符的字节数
	__u8  bDescriptorType  	= 0x04;    //描述符类型,4代表接口描述符
 
	__u8  bInterfaceNumber	= 0x01;     //接口号,当前配置支持的接口数组索引(从零开始)
	__u8  bAlternateSetting 	= 0x00;     //可选设置的索引值,这里无
	__u8  bNumEndpoints  	= 0x02;    //端点描述符数量,2个    
	__u8  bInterfaceClass    	= 0x0A;    //接口所属的类值,由USB说明保留, 2代表CDC data
	__u8  bInterfaceSubClass 	= 0x00;    //子类码 这些值的定义视bInterfaceClass域而定
	__u8  bInterfaceProtocol   = 0x00;    //协议码:bInterfaceClass 和bInterfaceSubClass 域的值而定
	__u8  iInterface        	= 0x06;    //描述此接口的字串描述表的索引值
} __attribute__ ((packed));
1.3.5.10 获取OUT端点描述符
/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {   ///USB 端点描述符(每个USB设备最多有16个端点)
__u8  bLength			= 0x07; ///描述符的字节长度
    __u8  bDescriptorType	= 0x05;///描述符类型,对于端点就是USB_DT_ENDPOINT
    __u8  bEndpointAddress	= 0x02;///bit0~3表示端点地址,bit8 表示方向,输入还是输出
    __u8  bmAttributes		= 0x02;///属性(bit0、bit1构成传输类型,00--控制,01--等时,10--批量,11--中断)
__le16 wMaxPacketSize	= 0x40;///端点一次可以处理的最大字节数
    __u8  bInterval			= 0x00;///希望主机轮询自己的时间间隔
 
/* NOTE:  these two are _only_ in audio endpoints. */
    /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
    __u8  bRefresh;
    __u8  bSynchAddress;
} __attribute__ ((packed));
1.3.5.11 获取IN端点描述符
/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {   ///USB 端点描述符(每个USB设备最多有16个端点)
__u8  bLength			= 0x07; ///描述符的字节长度
    __u8  bDescriptorType	= 0x05;///描述符类型,对于端点就是USB_DT_ENDPOINT
    __u8  bEndpointAddress	= 0x81;///bit0~3表示端点地址,bit8 表示方向,输入还是输出
__u8  bmAttributes		= 0x02;///属性(bit0、bit1构成传输类型,00--控制,01--等时,10--批量,11--中断)
   __le16 wMaxPacketSize	= 0x40;///端点一次可以处理的最大字节数
    __u8  bInterval			= 0x00;///希望主机轮询自己的时间间隔
 
    /* NOTE:  these two are _only_ in audio endpoints. */
    /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
    __u8  bRefresh;
    __u8  bSynchAddress;
} __attribute__ ((packed));

1.3.6 获取设备字符串描述符

1.3.6.1 获取字符串描述符语言ID
struct usb_ctrlrequest {
__u8 bRequestType		= 0x80;// 这是一个主机发给设备(bit0~bit4)的一个标准(bit5~bit6)的请求命令,请求的结果是要求设备给Host返回(bit7 == 1)
__u8 bRequest			= 0x06;// 是一个GET_DESCRIPTOR,即获取描述符的请求
__le16 wValue		= 0x0300;// 高字节表示描述符类型,01表示设备,02表示配置,3表示字符串;低字节表示索引。
__le16 wIndex			= 0x0000;
__le16 wLength		= 0x00FF;
} __attribute__ ((packed));
/* USB_DT_STRING: String descriptor */
struct usb_string_descriptor {
	__u8  bLength		= 0x04;
	__u8  bDescriptorType	= 0x03;

	__le16 wData[1]		= 0x0409;/* UTF-16LE encoded 代表0x0409的语言编码 */
} __attribute__ ((packed));
1.3.6.2 获取字符串描述符(产品信息)
struct usb_ctrlrequest {
__u8 bRequestType		= 0x80;// 这是一个主机发给设备(bit0~bit4)的一个标准(bit5~bit6)的请求命令,请求的结果是要求设备给Host返回(bit7 == 1)
__u8 bRequest			= 0x06;// 是一个GET_DESCRIPTOR,即获取描述符的请求
__le16 wValue		= 0x0301;// 高字节表示描述符类型,01表示设备,02表示配置,3表示字符串;低字节表示索引。
__le16 wIndex			= 0x0000;
__le16 wLength		= 0x00FF;
} __attribute__ ((packed));
/* USB_DT_STRING: String descriptor */
struct usb_string_descriptor {
	__u8  bLength		= 0x04;
	__u8  bDescriptorType	= 0x03;

	__le16 wData[1]		= “Gadget Serial v2.4”;/
} __attribute__ ((packed));
1.3.6.3 获取字符串描述符(商家信息)

无。

1.3.7 第三次获取设备描述符

同上。

1.3.8 第二次获取设备配置

同上。

1.3.9 选中设备配置

struct usb_ctrlrequest {
__u8 bRequestType		= 0x00;// 这是一个主机发给设备(bit0~bit4)的一个标准(bit5~bit6)的请求命令,请求的结果是要求设备给Host返回(bit7 == 1)
__u8 bRequest			= 0x09;// 是一个SET_CONFIGURATION,即配置设备。
__le16 wValue		= 0x0001;// 表示选中的配置Index
__le16 wIndex			= 0x0000;
__le16 wLength		= 0x0000;
} __attribute__ ((packed));

1.3.10 获取Line_Coding

struct usb_ctrlrequest {
__u8 bRequestType		= 0xA1;// 这是一个主机发给设备(bit0~bit4)的一个标准(bit5~bit6)的请求命令,请求的结果是要求设备给Host返回(bit7 == 1)
__u8 bRequest			= 0x21;
__le16 wValue		= 0x0000;
__le16 wIndex			= 0x0000;
__le16 wLength		= 0x0007;
} __attribute__ ((packed));
/* Line Coding Structure from CDC spec 6.2.13 */
struct usb_cdc_line_coding {
	__le32	dwDTERate		= 0x00;
	__u8	bCharFormat		= 0x00;
#define USB_CDC_1_STOP_BITS			0
#define USB_CDC_1_5_STOP_BITS			1
#define USB_CDC_2_STOP_BITS			2

	__u8	bParityType		= 0x00;
#define USB_CDC_NO_PARITY				0
#define USB_CDC_ODD_PARITY			1
#define USB_CDC_EVEN_PARITY			2
#define USB_CDC_MARK_PARITY			3
#define USB_CDC_SPACE_PARITY			4

	__u8	bDataBits			= 0x00;
} __attribute__ ((packed));

1.3.11 配置Line_Coding

struct usb_ctrlrequest {
__u8 bRequestType		= 0x21;// 这是一个主机发给设备(bit0~bit4)的一个标准(bit5~bit6)的请求命令,请求的结果是要求设备给Host返回(bit7 == 1)
__u8 bRequest			= 0x22;
__le16 wValue		= 0x0000;
__le16 wIndex			= 0x0000;
__le16 wLength		= 0x0000;
} __attribute__ ((packed));
2018-03-21 09:46:05 WMX843230304WMX 阅读数 995
  • 嵌入式Linux文件与串口编程

    本课程介绍Linux环境下shell编程,普通文件与设备文件的编程方法,串口介绍与应用编程。 学习条件: 1.C语言编程基础 2.嵌入式Linux开发基础

    7357 人正在学习 去看看 沈寒

linux虚拟串口(用于调试程序)

1 将下列Python代码保存成VitrualCom.py:

#! /usr/bin/env python

#coding=utf-8



import pty
import os
import select



def mkpty():
    # open virtual port
    master1, slave = pty.openpty()
    slaveName1 = os.ttyname(slave)
    master2, slave = pty.openpty()
    slaveName2 = os.ttyname(slave)
    print '\nslave device names: ', slaveName1, slaveName2
    return master1, master2


if __name__ == "__main__":

    master1, master2 = mkpty()
    while True:
        rl, wl, el = select.select([master1,master2], [], [], 1)
        for master in rl:
            data = os.read(master, 128)
            print "read %d data." % len(data)
            if master==master1:
                os.write(master2, data)
            else:
                os.write(master1, data)

2 在终端下面输入:

python VirtualCom.py &

3 便会显示:

slave device names:  /dev/pts/1 /dev/pts/2

这样/dev/pts/1与/dev/pts/2串口便相连接在一起了。

然后就可以利用这两个设备名在本机上进行虚拟串口之类的调试,使用完后用ps查看这个python进程的pid号,然后kill掉即可。

出处 http://blog.sina.com.cn/s/blog_6cb543ef0100x90j.html

2013-07-18 08:11:25 autumn20080101 阅读数 1219
  • 嵌入式Linux文件与串口编程

    本课程介绍Linux环境下shell编程,普通文件与设备文件的编程方法,串口介绍与应用编程。 学习条件: 1.C语言编程基础 2.嵌入式Linux开发基础

    7357 人正在学习 去看看 沈寒

 

Linux虚拟串口 及 Qt串口通信

 1337人阅读 评论(0) 收藏 举报
Linux虚拟串口 及 Qt串口通信

Linux下的虚拟终端

由于手上没有可以测试的串口设备,因此发了点时间找了一个Linux下的虚拟串口工具:http://fayaa.com/code/view/8500/

这个工具打开了两个伪终端,然后读两个口子的数据,如果是从1号口来的,就往2号口写入数据,从2号口来的就写到1号口。

经过我的修改后变成了这个样子:

#! /usr/bin/env python

#coding=utf-8

import pty
import os
import select

def mkpty():
    #
    master1, slave = pty.openpty()
    slaveName1 = os.ttyname(slave)
    master2, slave = pty.openpty()
    slaveName2 = os.ttyname(slave)
    print '/nslave device names: ', slaveName1, slaveName2
    return master1, master2


if __name__ == "__main__":

    master1, master2 = mkpty()
    while True:        
        rl, wl, el = select.select([master1,master2], [], [], 1)
        for master in rl:
            data = os.read(master, 128)
            if master==master1:
                print "read %d data:" % len(data)
                print data
                #os.write(master2, data)
            else:
                print "to write %d data:" % len(data)
                print data.strip()
                os.write(master1, data.strip())
改变后 我们让1号口为读入口(串口设备读入数据的口子),2号口为写出口(串口向外面写数据)

将其保存为com.py

#python com.py

slave device names:  /dev/pts/1 /dev/pts/2
意思是pts/1为1号口 pts/2为2号口

另建一个终端 #cd /dev/pts/

#echo 456 > 2

就会向2号口写数据,如果我们没有其他程序读串口的数据的话,那么就会出现4行数:

to write 5 data:
456
read 3 data:
456
那么我们只要用程序读/dev/pts/1就可以模拟串口通信了

============================================================

Qt下的串口通讯

Qt没有自带串口模块,只有第三方库

http://wenku.baidu.com/view/55849f4ffe4733687e21aa99.html

这篇文章介绍了简单的Qt串口通信

学着他的例子也做了一个程序,核心代码:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    com = new QextSerialPort("/dev/pts/1", QextSerialPort::Polling);
    com->open(QextSerialPort::ReadWrite);
    com->setBaudRate(BAUD9600);
    com->setDataBits(DATA_8);
    com->setParity(PAR_NONE);
    com->setStopBits(STOP_1);
    com->setFlowControl(FLOW_OFF);
    com->setTimeout(10);

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(readCOM()));
    timer->start(20);

}

void MainWindow::readCOM()
{
    if (com->bytesAvailable() > 1)
        ui->showText->insertPlainText(com->readAll());
}

void MainWindow::on_btnSend_clicked()
{
    com->write(ui->edit->text().toAscii().data());
}

运行结果:

Qt向串口写数据

收到数据:

 

串口向Qt写数据(下面那个终端控制)

 

==========================================================

注意:1号口和2号口的方向问题很难分清楚,暂时这样理解了没必要深究

           windows下的虚拟串口工具为VSPM,是Telnet管理的,建议先研究这个

2015-10-29 15:54:00 weixin_34279579 阅读数 80
  • 嵌入式Linux文件与串口编程

    本课程介绍Linux环境下shell编程,普通文件与设备文件的编程方法,串口介绍与应用编程。 学习条件: 1.C语言编程基础 2.嵌入式Linux开发基础

    7357 人正在学习 去看看 沈寒

Linux 虚拟串口及 Qt 串口通信实例

2011-06-22 17:49 佚名 互联网 字号:T | T

一键收藏,随时查看,分享好友!

Linux 虚拟串口及 Qt 串口通信实例是本文所要介绍的内容,在实现过程中,打开了两个伪终端,然后读两个口子的数据,如果是从1号口来的,就往2号口写入数据,从2号口来的就写到1号口。

AD:【线下活动】三大新锐HTML 5企业汇聚51CTO—大话移动前端技术

Linux下的虚拟终端

由于手上没有可以测试的串口设备,因此发了点时间找了一个Linux下的虚拟串口工具:http://fayaa.com/code/view/8500/ ,这个工具打开了两个伪终端,然后读两个口子的数据,如果是从1号口来的,就往2号口写入数据,从2号口来的就写到1号口。

经过我的修改后变成了这个样子:

  1. #! /usr/bin/env python 
  2.  
  3. #coding=utf-8 
  4.  
  5. import pty 
  6. import os 
  7. import select 
  8.  
  9. def mkpty(): 
  10.     # 
  11.     master1, slave = pty.openpty() 
  12.     slaveName1 = os.ttyname(slave) 
  13.     master2, slave = pty.openpty() 
  14.     slaveName2 = os.ttyname(slave) 
  15.     print '\nslave device names: ', slaveName1, slaveName2 
  16.     return master1, master2 
  17.  
  18.  
  19. if __name__ == "__main__": 
  20.  
  21.     master1, master2 = mkpty() 
  22.     while True:         
  23.         rl, wl, el = select.select([master1,master2], [], [], 1) 
  24.         for master in rl: 
  25.             data = os.read(master, 128) 
  26.             if master==master1: 
  27.                 print "read %d data:" % len(data) 
  28.                 print data 
  29.                 #os.write(master2, data) 
  30.             else: 
  31.                 print "to write %d data:" % len(data) 
  32.                 print data.strip() 
  33.                 os.write(master1, data.strip())

改变后 我们让1号口为读入口(串口设备读入数据的口子),2号口为写出口(串口向外面写数据),将其保存为com.py

  1. #python com.py 
  2. slave device names:  /dev/pts/1 /dev/pts/2

意思是pts/1为1号口 pts/2为2号口

另建一个终端 #cd /dev/pts/

  1. #echo 456 > 2

就会向2号口写数据,如果我们没有其他程序读串口的数据的话,那么就会出现4行数:

  1. to write 5 data: 
  2. 456 
  3. read 3 data: 
  4. 456

那么我们只要用程序读/dev/pts/1就可以模拟串口通信了

Qt下的串口通讯

Qt没有自带串口模块,只有第三方库 http://wenku.baidu.com/view/55849f4ffe4733687e21aa99.html,这篇文章介绍了简单的Qt串口通信

学着他的例子也做了一个程序,核心代码:

  1. MainWindow::MainWindow(QWidget *parent) : 
  2.     QMainWindow(parent), 
  3.     ui(new Ui::MainWindow) 
  4.     ui->setupUi(this); 
  5.     com = new QextSerialPort("/dev/pts/1", QextSerialPort::Polling); 
  6.     com->open(QextSerialPort::ReadWrite); 
  7.     com->setBaudRate(BAUD9600); 
  8.     com->setDataBits(DATA_8); 
  9.     com->setParity(PAR_NONE); 
  10.     com->setStopBits(STOP_1); 
  11.     com->setFlowControl(FLOW_OFF); 
  12.     com->setTimeout(10); 
  13.     QTimer *timer = new QTimer(this); 
  14.     connect(timer, SIGNAL(timeout()), this, SLOT(readCOM())); 
  15.     timer->start(20); 
  16. void MainWindow::readCOM() 
  17.     if (com->bytesAvailable() > 1) 
  18.         ui->showText->insertPlainText(com->readAll()); 
  19. void MainWindow::on_btnSend_clicked() 
  20.     com->write(ui->edit->text().toAscii().data()); 
  21. }

运行结果:Qt串口写数据

收到数据:

Linux 虚拟串口及 Qt 串口通信实例

串口Qt写数据(下面那个终端控制)

Linux 虚拟串口及 Qt 串口通信实例

注意:1号口和2号口的方向问题很难分清楚,暂时这样理解了没必要深究 windows下的虚拟串口工具为VSPM,是Telnet管理的,建议先研究这个。

小结:Linux 虚拟串口 Qt 串口通信实例的内容介绍完了,希望本文对你 有所帮助

没有更多推荐了,返回首页