硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3028|回复: 7
收起左侧

[RL-TCPnet教程] 【RL-TCPnet网络教程】第44章 RL-TCPnet之简单Web Server实现

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2018-1-5 15:18:50 | 显示全部楼层 |阅读模式
第44章      RL-TCPnet之简单Web Server实现

      本章节为大家讲解RL-TCPnet的简单Web Server实现,学习本章节前,务必要优先学习第41,42和43章的基础知识。有了这些基础知识之后,再搞本章节会有事半功倍的效果。
      本章教程含STM32F407开发板和STM32F429开发板。
44.1 初学者重要提示
44.2 HTTP配置说明(Net_Config.c)
44.3 HTTP调试说明(Net_Debug.c)
44.4 使用Notepad++制作网页
44.5 添加网页到MDK工程方法
44.6 访问开发板的Web服务器的方法
44.7 实验例程说明(RTX)
44.8      总结



44.1  初学者重要提示
1、学习本章节前,务必保证已经学习了第41,42和43章的基础知识。
2、首次创建Web服务器,需要大家稍花些时间按照教程里面的说明进行操作,待熟练了之后,创建一个自己的Web服务器就很方便了。
3、关于网页的制作方法和板子的操作步骤在本章的44.4,44.5和44.6小节有详细说明。做本章节配套的实验,必须要看!

努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-5 16:12:36 | 显示全部楼层
44.2  HTTP配置说明(Net_Config.c)
      (本章节配套例子的配置与本小节的说明相同)
      RL-TCPnet的配置工作是通过配置文件Net_Config.c实现。在MDK工程中打开文件Net_Config.c,可以看到下图所示的工程配置向导:
44.1.png
                              
RL-TCPnet要配置的选项非常多,我们这里把几个主要的配置选项简单介绍下。
44.2.png
System Definitions
(1)Local Host Name
      局域网域名。
      这里起名为armfly,使用局域网域名限制为15个字符。
(2)Memory Pool size
      参数范围1536-262144字节。
      内存池大小配置,单位字节。另外注意一点,配置向导这里显示的单位是字节,如果看原始定义,MDK会做一个自动的4字节倍数转换,比如我们这里配置的是8192字节,那么原始定义是#define MEM_SIZE  2048,也就是8192/4 = 2048。
(3)Tick Timer interval
      可取10,20,25,40,50,100,200,单位ms。
      系统滴答时钟间隔,也就是网络协议栈的系统时间基准,默认情况下,取值100ms。
44.3.png
Ethernet Network Interface
      以太网接口配置,勾选了此选项就可以配置了,如果没有使能DHCP的话,将使用这里配置的固定IP
(1)MAC Address
      局域网内可以随意配置,只要不跟局域网内其它设备的MAC地址冲突即可。
(2)IP Address
      IP地址。
(3)Subnet mask
     子网掩码。
(4)Default Gateway
      默认网关。
44.4.png
Ethernet Network Interface
      以太网接口配置,这个配置里面还有如下两项比较重要的配置需要说明。
(1)NetBIOS Name Service
      NetBIOS局域网域名服务,这里打上对勾就使能了。这样我们就可以通过前面配置的Local Host Name局域网域名进行访问,而不需要通过IP地址访问了。
(2)Dynaminc Host Configuration
      即DHCP,这里打上对勾就使能了。使能了DHCP后,RL-TCPnet就可以从外接的路由器上获得动态IP地址。
44.5.png
UDP Sockets
      UDP Sockets配置,打上对勾就使能了此项功能
(1)Number of UDP Sockets
     用于配置可创建的UDP Sockets数量,这里配置了5个。
      范围1 – 20。
44.6.png
TCP Sockets
      TCP Sockets配置,打上对勾就使能了此项功能
(1)Number of TCP Sockets
      用于配置可创建的TCP Sockets数量。
(2)Number of Retries
      范围0-20。
      用于配置重试次数,TCP数据传输时,如果在设置的重试时间内得不到应答,算一次重试失败,这里就是配置的最大重试次数。
(3)Retry Timeout in seconds
      范围1-10,单位秒。
      重试时间。如果发送的数据在重试时间内得不到应答,将重新发送数据。
(4)Default Connect Timeout in seconds
      范围1-600,单位秒。
      用于配置默认的保持连接时间,即我们常说的Keep Alive时间,如果时间到了将断开连接。常用于HTTP Server,Telnet Server等。
(5)Maximum Segment Size
      范围536-1460,单位字节。
      MSS定义了TCP数据包能够传输的最大数据分段。
(6)Receive Window Size
      范围536-65535,单位字节。
      TCP接收窗口大小。
44.7.png
HTTP Server
      HTTP配置,打上对勾就使能了此项功能
(1)Number of HTTP Sessions
      同时可以连接的会话个数,即可以连接的HTTP客户端个数。
      范围1-10。
(2)Port Number
      HTTP服务器的监听端口号,一般情况下Web服务器的端口号均为80。
      范围1-65535。
