找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3207|回复: 0
打印 上一主题 下一主题
收起左侧

单片机串口通信原理实现的上下位机设计

[复制链接]
跳转到指定楼层
楼主
ID:698492 发表于 2020-2-26 13:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本文转自:Flywithliye

1.  通信简介
通信有并行通信和串行通信两种方式。在多微机系统以及现代测控系统中信息的交换多采用串行通信方式。
1)  并行通信
并行通信是指所传送的数据各位同时进行传送。其优点是传送速度快,缺点是传输线多,通信线路费用较高,并行传送适用于近距离、传送速度高的场合。
2)  串行通信
串行通信时,传送数据的各位按分时顺序一位一位地传送(例如先低位、后高位)。其优点是传输线少,传送通道费用低,故适合长距离数据传送。缺点是传送速度较低。
图 1
2.  串行通信1)  串行通讯数据传送方向a)  单工方式
通信双方只有一条单向传输线,只允许数据由一方发送,另一方接收。
b)  半双工方式
通信双方只有一条双向传输线,允许数据双向传送,但每时刻上只能有一方发送,另一方接收,这是一种能够切换传送方向的单工方式。
c)  全双工方式
通信双方只有两条传输线,允许数据同时双向传送,其通信设备应具有完全独立的收发功能。
图 2
2)  串行通信基本方式
为了准确地发送、接收信息,发送者和接受者双方必须协调工作。这种协调方法,从原理上可分成两种:同步串行I/O和异步串行I/O。
a)  同步通信方式
在同步通信中,在数据或字符开始传送前用同步字符(SYNC)来指示(常约定l一2个),由时钟来实现发送端和接收端同步,当检测到规定的同步字符后,接下来就连续按顺序传送数据。同步字符是一特定的二进制序列,在传送的数据中不会出现。
同步通信方式由于不采用起始和停止位,是在同步字符后可以接较大的数据区,同步字符所占部分很小,因此有较高的传送效率。
发送、接收双方都由统一的时钟来发送、接收数据。也就是说,不光有数据传输线,还要附加同步时钟线。这种方式,硬件较复杂、成本较高、传送速率高。
b)  异步通信方式
异步通信方式时,数据一帧一帧地传送,不需要同步时钟,实现简单。
在异步方式中,为了避免连续传送过程中的误差积累,每个字符都要独立确定起始和结束(即每个字符都要重新同步),字符和字符间还可能有长度不定的空闲时间。
3)  异步串行通信数据格式
一个字符在异步传送中称为一帧数据。一帧数据由4部分组成:起始位、数据位、奇偶位、停止位。
图 3
上图所示为不包含奇偶检验位的一个数据帧。奇偶检验位应位于数据位后,停止位前。
a)  起始位
在没有数据传输时,通信线上处于逻辑“1”状态。当发送端要发送1个字符数据时,首先发送1个逻辑“0”,这个低电平便是帧格式的起始位。其作用是向接收端表示发送端开始发送一帧数据了。接收端检测到这个低电平后,就准备接收数据。
b)  数据位
在起始位之后,发送端发出(或接收端接收)的是数据位,数据的位数没有严格的限制,5~8 位均可。由低位到高位逐位发送。
c)  奇偶校验位
数据位发送完(接收完)之后,可发送一位用来验证数据在传送过程中是否出错的奇偶校验位。奇偶校验是收发双发预先约定的有限差错校验方法之一。有时也可不用奇偶校验。
d)  停止位
字符帧格式的最后部分是停止位,逻辑“高(1)”电平有效,它可占 1/2 位、1 位或 2 位。停止位表示传送一帧信息的结束,也为发送下一帧数据做好了准备。
4)  串行接口标准a)  RS-232
RS-232是美国电子工业协会EIA(Electronic Industry Association)制定的一种串行物理接口标准。RS是英文“推荐标准”的缩写,232为标识号。RS-232是对电气特性以及物理特性的规定,只作用于数据的传输通路上,它并不内含对数据的处理方式。RS-232标准是逻辑1为-3V~-15V,逻辑0为+3~+15V。
b)  RS-422
RS-422的电气性能与RS-485完全一样。主要的区别在于:RS-422 有4 根信号线:两根发送、两根接收。由于RS-422 的收与发是分开的所以可以同时收和发(全双工),也正因为全双工要求收发要有单独的信道,所以RS-422适用于两个站之间通信,星型网、环网,不可用于总线网;RS-485 只有2 根信号线,所以只能工作在半双工模式,常用于总线网。
c)  RS-485
RS-232接口可以实现点对点的通信方式,但这种方式不能实现联网功能。于是,为了解决这个问题,一个新的标准RS-485产生了。RS-485的数据信号采用差分传输方式,也称作平衡传输,它使用一对双绞线,将其中一线定义为A,另一线定义为B。通常情况下,发送驱动器A、B之间的正电平在+2~+6V,是一个逻辑状态,负电平在-2~-6V,是另一个逻辑状态。另有一个信号地C,在RS-485中还有一“使能”端,而在RS-422中这是可用可不用的。
3.  通信实验1)  实验环境的搭建
为实现在无附加硬件的条件下,使用PC机完成串行口通信实验。通过软件对实验环境配置如下:
a)  虚拟串口的创建
使用Configure Virtual Serial Port Driver软件在PC上创建一对虚拟串口(COM1和COM2),如图所示。
图 4
COM1和COM2为已连接的一对串口,分别为两台设备的接口(已虚拟连接)。设备A,B分别连接至COM1和COM2,即可收发数据。
b)  设备B的创建
此次实验中,设备B为单片微机(MCU)。其选型为AT89C52型,具备硬件UART功能。设备B电路实现由Protues软件进行模拟仿真。电路原理图如图所示。
图 5
由于RS-232标准采用负逻辑,即逻辑1为-3V~-15V,逻辑0为+3~+15V。而本单片机系统为TTL信号系统。TTL电平规定,+5V等价于逻辑“1”,0V等价于逻辑“0”。因此,DB-9与单片机的连接需要进行电平转换,如上图所示,选用了MAX232芯片。
图 6
如图所示,P1组件(COMPIM)即为DB-9接口,使用MAX232芯片进行电平转换后与AT89C52串行口P3.0/RXD,P3.1/TXD分别相连接。(由于软件特殊原因,在MAX232芯片1通道R1OUT及T1OUT处增加74LS04非门进行处理,实际中无需取反处理。)
图中组件RECEIVE和SEND为Protues软件提供的VIRTUAL TERMINAL(虚拟终端)可用于观察AT89C52接收和发送到的数据。仅用于调试观察。
2)  实验内容说明
本次实验涉及两个设备,设备B为上述单片微机,用以模拟一个外部设备。设备A为PC机本身。
设备A,B分别都运行有简单的程序。设备A的程序存储器中加载有简单回传程序,负责将接收到的字符/字符串(以回车换行结尾)保持原接收状态并向外发送。设备B即PC,其上运行有窗口程序,负责向设备A发送字符/字符串,并接收显示其回传的数据。
实验时设备A连接COM1口,设备B连接COM2口。由PC窗口程序输入测试数据后发送至单片微机后,由后者保持原样回传并显示在PC窗口程序接收窗口。
3)  单片机程序的编制
由于该芯片自带硬件UART功能且由于实验环境所限,此次实验中,发送接收通过配置相关寄存器控制硬件模块实现,未采用软件定时器模拟通信时序的方式。
程序主要包括以下三个部分:主函数,串行口配置函数,发送函数及串行口中断服务函数。
a)  程序变量定义及函数声明
b)  程序主函数
c)  其他子函数
其他在主函数中调用的具体子函数实现由附件1列出。
4)  窗口应用程序的编制
本次实验的窗口程序使用VB.NET语言在VS2010环境下编写。
程序中主要由.NET提供的SerialPort控件实现,辅之以必要的其他窗口控件。窗口布局如图所示:
图 7
a)  参数设置函数
b)  数据接收函数
SerialPort的事件DataReceived调用Sp_Receiving实现数据接收。当输入缓冲区接收到1个字符后驱动该事件发生,并调用Sp_Receiving函数准备开始接收数据。当读取到缓冲区中的回车换行符后,将接受到的数据显示在TextBox控件中。若在超时以后仍未读取到回车换行符,则执行空操作后退出接受程序,退出前清空接收缓冲区。既本窗口程序仅接受并显示以回车换行结尾的数据包。
c)  数据发送函数
数据发送过程由按键按下事件驱动调用。判断是否发送新行(本次实验中必须勾选)后是否为对话模式后,发送数据。
d)  其他子函数
其他子函数包括PC可用串口读取,串口打开,串口关闭,及相关事件处理函数。其具体实现由附件2给出。
5)  实验过程a)  串口有关参数设置
表 1
串口参数约定

