当前位置:文档之家› TCP通信程序设计

TCP通信程序设计

TCP通信程序设计
TCP通信程序设计

TCP/IP通信程序设计

1、实验目的

初步掌握C 语言TCP/IP 通信程序的设计。

2、实验环境

1、Windows 2000/NT/XP操作系统。

2、TCP/IP协议。

3、编程工具:Microsoft Visual C++ 2005。

3、相关知识

3.1 TCP/IP协议族

表1 TCP/IP协议族

1、面向连接。端到端的TCP连接会关注连接的状态,而网络的中间路由器只关心IP分组的转发。

2、可靠数据传递。TCP使用顺序号、采用直接应答方式,并在必要时通过重传来保证发自源端的数据能成功地被传递到目的地。

3、流量控制。接收方向发送方发送一个接收窗口值,告诉发送方接收方能够处理多少数据。在收到接收方发来的应答前,TCP发送方最多只能发送等于该窗口值的数据量。

4、拥塞控制。用于防止TCP发送方发送的信息量超过网络中链路或路由器的最大处理能力。

流量控制和拥塞控制结合起来,使得TCP主机能迅速而公平地调整其发送速率,

以达到与网络及接收方的处理能力相匹配。

3.2 端口与Socket

在进程通信的意义上,网络通信的最终地址不仅网络层提供的IP地址,还应包括描述进程的协议端口(protocol port)。若没有端口,传输层就无法知道数据应当交付给应用层的哪个进程。因此,端口标示了应用层的进程。

TCP和UDP分别提供了216个不同的端口值。端口分为两类:

1、周知端口(well-know port),其值为0-1023,由ICANN负责分配(见RFC 1700)。其中TCP和UDP均规定小于256的端口作为保留端口。

2、临时端口,也称本地分配。进程需要访问传输服务时,向本地操作系统提出动态申请,操作系统返回一个本地唯一的端口号,进程通过合适的系统调用将自己和相应的端口号联系起来。

Socket由4BSD UNIX首先提出,目的是解决网络通信问题。Socket的英文原义是“插座”,Socket与电话交换机的插座非常类似,进程通信前,双方各创建一个端点,每一个Socket有一个本地唯一的Socket号,由操作系统分配。Socket与IP 地址、IP地址的关系如图1所示。

IP地址端口号

Socket

图1 Socket与IP地址、端口号

由于TCP面向连接的特性,如果多台主机或一台主机的多个进程连接同一台服务器,则必须创建多个连接,如图2所示。

202.113.121.168

图2 与同一台主机建立三个连接

TCP/IP标准指定了一个概念层接口,包含了一系列过程和函数。标准建议了每个过程和函数所需要的参数及其所执行操作的语义,但没有进一步指定数据表示的细节。详细的接口通常由操作系统来定义,只要完成TCP/IP标准中的功能,可以有不同的细节选择。这样,不同的操作系统的应用程序编程接口是各不相同的。例如,广泛使用的Berkeley Software Distribution UNIX的Socket接口、Windows的接口定义Winsock、System V的接口定义TLI接口等。

3.3 Socket的操作方式

Socket有两种主要的操作方式:面向连接和面向无连接。面向连接的BSD UNIX Socket的工作流程如图3所示,而面向无连接的BSD UNIX Socket的工作流程如图4所示。

到底用哪种模式是由应用程序的需要决定的。如果要求可靠性,用面向连接的操作就会好一些。对于面向无连接的C/S模式,Socket不需要连接目的地的Socket,它只是简单地投出数据报。无连接的操作简单高效,但数据的安全性不佳。

服务器

图3 面向连接的C/S

时序图

服务器

图4 面向无连接的C/S 时序图

4、TCP通信程序设计

4.1 编程要点

由于TCP协议要求服务器和客户端建立连接,所以服务器需要通过Listen方法监听客户端的请求。当客户端发出连接请求后,服务器在ConnectionRequest事件中调用Accept方法接受请求,从而与客户端建立连接。

只有双方建立连接后,才能进行数据的收发。如果在通信过程中任一方断开连接,则通信过程终止。

4.2 客户端程序

客户端程序遵循以下步骤:

1)建立客户端Socket连接。

2)得到Socket读和写的流。

3)操作流。

4)关闭流。

5)关闭Socket。

客户端的源程序代码如下:

// Module Name: Client.c

//

// Description:

// This sample is the echo client. It connects to the TCP server,

// sends data, and reads data back from the server.

//

// Compile:

// cl -o Client Client.c ws2_32.lib

//

// Command Line Options:

// client [-p:x] [-s:IP] [-n:x] [-o]

// -p:x Remote port to send to

// -s:IP Server's IP address or hostname

// -n:x Number of times to send message

// -o Send messages only; don't receive

//

#include

#include

#include

#pragma comment(lib,"ws2_32")

#define DEFAULT_COUNT 20

#define DEFAULT_PORT 5150

#define DEFAULT_BUFFER 2048

#define DEFAULT_MESSAGE "This is a test of the emergency \ broadcasting system"

char szServer[128], // Server to connect to

szMessage[1024]; // Message to send to sever

intiPort = DEFAULT_PORT; // Port on server to connect to

DWORD dwCount = DEFAULT_COUNT; // Number of times to send message BOOL bSendOnly = FALSE; // Send data only; don't receive

//

// Function: usage:

//

// Description:

// Print usage information and exit

//

void usage()

{

printf("usage: client [-p:x] [-s:IP] [-n:x] [-o]\n\n");

printf(" -p:x Remote port to send to\n");

printf(" -s:IP Server's IP address or hostname\n");

printf(" -n:x Number of times to send message\n");

printf(" -o Send messages only; don't receive\n"); ExitProcess(1);

}

//

// Function: ValidateArgs

//

// Description:

// Parse the command line arguments, and set some global flags

// to indicate what actions to perform

//

void ValidateArgs(intargc, char **argv)

{

int i;

for(i = 1; i

{

if ((argv[i][0] == '-') || (argv[i][0] == '/'))

{

switch (tolower(argv[i][1]))

{

case 'p': // Remote port

if (strlen(argv[i]) > 3)

iPort = atoi(&argv[i][3]);

break;

case 's': // Server

if (strlen(argv[i]) > 3)

strcpy(szServer, &argv[i][3]);

break;

case 'n': // Number of times to send message

if (strlen(argv[i]) > 3)

dwCount = atol(&argv[i][3]);

break;

case 'o': // Only send message; don't receive bSendOnly = TRUE;

break;

default:

usage();

break;

}

}

}

}

//

// Function: main

//

// Description:

// Main thread of execution. Initialize Winsock, parse the

// command line arguments, create a socket, connect to the

// server, and then send and receive data.

//

int main(intargc, char **argv)

{

WSADATA wsd;

SOCKET sClient;

char szBuffer[DEFAULT_BUFFER];

int ret,

i;

structsockaddr_in server;

structhostent *host = NULL;

// Parse the command line and load Winsock

//

ValidateArgs(argc, argv);

if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)

{

printf("Failed to load Winsock library!\n");

return 1;

}

strcpy(szMessage, DEFAULT_MESSAGE);

//

// Create the socket, and attempt to connect to the server //

sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (sClient == INVALID_SOCKET)

{

printf("socket() failed: %d\n", WSAGetLastError());

return 1;

}

server.sin_family = AF_INET;

server.sin_port = htons(iPort);

server.sin_addr.s_addr = inet_addr(szServer);

//

// If the supplied server address wasn't in the form

// "https://www.doczj.com/doc/5616902268.html,c.ddd" it's a hostname, so try to resolve it

//

if (server.sin_addr.s_addr == INADDR_NONE)

{

host = gethostbyname(szServer);

if (host == NULL)

{

printf("Unable to resolve server: %s\n", szServer);

return 1;

}

CopyMemory(&server.sin_addr, host->h_addr_list[0],

host->h_length);

}

if (connect(sClient, (structsockaddr *)&server,

sizeof(server)) == SOCKET_ERROR)

{

printf("connect() failed: %d\n", WSAGetLastError());

return 1;

}

// Send and receive data

//

for(i = 0; i

{

ret = send(sClient, szMessage, strlen(szMessage), 0);

if (ret == 0)

break;

else if (ret == SOCKET_ERROR)

{

printf("send() failed: %d\n", WSAGetLastError());

break;

}

printf("Send %d bytes\n", ret);

if (!bSendOnly)

{

ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);

if (ret == 0) // Graceful close

break;

else if (ret == SOCKET_ERROR)

{

printf("recv() failed: %d\n", WSAGetLastError());

break;

}

szBuffer[ret] = '\0';

printf("RECV [%d bytes]: '%s'\n", ret, szBuffer);

}

}

closesocket(sClient);

WSACleanup();

return 0;

}

