你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 4948|回复: 24

[STM32F769-DISC] 【F769IDISCOVERY评测】LwIP TCP编程之LED远程控制

  [复制链接]

33

主题

1243

回帖

0

蝴蝶豆

论坛元老

最后登录
2019-3-9
发表于 2016-12-11 20:02:44 | 显示全部楼层 |阅读模式
  STM32F769IDISCOVERY开发板(STM32官网)集成了有线网络接口和WIFI接口,在上一篇帖子中介绍了一个网口应用实力,演示一个HTTPServer的demo,本文介绍自己开发一个简单的TCPServer,实现以下功能:

  1.开发板作为服务器,等待客户端链接
  2.客户端链接成功后,向服务器发送字符串或命令
  3.开发板收到客户端的命令后,将收到的命令显示在LCD屏幕上
  4.将收到的命令发送回客户端,客户端显示出来
  5.几个特殊命令,控制开发板上两个LED的亮和灭

  本文的程序基于上一篇帖子介绍的例子https://www.stmcu.org.cn/module/forum/thread-609498-1-1.html
移植而来,该例子库STM32CubeF7中STM32Cube_FW_F7_V1.5.0\Projects\STM32F769I-Discovery\Applications\LwIP\LwIP_HTTP_Server_Socket_RTOS

        先简单介绍一下这个例子的代码结构,有利于自己移植的时候修改
image74.png
main函数:
  -使能CPUICACHEDCACHE
  -HAL 库初始化
  -配置系统时钟
  -定义和创建一个线程作为启动线程
  -启动FreeRTOS内核,将CPU控制权交给内核
  -进入死循环,CPU已经由内核控制,不会再运行到这里


接下来,FreeRTOS内核控制CPU后会执行启动线程
image75.png
StartThread:
  -BSP初始化,主要是初始化了开发板上的LED和LCD,用来显示
  -初始化TCP/IP协议栈
  -网口配置,配置网口参数,MCU底层网口初始化,创建和配置网络状态改变,接收发送等相关回调函数,创建数据接收线程
  -初始化httpserver,这就是修改的地方,将替换成我们自己的server相关函数,该函数里将会创建一个线程,用于运行我们自己的服务器代码
  -在LCD显示前面初始化是否成功的状态
  -如果使用DHCP,创建DHCP线程
  -删除本线程,即删除启动线程


   再接下来,内核已经有多个线程在运行,此处只关心服务器线程,也就是由http_server_socket_init函数创建的http_server_socket_thread线程,在之后的修改中,这两个函数都将会被替换为我们自己写的函数
image76.png
image77.png
http_server_socket_thread:
  -创建socket
  -绑定socket监听地址和端口
  -设置监听socket
  -调用accept等待链接,该函数将会阻塞,线程挂起,直到有客户端链接才会返回
  -一旦有了链接,就转入具体服务函数http_server_serve,就是发送和接收数据,这个函数也会被替换成自己的服务函数

讲完了例子的代码结构,总结起来需要修改的地方也不多,就3个:
1.http_server_socket_init换成my_server_init,完成初始化
2.http_server_socket_thread换成my_server_thread,服务器端代码
3.http_server_serve换成my_server_echo,具体功能实现

        三个函数主要部分代码如下:

  1. void my_server_init(void)
  2. {
  3.     sys_thread_new("MY_SERVER", my_server_thread, NULL, DEFAULT_THREAD_STACKSIZE * 2, TCPIP_THREAD_PRIO);
  4. }