设备A(PC)
设备B(MCU)
COM编号
COM1
COM2
波特率(bps)
9600
数据位
8
校验位
停止位
1
按照表1设置串口参数如下。
图 8
图 9

左图为窗口程序设置,右图为仿真软件中对与MCU接口的DB-9接头的属性设置。MCU中的配置由配置相关寄存器完成,如下所示。
b)  启动MCU仿真
点击下图第一个按钮启动仿真。
图 10
出现如下图所示内容说明仿真成功执行。
图 11
c)  打开上位机串口
点击打开串口按键,若在串口状态处显示已打开,则说明上位机以成功打开串口。
图 12
d)  输入信息并发送
在发送输入下的文本框中输入任意字符串(长度不可超出单片机接收缓冲区长度-2)后,点击右侧发送按钮。此处发送“This is a test!”。
图 13
e)  单片机回传数据
上位机发送数据“This is a test!”之后,单片机回传“MCU received: This is a test!”并显示在接收显示窗口中,如下图所示。
图 14
f)  单片机接收/发送
在步骤e)执行之前,单片机接收到的内容和发送的内容如下图所示。
图 15
图 16


2、  TCP通信1.  Socket套接字1)  简介
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
2)  分类
TCP/IP的socket提供下列三种类型套接字。
a)  流式套接字(SOCK_STREAM)
提供了一个面向连接(TCP)、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用流式套接字。
b)  数据报式套接字(SOCK_DGRAM)
提供了一个无连接服务(UDP)。数据包以独立包形式被发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。网络文件系统(NFS)使用数据报式套接字。
c)  原始式套接字(SOCK_RAW)
该接口允许对较低层协议,如IP、ICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备。
2.  TCP简介
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。利用TCP协议进行通信时,首先要建立通信双方的连接。一旦连接建立完成,就可以进行通信。TCP提供了数据确认和数据重传机制,保证了发送的数据一定能到达通信的对方。
3.  TCP通信过程
TCP通信过程如下图所示。
图 17
服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用(accept)阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就成功建立。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
4.  TCP服务器程序流程1)  建立连接阶段
  • 调用socket(),分配文件描述符,即监听套接字。
  • 调用bind(),将套接字与本地IP地址和端口绑定。
  • 调用listen(),监听特定端口,socket()创建的套接字是主动的,调用listen使得该文件描述符为监听套接字,变主动为被动。
  • 调用accept(),阻塞等待客户端连接。