(3)Server-Id header
      HTTPServer header,如果用户没有配置此选项,将使用默认的header,如果配置了,将使用用户配置的。(实际测试发现,这个选项貌似没什么用)
(4)Enable User Authentication
      用户认证,如果此选项打上对勾的话,将使能用户认证。
      AuthenticationRealm  认证领域。
      AuthenticationUsername 用户名。
      AuthenticationPassword 用户密码。

44.3  HTTP调试说明(Net_Debug.c)
      (重要说明,RL-TCPnet的调试是通过串口打印出来的)
      RL-TCPnet的调试功能是通过配置文件Net_Debug.c实现。在MDK工程中打开文件Net_Debug.c,可以看到下图所示的工程配置向导:
44.8.png
Print Time Stamp
      勾选了此选项的话,打印消息时,前面会附带时间信息。
其它所有的选项
      默认情况下,所有的调试选项都关闭了,每个选项有三个调试级别可选择,这里我们以HTTP Server Debug为例,点击下拉列表,可以看到里面有Off,Errors only和Fulldebug三个调试级别可供选择,每个调试选项里面都是这三个级别。
44.9.png
      Off:表示关闭此选项的调试功能。
      Errorsonly:表示仅在此选项出错时,将其错误打印出来。
      Fulldebug:表示此选项的全功能调试。

      具体测试,我们这里就不做了,大家可以按照第11章讲解的调试方法进行测试

努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-5 16:28:45 | 显示全部楼层
44.4 使用Notepad++制作网页
      学习本小节前,务必保证已经学习了第43章!如果还没有学习,务必先学习下!!

44.4.1 第1步:点击新建按钮
      效果如下:
44.10.png

                              
44.4.2 第2步:新建后设置语言为HTML
44.11.png


44.4.3 第3步:设置网页编码类型
      网页编码类型一定要设置,防止网页编码类型与大家在代码中设置的编码类型不一致,造成汉字显示乱码。Notepad++新建的文件,默认编码是UTF-8,看右下角即可:
44.12.png
我们不选用此编码,防止出现MDK5修改编码的问题,见此贴:http://bbs.armfly.com/read.php?tid=21174
      我们这里统一选用ANSI编码,ANSI就是本地系统编码,如果是简体中文Windows操作系统,ANSI 编码代表 GBK 或者GB2312;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。
      测试发现,有时候选择转换ANSI不是很好用,特别是代码中无中文的时候,转换后,重新打开没有效果,还是UTF-8编码,所以我们这里直接选择编码字符集。
     点击“编码”菜单 –>编码字符集->中文->GB2312:
44.13.png
可以看到右下角已经变成GB2312编码格式:
44.14.png

44.4.4 第4步:编写HTML代码
      下面可以编写代码了,编写的代码内容如下:
  1. <html>

  2.   <head>

  3.     <meta http-equiv="Content-Type" content="text/html; charset= GBK" />

  4.     <title>安富莱嵌入式网络服务器</title>

  5.   </head>

  6.   <body>

  7.     <br />

  8.     <div align="center">

  9.       <table style="border: 1px solid #000080" height="600" cellspacing="0" cellpadding="0" width="800">

  10.       

  11.         <tr bgcolor="#EEEEEE">

  12.           <td style="border-bottom: 1px solid #000080" valign="bottom" nowrap="nowrap" height="90" width="800">

  13.             <h1 align="center">

  14.               <font face="verdana" color="#006699">安富莱嵌入式网络服务器</font>

  15.             </h1>

  16.           </td>

  17.         </tr>

  18.         

  19.         <tr bgcolor="#EEEEEE">

  20.           <td valign="top" height="510" width="800">

  21.             <h2 align="center">

  22.               <b>

  23.                 <font face="verdana" color="#003366">安富莱电子微信公众号</font>

  24.               </b>

  25.             </h2>

  26.             <p align="center">

  27.               <img border="0" src="weixin.jpg" />

  28.             </p>

  29.             <p align="center" leftmargin="10">

  30.               <font face="Verdana"

  31.               size="3">基于RL-TCPnet网络协议栈的嵌入式Web服务器器</font>

  32.             </p>

  33.             <p align="center">

  34.               <a href="http://www.armfly.com/" target="_blank">

  35.                 <font face="Verdana" size="4">

  36.                   <b>www.armfly.com</b>

  37.                 </font>

  38.               </a>

  39.             </p>

  40.           </td>

  41.         </tr>

  42.         

  43.         <tr bgcolor="#EEEEEE">

  44.           <td>

  45.             <p align="center">

  46.               <font face="Verdana" size="3">Copyright &#169; 2017-2020

  47.               <a href="http://www.armfly.com/">武汉安富莱电子有限公司</a> 版权所有.</font>

  48.             </p>

  49.           </td>

  50.         </tr>

  51.         

  52.       </table>

  53.     </div>

  54.   </body>

  55. </html>
