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

查看: 4672|回复: 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管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版