2)  数据交互阶段
  • 调用read(),阻塞等待客户端发送请求,收到请求后从read()返回,处理客户端请求。
  • 调用write(),将处理结果发送给客户端,然后继续调用read()等待客户端请求。
3)  关闭连接
  • read()返回0的时候,说明客户端发来了FIN数据包,即关闭连接,也会调用close()关闭连接套接字和监听套接字。
5.  TCP客户端程序流程1)  建立连接阶段
  • 调用socket(),分配文件描述符。
  • 调用connect(),向服务器发送建立连接请求。
2)  数据交互阶段
  • 调用write(),将请求发送给服务器。
  • 调用read(),阻塞等待服务器应答。
3)  关闭连接
  • 当没有数据发送的时候,调用close()关闭连接套接字,即关闭连接,向服务器发送FIN数据报。
6.  通信实验1)  实验环境的搭建
在编写实验程序前,须在编译器中添加库文件ws2_32.lib。可通过编译器软件设置实现,也可通过包含如下代码实现:#pragma comment(lib,"ws2_32.lib")
2)  实验内容说明
本次实验包括服务器端程序和客户端程序,由C语言编写的控制台程序实现。程序顺序执行。实验实现客户端程序和服务器端程序的通信(字符串)。
3)  服务器端程序的编制a)  程序变量定义及函数声明
b)  程序主函数
c)  其他子函数
其他子函数包括用于初始化套接字,创建套接字,绑定IP和端口,设置监听状态,等待客户端发起连接的程序,其中分别调用了Socket中提供的功能函数,但是加入了一些简单的显示和错误处理。其具体实现由附件3给出。
4)  客户端程序的编制a)  程序变量定义及函数声明
b)  程序主函数
c)  其他子函数
其他子函数包含用于初始化套接字,创建套接字,连接服务器及释放套接字的函数。为了适应在本地实验和同网段实验的需求,连接服务器的子函数Connect_Socket()中从键盘获取输入的IP地址和端口实现连接。其具体实现由附件4给出。
5)  实验过程a)  启动服务器端程序并等待连接b)  启动客户端程序并发起连接
输入服务器IP地址和端口后即可发起连接。
c)  客户端发送消息
输入消息并回车即可发送。
图 18
图 19
d)  服务器端发送消息
输入消息并回车即可发送。
注意:由于程序顺序/循环执行,非事件驱动结构,因此必须在接收到对方发送的数据后,己方方可发送。
3、  UDP通信1.  UDP简介
UDP是无连接的不可靠的传输协议。采用UDP进行通信时,不需要建立连接,可以直接向一个IP地址发送数据,但是不能保证对方能收到。
对于基于UDP面向无连接的套接字编程来说,服务器端和客户端这种概念不是特别的严格。可以把服务器端称为接收端,客户端就是发送数据的发送端。
2.  UDP通信过程
图 20
服务器端先初始化Socket,然后与端口绑定(bind),在这时如果有个客户端初始化一个Socket,客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,一次交互结束。
注意到,在进行端口绑定(bind)之后,服务器端不需要对端口进行监听(listen),也不需要调用等待连接(accept)阻塞,等待客户端连接。而客户端无需使用连接(connect)事先与服务器建立连接。
3.  UDP服务器程序流程
  • 建立套接字文件描述符,使用函数socket(),生成套接字文件描述符。
  • 设置服务器地址和侦听端口,初始化要绑定的网络地址结构。
  • 绑定侦听端口,使用bind()函数,将套接字文件描述符和一个地址类型变量进行绑定。
  • 接收客户端的数据,使用recvfrom()函数接收客户端的网络数据。
  • 向客户端发送数据,使用sendto()函数向服务器主机发送数据。
  • 关闭套接字,使用close()函数释放资源。UDP协议的客户端流程.