复制代码
特别注意,代码中也要设置编码类型,由于我们前面已经设置网页的编码类型是GB2312了,这里写GBK或者GB2312均可,否则网页中显示汉字的时候将是乱码:
44.15.png

44.4.5 第5步:保存编辑好的HTML文件
      现在就可以保存了,保存这一步也十分重要,不能使用html后缀,一定要使用htm后缀,否则将有这个帖子中的问题:http://bbs.armfly.com/read.php?tid=35366
      首先,点击保存:
44.16.png
点击保存后弹出如下窗口:
44.17.png
此时桌面就会多了一个HTML文件(我这里是Google浏览器,所以显示是下面这种效果)。
44.18.png

44.4.6 第6步:添加网页中用到的图片
      本次编辑的HTML网页用到了一个JPG图片,所以需要大家将图片也放在桌面路径(此图片已经放在本章节配套例子的Doc文件夹),当前不限制一定要在桌面路径,大家仅需要保证我们保存的index.htm文件和这个图片文件在一个路径下即可,防止Notepad++找不到这个文件。所以,当设计的网页文件和图片较多的时候需要专门创建一个文件夹进行管理。我们这里只有两个文件,放在桌面即可:
44.19.png

44.4.7 第7步:测试
      现在就可以测试效果了,可以使用浏览器直接打开index.htm文件或者在Notepad++里面启动浏览器,当前Notepad++支持各种主流浏览器的调用,调用前请务必保证已经保存了HTML文件,如果新建的文件还没有保存,调用浏览器是不成功的,并且每修改一次HTML文件,务必点击保存后再启动浏览器。大家用的什么浏览器,打开那个选项即可,我这里是GoogleChrome,所以选择此选项。
44.20.png
点击此选项后,就可以直接查看运行效果了。
44.21.png
至此,大家就完成了一个完整的HTML网页编辑和测试,下面就为大家讲解如何将这个网页添加到MDK工程里面。

努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-5 17:00:12 | 显示全部楼层
44.5 添加网页到MDK工程的方法
      将网页添加到MDK工程中,要注意的事项较多。总体就是先创建两个文件Web.c(可选)和Web.inp,将其添加到MDK,并将我们的htm类型文件也添加到MDK(可选)。下面详细讲解,首先建立一个RL-TCPnet/Web分组,专门用来管理网页相关的文件。
44.22.png
                              
然后在工程目录的Project\MDK-ARM(uV4)文件夹里面新建一个Web文件夹,而且特别要注意,这个新建的文件夹一定要和你的MDK工程文件名xxx.uvproj(MDK5中的后缀是uvprojx)在一起。
44.23.png

44.5.1 第1步:创建并添加Web.inp到MDK
      这个文件非常重要,设置的时候要特别注意。
新建文件
44.24.png
点击保存
44.25.png
点击保存后弹出如下窗口:
44.26.png
保存后,将新建的文件Web.inp添加到工程里面,鼠标双击RL-TCPnet/Web分组。
44.27.png
弹出如下对话框,选择Web.inp文件:
44.28.png
这一步比较重要了,点击Add后,弹出如下窗口:
44.29.png
点击OK后,文件Web.inp就已经添加到MDK工程项目里面了,然后点击Close按钮,关闭弹出的窗口:
44.30.png
文件添加上之后,就是如何编辑和设置这个文件了。首先给这个文件中编辑如下内容:
  1. weixin.jpg, index.htm to Web.c nopr root(Web)