复制代码
创建新线程,运行my_server_thread函数
  1. void my_server_thread(void *arg)
  2. {
  3.     int listenfd,connectfd;
  4.     struct sockaddr_in server,client;
  5.     socklen_t addrlen;

  6.     if((listenfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
  7.     {
  8.         return ;
  9.     }

  10.     server.sin_family = AF_INET;
  11.     server.sin_port = htons(PORT);
  12.     server.sin_addr.s_addr = htonl(INADDR_ANY);

  13.     if(bind(listenfd,(struct sockaddr *)&server,sizeof(server)) == -1)
  14.     {
  15.         return;
  16.     }
  17.     if(listen(listenfd,BACKLOG) == -1)
  18.     {
  19.         return;
  20.     }
  21.     addrlen = sizeof(client);

  22.     while(1)
  23.     {
  24.         connectfd = accept(listenfd,(struct sockaddr*)&client,&addrlen);

  25.         my_server_echo(connectfd);
  26.     }

  27.     close(listenfd);
  28. }
复制代码

一旦有客户端链接,就调用my_server_echo函数

  1. void my_server_echo(int connfd)
  2. {
  3.     int rxsize;
  4. while(1)
  5.     {
  6.         if((rxsize = read(connfd, recvbuf, MAX_BUFF_SIZE)) == -1)
  7.         {
  8.             continue;
  9.         }
  10.         else
  11.         {
  12.                   recvbuf[rxsize - 1] = '\0';
  13.                
  14.                 if(strncmp(recvbuf,LED1_ON,sizeof(LED1_ON)) == 0)
  15.                         BSP_LED_On(LED1);
  16.                 else if(strncmp(recvbuf,LED1_OFF,sizeof(LED1_OFF)) == 0)
  17.                         BSP_LED_Off(LED1);
  18.                 else if(strncmp(recvbuf,LED2_ON,sizeof(LED2_ON)) == 0)
  19.                         BSP_LED_On(LED2);
  20.                 else if(strncmp(recvbuf,LED2_OFF,sizeof(LED2_OFF)) == 0)
  21.                         BSP_LED_Off(LED2);
  22.   LCD_UsrLog("%s\n",recvbuf);
  23.                 write(connfd, recvbuf, rxsize);
  24.         }
  25.         osDelay(10);
  26.     }
复制代码
    由于客户端输入命令以回车键结束,所以接收到的最后一个字符recvbuf[rxsize- 1]原本应该是'\n',应该执行recvbuf[rxsize]= '\0';作为字符串结束,不过为了和设置的宏定义比较,直接把接收到的最后一个字符recvbuf[rxsize- 1]换成字符串结束符,以便strncmp能获得正确的结果

    现在服务器有了,还需要客户端,客户端运行在linux系统,这里就不贴代码了,有需要的在文末链接去找。
代码写好了接下来编译运行,看看效果
image78.png

复位运行,没有客户端链接
image79.png
有一个客户端链接上了,
ip地址 192.168.1.149 (我的电脑)
port  59614  (分配的临时端口,每次连接不一定一样)
此时led1onled2off状态
image80.png
输入led1off,led2on
此时led1被关闭,led2打开
image81.png

输入led1on,两个led都打开
image82.png

输入led1off,led2off,连个led都关闭
image83.png
  测试一下回显功能,就是服务器发回客户端发送的命令,其实前面已经可以看到,电脑上的窗口中,输入的命令显示了两次,一次为输入,一次为从服务器读取的回显

这个小程序就完成了,再次感谢ST中文网http://www.stmcu.com.cn/提供试用

需要完整代码的可以去下面链接下载:


评分

参与人数 1ST金币 +30 收起 理由
zero99 + 30

查看全部评分

回复

使用道具 举报

47

主题

3404

回帖

30

蝴蝶豆

版主

最后登录
2020-12-7
发表于 2016-12-11 20:10:12 | 显示全部楼层
赞,支持支持。。。
回复 支持 反对

使用道具 举报

107

主题

812

回帖

5

蝴蝶豆

论坛元老

最后登录
2019-8-28
发表于 2016-12-11 20:38:18 | 显示全部楼层
赞一个,严重支持
回复 支持 反对

使用道具 举报

6

主题

1026

回帖

7

蝴蝶豆

金牌会员

最后登录
2020-11-25
发表于 2016-12-11 21:13:44 | 显示全部楼层
写的非常好,谢谢分享:
回复 支持 反对

使用道具 举报

0

主题

2189

回帖

397

蝴蝶豆

论坛元老

最后登录
2020-10-13
发表于 2016-12-11 21:42:49 | 显示全部楼层
谢谢楼主整理资源。
回复 支持 反对

使用道具 举报

11

主题

449

回帖

0

蝴蝶豆

金牌会员

最后登录
2018-12-18
发表于 2016-12-11 22:10:29 | 显示全部楼层
回复 支持 反对

使用道具 举报

60

主题

2051

回帖

31

蝴蝶豆

版主

最后登录
2020-12-9
发表于 2016-12-11 22:33:27 | 显示全部楼层
厉害                     
回复 支持 反对

使用道具 举报

74

主题

1368

回帖

194

蝴蝶豆

版主

最后登录
2020-5-12
发表于 2016-12-11 22:47:10 | 显示全部楼层
不错,赞一个
回复 支持 反对

使用道具 举报

10

主题

693

回帖

0

蝴蝶豆

金牌会员

最后登录
2018-6-15
发表于 2016-12-11 23:07:48 | 显示全部楼层
谢谢分享                     
回复 支持 反对

使用道具 举报

4

主题

881

回帖

5

蝴蝶豆

论坛元老

最后登录
2020-11-28
发表于 2016-12-12 08:51:43 | 显示全部楼层
顶           
回复 支持 反对

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版