4.  UDP客户端程序流程
  • 建立套接字文件描述符,socket()
  • 设置服务器地址和端口,struct sockaddr
  • 向服务器发送数据,sendto()
  • 接收服务器的数据,recvfrom()
  • 关闭套接字,close()
5.  通信实验1)  实验内容说明
本次实验进行了更为简单的验证次实验启动服务器后监听某端口后,由客户端发送一固定数据给服务器,服务器接收并显示后。双方释放套接字并结束程序。
2)  服务器端程序的编制a)  程序变量定义及函数声明
b)  程序主函数
c)  其他子函数
其他子函数包括用于初始化套接字,绑定IP和端口的函数,其中分别调用了Socket中提供的功能函数。其具体实现由附件5给出。
3)  客户端程序的编制a)  程序变量定义及函数声明
b)  程序主函数
c)  其他子函数
其他子函数包括用于初始化套接字,设置服务器IP和端口的函数,其中分别调用了Socket中提供的功能函数。其具体实现由附件6给出。
4)  实验过程a)  启动服务器并监听端口b)  启动客户端向服务器发送c)  服务器接收并显示
图 21
图 22

5.  附件五(UDP Server程序)
  #include<stdio.h>  
  #include<winsock.h>                           /*引入winsock头文件*/  
  #pragma comment(lib,"ws2_32.lib")  
   
  char Receivebuf[100];       /*接受数据的缓冲区*/  
  int length;  
   
  SOCKET socket_send;         /*定义套接字*/  
  SOCKADDR_IN Server_add;     /*服务器地址信息结构*/  
