单片机之UIP--TCP作为服务器,主动发送数据 ACK

作者:LZMCSDN: http://blog.csdn.net/kaly_liu

邮箱:[email protected]

uip下的TCP作为服务器,主动发送数据===最近弄这个,在网上找资料好累,而且都是含糊不清的讲述,没有实例的,我实在是受不了了,好不容易弄好了一个,现在来分享下。

1.添加STC12C5A单片机的引脚定义:在reg52.h里面:sfr P4=0xC0;

2.修改对应引脚,按照电路图修改,SPI接口采用单片机IO口模拟,只需根据实际的硬件电路设计(IO口需要上/下拉电阻),在spi.h文件中修改IO脚定义即可,需要注意的是ENC28J60采用SPI0模式,即时钟信号上升沿接收数据,下降沿发送数据,本例中SPI通讯时序已经调通,可以直接使用,至少要接SCK,CS,SI,SO即可,INT没有使用,可以不接,如果接上,ENC28J60驱动代码已经开启了接收中断,程序中可以接收到,但在使用中断模式时,请考虑收,发包的同步情况,比如:网卡支持全双工模式,正在发送包时,又收到一个包产生中断,而uIP协议栈是共用缓存的(为节约内存),如果再次去调用协议栈,会将协议栈缓存出错。


3.添加串口中断,在MCU_UART.C中修改init_uart()函数,开启串口中断

4.在main.c中添加中断voiduart(void) interrupt 4

为了把串口接收到的数据先保存在缓存中,需要先设置一个数组temp[64]来临时存储数据,接收到数据字节数rxnum,以及接收完成标志sendtotcpflag;

从串口接收数据是一个字节一个字节的接收,所以要接收到完整的数据后再处理,就需要有一个标志,表示全部接收完毕了,然后再处理。这里我利用在数据前后加入‘*’和‘#’分别作为开始和结束的标志,单有这两个符号出现后sendtotcpflag就会自加一;在程序中判断sendtotcpflag为2时候,就表示数据接收完毕了,就进入数据处理函数,处理收到的数据。有个地方要注意的是:我直接用:SBUF==’*’来做判断,不行,不知道为什么一定要用到temp[rxnum]作为中间量后,使用temp[rxnum]==’*’才可以作为判断。

5.实现串口发送数据到TCP客户端。

单片机先接受串口数据,然后通过TCP服务器发送数据到PC机的客户端。在 uIP中,主动发送数据有两个方法:

1)用uip_input:当检测到新的数据时,调用uip_input(),把接收到的IP包解包,然后提取出用户数据,然后调用app_call,在app_call中调用uip_send()或者uip_udp_send()来发送数据。

2)用uip_periodic(),即在主循环超时仍没有接收到新数据时,调用 uip_periodic(),像uip_input那样在其里面调用app_call,再调用uip_send()或者uip_udp_send()来发送数据。

在程序中,使用的是第一种方法,只有当服务器检测到新数据时,服务器才可以发送数据到客户端。在example0.c文件的example0_app()函数中,添加程序:

在if(uip_newdata()|| uip_rexmit())中添加一个if(sendtotcpflag>2)的判断执行程序,代码如下:

具体操作流程如下:

首先,将设备连接完善,串口,网线连接好;

第二步,打开串口、网络调试助手;

第三步,开启设备,并将网络调试助手连接上服务器;设置好TCP客户端的端口号以及IP号:端口PORT: 8000 IP: 192.168.1.13

第四步,在串口输入要发送的数据“*xxxxx#”;

第五步,网络调试助手客户端发送随意数据到服务器;

第六步,就看到刚才的串口数据从服务器发送到客户端了。

6.服务器的IP与端口设置以及MAC地址设置,IP与MAC地址设置在uipopt.h文件里(设置的是静态的);端口在tcp_server.c里。

另外可以利用函数来设置IP和mac地址,修改在uipopt.h文件里的UIP_FIXEDADDR的值:

#define UIP_FIXEDADDR 0 //1 为1时MCU设置为静态IP。当UIP_ FIXEDADDR为0时可以利用函数设置IP(建议使用)。可以在main.c中添加如下函数,当然首先要在mian()里定义个数组:u16_t ipaddr[2];

最终实现的是:首先串口发送数据,但是不会直接发到TCP客户端,只会保存在单片机中;然后TCP客户端发送数据到单片机,当单片机接收到数据后,就会将串口数据发送到TCP客户端。

20130426进行改进中:

7.修改5中的内容,实现功能TCP客户端发送命令‘C’到TCP服务器,TCP服务器收到此数据,认为此时需要从串口发送数据到TCP客户端。在TCP客户端收到’C’后,就进入一段上限长达30S的延时,串口需要在时间限制内发送一段数据。当TCP服务器收到数据(数据时以‘*’和‘#’为开始和结束标志)后,串口数据接收标志sendtotcpflag值就为2了,此时满足跳出延时的条件,程序便从循环的延时中break出来,将从串口收到的数据发送到TCP客户端。代码中的senddataflag是用来标记串口数据的来源的,为了确保串口数据是在TCP服务器接收到‘C’命令后发来的。具体的代码修改如下:

为了保证串口数据是在TCP服务器接收到‘C’命令后发来的,在main中需要进行判断,当senddataflag的值为0的时候,说明了此时的串口数据不是需要的,因此此时任何串口数据都不要保存在temp[]中,需要将temp[]清零。而当senddataflag的值为10的时候,说明此时是所需要的串口数据,即串口数据是在TCP服务器收到了TCP客户端发来的‘C’命令后发来的。相关代码如下所示:

本程序已上传到资源中,连接在我的评论里面。http://download.csdn.net/detail/kaly_liu/5312012

 

作者:LZMCSDN: http://blog.csdn.net/kaly_liu

邮箱:[email protected]

猜你喜欢

转载自liuzongming.iteye.com/blog/2280499
ACK