下面解释与TCP套接字编程相关的内容。

1、加载Winsock库

WSAStartup(MAKEWORD(2,2), &wsd);

其中,第一个参数是Winsock的版本2.2,第二个参数接受返回的库版本信息。

2、创建套接字

socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

该调用要接收三个参数:af、type、protocol。参数af指定通信发生的区域,UNIX系统支持的地址族有:AF_UNIX、AF_INET、AF_NS等,而DOS、WINDOWS 中仅支持AF_INET,它是网际网区域。因此,地址族与协议族相同。参数type 描述要建立的套接字的类型。参数protocol说明该套接字使用的特定协议,如果调用者不希望特别指定使用的协议,则置为0,使用默认的连接模式。根据这三个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号。因此,socket()系统调用实际上指定了相关五元组中的“协议”这一元。

3、建立套接字连接

connect()用于建立连接。无连接的套接字进程也可以调用connect(),但这时在进程之间没有实际的报文交换,调用将从本地操作系统直接返回。这样做的优点是程序员不必为每一数据指定目的地址,而且如果收到的一个数据报,其目的端口未与任何套接字建立“连接”,便能判断该端口不可操作。

connect()的调用格式如下:

connect(SOCKET s, conststructsockaddr FAR * name, intnamelen);

参数s是欲建立连接的本地套接字描述符。参数name指出说明对方套接字地址结构的指针。对方套接字地址长度由namelen说明。

如果没有错误发生,connect()返回0。否则返回SOCKET_ERROR。在面向连接的协议中,该调用导致本地系统和外部系统之间连接实际建立。

由于地址族总被包含在套接字地址结构的前两个字节中,并通过socket()调用与某个协议族相关。因此bind()和connect()无须协议作为参数。

4、数据传输- send()与recv()

当一个连接建立以后,就可以传输数据了。常用的系统调用有send()和recv()。

send()调用用于在参数s指定的已连接的数据报或流套接字上发送输出数据,格式如下:

send(SOCKET s, const char FAR *buf, intlen, int flags);

参数s为已连接的本地套接字描述符。buf指向存有发送数据的缓冲区的指针,其长度由len指定。flags 指定传输控制方式,如是否发送带外数据等。如果没有错误发生,send()返回总共发送的字节数。否则它返回SOCKET_ERROR。

recv()调用用于在参数s指定的已连接的数据报或流套接字上接收输入数据,格式如下:

recv(SOCKET s, char FAR *buf, intlen, int flags);

参数s 为已连接的套接字描述符。buf指向接收输入数据缓冲区的指针,其长度由len指定。flags 指定传输控制方式,如是否接收带外数据等。如果没有错误发生,recv()返回总共接收的字节数。如果连接被关闭,返回0。否则它返回SOCKET_ERROR。

5、关闭套接字- closesocket()

closesocket()关闭套接字s,并释放分配给该套接字的资源;如果s涉及一个打开的TCP连接,则该连接被释放。closesocket()的调用格式如下:

closesocket(SOCKET s);

参数s待关闭的套接字描述符。如果没有错误发生,closesocket()返回0。否则返回值SOCKET_ERROR。

4.3 服务器端程序

服务器端程序遵循以下基本步骤:

1)建立一个服务器Socket并开始监听。

2)使用accept()取得新的连接。

3)建立输入和输出流。

4)在已有的协议上产生会话。

5)关闭客户端流和Socket。

6)关闭服务器Socket。

服务器的处理过程是并发的,它为每个客户请求分配一个线程,而不是来一个处理一个。所以看起来它在同时处理多个请求。

服务器端的源程序代码如下:

// Module Name: Server.c

//

// Description:

// This example illustrates a simple TCP server that accepts // incoming client connections. Once a client connection is

// established, a thread is spawned to read data from the

// client and echo it back (if the echo option is not

// disabled).

//

// Compile:

// cl -o Server Server.c ws2_32.lib

//

// Command line options:

// server [-p:x] [-i:IP] [-o]

// -p:x Port number to listen on

// -i:str Interface to listen on

// -o Receive only, don't echo the data back //

#include

#include

#include

#pragma comment(lib,"ws2_32")

#define DEFAULT_PORT 5150

#define DEFAULT_BUFFER 4096

intiPort = DEFAULT_PORT; // Port to listen for clients on BOOL bInterface = FALSE, // Listen on the specified interface bRecvOnly = FALSE; // Receive data only; don't echo back char szAddress[128]; // Interface to listen for clients on //

// Function: usage

//

// Description:

// Print usage information and exit

//

void usage()

{

printf("usage: server [-p:x] [-i:IP] [-o]\n\n");

printf(" -p:x Port number to listen on\n");

printf(" -i:str Interface to listen on\n");

printf(" -o Don't echo the data back\n\n"); ExitProcess(1);

}

//

// Function: ValidateArgs

//

// Description:

// Parse the command line arguments, and set some global flags // to indicate what actions to perform

//

void ValidateArgs(intargc, char **argv)

{

int i;

for(i = 1; i

{

if ((argv[i][0] == '-') || (argv[i][0] == '/'))

{

switch (tolower(argv[i][1]))

{

case 'p':

iPort = atoi(&argv[i][3]);

break;

case 'i':

bInterface = TRUE;

if (strlen(argv[i]) > 3)

strcpy(szAddress, &argv[i][3]);

break;

case 'o':

bRecvOnly = TRUE;

break;

default:

usage();

break;

}

}

}

}

//

// Function: ClientThread

//

// Description:

// This function is called as a thread, and it handles a given

// client connection. The parameter passed in is the socket // handle returned from an accept() call. This function reads // data from the client and writes it back.

//

DWORD WINAPI ClientThread(LPVOID lpParam)

{

SOCKET sock=(SOCKET)lpParam;

char szBuff[DEFAULT_BUFFER];

int ret,

nLeft,

idx;

while(1)

{

// Perform a blocking recv() call

//

ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);

if (ret == 0) // Graceful close

break;

else if (ret == SOCKET_ERROR)

{

printf("recv() failed: %d\n", WSAGetLastError());

break;

}

szBuff[ret] = '\0';

printf("RECV: '%s'\n", szBuff);

//

// If we selected to echo the data back, do it

//

if (!bRecvOnly)

{

nLeft = ret;

idx = 0;

//

// Make sure we write all the data

//

while(nLeft> 0)

{

ret = send(sock, &szBuff[idx], nLeft, 0);

if (ret == 0)

break;

else if (ret == SOCKET_ERROR)

{

printf("send() failed: %d\n",

WSAGetLastError());

break;

}

nLeft -= ret;

idx += ret;

}

}

}

return 0;

}