SOCKADDR_IN Client_add;     /*客户端地址信息结构*/  
WORD wVersionRequested;     /*字(word):unsigned short*/  
WSADATA wsaData;            /*库版本信息结构*/  
int error;                  /*表示错误*/  
  
void Init_Socket();         /*初始化套接字*/  
void Bind_Socket();         /*绑定套接字*/  
  
int main()  
{  
    memset(Receivebuf,0,100);                  /*清空接收缓冲*/  
    Init_Socket();                             /*初始化套接字*/  
  
    socket_send=socket(AF_INET,SOCK_DGRAM,0);  /*创建套接字*/  
    Bind_Socket();                             /*绑定套接字*/  
      
    recvfrom(socket_send,Receivebuf,100,0,(SOCKADDR*)&Client_add,&length);  
    printf("客户端:%s\n",Receivebuf);         /*接收并显示数据*/  
  
    closesocket(socket_send);                  /*释放套接字资源*/  
    WSACleanup();                              /*关闭动态链接库*/  
    system("pause");  
    return 0;  
}  
  
void Init_Socket()  
{  
    /*-------------------------初始化套接字库---------------------------*/  
    /*定义版本类型。将两个字节组合成一个字,前面是第字节,后面是高字节*/  
    wVersionRequested = MAKEWORD( 2, 2 );     
    /*加载套接字库,初始化Ws2_32.dll动态链接库*/  
    error = WSAStartup( wVersionRequested, &wsaData);     
    if(error!=0)  
    {  
        printf("加载套接字失败!\n");  
        return 0;                              /*程序结束*/  
    }  
    /*判断请求加载的版本号是否符合要求*/  
    if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2)   
    {     
        WSACleanup( );                         /*不符合,关闭套接字库*/  
        return 0;                              /*程序结束*/  
    }  
    printf("加载套接字成功。\n");  
}  
  
void Bind_Socket()  
{  
    /*----------------------设置服务器地址-----------------------*/  
    Server_add.sin_family=AF_INET;/*地址家族,对于必须是AF_INET,注意只有它不是网络网络字节顺序*/  
    Server_add.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  
    Server_add.sin_port=htons(5000);/*端口号*/  
  
    /*绑定套接字*/  
    bind(socket_send,(SOCKADDR*)&Server_add,sizeof(SOCKADDR));  
    length=sizeof(SOCKADDR);  
    printf("绑定成功。\n正在监听\n");  
}  

6.  附件六(UDP Client程序)
  #include<stdio.h>  
  #include<winsock.h>               /*引入winsock头文件*/  
  #pragma comment(lib,"ws2_32.lib")  
   
  #define Msg "This is a test!"   /*待发送数据*/  
  SOCKET socket_client;           /*定义套接字*/  
  SOCKADDR_IN Server_add;         /*服务器地址信息结构*/  
  WORD wVersionRequested;         /*字(word):unsigned short*/  
  WSADATA wsaData;                /*库版本信息结构*/  
int error;                      /*表示错误*/  
  
void Init_Socket();             /*初始化套接字*/  
void Set_Server();              /*设置服务器地址和端口*/  
int main()  
{  
    Init_Socket();                                 /*初始化套接字*/                                       
    socket_client=socket(AF_INET,SOCK_DGRAM,0);    /*创建套接字*/  
    Set_Server();                                  /*设置服务器地址和端口*/  
    /*发送数据*/  
    sendto(socket_client,Msg,strlen(Msg)+1,0,(SOCKADDR*)&Server_add,sizeof(SOCKADDR));  
    printf("已发送数据至服务器\n");  
    closesocket(socket_client);                    /*释放套接字资源*/  
    WSACleanup();                                  /*关闭动态链接库*/  
    system("pause");  
    return 0;  
}  
  