复制代码
这句话代表什么意思呢?他的意思就是将我们44.5小节中制作的网页文件weixin.jpg和index.htm转换成C文件Web.c,并将这个Web.c文件存到前面创建的Web文件夹里面。其中nopr表示禁止生成xx.lst列表文件。以后大家添加自己制作的多个网页文件,方法是一样的,htm文件和图片需要都添加上,有多少个添加多少个,并且用半角逗号隔开。(注:关于这部分代码涉及到MDK的FCARM指令,更多相关介绍可以看此贴http://bbs.armfly.com/read.php?tid=35496 。)
接下来就是配置此文件,在MDK工程目录中右击此文件:
44.31.png
弹出如下窗口:
44.32.png
需要填写的参数如下:
  1. $KARM\bin\fcarm @@Web\Web.inp
复制代码
这么一条看似简单的参数,却包含了很多信息,首先开头的字符$和字符K是两个命令参数,他们都属于MDK的工具参数(关于MDK工具参数的详情看此贴:http://bbs.armfly.com/read.php?tid=35484)。
(1K : 表示MDK的安装目录,比如我这里是安装在了C盘,用的MDK4.74,即路径C:\Keil_v474\。
(2)$ : 表示后面跟的代码是一个路径,配合字符K就表示路径C:\Keil_v474\。
(3)而$K后面的代码ARM\bin\fcarm就是fcarm.exe文件在MDK安装目录的具体路径了。这里通过$K巧妙的屏蔽了大家将MDK安装在不同的盘符。
(4)fcarm@@Web\Web.inp
      这里算是执行命令fcarm,即FCARM @commandfile,这里的操作就是执行文件Web.inp里面的内容,即:fcarm weixin.jpg, index.htm to web.c nopr root(Web)
      大家可能注意到,为什么这里两个字符@,因为在命令行中,字符$, #, %, @, ~, ^都需要写两次,即$$, ##, %%, @@, ~~, ^^。更多详情看帖子:http://bbs.armfly.com/read.php?tid=35484 里面的说明。

至此,最麻烦的Web.inp文件就算完成了,在第3步的末尾,大家就会看到FCARM命令在编译MDK时的效果:
44.33.png
这个里面的Custom:C:\Keil_v474\ARM\bin\fcarm @Web\Web.inp就是我们前面啰嗦了那么多的最终效果。

44.5.2 第2步:添加网页文件到MDK工程
      首先将前面44.4小节中的两个文件(以后自己设计网页时,所有完成的htm类型文件和图片文件都要复制):
44.34.png
复制到Web文件夹中:
44.35.png
关于这两个文件加入或者不加入到MDK工程项目中均可,不过强烈建议htm类型的文件要加入,因为方便我们直接在MDK中就可以做修改,而图片weixin.jpg就无需加入了,因为加入到MDK后只能看到乱码,没有加入的价值。
     添加index.htm文件的时候会弹出如下这个选项,要选择Text Document file:
44.36.png
添加后的效果:
44.37.png
添加后,打开index.htm文件,可以看到还可以正常编辑此文件,只是没有使用Notepad++那么方便了,语法没有高亮,代码没有提示功能,代码也无法对齐。不过做一些简单的修改还是非常方便的,适合Web页面的微调。
44.38.png
如果大家需要将图片加入的话,也要选择Text Document file:
44.39.png
加入后打开工程,可以看到显示的内容就是乱码:
44.40.png
所以图片文件没有加入的必要。

44.5.3 第3步:添加网页转换后的Web.c文件
      MDK会自动生成Web.c文件,不需要用户单独创建Web.c。前两部添加了Web.inp和index.htm后就可以全编译工程了(保证其它的配置工作已经做好,主要是使能Net_Config.c文件中的HTTP Server)。
      编译后可以看到Web文件夹中多了一个Web.c文件。
44.41.png
这个Web.c文件务必要添加MDK工程中,否则Web服务器的网页是无法访问的,会出现如下界面:
44.42.png
      另外,大家也可以自己创建空的C文件到MDK中,仅需要保证与Web.inp中设置的文件名一样即可,即创建一个Web.c文件。添加到MDK工程后,里面什么都不需要填写,全编译工程后,此文件里面会自动填充Web相关文件转换后的内容。
      至此,Web网页的设计工作就完成了,最终添加到MDK工程的文件效果如下:
44.43.png
最后,特别注意一点,编译MDK的时候,会有FCARM指令执行的提示:
44.44.png

努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-5 17:04:52 | 显示全部楼层
本帖最后由 席萌0209 于 2018-1-5 17:05 编辑

44.6 访问开发板Web服务器的方法
      (强烈推荐将网线接到路由器或者交换机上面测试,因为已经使能了DHCP,可以自动获取IP地址
      用户可在浏览器中直接输入IP地址访问Web服务器,跟大家访问路由器后台一样,也可以通过NetBIOS Name直接访问,即http://armfly/,这样就无需查看具体IP了。下面我们两种方式都说下。

44.6.1 输入NetBIOS Name访问

1、浏览器输入地址http://armfly/,点击键盘回车键(点击回车后,前面的http://会自动隐藏了)。
44.45.png

2、用户名输入admin,密码输入123456,点击“登录”按钮即可访问:
44.46.png

3、登录Web服务器后的效果如下:
44.47.png


44.6.2 输入IP地址访问
访问Web服务器前,要先获取板子的IP地址。由于已经使能了DHCP,板子可以自动获取IP地址,而且使能了局域网域名NetBIOS,用户只需在电脑端ping armfly就可以获取板子的IP地址,获取方法如下:
(1)WIN+R组合键打开“运行”窗口,输入cmd。
44.48.png
(2)弹出的命令窗口中,输入ping armfly。
44.49.png
(3)输入ping armfly后,回车。
44.50.png
获得IP地址是192.168.1.13。
1、浏览器输入192.168.1.13,点击键盘回车键(IP地址前面加不加http://都没有关系,不加的话,浏览器会自动加上)。
44.51.png
2、用户名输入admin,密码输入123456,点击“登录”按钮即可访问:
44.52.png
3、登录Web服务器后的效果如下:
44.53.png
至此,访问开发板Web服务器的方法已经介绍完毕。


努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-6 16:33:18 | 显示全部楼层
44.7 实验例程说明(RTX)

44.7.1 STM32F407开发板实验
配套例子:
      V5-1063_RL-TCPnet实验_简单Web Server实现(RTX)
实验目的:
      1.     学习网页制作方法和RL-TCPnet的Web服务器实现。
实验内容:
      1.      强烈推荐将网线接到路由器或者交换机上面测试,因为已经使能了DHCP,可以自动获取IP地址。
      2.      用户可在浏览器中直接输入IP地址访问Web服务器,跟大家访问路由器后台一样,也可以通过NetBIOS局域网域名直接访问,即http://armfly/,这样就无需查看具体IP了。
      3.      Web服务器的用户名admin,密码123456。
      4.      关于网页的制作和Web服务器的测试方法,务必看本例子配套的教程,有详细讲解!!!
网页制作:
      详见本章节44.4和44.5小节。
配置向导文件设置(Net_Config.c):
      详见本章节44.2小节。
调试文件设置(Net_Debug.c):
      详见本章节44.3小节。
Web服务器访问效果:
      详见本章节44.6小节。
RTX配置:
      RTX配置向导详情如下:
44.54.png
                              
Task Configuration
(1)Number of concurrent running tasks
      允许创建6个任务,实际创建了如下5个任务:
      AppTaskUserIF任务   :按键消息处理。
      AppTaskLED任务     :LED闪烁。
      AppTaskMsgPro任务 :按键检测。
      AppTaskTCPMain任务:RL-TCPnet测试任务。
      AppTaskStart任务  :启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。
(2)Number of tasks with user-provided stack
      创建的5个任务都是采用自定义堆栈方式。
(3)Run in privileged mode
      设置任务运行在非特权级模式。
RTX任务调试信息:
44.55.png
程序设计:
任务栈大小分配:
      staticuint64_t AppTaskUserIFStk[1024/8];   /* 任务栈 */
      staticuint64_t AppTaskLEDStk[1024/8];      /* 任务栈 */
      staticuint64_t AppTaskMsgProStk[1024/8];  /* 任务栈 */
      staticuint64_t AppTaskTCPMainStk[4096/8]; /* 任务栈 */
      staticuint64_t AppTaskStartStk[1024/8];     /* 任务栈 */
    将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数、浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
44.56.png
RTX初始化:
  1. /*

  2. *********************************************************************************************************

  3. *    函 数 名: main

  4. *    功能说明: 标准c程序入口。

  5. *    形    参: 无

  6. *    返 回 值: 无

  7. *********************************************************************************************************

  8. */

  9. int main (void)

  10. {   

  11.      /* 初始化外设 */

  12.      bsp_Init();

  13.    

  14.      /* 创建启动任务 */

  15.      os_sys_init_user (AppTaskStart,              /* 任务函数 */

  16.                        5,                         /* 任务优先级 */

  17.                        &AppTaskStartStk,          /* 任务栈 */

  18.                        sizeof(AppTaskStartStk));  /* 任务栈大小,单位字节数 */

  19.      while(1);

  20. }
复制代码

硬件外设初始化
      硬件外设的初始化是在 bsp.c 文件实现:
  1. /*

  2. *********************************************************************************************************

  3. *    函 数 名: bsp_Init

  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次

  5. *    形    参:无

  6. *    返 回 值: 无

  7. *********************************************************************************************************

  8. */

  9. void bsp_Init(void)

  10. {

  11.      /*

  12.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。

  13.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。



  14.          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件

  15.      */

  16.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/

  17.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);



  18.      bsp_InitDWT();     /* 初始化DWT */

  19.      bsp_InitUart();    /* 初始化串口 */

  20.      bsp_InitKey();    /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */

  21.      bsp_InitLed();    /* 初始LED指示灯端口 */

  22. }
复制代码

RTX任务创建:
  1. /*

  2. *********************************************************************************************************

  3. *    函 数 名: AppTaskCreate

  4. *    功能说明: 创建应用任务

  5. *    形    参: 无

  6. *    返 回 值: 无

  7. *********************************************************************************************************

  8. */

  9. static void AppTaskCreate (void)

  10. {

  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */

  12.                                            1,                         /* 任务优先级 */

  13.                                            &AppTaskUserIFStk,         /* 任务栈 */

  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */

  15.    

  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */

  17.                                         2,                       /* 任务优先级 */

  18.                                         &AppTaskLEDStk,          /* 任务栈 */

  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */

  20.    

  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */

  22.                                            3,                         /* 任务优先级 */

  23.                                            &AppTaskMsgProStk,         /* 任务栈 */

  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */

  25.    

  26.     HandleTaskTCPMain = os_tsk_create_user(AppTaskTCPMain,             /* 任务函数 */

  27.                                            4,                         /* 任务优先级 */

  28.                                            &AppTaskTCPMainStk,         /* 任务栈 */

  29.                                            sizeof(AppTaskTCPMainStk)); /* 任务栈大小,单位字节数 */

  30. }
复制代码

五个RTX任务的实现:
  1. /*

  2. *********************************************************************************************************

  3. *    函 数 名: AppTaskUserIF

  4. *    功能说明: 按键消息处理     

  5. *    形    参: 无

  6. *    返 回 值: 无

  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)

  8. *********************************************************************************************************

  9. */

  10. __task void AppTaskUserIF(void)

  11. {

  12.      uint8_t ucKeyCode;



  13.     while(1)

  14.     {

  15.          ucKeyCode = bsp_GetKey();

  16.         

  17.          if (ucKeyCode != KEY_NONE)

  18.          {

  19.               switch (ucKeyCode)

  20.               {

  21.                    /* K1键按下 */

  22.                    case KEY_DOWN_K1:

  23.                        printf("K1键按下\r\n");        

  24.                        break;  



  25.                    /* K2键按下 */

  26.                    case KEY_DOWN_K2:

  27.                        printf("K2键按下\r\n");        

  28.                        break;  

  29.                   

  30.                    /* K3键按下 */

  31.                    case KEY_DOWN_K3:

  32.                        printf("K3键按下\r\n");

  33.                        break;

  34.                                     

  35.                    /* 其他的键值不处理 */

  36.                    default:                    

  37.                        break;

  38.               }

  39.          }

  40.         

  41.          os_dly_wait(20);

  42.      }

  43. }



  44. /*

  45. *********************************************************************************************************

  46. *    函 数 名: AppTaskLED

  47. *    功能说明: LED闪烁。

  48. *    形    参: 无

  49. *    返 回 值: 无

  50. *   优 先 级: 2

  51. *********************************************************************************************************

  52. */

  53. __task void AppTaskLED(void)

  54. {

  55.      const uint16_t usFrequency = 500; /* 延迟周期 */

  56.    

  57.      /* 设置延迟周期 */

  58.      os_itv_set(usFrequency);

  59.    

  60.     while(1)

  61.     {

  62.          bsp_LedToggle(2);



  63.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/

  64.          os_itv_wait();

  65.     }

  66. }



  67. /*

  68. *********************************************************************************************************

  69. *    函 数 名: AppTaskMsgPro

  70. *    功能说明: 按键检测

  71. *    形    参: 无

  72. *    返 回 值: 无

  73. *   优 先 级: 3

  74. *********************************************************************************************************

  75. */

  76. __task void AppTaskMsgPro(void)

  77. {

  78.     while(1)

  79.     {

  80.          bsp_KeyScan();

  81.          os_dly_wait(10);

  82.     }

  83. }



  84. /*

  85. *********************************************************************************************************

  86. *    函 数 名: AppTaskTCPMain

  87. *    功能说明: RL-TCPnet测试任务

  88. *    形    参: 无

  89. *    返 回 值: 无

  90. *   优 先 级: 4

  91. *********************************************************************************************************

  92. */

  93. __task void AppTaskTCPMain(void)

  94. {

  95.      while (1)

  96.      {

  97.          TCPnetTest();

  98.      }

  99. }



  100. /*

  101. *********************************************************************************************************

  102. *    函 数 名: AppTaskStart

  103. *    功能说明: 启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。

  104. *    形    参: 无

  105. *    返 回 值: 无

  106. *   优 先 级: 5

  107. *********************************************************************************************************

  108. */

  109. __task void AppTaskStart(void)

  110. {

  111.      /* 初始化RL-TCPnet */

  112.      init_TcpNet ();

  113.    

  114.      /* 创建任务 */

  115.      AppTaskCreate();

  116.    

  117.      os_itv_set (100);

  118.    

  119.     while(1)

  120.     {

  121.          os_itv_wait ();

  122.         

  123.          /* RL-TCPnet时间基准更新函数 */

  124.          timer_tick ();

  125.          os_evt_set(0x0001, HandleTaskTCPMain);

  126.     }

  127. }
复制代码

RL-TCPnet功能测试
      这里专门创建了一个app_tcpnet_lib.c文件用于RL-TCPnet功能的测试,此文件主要实现网络主函数main_TcpNet的调用。
  1. #include "includes.h"







  2. /*

  3. *********************************************************************************************************

  4. *    函 数 名: TCPnetTest

  5. *    功能说明: TCPent测试函数。

  6. *    形    参: 无

  7. *    返 回 值: 无

  8. *********************************************************************************************************

  9. */

  10. void TCPnetTest(void)

  11. {

  12.    

  13.      while (1)

  14.      {

  15.          os_evt_wait_or(0x0001, 0xFFFF);

  16.         

  17.          /* RL-TCPnet主处理函数 */      

  18.          while (main_TcpNet() == __TRUE);

  19.      }

  20. }
复制代码



努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-6 16:37:50 | 显示全部楼层
44.7.2 STM32F429开发板实验
配套例子:
      V6-1063_RL-TCPnet实验_简单Web Server实现(RTX)
实验目的:
      1.     学习网页制作方法和RL-TCPnet的Web服务器实现。
实验内容:
      1.      强烈推荐将网线接到路由器或者交换机上面测试,因为已经使能了DHCP,可以自动获取IP地址。
      2.      用户可在浏览器中直接输入IP地址访问Web服务器,跟大家访问路由器后台一样,也可以通过NetBIOS局域网域名直接访问,即http://armfly/,这样就无需查看具体IP了。
      3.      Web服务器的用户名admin,密码123456。
      4.      关于网页的制作和Web服务器的测试方法,务必看本例子配套的教程,有详细讲解!!!
网页制作:
      详见本章节44.4和44.5小节。
配置向导文件设置(Net_Config.c):
      详见本章节44.2小节。
调试文件设置(Net_Debug.c):
      详见本章节44.3小节。
Web服务器访问效果:
      详见本章节44.6小节。
RTX配置:
      RTX配置向导详情如下:
44.57.png
                              
Task Configuration
(1)Number of concurrent running tasks
      允许创建6个任务,实际创建了如下5个任务:
      AppTaskUserIF任务   :按键消息处理。
      AppTaskLED任务     :LED闪烁。
      AppTaskMsgPro任务 :按键检测。
      AppTaskTCPMain任务:RL-TCPnet测试任务。
      AppTaskStart任务  :启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。
(2)Number of tasks with user-provided stack
      创建的5个任务都是采用自定义堆栈方式。
(3)Run in privileged mode
      设置任务运行在非特权级模式。
RTX任务调试信息:
44.58.png
程序设计:
任务栈大小分配:
     staticuint64_t AppTaskUserIFStk[1024/8];   /* 任务栈 */
     staticuint64_t AppTaskLEDStk[1024/8];      /* 任务栈 */
     staticuint64_t AppTaskMsgProStk[1024/8];  /* 任务栈 */
     staticuint64_t AppTaskTCPMainStk[4096/8]; /* 任务栈 */
     staticuint64_t AppTaskStartStk[1024/8];     /* 任务栈 */
      将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数、浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
44.59.png
RTX初始化:
  1. /*

  2. *********************************************************************************************************

  3. *    函 数 名: main

  4. *    功能说明: 标准c程序入口。

  5. *    形    参: 无

  6. *    返 回 值: 无

  7. *********************************************************************************************************

  8. */

  9. int main (void)

  10. {   

  11.      /* 初始化外设 */

  12.      bsp_Init();

  13.    

  14.      /* 创建启动任务 */

  15.      os_sys_init_user (AppTaskStart,              /* 任务函数 */

  16.                        5,                         /* 任务优先级 */

  17.                        &AppTaskStartStk,          /* 任务栈 */

  18.                        sizeof(AppTaskStartStk));  /* 任务栈大小,单位字节数 */

  19.      while(1);

  20. }
复制代码

硬件外设初始化
     硬件外设的初始化是在 bsp.c 文件实现:
  1. /*

  2. *********************************************************************************************************

  3. *    函 数 名: bsp_Init

  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次

  5. *    形    参:无

  6. *    返 回 值: 无

  7. *********************************************************************************************************

  8. */

  9. void bsp_Init(void)

  10. {

  11.      /*

  12.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。

  13.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。



  14.          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件

  15.      */

  16.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/

  17.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);



  18.      SystemCoreClockUpdate();    /* 根据PLL配置更新系统时钟频率变量 SystemCoreClock */



  19.      bsp_InitDWT();      /* 初始化DWT */

  20.      bsp_InitUart();     /* 初始化串口 */

  21.      bsp_InitKey();     /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */



  22.      bsp_InitExtIO();    /* FMC总线上扩展了32位输出IO, 操作LED等外设必须初始化 */

  23.      bsp_InitLed();      /* 初始LED指示灯端口 */

  24. }
复制代码

RTX任务创建:
  1. /*

  2. *********************************************************************************************************

  3. *    函 数 名: AppTaskCreate

  4. *    功能说明: 创建应用任务

  5. *    形    参: 无

  6. *    返 回 值: 无

  7. *********************************************************************************************************

  8. */

  9. static void AppTaskCreate (void)

  10. {

  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */

  12.                                            1,                         /* 任务优先级 */

  13.                                            &AppTaskUserIFStk,         /* 任务栈 */

  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */

  15.    

  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */

  17.                                         2,                       /* 任务优先级 */

  18.                                         &AppTaskLEDStk,          /* 任务栈 */

  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */

  20.    

  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */

  22.                                            3,                         /* 任务优先级 */

  23.                                            &AppTaskMsgProStk,         /* 任务栈 */

  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */

  25.    

  26.     HandleTaskTCPMain = os_tsk_create_user(AppTaskTCPMain,             /* 任务函数 */

  27.                                            4,                         /* 任务优先级 */

  28.                                            &AppTaskTCPMainStk,         /* 任务栈 */

  29.                                            sizeof(AppTaskTCPMainStk)); /* 任务栈大小,单位字节数 */

  30. }
复制代码

五个RTX任务的实现:
  1. /*

  2. *********************************************************************************************************

  3. *    函 数 名: AppTaskUserIF

  4. *    功能说明: 按键消息处理     

  5. *    形    参: 无

  6. *    返 回 值: 无

  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)

  8. *********************************************************************************************************

  9. */

  10. __task void AppTaskUserIF(void)

  11. {

  12.      uint8_t ucKeyCode;



  13.     while(1)

  14.     {

  15.          ucKeyCode = bsp_GetKey();

  16.         

  17.          if (ucKeyCode != KEY_NONE)

  18.          {

  19.               switch (ucKeyCode)

  20.               {

  21.                    /* K1键按下 */

  22.                    case KEY_DOWN_K1:

  23.                        printf("K1键按下\r\n");        

  24.                        break;  



  25.                    /* K2键按下 */

  26.                    case KEY_DOWN_K2:

  27.                        printf("K2键按下\r\n");        

  28.                        break;  

  29.                   

  30.                    /* K3键按下 */

  31.                    case KEY_DOWN_K3:

  32.                        printf("K3键按下\r\n");

  33.                        break;

  34.                                     

  35.                    /* 其他的键值不处理 */

  36.                    default:                    

  37.                        break;

  38.               }

  39.          }

  40.         

  41.          os_dly_wait(20);

  42.      }

  43. }



  44. /*

  45. *********************************************************************************************************

  46. *    函 数 名: AppTaskLED

  47. *    功能说明: LED闪烁。

  48. *    形    参: 无

  49. *    返 回 值: 无

  50. *   优 先 级: 2

  51. *********************************************************************************************************

  52. */

  53. __task void AppTaskLED(void)

  54. {

  55.      const uint16_t usFrequency = 500; /* 延迟周期 */

  56.    

  57.      /* 设置延迟周期 */

  58.      os_itv_set(usFrequency);

  59.    

  60.     while(1)

  61.     {

  62.          bsp_LedToggle(2);



  63.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/

  64.          os_itv_wait();

  65.     }

  66. }



  67. /*

  68. *********************************************************************************************************

  69. *    函 数 名: AppTaskMsgPro

  70. *    功能说明: 按键检测

  71. *    形    参: 无

  72. *    返 回 值: 无

  73. *   优 先 级: 3

  74. *********************************************************************************************************

  75. */

  76. __task void AppTaskMsgPro(void)

  77. {

  78.     while(1)

  79.     {

  80.          bsp_KeyScan();

  81.          os_dly_wait(10);

  82.     }

  83. }



  84. /*

  85. *********************************************************************************************************

  86. *    函 数 名: AppTaskTCPMain

  87. *    功能说明: RL-TCPnet测试任务

  88. *    形    参: 无

  89. *    返 回 值: 无

  90. *   优 先 级: 4

  91. *********************************************************************************************************

  92. */

  93. __task void AppTaskTCPMain(void)

  94. {

  95.      while (1)

  96.      {

  97.          TCPnetTest();

  98.      }

  99. }



  100. /*

  101. *********************************************************************************************************

  102. *    函 数 名: AppTaskStart

  103. *    功能说明: 启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。

  104. *    形    参: 无

  105. *    返 回 值: 无

  106. *   优 先 级: 5

  107. *********************************************************************************************************

  108. */

  109. __task void AppTaskStart(void)

  110. {

  111.      /* 初始化RL-TCPnet */

  112.      init_TcpNet ();

  113.    

  114.      /* 创建任务 */

  115.      AppTaskCreate();

  116.    

  117.      os_itv_set (100);

  118.    

  119.     while(1)

  120.     {

  121.          os_itv_wait ();

  122.         

  123.          /* RL-TCPnet时间基准更新函数 */

  124.          timer_tick ();

  125.          os_evt_set(0x0001, HandleTaskTCPMain);

  126.     }

  127. }
复制代码

RL-TCPnet功能测试
      这里专门创建了一个app_tcpnet_lib.c文件用于RL-TCPnet功能的测试,此文件主要实现网络主函数main_TcpNet的调用。
  1. #include "includes.h"







  2. /*

  3. *********************************************************************************************************

  4. *    函 数 名: TCPnetTest

  5. *    功能说明: TCPent测试函数。

  6. *    形    参: 无

  7. *    返 回 值: 无

  8. *********************************************************************************************************

  9. */

  10. void TCPnetTest(void)

  11. {

  12.    

  13.      while (1)

  14.      {

  15.          os_evt_wait_or(0x0001, 0xFFFF);

  16.         

  17.          /* RL-TCPnet主处理函数 */      

  18.          while (main_TcpNet() == __TRUE);

  19.      }

  20. }
复制代码


努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-6 16:38:22 | 显示全部楼层
44.8   总结      

      本章节就为大家讲解这么多,相比前面章节,Web服务器的设计要稍麻烦些,希望大家实际动手操作一遍,并将其熟练掌握。


努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-11-1 07:11 , Processed in 0.306215 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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