//

// Function: main

//

// Description:

// Main thread of execution. Initialize Winsock, parse the

// command line arguments, create the listening socket, bind // to the local address, and wait for client connections.

//

int main(intargc, char **argv)

{

WSADATA wsd;

SOCKET sListen,

sClient;

intiAddrSize;

HANDLE hThread;

DWORD dwThreadId;

structsockaddr_in local,

client;

ValidateArgs(argc, argv);

if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)

{

printf("Failed to load Winsock!\n");

return 1;

}

// Create our listening socket

//

sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

if (sListen == SOCKET_ERROR)

{

printf("socket() failed: %d\n", WSAGetLastError());

return 1;

}

// Select the local interface and bind to it

//

if (bInterface)

{

local.sin_addr.s_addr = inet_addr(szAddress);

if (local.sin_addr.s_addr == INADDR_NONE)

usage();

}

else

local.sin_addr.s_addr = htonl(INADDR_ANY);

local.sin_family = AF_INET;

local.sin_port = htons(iPort);

if (bind(sListen, (structsockaddr *)&local,

sizeof(local)) == SOCKET_ERROR)

{

printf("bind() failed: %d\n", WSAGetLastError());

return 1;

}

listen(sListen, 8);

//

// In a continous loop, wait for incoming clients. Once one // is detected, create a thread and pass the handle off to it.

//

while (1)

{

iAddrSize = sizeof(client);

sClient = accept(sListen, (structsockaddr *)&client,

&iAddrSize);

if (sClient == INVALID_SOCKET)

{

printf("accept() failed: %d\n", WSAGetLastError());

break;

}

printf("Accepted client: %s:%d\n",

inet_ntoa(client.sin_addr), ntohs(client.sin_port));

hThread = CreateThread(NULL, 0, ClientThread,

(LPVOID)sClient, 0, &dwThreadId);

if (hThread == NULL)

{

printf("CreateThread() failed: %d\n", GetLastError());

break;

}

CloseHandle(hThread);

}

closesocket(sListen);

WSACleanup();

return 0;

}

与客户端程序相比,服务器端在以下几个方面存在差异。

1、指定本地地址──bind()

当一个套接字用socket()创建后,存在一个名字空间(地址族),但它没有被命名。bind()将套接字地址(包括本地主机地址和本地端口地址)与所创建的套接字号联系起来,即将名字赋予套接字,以指定本地半相关。其调用格式如下:

bind(SOCKET s, conststructsockaddr FAR * name, intnamelen);

参数s是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。参数name 是赋给套接字s的本地地址(名字),其长度可变,结构随通信域的不同而不同。namelen表明了name的长度。

如果没有错误发生,bind()返回0。否则返回值SOCKET_ERROR。

地址在建立套接字通信过程中起着重要作用,作为一个网络应用程序设计者对套接字地址结构必须有明确认识。例如,UNIX BSD有一组描述套接字地址的数据结构,其中使用TCP/IP协议的地址结构为:

structsockaddr_in{

shortsin_family; /*AF_INET*/

u_shortsin_port; /*16位端口号,网络字节顺序*/

structin_addrsin_addr; /*32位IP地址,网络字节顺序*/

char sin_zero[8]; /*保留*/

}

2、监听连接- listen()

此调用用于面向连接服务器,表明它愿意接收连接。listen()需在accept()之前调用,其调用格式如下:

listen(SOCKET s, int backlog);

参数s标识一个本地已建立、尚未连接的套接字号,服务器愿意从它上面接收请求。backlog表示请求连接队列的最大长度,用于限制排队请求的个数,目前允许的最大值为5。如果没有错误发生,listen()返回0。否则它返回SOCKET_ERROR。

listen()在执行调用过程中可为没有调用过bind()的套接字s完成所必须的连接,并建立长度为backlog的请求连接队列。

调用listen()是服务器接收一个连接请求的四个步骤中的第三步。它在调用socket()分配一个流套接字,且调用bind()给s赋于一个名字之后调用,而且一定要在accept()之前调用。

3、accept()调用

accept(SOCKET s, structsockaddr FAR* addr, int FAR* addrlen);

accept()用于面向连接服务。参数addr和addrlen存放客户方的地址信息。调用前,参数addr指向一个初始值为空的地址结构,而addrlen的初始值为0;调用accept()后,服务器等待从编号为s的套接字上接受客户连接请求,而连接请求是由客户方的connect()调用发出的。当有连接请求到达时,accept()调用将请求连接队列上的第一个客户方套接字地址及长度放入addr和addrlen,并创建一个与s有相同特性的新套接字号。新的套接字可用于处理服务器并发请求。

参数s为本地套接字描述符,在用做accept()调用的参数前应该先调用过listen()。addr指向客户方套接字地址结构的指针,用来接收连接实体的地址。addr 的确切格式由套接字创建时建立的地址族决定。addrlen为客户方套接字地址的长度(字节数)。如果没有错误发生,accept()返回一个SOCKET类型的值,表示接收到的套接字的描述符。否则返回值INVALID_SOCKET。

5、实验任务

1、两人一组,分别编写网络程序Server和Client,以实现最简单的TCP通信。

说明:如果使用提供的Server.c和Client.c,则在文件菜单中读入程序后,可直接“Build”成执行文件运行。当询问“This build command requires an active project workspace … ?”时,单击“确定”按钮即可。

2、在VC++ 6.0集成环境下单步调试程序,参考《Winsock基础》,弄清楚程序中相关函数的用法、每个数据结构的含义。

6、提交实验报告

1.画出你所写程序的框图。

2.在报告中说明你所修改后程序的任何独特之处。

3.实验日期:第18周星期五(2010-7-2)晚上7:00 – 10:00。

实验地点:南3楼网络中心机房。

4.实验报告(含框图、修改说明及程序源代码)通过电子文档形式提交:以“学

号-姓名-TCP通信”为文件名,发送至:hzjun2004@https://www.doczj.com/doc/5616902268.html,。截至时间:

2010-7-9 17: 00整。

用C#一步步写串口通信分析解析

我们来看具体的实现步骤。 公司要求实现以下几个功能: 1):实现两台计算机之前的串口通信,以16进制形式和字符串两种形式传送和接收。 2):根据需要设置串口通信的必要参数。 3):定时发送数据。 4):保存串口设置。 看着好像挺复杂,其实都是纸老虎,一戳就破,前提是你敢去戳。我尽量讲的详细一些,争取说到每个知识点。 在编写程序前,需要将你要测试的COM口短接,就是收发信息都在本地计算机,短接的方式是将COM口的2、3号针接起来。COM 口各针的具体作用,度娘是这么说的:COM口。记住2、3针连接一定要连接牢固,我就是因为接触不良,导致本身就不通,白白花掉了一大半天时间调试代码。 下面给出主要的操作界面,如下:

顺便,我将所有控件对应的代码名字也附上了,相信对初学者来说,再看下面的代码会轻松很多。控件名字命名的方法是“控件名+作用”的形式,例如“打开串口”的开关按钮,其名字是btnSwitch (btn就是button的简写了)。我认为这种命名控件的方式比较好,建议大家使用,如果你有好的命名方式,希望你能告诉我! 下面我们将各个功能按照从主到次的顺序逐个实现。(我分块给出代码实现,详细代码见链接:《C#串口通信工具》)

一、获取计算机的COM口总个数,将它们列为控件cbSerial的候选项,并将第一个设为cbSerial的默认选项。 这部分是在窗体加载时完成的。请看代码: (很多信息代码的注释里讲的很清楚,我就不赘述了。) [csharp]view plaincopyprint? 1.//检查是否含有串口 2. string[] str = SerialPort.GetPortNames(); 3. if (str == null) 4. { 5. MessageBox.Show("本机没有串口!", "Error"); 6. return; 7. } 8. 9. //添加串口项目 10. foreach (string s in System.IO.Ports.SerialPort.GetPortNames()) 11. {//获取有多少个COM口 12. cbSerial.Items.Add(s); 13. } 14. 15. //串口设置默认选择项

MODBUS通讯协议及编程

通讯协议及编程 通讯协议分为协议和协议,我公司的多种仪表都采用通讯协议,如:2000智能电力监测仪、巡检表、数显表、光柱数显表等。下面就协议简要介绍如下: 一、通讯协议 (一)、通讯传送方式: 通讯传送分为独立的信息头,和发送的编码数据。以下的通讯传送方式定义也与通讯规约相兼容: 初始结构= ≥4字节的时间 地址码 = 1 字节 功能码 = 1 字节 数据区 = N 字节 错误校检 = 16位码 结束结构= ≥4字节的时间 地址码:地址码为通讯传送的第一个字节。这个字节表明由用户设定地址码的从机将接收由主机发送来的信息。并且每个从机都有具有唯一的地址码,并且响应回送均以各自的地址码开始。主机发送的地址码表明将发送到的从机地址,而从机发送的地址码表明回送的从机地址。 功能码:通讯传送的第二个字节。通讯规约定义功能号为1到127。本仪表只利用其中的一部分功能码。作为主机请求发送,通过功能码告诉从机执行什么动作。作为从机响应,从机发送的功能码与从主机发送来的功能码一样,并表明从机已响应主机进行操作。如果从机发送的功能码的最高位为1(比如功能码大与此同时127),则表明从机没有响应操作或发送出错。 数据区:数据区是根据不同的功能码而不同。数据区可以是实际数值、设置点、主机发送给从机或从机发送给主机的地址。 码:二字节的错误检测码。 (二)、通讯规约: 当通讯命令发送至仪器时,符合相应地址码的设备接通讯命令,并除去地址码,读取信息,如果没有出错,则执行相应的任务;然后把执行结果返送给发送者。返送的信息

中包括地址码、执行动作的功能码、执行动作后结果的数据以及错误校验码。如果出错就不发送任何信息。 1.信息帧结构 地址码:地址码是信息帧的第一字节(8位),从0到255。这个字节表明由用户设置地址的从机将接收由主机发送来的信息。每个从机都必须有唯一的地址码,并且只有符合地址码的从机才能响应回送。当从机回送信息时,相当的地址码表明该信息来自于何处。 功能码:主机发送的功能码告诉从机执行什么任务。表1-1列出的功能码都有具体的含义及操作。 数据区:数据区包含需要从机执行什么动作或由从机采集的返送信息。这些信息可以是数值、参考地址等等。例如,功能码告诉从机读取寄存器的值,则数据区必需包含要读取寄存器的起始地址及读取长度。对于不同的从机,地址和数据信息都不相同。 错误校验码:主机或从机可用校验码进行判别接收信息是否出错。有时,由于电子噪声或其它一些干扰,信息在传输过程中会发生细微的变化,错误校验码保证了主机或从机对在传送过程中出错的信息不起作用。这样增加了系统的安全和效率。错误校验采用16校验方法。 注:信息帧的格式都基本相同:地址码、功能码、数据区和错误校验码。 2.错误校验 冗余循环码()包含2个字节,即16位二进制。码由发送设备计算,放置于发送信息的尾部。接收信息的设备再重新计算接收到信息的码,比较计算得到的码是否与接收到的相符,如果两者不相符,则表明出错。 码的计算方法是,先预置16位寄存器全为1。再逐步把每8位数据信息进行处理。在进行码计算时只用8位数据位,起始位及停止位,如有奇偶校验位的话也包括奇偶校验位,都不参与码计算。 在计算码时,8位数据与寄存器的数据相异或,得到的结果向低位移一字节,用0 填补最高位。再检查最低位,如果最低位为1,把寄存器的内容与预置数相异或,如果最低位为0,不进行异或运算。 这个过程一直重复8次。第8次移位后,下一个8位再与现在寄存器的内容相相异或,这个过程与以上一样重复8次。当所有的数据信息处理完后,最后寄存器的内容即为码值。码中的数据发送、接收时低字节在前。 计算码的步骤为:

C语言串口通信助手代码

该程序全部由C写成没有C++ 更没用MFC 完全是自娱自乐给需要的人一个参考 #include "stdafx.h" #include #include "resource.h" #include "MainDlg.h" #include #include #include HANDLE hComm;//用于获取串口打开函数的返回值(句柄或错误值)OVERLAPPED m_ov; COMSTAT comstat; DWORD m_dwCommEvents;

TCHAR cRecs[200],cSends[100]; //接收字符串发送字符串 char j=0,*cCom; //接收用统计数据大小变量端口选择 BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog); HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand); HANDLE_MSG(hWnd,WM_CLOSE, Main_OnClose); } return FALSE; } /*系统初始化函数*/ BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { HWND hwndCombo1=GetDlgItem(hwnd,IDC_COMBO1); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM1")); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM2"));

S7-200通讯的编程步骤---自由口通讯

PLC 和变频器 频器博客原创(https://www.doczj.com/doc/5616902268.html,)
S7通讯的编程步骤-----自由口通讯 S7-200 通讯的编程步骤---自由口通讯
S7-200 自由口通讯是基于 RS485 通讯基础的半双工通讯, 因此, 发送和接收指令不能同时执行。 自由口通讯使用 SMB30(口 0)和 SMB130(口 1)来定义通讯口 的工作模式。SMB30/SMB130 各位的定义如下:
图 1:通讯口工作模式寄存器
使用自有口通讯,SM30.0 和 SM30.1(SM130.0 和 SM130.1=0) 必须分别为 1 和 0。 发送指令(XMT) 一、 发送指令(XMT) 使用 XMT 发送指令可以把存于缓冲区中的数据, 一次发送一个或
1

PLC 和变频器 频器博客原创(https://www.doczj.com/doc/5616902268.html,)
多个字节的数据,最多为 255 个。发送完最后一个字符后还可以连接 到一个发送完中断(端口 0 为 9,端口 1 位 26,见下表) 。
图 2:中断事件表
2

PLC 和变频器 频器博客原创(https://www.doczj.com/doc/5616902268.html,)
发送缓冲区的格式如下表所示:
图 3:发送缓冲区的格式 说明: T+0:发送信息的字节个数需要提前定义。 T+1~T+255:要发送的数据字节
和 XMT 有关的寄存器:SMB4 的 SM4.5 和 SM4.6。SM4.5=1 时,口 0 发送完毕;SM4.6=1 时,口 1 发送完毕。 由以上可以看出,有两种方法可以检测端口 0 或 1 的数据发送 状态:一种是利用中断,一种是利用寄存器 SMB4 的第 5 位(口 0) 和第 6 位(口 1) 。 接收指令(RCV) 二、 接收指令(RCV) 使用接收指令(RCV)可以从端口 0 或 1 接收一个或多个字节的 数据(最多 255 个) ,并存于数据缓冲区。接收完最后一个字节后可 以连接到一个接收完中断(口 0 是 23,口 1 是 24,见图 2 所示) 。 接收缓冲区的格式如下表所示:
3

C#串口通讯编程

C#中串口通信编程收藏 本文将介绍如何在.NET平台下使用C#创建串口通信程序,.NET 2.0提供了串口通信的功能,其命名 空间是System.IO.Ports。这个新的框架不但可以访问计算机上的串口,还可以和串口设备进行通信。 我们将使用标准的RS 232 C 在PC间通信。它工作在全双工模式下,而且我们不打算使用任何的握手 或流控制器,而是使用无modem连接。 命名空间 System.IO.Ports命名空间中最重用的是SerialPort 类。 创建SerialPort 对象 通过创建SerialPort 对象,我们可以在程序中控制串口通信的全过程。 我们将要用到的SerialPort 类的方法: ReadLine():从输入缓冲区读一新行的值,如果没有,会返回NULL WriteLine(string):写入输出缓冲 Open():打开一个新的串口连接 Close():关闭 Code: //create a Serial Port object SerialPort sp = new SerialPort (); 默认情况下,DataBits 值是8,StopBits 是1,通信端口是COM1。这些都可以在下面的属性中重新设置 : BaudRate:串口的波特率 StopBits:每个字节的停止位数量 ReadTimeout:当读操作没有完成时的停止时间。单位,毫秒 还有不少其它公共属性,自己查阅MSDN。 串口的硬件知识

在数据传输的时候,每个字节的数据通过单个的电缆线传输。包包括开始位,数据,结束为。一旦 开始位传出,后面就会传数据,可能是5,6,7或8位,就看你的设定了。发送和接收必须设定同样 的波特率和数据位数。 无猫模式 没有Modem模式的电缆只是简单地交叉传送和接收线。同样DTR & DSR, 和RTS & CTS 也需要交叉。 RS232针图 这里,我们三条线。互连2和3(一段的2pin连接3pin),连接两端的5pin。 [示例程序] 主程序 如果想使用默认属性,按“Save Status”按钮,如果想改变属性按“Property”。它会弹出下图:

1C#中串口通信编程教程

C#中串口通信编程教程 本文将介绍如何在.NET平台下使用C#创建串口通信程序,.NET2.0提供了串口通信的功能,其命名空间是System.IO.Ports。这个新的框架不但可以访问计算机上的串口,还可以和串口设备进行通信。我们将使用标准的RS232C在PC间通信。它工作在全双工模式下,而且我们不打算使用任何的握手或流控制器,而是使用无modem连接。 命名空间 System.IO.Ports命名空间中最重用的是SerialPort类。 创建SerialPort对象 通过创建SerialPort对象,我们可以在程序中控制串口通信的全过程。 我们将要用到的SerialPort类的方法: ReadLine():从输入缓冲区读一新行的值,如果没有,会返回NULL WriteLine(string):写入输出缓冲 Open():打开一个新的串口连接 Close():关闭 Code: //create a Serial Port object SerialPort sp=new SerialPort(); 默认情况下,DataBits值是8,StopBits是1,通信端口是COM1。这些都可以在下面的属性中重新设置 : BaudRate:串口的波特率 StopBits:每个字节的停止位数量 ReadTimeout:当读操作没有完成时的停止时间。单位,毫秒 还有不少其它公共属性,自己查阅MSDN。 串口的硬件知识 在数据传输的时候,每个字节的数据通过单个的电缆线传输。包包括开始位,数据,结束为。一旦开始位传出,后面就会传数据,可能是5,6,7或8位,就看你的设定了。发送和接收必须设定同样的波特率和数据位数。

VC与c51串口通讯程序

跟着步骤学习 1.建立项目:打开VC++6.0,建立一个基于对话框的MFC应用程序SCommTest 2.在项目中插入MSComm控件选择Project菜单下Add To Project子菜单中的 Components and Controls…选项,在弹出的对话框中双击Registered ActiveX Controls项(稍等一会,这个过程较慢),则所有注册过的ActiveX控件出现在列表框中。选择Microsoft Communications Control, version 6.0,,单击Insert按钮将它插入到我们的Project中来,接受缺省的选项。(如果你在控件列表中看不到Microsoft Communications Control, version 6.0,那可能是你在安装VC6时没有把ActiveX一项选上,重新安装VC6,选上ActiveX就可以了), 这时在ClassView视窗中就可以看到CMSComm类了,(注意:此类在ClassWizard中看不到,重构clw 文件也一样),并且在控件工具栏Controls中出现了电话图标(如图1所示),现在要做的是用鼠标 将此图标拖到对话框中,程序运行后,这个图标是看不到的。 3.利用ClassWizard定义CMSComm类控制对象打开ClassWizard ->Member Viariables选项卡,选择CSCommTestDlg类,为IDC_MSCOMM1 添加控制变量:m_ctrlComm,这时你可以看一看,在对话框头文件中自动 加入了//{{AFX_INCLUDES() #include "mscomm.h" //}}AFX_INCLUDES (这时运行程序,如果有错,那就再从头开始)。 4.在对话框中添加控件向主对话框中添加两个编辑框,一个用于接收显 示数据ID为IDC_EDIT_RXDATA,另一个用于输入发送数据,ID为 IDC_EDIT_TXDATA,再添加一个按钮,功能是按一次就把发送编辑框中的内 容发送一次,将其ID设为IDC_BUTTON_MANUALSEND。别忘记了将接收编辑 框的Properties->Styles中把Miltiline和Vertical Scroll属性选上,发送编辑框若你想输入多行文字,也可选上Miltiline。 再打开ClassWizard->Member Viariables选项卡,选择CSCommTestDlg类,为IDC_EDIT_RXDATA 添加CString变量m_strRXData,为IDC_EDIT_TXDATA添加CString变量m_strTXData。说明: m_strRXData和m_strTXData分别用来放入接收和发送的字符数据。 5.添加串口事件消息处理函数OnComm()打开ClassWizard->Message Maps,选择类CSCommTestDlg,选择IDC_MSCOMM1,双击消息OnComm,将弹出的对话框中将函数名改为OnComm,(好记而已)OK。 这个函数是用来处理串口消息事件的,如每当串口接收到数据,就会产生一个串口接收数据缓冲区中有字符的消息事件,我们刚才添加的函数就会执行,我们在OnComm()函数加入相应的处理代码就能实现自已想要的功能了。请你在函数中加入如下代码: void CSCommTestDlg::OnComm() { // TODO: Add your control notification handler code here VARIANT variant_inp; COleSafeArray safearray_inp; LONG len,k; BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed. CString strtemp; if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符 { ////////以下你可以根据自己的通信协议加入处理代码 variant_inp=m_ctrlComm.GetInput(); //读缓冲区 safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量 len=safearray_inp.GetOneDimSize(); //得到有效数据长度 for(k=0;k

通用串口通讯程序设计

通用串口通讯程序设计 作者:和光同尘版本:V1.0 序 做硬件开发近20载,花了近十年做基础开发,对硬件开发略知一二,接触的做国防/工业大项目的人才我就是和他们沟通中获取了很多思想;人生已过而立之年,不惑解疑,总想写点什么。从一线研发(做了4年),开发(3年),硬件开发主管(12年),算起来人生从不到弱冠之年(中专毕业)开始接触MCS51、AVR等8位处理器到ARM v7核、CoretxM 核的32位处理器,CPLD/FPGA、PLC…………啰嗦了!! 最近因为工作原因需要把一些自己感悟的记录下来,希望传递给入门的有心沉下心做基础健壮扎实的初学者。

正文 做嵌入式硬件开发一般都会用到通讯数据交互,这就涉及通讯协议/规约的设计。本文从基础的串口(RS232、RS485等)为模型进行讲解。 说道串口通讯,就是编写串口程序,简单的就是1个字节的发送,1个字节的接收,但这不能满足绝大多数实际工作业务需求,实际需要一串字节数据的交互,A发送,B接收……Z 接收;Z机……B机收到根据情况需要回复(ACK)A机,这个过程就叫交互双向通讯(本文不讨论多主机、1主机相对复杂通讯机制。)。这种通讯就需要提前设计好通讯的规约(大家约定好暗号——每个字节代表什么意思)。 接下来编写通信程序(发送/接收),如何写出一个健壮高效串口程序?是否健壮高效其实很大一部分取决于通讯接收程序的架构。 通讯程序编写依据是——通讯规约,通讯帧的设计。 ●I类通用型: ||帧头段|===|数据段|===|校验码|===|帧尾段|| ●II类时隙通讯: ||开始时隙T(T1T2T3T4T5T6)|=|功能码|=|数据段|=|校验码|=|结束时隙T(T1T2T3)|注意:时隙只是纯粹的前后两帧数据的间隔时间,这期间坚决不能有数据产生。 1.1I类通用型 ◆帧头段 帧头段用于鉴别一串字节流中1帧数据起始位置,这个帧头段必须具有足够的特殊标识(易分辨)。 什么样的特殊标识可作为帧头? 根据个人经验: ①具有监测通讯波特率功能特点:0B01010101(55H)、0B10101010(AAH)或0B00000000(00H)、0B11111111(FFH); ②利用ASCII码如MODBUS ASCII规约以冒号‘:’(3AH)作为帧头。也可以采用ASCII ‘U’(55H)、‘@’(40H)等等 只要保证帧头字节数据内容,在所有通讯数据字节流中,除帧头有意为之而出现,那就是帧头。建议最好有两个字节及以上,这样数据出现与帧头一致的概率更加小,才做到独一无二的特殊性。

串行端口程序设计

串行端口程序设计 一、实验目的 了解在linux环境下串行程序设计的基本方法。 掌握终端的主要属性及设置方法,熟悉终端I /O函数的使用。 学习使用多线程来完成串口的收发处理。 二、实验内容 读懂程序源代码,学习终端I /O函数的使用方法,学习将多线程编程应用到串口的接收和发送程序设计中。 三、预备知识 有C语言基础。 掌握在Linux下常用编辑器的使用。 掌握Makefile 的编写和使用。 掌握Linux下的程序编译与交叉编译过程 四、实验设备及工具 硬件:UP-CUP S2410 经典平台、PC机Pentium 500以上, 硬盘10G以上。 软件:PC机操作系统REDHAT LINUX 9.0+MINICOM+ARM-LINUX开发环境 五、实验原理 异步串行I /O方式是将传输数据的每个字符一位接一位(例如先低位、后高位)地传送。数据的各不同位可以分时使用同一传输通道,因此串行I/O可以减少信号连线,最少用一对线即可进行。接收方对于同一根线上一连串的数字信号,首先要分割成位,再按位组成字符。

为了恢复发送的信息,双方必须协调工作。在微型计算机中大量使用异步串行I/O方式,双方使用各自的时钟信号,而且允许时钟频率有一定误差,因此实现较容易。但是由于每个字符都要独立确定起始和结束(即每个字符都要重新同步),字符和字符间还可能有长度不定的空闲时间,因此效率较低。 图2.3.1串行通信字符格式 图2.3.1给出异步串行通信中一个字符的传送格式。开始前,线路处于空闲状态,送出连续“1”。传送开始时首先发一个“0”作为起始位,然后出现在通信线上的是字符的二进制编码数据。每个字符的数据位长可以约定为5位、6位、7位或8位,一般采用ASCII编码。后面是奇偶校验位,根据约定,用奇偶校验位将所传字符中为“1”的位数凑成奇数个或偶数个。也可以约定不要奇偶校验,这样就取消奇偶校验位。最后是表示停止位的“1”信号,这个停止位可以约定持续1位、1.5位或2位的时间宽度。至此一个字符传送完毕,线路又进入空闲,持续为“1”。经过一段随机的时间后,下一个字符开始传送才又发出起始位。每一个数据位的宽度等于传送波特率的倒数。微机异步串行通信中,常用的波特率为50,95,110,150,300,600,1200,2400,4800,9600等。 接收方按约定的格式接收数据,并进行检查,可以查出以下三种错误: ●奇偶错:在约定奇偶检查的情况下,接收到的字符奇偶状态和约定不符。 ●帧格式错:一个字符从起始位到停止位的总位数不对。 ●溢出错:若先接收的字符尚未被微机读取,后面的字符又传送过来,则产生溢出错。 每一种错误都会给出相应的出错信息,提示用户处理。一般串口调试都使用空的MODEM 连接电缆,其连接方式如下:

C语言串口通信-源代码

#include #include #include #include #define COM232 0x2f8 #define COMINT 0x0b #define MaxBufLen 500 #define Port8259 0x20 #define EofInt 0x20 static int comportaddr; static char intvectnum; static unsigned char maskb; static unsigned char Buffer[MaxBufLen]; static int CharsInBuf,CircIn,CircOut; static void (interrupt far *OldAsyncInt)(); static void interrupt far AsyncInt(void); void Init_COM(int ComPortAddr, unsigned char IntVectNum, int Baud, unsigned char Data, unsigned char Stop, unsigned char Parity) { unsigned char High,Low; int f; comportaddr=ComPortAddr; intvectnum=IntVectNum; CharsInBuf=0;CircIn=0;CircOut=0; f=(Baud/100); f=1152/f; High=f/256; Low=f-High*256; outp(ComPortAddr+3,0x80); outp(ComPortAddr,Low); outp(ComPortAddr+1,High); Data=(Data-5)|((Stop-1)*4); if(Parity==2) Data=Data|0x18; else if(Parity==1) Data=Data|0x8; outp(ComPortAddr+3,Data);

通信程序设计实习报告

通信工程程序设计实习报告 经过为期十天的通信实习,我认识到了很多程序设计方面的东西,也学到了很多专业方面的知识。 从一开始上课时,我初步了解到了这几天的程序设计实习到底该做些什么,要做到什么样的程度,有些什么样的要求和内容。在老师所提供的几个选题中我们小组选择了现阶段使用的较多的语音查询系统“10086”,来进行我们的设计。 第一天实习,是比较手忙脚乱的,也是毫无头绪的,都是没头苍蝇乱撞。鉴于第一次在机房里头旁边还有个电话机,我还是有点小激动的,首先便把东进语音卡小玩了一下。平常编程时,编的都是一些比较小的程序,只是些简单的算法。在编语音卡程序时,我发现平常我们所学的东西好像实用性非常差,我的实践能力的缺乏。花了一天的时间,我就了解了一下语音卡使用的一部份内容,着重练习了MFC控件的使用。主要学习了如何添加按钮框,怎样实现点击按钮之后的内容的显示,以及按钮之间的内容的传递等。这一天的程序设计实习让我非常的担忧,我感觉我会的东西实在太少了,实在是不足以驾驭这样的实习,不过见大家都是这样,心情也没有那么差。 之后,我们便做了语音卡的放音,一开始我们先自己试着做,但是实在是由于对这个东西的了解太少了,搞了半天也实在是不知道从何处下手。然后我就试着从老师所给的语音卡实习指导书和DBDK编程参考手册中寻找解决方法,遇到不知道的问题或者不明白的东西就百度或者询问老师,开始我们找到了BOOL WINAPI StartPlayFile ( WORD wChnlNo, LPSTR FileName, DWORD StartPos )这个函数,但是对于函数的参数不了解,介于当时没有讲List,所以对于这样一个函数还是不知道从何下手的,上网百度后也没有找到比较好的讲解,正当我们手足无措的时候,老师给我们发过来一个示例,我们试运行了,直观地了解到了这个程序的功能。不过在运行时并没有直接的听到放音的效果,这下子又有点懵了,老师运行的时候明明是好的,怎么到了我们这儿就不行了呢?试了几次依然是什么声音都没有,我们便又开始寻找原因,对照函数看函数中的各个参数的意义,在看到通道号的时候,我们看了会儿才知道原来是通道号错了,是我们的通道号和老师所使用的机子不一样导致的,之后我们修改了,便运行正常。当时感觉就

Java串口通信编程指南

Java串口通信编程指南

1. 概述 在java中,利用Java Communication包可以操作串口,但官方的包在3.0之后就只支持Linux和Solaris平台了,Windows平台的只支持到98年出的2.0版本,不过在XP下还能使用。另外,也可以用开源的Rxtx实现串口通信,这里仅以Java Communication包,在Windows 平台实现串口通信进行说明。 2. 前期准备 2.1. 下载Java Communication包 ?下载地址如下:https://www.doczj.com/doc/5616902268.html,/Jolt/javacomm20-win32.zip。 ?如果是非Windows平台,请到Sun网站选择其他版本下载。地址如下: https://www.doczj.com/doc/5616902268.html,/download/products.xml?id=43208d3d 2.2. 配置 ?解压缩javacomm20-win32.zip ?把win32com.dll拷贝到{JAVA_HOME}\jre\bin ?把comm.jar拷贝到{JAVA_HOME}\jre\lib\ext ?把https://www.doczj.com/doc/5616902268.html,m.properties拷贝到{JAVA_HOME}\jre\lib ?set CLASSPATH={JAVA_HOME}\jre \lib\ext \comm.jar;%classpath%

3. 实现过程 主要步骤包括: ?获得串口标识 ?打开串口 ?设置串行端口通讯参数 ?获取输入(出)流 ?进行读写操作 3.1. 获得串口标识 指定串口的端口号,生成串口的标识类的实例。 https://www.doczj.com/doc/5616902268.html,mPortIdentifier是通讯端口管理器,控制访问到通讯端口的中心类。一个应用程序首先使用CommPortIdentifier中的方法,通过相关的驱动去获取那些通讯端口是可用的并且选择一个端口便于开始。它包括如下功能: a. 通过驱动决定通讯端口是可用的。 b. 打开通讯端口为了I/O操作。 c. 决定端口的拥有者。 d. 解析端口拥有者的争夺。 e. 管理事件显示在端口拥有者的中的状态改变。 示例代码如下: 代码: 3.2. 打开串口 示例代码如下: 代码:

串行异步通信程序设计

******************* 实践教学 ******************* 兰州理工大学 计算机与通信学院 2014年秋季学期 《通信系统综合训练》课程设计 题目:串行异步通信程序设计 专业班级:通信工程(1)班 姓名:李银环 学号:11250134 指导教师:王惠琴 成绩:

摘要 在Windows环境下实现通信的方法主要有利用MSComm控件和直接用Windows API编程,软件采用Microsoft Visual C++ 6.0,利用MSComm控件编程相对来说更简单一些,而直接使用Windows API编程更灵活一些。 本次课程设计分析了串行异步通信的基本原理,在VC++6.0的环境下利用MSComm控件实现了两个PC机的COM口间的数据发送和接收。本文通过对COM1口进行初始化编程,以及对建立的工程中的每个对话框和按钮分别进行编程和设置,成功的实现了利用PC机的两个COM口进行异步通信,并能根据设置调整异步传行通信参数。 关键词:VC++6.0;MSComm控件;串行异步通信

目录 前言 (1) 第1章串行异步通信基本原理 (2) 1.1 串行通信协议 (2) 1.2 串口通信的基本概念 (3) 1.3 RS-232简介 (4) 第2章 VC++软件简介 (5) 2.1 VC++6.0简介 (5) 2.2 Microsoft Communications Control 控件 (6) 第3章串行异步通信系统分析 (7) 第4章串行异步通信系统设计 (8) 4.1建立工程 (8) 4.2 在程序中添加MSComm控件 (9) 4.3 初始化串口:设置MSComm控件的属性 (11) 4.4 发送数据 (12) 第5章串行异步通信程序调试 (18) 5.1 计算机串口设置 (18) 5.2 程序运行结果 (18) 参考文献 (20) 附录 (21) 致谢 (29)

串口通信

一. 实验目的及实验环境 <1>实验环境 Java eclipse下 <2>实验目的 了解串行通信的背景知识后,通过三线制制作一条串口通信线(PC-PC),并编程实现两台PC间通过RS-232C通信。要求两台PC机能进行实时的字符通信,并了解工业自动化控制中的基本通信方式。 二.实验内容 1、检查PC是否具有串行通信接口,并按其针脚类准备一条串口通信线缆。 2、串口包的安装,下载javacomm20-win32.zip并解压,将win32com.dll复制到\bin目录下;将comm.jar复制到\lib;把https://www.doczj.com/doc/5616902268.html,m.properties 也同样拷贝到\lib目录下,再将上面提到的文件放到JRE相应的目录下就可以了。 三、方案设计 1、将实验所需RS-232缆线准备好,并将JAVA串口包复制到相应地目录下。 2、查找有关串口通信的书籍以及在网上查找相应地串口通信代码。 3、用JAVA编程软件JCreator编写代码。 四.测试数据及运行结果 图一主界面

图二发送消息 图三接收消息 五.总结 1、实验过程中遇到的问题及解决办法; 串口包的安装配置比较难完成,最后在网上看各种博客和论坛,才将问题解决。还有一些代码问题,最后找同学调试好了。 2、对设计及调试过程的心得体会。 通过本次串口实验,我对串口通信的知识了解的更透彻,这是在刚开始对串口通信知识不了解的情况下就编程而造成许多错误之后才得到的结果。在网上查找资料的时候也接触到了不少其他的编程语言例如VB,delphi,C#等,这也让我对这些从没有学过的语言有所了解,我想这些知识对以后的实验工作都有帮助。我也进一步发现了自己动手能力和自学能力都得到很多的进步,同时也对串口的发送与接收信息有了进一步的了解。 六.附录:源代码

VB串口通信程序代码

vb中怎样用mscomm控件实现串口通信 本问分两部分均来自https://www.doczj.com/doc/5616902268.html, 第一部分jessezappy(晶晶) ================================================================================== If MSComm1.PortOpen Then MSComm1.PortOpen = False https://www.doczj.com/doc/5616902268.html,mPort = 1 '假定是用COM1口 ' 设定传输速率等,可依照您的需求更改 MSComm1.Settings = "9600,N,8,1" MSComm1.PortOpen = True '---------初始化Modem------------- MSComm1.Output = "ATZ" MSComm1.Output = "AT&F" MSComm1.Output = "ATE0" MSComm1.Output = "ATM1" MSComm1.Output = "ATQ0" MSComm1.Output = "ATV0" '--------------------------拨号------------- MSComm1.Output ="ATDT163" '拨163 '---------------------------接通后 MSComm1.Output ="SDFJDKSJLKFA" '发送字符串 '--------------------- Private Sub MSComm1_OnComm() '用串口事件捕捉数据.. If MSComm1.InBufferCount Then ' 通讯埠中假如有资料的话, 则读取进来 InStringB = InStringB & MSComm1.Input ' 如果资料中有Chr(13) 和Chr(10) 的话, 则显示出来 If InStr(InStringB, vbCrLf) Then instring = instring & InStringB AddText Text3, InStringB, False InStringB = "" End If End If END SUB

基于单片机的双机通信程序设计

前言 单片机的通信接口是各台仪表之间或仪表与计算机之间进行信息交换和传输的联络装置。主要有五种类型,串行通信接口、并行通信接口、USB接口、现场总线接口以及以太网接口。 串行通讯是单片机的一个重要应用。本设计就是利用两块单片机来完成一个系统,实现单片机之间的串行通讯。 随着计算机的不断普及,在我们的周围可能会同时出现多台微型计算机,而且这些计算机的牌号,后型号不同,而且有的格式不兼容。于是利用单片机串行口实现不同计算机之间的相互通信,以达到信息或程序的共享是非常有用的。从智能家用电器到工业上的控制系统都采用了上位机与下位机基于串行通信的主从工作方式,这样就充分利用了微机分析处理能力强、速度快的特点及下位机(单片机)面向控制、使用灵活方便的优势。利用多机通讯构成的分布式系统逐渐普及。本实验就点对点的双机通信进行训练。学习串口的工作方式,初始化编程,和单片机与单片机点对点通信的编程方法以及硬件电路的设计方法。

1.总体设计方案 1.1 串口通信的设计原理 复位电路复位电路 单片机单片机 电源电路电源电路 时钟电路时钟电路 按键输入1位LED数码管 显示电路 图1 串口通信的设计原理框图 本次设计用于两片89S51,PC机的串行口采用的是标准的RS232接口,单片机的串行口电平是FTL电平,而TTL电平特性与RS232的电气特性不匹配,因此为了使单片机的串行口能与RS232接口通信,必须将串行口的输入/输出电平进行转换。通常用MAX232芯片来完成电平转换。单片机的发送方的数据由串行口TXD段输出,经过电平转换芯片MAX232将TTL电平转换为RS232电平输出,经过传输线将信号传送到接收端。接收方也使用MAX232芯片进行电平转换后,信号到达接收方串行口的接收端。接收方接收后,在数码管上显示接收的信息,实现串口通讯数据的发送和接收,该系统可采用max232进行串口通讯数据传送。可用LED显示发送的相应据。 1.2 数据传输方案比较与选折 在串行通信中,数据是在两个站之间传送的。按照数据传送方向,串行通信可采用三种方案。 方案一:单工制式 单工制式是指甲乙双方通信只能单向传送数据。 发送器A 接收器B 图2 单工制式

C#中串口通信编程

本文将介绍如何在.NET平台下使用C#创建串口通信程序,.NET 2.0提供了串口通信的功能,其命名 空间是System.IO.Ports。这个新的框架不但可以访问计算机上的串口,还可以和串口设备进行通信。 我们将使用标准的RS 232 C 在PC间通信。它工作在全双工模式下,而且我们不打算使用任何的握手或流控制器,而是使用无modem连接。 命名空间 System.IO.Ports命名空间中最重用的是SerialPort 类。 创建SerialPort 对象 通过创建SerialPort 对象,我们可以在程序中控制串口通信的全过程。 我们将要用到的SerialPort 类的方法: ReadLine():从输入缓冲区读一新行的值,如果没有,会返回NULL WriteLine(string):写入输出缓冲 Open():打开一个新的串口连接 Close():关闭 Code: //create a Serial Port object SerialPort sp = new SerialPort (); 默认情况下,DataBits 值是8,StopBits 是1,通信端口是COM1。这些都可以在下面的属性中重新设置: BaudRate:串口的波特率 StopBits:每个字节的停止位数量 ReadTimeout:当读操作没有完成时的停止时间。单位,毫秒 还有不少其它公共属性,自己查阅MSDN。

串口的硬件知识 在数据传输的时候,每个字节的数据通过单个的电缆线传输。包包括开始位,数据,结束为。一旦 开始位传出,后面就会传数据,可能是5,6,7或8位,就看你的设定了。发送和接收必须设定同样 的波特率和数据位数。 无猫模式 没有Modem模式的电缆只是简单地交叉传送和接收线。同样DTR & DSR, 和 RTS & CTS也需要交叉。RS232针图 这里,我们三条线。互连2和3(一段的2pin连接3pin),连接两端的5pin。 [示例程序] 主程序

MFC串口通信编程详解解析

MFC串口通信编程介绍 主要介绍了用CreateFile(函数和WriteFile(函数读写串口的实例,以及设置串口属性的实例. 在工业控制中,工控机(一般都基于Windows平台经常需要与智能仪表通过串口 进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半双工的,只能由作为主节点的工控PC机依次轮询网络上的各智能控制单元子节点.每次通信都是由PC机通过串口向智能控制单元发布命令,智能控制单元在接收到正确的命令后作出应答. 在Win32下,可以使用两种编程方式实现串口通信,其一是使用ActiveX控件,这种方法程序简单,但欠灵活.其二是调用Windows的API函数,这种方法可以清楚地掌握串口通信的机制,并且自由灵活.下面只介绍API串口通信部分. 串口的操作可以有两种操作方式:同步操作方式和重叠操作方式(又称为异步操作方式.同步操作时,API函数会阻塞直到操作完成以后才能返回(在多线程方式中, 虽然不会阻塞主线程,但是仍然会阻塞监听线程;而重叠操作方式,API函数会立即返回,操作在后台进行,避免线程的阻塞. 无论哪种操作方式,一般都通过四个步骤来完成: (1打开串口 (2配置串口 (3读写串口 (4关闭串口

一打开串口 Win32系统把文件的概念进行了扩展.无论是文件、通信设备、命名管道、邮件槽、磁盘、还是控制台,都是用API函数CreateFile来打开或创建的.该函数的原型为: HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDistribution, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile; ?lpFileName:将要打开的串口逻辑名,如“COM1”; ?dwDesiredAccess:指定串口访问的类型,可以是读取、写入或二者并列; ?dwShareMode:指定共享属性,由于串口不能共享,该参数必须置为0; ?lpSecurityAttributes:引用安全性属性结构,缺省值为NULL; ?dwCreationDistribution:创建标志,对串口操作该参数必须置为 OPEN_EXISTING; ?dwFlagsAndAttributes:属性描述,用于指定该串口是否进行异步操作,该值为FILE_FLAG_OVERLAPPED,表示使用异步的I/O;该值为0,表示同步I/O操 作;

相关主题
文本预览
相关文档 最新文档