void Init_Socket()  
{  
    /*-------------------------初始化套接字库---------------------------*/  
    /*定义版本类型。将两个字节组合成一个字,前面是第字节,后面是高字节*/  
    wVersionRequested = MAKEWORD( 2, 2 );     
    /*加载套接字库,初始化Ws2_32.dll动态链接库*/  
    error = WSAStartup( wVersionRequested, &wsaData);     
    if(error!=0)  
    {  
        printf("加载套接字失败!\n");  
        return 0;                                  /*程序结束*/  
    }  
    /*判断请求加载的版本号是否符合要求*/  
    if ( LOBYTE( wsaData.wVersion ) != 2 ||  
           HIBYTE( wsaData.wVersion ) != 2 )   
    {     
        WSACleanup( );                             /*不符合,关闭套接字库*/  
        return 0;                                  /*程序结束*/  
    }  
    printf("加载套接字成功。\n");  
}  
  
void Set_Server()  
{  
    /*----------------------设置服务器地址-----------------------*/  
    Server_add.sin_family=AF_INET;/*地址家族,对于必须是AF_INET,注意只有它不是网络网络字节顺序*/  
    Server_add.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  
    Server_add.sin_port=htons(5000);               /*端口号*/  
    printf("服务器设置成功。\n");  
}  


4.  附件四(TCP Client程序)
  #include<stdio.h>  
  #include<winsock.h>       /*引入winsock头文件*/  
  #pragma comment(lib,"ws2_32.lib")  
   
  char Sendbuf[100];      /*发送数据的缓冲区*/  
  char Receivebuf[100];   /*接受数据的缓冲区*/  
  int SendLen;            /*发送数据的长度*/  
  int ReceiveLen;         /*接收数据的长度*/  
  char IPaddress[16];     /*IP地址数组*/  
char Port[6];           /*端口数组*/  
  
SOCKET socket_send;     /*定义套接字*/  
SOCKADDR_IN Server_add; /*服务器地址信息结构*/  
WORD wVersionRequested; /*字(word):unsigned short*/  
WSADATA wsaData;        /*库版本信息结构*/  
int error;              /*表示错误*/  
  
int Init_Socket();      /*初始化套接字*/  
void Create_Socket();   /*创建套接字*/  
void Connect_Socket();  /*连接服务器*/  
void Close_Socket();    /*释放套接字*/  
  
int main()  
{  
    Init_Socket();                                      /*初始化套接字*/  
    Create_Socket();                                    /*创建套接字*/  
    Connect_Socket();                                   /*连接服务器*/  
  
    while(1)                                            /*具体通信过程*/  
    {     
        /*---------------发送数据过程----------*/  
        printf("请输入消息:");  
        gets(Sendbuf);                                  //获取输入的数据  
        SendLen = send(socket_send,Sendbuf,100,0);      //启动发送  
        if(SendLen < 0)  
        {  
            printf("发送失败!\n");                      //发送失败  
            break;  
        }  
  
        /*--------------接收数据过程---------------*/  
        ReceiveLen =recv(socket_send,Receivebuf,100,0); //结束数据存缓冲区  
        if(ReceiveLen<0)  
        {  
            printf("连接关闭或接收失败\n程序退出\n");   //接收或连接失败  
            break;  
        }  
        else                                             
        {  
            printf("来自服务器:%s\n",Receivebuf);      //显示收到的数据  
        }     
    }  
    Close_Socket();                                     /*释放套接字*/  
    return 0;  
}  
  
int Init_Socket()  
{  
    /*------------初始化套接字库---------------*/  
    /*定义版本类型。将两个字节组合成一个字,前面是第字节,后面是高字节*/  
    wVersionRequested = MAKEWORD( 2, 2 );     
    /*加载套接字库,初始化Ws2_32.dll动态链接库*/  
    error = WSAStartup( wVersionRequested, &wsaData);     
    if(error!=0)  
    {  
        printf("加载套接字失败。\n");  
        return 0;                                       /*程序结束*/  
    }  
    else  
    {  
        printf("加载套接字成功。\n");  
    }  
    /*判断请求加载的版本号是否符合要求*/  
    if(LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2)   
    {     
        WSACleanup( );                                  /*不符合,关闭套接字库*/  
        return 0;                                       /*程序结束*/  
    }  
    else  
    {  
        printf("加载版本号符合。\n");  
    }  
}  
  
void Create_Socket()  
{  
    /*-------------进行连接服务器--------------*/  
    /*客户端创建套接字,但是不需要绑定的,只需要和服务器建立起连接就可以了。*/  
    /*socket_sendr表示的是套接字,Server_add服务器的地址结构*/  
    socket_send=socket(AF_INET,SOCK_STREAM,0);  
}  
  
void Connect_Socket()  
{  
    /*------------设置服务器地址---------------*/  
    Server_add.sin_family=AF_INET;/*地址家族,对于必须是AF_INET,注意只有它不是网络网络字节顺序*/  
    /*服务器的地址,将一个点分十进制表示为IP地址,inet_ntoa是将地址转成字符串*/  
    puts("输入IP地址:");  
    gets(IPaddress);  
    puts("输入端口:");  
    gets(Port);  
    Server_add.sin_addr.S_un.S_addr = inet_addr(IPaddress);  
    Server_add.sin_port=htons(atoi(Port));              /*端口号*/  
    /*-------------创建用于连接的套接字--------*/  
    /*AF_INET表示指定地址族,SOCK_STREAM表示流式套接字TCP,特定的地址家族相关的协议。*/  
    if(connect(socket_send,(SOCKADDR*)&Server_add,sizeof(SOCKADDR)) == SOCKET_ERROR)  
    {  
        printf("服务器连接失败。\n");  
    }  
    else  
    {  
        printf("服务器连接成功。\n");  
    }  
}  
  
void Close_Socket()  
{  
    /*---------释放套接字,关闭动态库----------*/  
    closesocket(socket_send);   /*释放套接字资源*/  
    WSACleanup();               /*关闭动态链接库*/  
}  

3.  附件三(TCP Server程序)
      #include<stdio.h>  
  #include<winsock.h>       /*引入winsock头文件*/  
  #pragma comment(lib,"ws2_32.lib")  
   
  #define IPaddress "127.0.0.1" /*IP地址*/  
  #define Port "5000"           /*端口*/  
   
  char Sendbuf[100];      /*发送数据的缓冲区*/  
  char Receivebuf[100];   /*接受数据的缓冲区*/  
int SendLen;            /*发送数据的长度*/  
int ReceiveLen;         /*接收数据的长度*/  
int Length;             /*表示SOCKADDR的大小*/  
  
SOCKET socket_server;   /*定义服务器套接字*/  
SOCKET socket_receive;  /*定义用于连接套接字*/  
SOCKADDR_IN Server_add; /*服务器地址信息结构*/  
SOCKADDR_IN Client_add; /*客户端地址信息结构*/  
WORD wVersionRequested; /*字(word):unsigned short*/  
WSADATA wsaData;        /*库版本信息结构*/  
int error;              /*表示错误*/  
  
int Init_Socket();      /*初始化套接字*/  
void Create_Socket();   /*创建套接字*/  
int Bind_Socket();      /*绑定IP和端口*/  
int Listen_Socket();    /*设置监听状态*/  
int Wait_Socket();      /*等待客户端连接*/  
void Close_Socket();    /*释放套接字*/  
  
int main()  
{  
    Init_Socket();                                            /*初始化套接字*/  
    Create_Socket();                                          /*创建套接字*/  
    Bind_Socket();                                            /*绑定IP和端口*/  
    Listen_Socket();                                          /*设置监听状态*/  
    Wait_Socket();                                            /*等待客户端连接*/  
      
    while(1)            /*具体通信过程*/  
    {     
        /*--------接收数据---------*/  
        ReceiveLen =recv(socket_receive,Receivebuf,100,0);    //接收数据存缓冲区  
        if(ReceiveLen<0)                                      //连接或接收失败  
        {  
            printf("客户端中断连接或接收失败\n程序退出\n");  
            break;  
        }  
        else  
        {  
            printf("来自客户端:%s\n",Receivebuf);            //显示接收到的数据  
        }     
         
        /*--------发送数据---------*/  
        printf("请输入消息:");  
        gets(Sendbuf);                                        //获取输入的数据  
        SendLen=send(socket_receive,Sendbuf,100,0);           //启动发送  
        if(SendLen<0)  
        {  
            printf("发送失败。\n");                           //本次发送失败  
            break;  
        }  
    }  
    Close_Socket();                                           /*释放连接*/  
    return 0;  
}  
  
int Init_Socket()  
{  
    /*------------初始化套接字库---------------*/  
    /*定义版本类型。将两个字节组合成一个字,前面是第字节,后面是高字节*/  
    wVersionRequested = MAKEWORD( 2, 2 );     
    /*加载套接字库,初始化Ws2_32.dll动态链接库*/  
    error = WSAStartup( wVersionRequested, &wsaData);     
    if(error!=0)  
    {  
        printf("加载套接字失败。\n");  
        return 0;                                             /*程序结束*/  
    }  
    else  
    {  
        printf("加载套接字成功。\n");  
    }  
    /*判断请求加载的版本号是否符合要求*/  
    if(LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2)   
    {     
        WSACleanup( );                                        /*不符合,关闭套接字库*/  
        return 0;                                             /*程序结束*/  
    }  
    else  
    {  
        printf("加载版本号符合。\n");  
    }  
    return 1;  
}  
  
void Create_Socket()  
{  
    /*------------设置连接地址-----------------*/  
    Server_add.sin_family=AF_INET;/*地址家族,对于必须是AF_INET,注意只有它不是网络网络字节顺序*/  
    Server_add.sin_addr.S_un.S_addr=inet_addr(IPaddress);     /*主机地址*/  
    Server_add.sin_port=htons(atoi(Port));/*端口号*/  
  
    /*------------创建套接字-------------------*/  
    /*AF_INET表示指定地址族,SOCK_STREAM表示流式套接字TCP,特定的地址家族相关的协议。*/  
    socket_server=socket(AF_INET,SOCK_STREAM,0);  
}  
  
int Bind_Socket()  
{  
    /*---绑定套接字到本地的某个地址和端口上----*/  
    /*socket_server为套接字,(SOCKADDR*)&Server_add为服务器地址*/  
    if(bind(socket_server,(SOCKADDR*)&Server_add,sizeof(SOCKADDR) )==SOCKET_ERROR)  
    {  
        printf("绑定失败。\n");  
        return 0;  
    }  
    else  
    {  
        printf("套接字绑定成功。\n");  
        printf("当前主机地址:");  
        printf(IPaddress);  
        printf("\n当前主机端口:");  
        printf(Port);  
        printf("\n");  
    }  
    return 1;  
}  
  
int Listen_Socket()  
{  
    /*------------设置套接字为监听状态---------*/  
    /*监听状态,为连接做准备,最大等待的数目为5*/  
    if(listen(socket_server,5)<0)  
    {  
        printf("监听失败\n");  
        return 0;  
    }  
    else  
    {  
        printf("监听成功\n");  
        return 1;  
    }  
}  
  
int Wait_Socket()  
{  
    /*------------接受连接---------------------*/  
    Length=sizeof(SOCKADDR);  
    /*接受客户端的发送请求,等待客户端发送connect请求*/  
    socket_receive=accept(socket_server,(SOCKADDR*)&Client_add,&Length);  
    if(socket_receive==SOCKET_ERROR)  
    {  
        printf("客户端连接失败。");  
        return 0;  
    }  
    else  
    {  
        printf("客户端连接成功。\n");  
        return 1;  
    }  
}  
  
void Close_Socket()  
{  
    /*---------释放套接字,关闭动态库----------*/  
    closesocket(socket_receive);                              /*释放客户端的套接字资源*/  
    closesocket(socket_server);                               /*释放套接字资源*/  
    WSACleanup();                                             /*关闭动态链接库*/  
}  

7.  附件七(单片机原理图)




转自 Flywithliye 相关资料下载:http://www.51hei.com/bbs/dpj-180566-1.html

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表