硬汉嵌入式论坛

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

[RL-TCPnet教程] 【RL-TCPnet网络教程】第52章 RL-TCPnet之Web服务器的Ajax实现

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2018-1-17 16:00:30 | 显示全部楼层 |阅读模式
第52章    RL-TCPnet之Web服务器的Ajax实现

      本章节为大家讲解RL-TCPnet的Ajax实现动态网页的局部刷新,前面第47章讲解了动态网页的整体刷新,本章节为大家讲解局部刷新方法。
      本章教程含STM32F407开发板和STM32F429开发板。
52.1 初学者重要提示
52.2 HTTP配置说明(Net_Config.c)
52.3 HTTP调试说明(Net_Debug.c)
52.4 制作HTML,CGI和XML文件
52.5 访问开发板Web服务器的方法
52.6 实验例程说明(RTX)
52.7      总结



52.1  初学者重要提示
1、学习本章节前,务必保证已经学习了第48,49,50和51章节,如果没有学习就直接学习本章节的话,将比较吃力,特别是Ajax相关知识点的理解、网页制作以及工程建立的时候。
2、前面第47章使用CGI脚本做网页更新时,整个页面都会重新加载,而本章节学习的Ajax可以做网页局部刷新。

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

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-17 16:16:22 | 显示全部楼层
52.2  HTTP配置说明(Net_Config.c)
      (本章节配套例子的配置与本小节的说明相同)
      RL-TCPnet的配置工作是通过配置文件Net_Config.c实现。在MDK工程中打开文件Net_Config.c,可以看到下图所示的工程配置向导:
2.1.png
                              
RL-TCPnet要配置的选项非常多,我们这里把几个主要的配置选项简单介绍下。
2.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。
2.3.png
Ethernet Network Interface
      以太网接口配置,勾选了此选项就可以配置了,如果没有使能DHCP的话,将使用这里配置的固定IP
(1)MAC Address
      局域网内可以随意配置,只要不跟局域网内其它设备的MAC地址冲突即可。
(2)IP Address
      IP地址。
(3)Subnet mask
      子网掩码。
(4)Default Gateway
      默认网关。
2.4.png
Ethernet Network Interface
      以太网接口配置,这个配置里面还有如下两项比较重要的配置需要说明。
(1)NetBIOS Name Service
      NetBIOS局域网域名服务,这里打上对勾就使能了。这样我们就可以通过前面配置的Local Host Name局域网域名进行访问,而不需要通过IP地址访问了。
(2)Dynaminc Host Configuration
      即DHCP,这里打上对勾就使能了。使能了DHCP后,RL-TCPnet就可以从外接的路由器上获得动态IP地址。
2.5.png
UDP Sockets
      UDP Sockets配置,打上对勾就使能了此项功能
(1)Number of UDP Sockets
      用于配置可创建的UDP Sockets数量,这里配置了5个。
      范围1 – 20。
2.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接收窗口大小。
2.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 用户密码。

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

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

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-17 16:38:46 | 显示全部楼层
本帖最后由 席萌0209 于 2018-1-17 16:40 编辑

52.4 制作HTML,CGI和XML文件
      下面要制作的网页是在前面第44章的基础上实现的,所以第44章节的网页制作方法务必要掌握。我们这里实现一个如下的网页效果:
2.10.png
                              
点击网页中的“温度监控”后,弹出如下的页面:
2.11.png
点击网页中的“无源蜂鸣器控制”后,弹出如下的页面:
2.12.png
对比第44章制作的网页,主页面上面多了一个小房子一样的图标(用于返回主页面)以及“温度监控”和“无源蜂鸣器控制”链接。这三个都比较好实现,看下面代码中置红的部分:
  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.         <tr bgcolor="#EEEEEE">

  11.           <td style="border-bottom: 1px solid #000080" valign="bottom" nowrap="nowrap" height="90"

  12. margin="50" width="700">

  13.             <h1 align="center">

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

  15.                 <a href="index.htm">

  16.                  <img border="0" src="home.png" align="center" width="31" height="29">

  17.                 </a>

  18.             </h1>

  19.           </td>

  20.         </tr>

  21.         <tr bgcolor="#EEEEEE">

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

  23.             <h2 align="center">

  24.               <b>

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

  26.               </b>

  27.             </h2>

  28.             <p align="center">

  29.               <img border="0" src="weixin.jpg" width="200" height="200"/>

  30.             </p>

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

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

  33.             </p>

  34.             <p align="center">

  35.                    <a href="/ds18b20.cgi">温度监控</a> |

  36.                    <a href="/beep.cgi">无源蜂鸣器控制</a>

  37.             </p>

  38.           </td>

  39.         </tr>

  40.         

  41.         <tr bgcolor="#EEEEEE">

  42.           <td width="800">

  43.             <p align="center">

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

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

  46.             </p>

  47.           </td>

  48.         </tr>

  49.       </table>

  50.     </div>

  51.   </body>

  52. </html>
复制代码
主页面做好之后,就是子页面的设计了。这个子页面是我们本章节的重点。

52.4.1 第1步:制作蜂鸣器控制页面的HTML文件
      Notepad++的设置就不再赘述了,前面第44章已经详细讲解,我们这里的编码字符集依然要选择GB2312。页面的HTML代码如下:
  1. <html>

  2.   <head>

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

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

  5.      <script language=JavaScript type="text/javascript" src="xml_http.js"></script>

  6.      <script>

  7.        var formUpdate = new periodicObj("beep.cgx", 300);

  8.      </script>

  9.   </head>

  10.   <body>

  11.     <br />

  12.     <div align="center">

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

  14.         <tr bgcolor="#EEEEEE">

  15.           <td style="border-bottom: 1px solid #000080" valign="bottom" nowrap="nowrap" height="90"

  16.   margin="50" width="700">

  17.             <h1 align="center">

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

  19.                 <a href="index.htm">

  20.                  <img border="0" src="home.png" align="center" width="31" height="29">

  21.                 </a>

  22.             </h1>

  23.           </td>

  24.         </tr>

  25.         

  26.         <tr bgcolor="#EEEEEE">

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

  28.           <h2 align="center">

  29.           <br />无源蜂鸣器控制</h2>

  30.           <p align="left">

  31.             <font size="3">1. 无源蜂鸣器的控制采用JavaScript + XML,

  32.              从而点击按钮控制的时候实现平滑且无闪烁的更新效果。<br/>2. 如果用的比较老的V5开发板,

  33.              请查看板子上面是否有无源蜂鸣器,后来出的V5板子都带无源蜂鸣器,V6板子都带无源蜂鸣器。

  34.             <br />

  35.             <br /></font>

  36.           </p>

  37.           <form action="beep.cgi" method="post" name="form">

  38.             <table border="0" width="90%" align="center">

  39.               <tr bgcolor="#AACCFF">

  40.                 <th width="40%">

  41.                   <font size="3">选项</font>

  42.                 </th>

  43.                 <th width="60%">设置</th>

  44.               </tr>

  45.               <tr>

  46.                 <td>

  47.                 蜂鸣器控制:

  48.                    </td>

  49.                 <td>

  50.                  <input type="button" id="Btn1" value="蜂鸣器响两次" onclick="updateMultiple(formUpdate)">

  51.                 </td>                                                                     

  52.               </tr>

  53.             </table>

  54.           </form>

  55.         </td>

  56.       </tr>

  57.         

  58.         <tr bgcolor="#EEEEEE">

  59.           <td width="800">

  60.             <p align="center">

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

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

  63.             </p>

  64.           </td>

  65.         </tr>

  66.       </table>

  67.     </div>

  68.   </body>

  69. </html>
复制代码
实际测试显示效果:
2.13.png
对于这个子界面,主要是插入了JavaScript。当用户在浏览器上按下“蜂鸣器响两次”的按钮后,会触发按钮事件onclick=“updateMultiple(formUpdate)”,从而浏览器会从服务器下载JavaScript函数updateMultiple()并执行,函数updateMultiple是在xml_http.js(以MDK4.74为例,在MDK安装目录的C:\Keil_v474\ARM\RL\TCPnet\Java文件里面)文件中实现。
      函数updateMultiple的形参是formUpdate,这个是在子界面中创建的JavaScript对象:
  1. var formUpdate = new periodicObj("beep.cgx", 300);
复制代码
而函数periodicObj也是在xml_http.js中实现,定义了周期性更新的文件,时间单位ms。这里是浏览器300ms后下载一次beep.cgx文件进行更新。

52.4.2 第2步:制作蜂鸣器页面所需的XML文件
      这一步,我们需要制作XML文件beep.cgx(XML文件一定要以cgx作为后缀),这个文件制作比较简单,内容也比较简单。大家直接在MDK里面新建一个文件。
新建文件:
2.14.png
点击保存:
2.15.png
点击保存后弹出如下窗口:
2.16.png
保存后,将新建的文件beep.cgx添加到工程里面,鼠标双击RL-TCPnet/Web分组。
2.17.png
弹出如下对话框,选择beep.cgx文件:
2.18.png
这一步比较重要了,点击Add后,弹出如下窗口:
2.19.png
点击OK后,文件beep.cgx就已经添加到MDK工程项目里面了,然后点击Close按钮,关闭弹出的窗口:
2.20.png
文件添加上之后,就是如何编辑和设置这个文件了,beep.cgx文件的实现如下。
  1. t <form>

  2. t <button>

  3. t <id>Btn1</id>

  4. c q1

  5. t </button>

  6. t </form>

  7. .
复制代码
对于XML文件来说,仅写入要更新的元素即可,并以标签<form>开始,标签</form>结束。这个XML文件里面也有CGI脚本命令(特别注意末尾的点号不可省略,表示文件结束),会触发HTTP_CGI.c文件中的脚本解析函数cgi_func的执行:
  1. /* BEEP Input - xml file 'beep.cgx' */

  2.      case 'q':

  3.         switch (env[1]) {

  4.         case '1':

  5.               BEEP_Start(5, 1, 2);

  6.               break;

  7.          }

  8.        len = 0;

  9.       break;
复制代码
我们这里仅执行了蜂鸣器的鸣响函数,无返回数据。至此,就完成了无源蜂鸣器的控制。

52.4.3 第3步:制作温度监控页面的HTML文件
      Notepad++的设置就不再赘述了,前面第44章已经详细讲解,我们这里的编码字符集依然要选择GB2312。页面的HTML代码如下:
  1. <html>

  2.   <head>

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

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

  5.     <script language="JavaScript" type="text/javascript" src="xml_http.js"></script>

  6.     <script>

  7.      var formUpdate = new periodicObj("ds18b20.cgx";, 500);

  8.      function periodicUpdateTemp()

  9.      {

  10.          if(document.getElementById("TempChkBox").checked == true)

  11.          {

  12.               updateMultiple(formUpdate);

  13.               TempTime = setTimeout(periodicUpdateTemp, formUpdate.period);

  14.          }

  15.          else

  16.          {

  17.               clearTimeout(TempTime);                                

  18.          }

  19.      }

  20.     </script>

  21. </head>

  22.   <body>

  23.     <br />

  24.     <div align="center">

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

  26.         <tr bgcolor="#EEEEEE">

  27.           <td style="border-bottom: 1px solid #000080" valign="bottom" nowrap="nowrap" height="90" margin="50"

  28.                width="700">

  29.             <h1 align="center">

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

  31.             <a href="index.htm">

  32.               <img border="0" src="home.png" align="center" width="31" height="29" />

  33.             </a></h1>

  34.           </td>

  35.         </tr>

  36.         <tr bgcolor="#EEEEEE">

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

  38.             <h2 align="center">

  39.             <br />温度监控</h2>

  40.             <p align="left">

  41.               <font size="3">1. 本页的数据更新支持手动和自动,自动更新是基于JavaScript + XML,

  42.               从而实现平滑且无闪烁的更新效果。

  43.               <br />2. 测试前请务必将DS18B20器件插到开发板上。

  44.               <br />3. 为了保证

  45.               RTC实时时钟能够正常起振,下载程序后将板子断电然后重新上电再测试。

  46.               <br />

  47.               <br /></font>

  48.             </p>

  49.             <form action="ds18b20.cgx" method="post" name="form">

  50.               <table border="0" width="90%" align="center">

  51.                 <tr bgcolor="#AACCFF">

  52.                   <th width="20%">

  53.                     <font size="3">选项</font>

  54.                   </th>

  55.                   <th width="40%">

  56.                     <font size="3">RTC实时时钟</font>

  57.                   </th>

  58.                   <th width="40%">

  59.                     <font size="3">温度</font>

  60.                   </th>

  61.                 </tr>

  62.                 <tr>

  63.                   <td style="background-color: transparent; border:0px; font-size:16px">DS18B20:</td>

  64.                   <td align="center">

  65.                     <input type="text" readonly="readonly" style="background-color:transparent; border:0px;

  66.                        font-size:16px"

  67.                     size="6" id="rtc_value" value="%0.2d:%0.2d:%0.2d" />

  68.                   </td>

  69.                   <td align="center">

  70.                     <input type="text" readonly="readonly" style="background-color: transparent; border:

  71.                        0px;font-size:16px"

  72.                     size="6" id="temperature " value="%4.1f C" />

  73.                   </td>

  74.                 </tr>

  75.               </table>

  76.               <p align="center">

  77.               <input type="button" value="手动更新" onclick="updateMultiple(formUpdate)" />

  78.               <br />

  79.               <br />自动更新:

  80.               <input type="checkbox" id="TempChkBox" onclick="periodicUpdateTemp()" /></p>

  81.             </form>

  82.           </td>

  83.         </tr>

  84.         <tr bgcolor="#EEEEEE">

  85.           <td width="800">

  86.             <p align="center">

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

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

  89.             </p>

  90.           </td>

  91.         </tr>

  92.       </table>

  93.     </div>

  94.   </body>

  95. </html>
复制代码
实际测试显示效果:
2.21.png
对于这个子界面,“手动更新”按钮实现的功能跟第1步中无源蜂鸣器控制按钮实现的功能是一样的,只是这里是500ms。下面重点说下“自动更新”的复选框,如果用户选中了定期更新复选框,浏览器将调用函数periodicUpdateTemp()并执行。
  1. var formUpdate = new periodicObj("ds18b20.cgx";, 500);

  2. function periodicUpdateTemp()

  3. {

  4.      if(document.getElementById("TempChkBox").checked == true)

  5.      {

  6.          updateMultiple(formUpdate);

  7.          TempTime = setTimeout(periodicUpdateTemp, formUpdate.period);

  8.      }

  9.      else

  10.      {

  11.          clearTimeout(TempTime);                              

  12.      }

  13. }
复制代码
1、函数的主要功能是判断复选框是否选中了,如果选中了,将调用函数updateMultiple来更新温度数值和RTC时间,并返回给浏览器。这里通过函数setTimeout启动了一个单次定时器,设置时间为formUpdate.period,单位毫秒。时间到后会再次调用函数periodicUpdateTemp,从而实现了周期性更新的效果。
2、如果复选框取消选中或者未选中,调用函数clearTimeout停止开启的单次定时器。

52.4.4 第4步:将温度监控页面的HTML文件改为CGI文件
      由于我们希望用户打开温度监控页面就可以看到更新的温度数值和RTC时间,需要将这个HTML修改为CGI文件。
  1. t <html>

  2. t <head>

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

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

  5. t <script language=JavaScript type="text/javascript" src="xml_http.js"></script>

  6. t <script>

  7. t var formUpdate = new periodicObj("ds18b20.cgx", 500);

  8. t function periodicUpdateTemp()

  9. t {

  10. t if(document.getElementById("TempChkBox").checked == true)

  11. t {

  12. t updateMultiple(formUpdate);

  13. t TempTime = setTimeout(periodicUpdateTemp, formUpdate.period);

  14. t }

  15. t else

  16. t {

  17. t clearTimeout(TempTime);               

  18. t }

  19. t }

  20. t </script>

  21. t </head>

  22. t <body>

  23. t <br />

  24. t <div align="center">

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

  26. t <tr bgcolor="#EEEEEE">

  27. t <td style="border-bottom: 1px solid #000080" valign="bottom" nowrap="nowrap" height="90"  margin="50" width="700">

  28. t <h1 align="center">

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

  30. t <a href="index.htm">

  31. t <img border="0" src="home.png" align="center" width="31" height="29">

  32. t </a>

  33. t </h1>

  34. t </td>

  35. t </tr>

  36. t <tr bgcolor="#EEEEEE">

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

  38. t <h2 align="center">

  39. t <br />温度监控</h2>

  40. t <p align="left">

  41. t <font size="3">1. 本页的数据更新支持手动和自动,自动更新是基于JavaScript + XML,

  42. t 从而实现平滑且无闪烁的更新效果。<br/>2. 测试前请务必将DS18B20器件插到开发板上。<br/>3. 为了保证

  43. t RTC实时时钟能够正常起振,下载程序后将板子断电然后重新上电再测试。

  44. t <br />

  45. t <br /></font>

  46. t </p>

  47. t <form action="ds18b20.cgx" method="post" name="form">

  48. t <table border="0" width="90%" align="center">

  49. t <tr bgcolor="#AACCFF">

  50. t <th width="20%"><font size="3">选项</font></th>

  51. t <th width="40%"><font size="3">RTC实时时钟</font></th>

  52. t <th width="40%"><font size="3">温度</font></th>

  53. t </tr>

  54. t <tr>

  55. t <td style="background-color: transparent; border:0px; font-size:16px">

  56. t DS18B20:

  57. t </td>

  58. t <td align="center">

  59. t <input type="text" readonly style="background-color:transparent; border:0px; font-size:16px"

  60. c g 1  size="6" id="rtc_value" value="%0.2d:%0.2d:%0.2d"></td>

  61. t <td align="center">

  62. t <input type="text" readonly="readonly" style="background-color: transparent; border: 0px;font-size:16px" size="6"

  63. c g 2 id="temperature " value="%4.1f C" />

  64. t </td>

  65. t </tr>

  66. t </table>

  67. t <p align="center">

  68. t <input type="button" value="手动更新" onclick="updateMultiple(formUpdate)" />

  69. t <br />

  70. t <br />自动更新:

  71. t <input type="checkbox" id="TempChkBox" onclick="periodicUpdateTemp()" /></p>

  72. t </form>

  73. t </td>

  74. t </tr>

  75. t <tr bgcolor="#EEEEEE">

  76. t <td width="800">

  77. t <p align="center">

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

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

  80. t </p>

  81. t </td>

  82. t </tr>

  83. t </table>

  84. t </div>

  85. t </body>

  86. t </html>

  87. .
复制代码
主要在上面代码中置红的语句前加上c命令行即可。这样一来,打开温度监控页面就会看到更新的RTC时间和温度数值。c命令行会触发HTTP_CGI.c文件中cgi_func函数的执行,进行命令行解析。
  1. case 'g':

  2.   /* DS18B20 Input - xml file 'ds180b20.cgi' */

  3.   switch (env[2]) {

  4.      case '1':

  5.            RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);

  6.            len = sprintf((char *)buf,(const char *)&env[4],  RTC_TimeStructure.RTC_Hours,

  7.                                                                     RTC_TimeStructure.RTC_Minutes,

  8.                                                                     RTC_TimeStructure.RTC_Seconds);

  9.        break;

  10.          

  11.      case '2':

  12.        len = sprintf((char *)buf,(const char *)&env[4],(float)iTemp/16);

  13.        break;

  14.   }

  15.   break;
复制代码
字符命令“g1”会返回RTC时间,字符命令“g2”会返回温度数值。

52.4.5 第5步:制作温度控制页面所需的XML文件
     这一步要制作ds18b20.cgx文件,制作方法同52.4.2小节,这里就不重复讲解了,内容如下:
  1. t <form>

  2. t <text>

  3. t <id>temperature</id>

  4. c x<value>%4.1f C</value>

  5. t </text>

  6. t <text>

  7. t <id>rtc_value</id>

  8. c p<value>%0.2d:%0.2d:%0.2d</value>

  9. t </text>

  10. t </form>

  11. .
复制代码
对于XML文件来说,仅写入要更新的元素即可,并以标签<form>开始,标签</form>结束。这个XML文件里面也有CGI脚本命令(特别注意文件末尾的点号不可省略,表示文件结束),会触发HTTP_CGI.c文件中的脚本解析函数cgi_func的执行:
  1. case 'p':

  2.   /* DS18B20 Input - xml file 'ds180b20.cgx' */

  3.   RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);

  4.   len = sprintf((char *)buf,(const char *)&env[1], RTC_TimeStructure.RTC_Hours,

  5.                                                     RTC_TimeStructure.RTC_Minutes,

  6.                                                     RTC_TimeStructure.RTC_Seconds);

  7.   break;



  8. case 'x':

  9.   /* DS18B20 Input - xml file 'ds180b20.cgx' */

  10.   len = sprintf((char *)buf,(const char *)&env[1], (float)iTemp/16);

  11.   break;
复制代码
收到字符命令“p”会返回RTC时间,收到字符命令“x”会返回DS18B20的温度值。

52.4.6 第6步:最后一步,所需的文件都添加上
      添加方法和网页相关文件的存放路径位置已经在前面第44章节详细进行了说明,我们这里不再赘述。如果还没有掌握好,务必要返回第44章学习如何添加
1、添加index.htm,beep.htm,beep.cgx,ds18b20.cgi和ds18b20.cgx文件到MDK工程。
2.22.png
2、新建并添加一个Web.inp文件到MDK工程。
      这个文件要设置的地方较多,详情看第44章。
2.23.png
文件Web.inp填写的内容如下:
  1. weixin.jpg,

  2. beep.htm,

  3. beep.cgx,

  4. home.png,

  5. ds18b20.cgi,

  6. ds18b20.cgx,

  7. xml_http.js,

  8. <font size="3">index.htm to Web.c nopr root(Web)</font>
复制代码
这里是将文件weixin.jpg,beep.htm,beep.cgx,home.png,ds18b20.cgi,ds18b20.cgx,xml_http.js和index.htm通过FCARM命令转换后存到Web.c文件里面。
3、添加HTTP_CGI.c文件。
      这个文件也要添加到MDK中,此文件在MDK4.74安装目录:C:\Keil_v474\ARM\RL\TCPnet\User里面。我们这里将其复制到工程目录:\RL-ARM\RL-TCPnet里面了。用户添加此文件到MDK工程中后,要根据自己设计的网页来修改此文件。具体此文件的实现看本章节配套的例子即可。
      HTTP_CGI.c文件也添加到MDK工程后:
2.24.png
4、添加xml_http.js文件。
      这个是最后一步了,添加xml_http.js(以MDK4.74为例,在MDK安装目录的C:\Keil_v474\ARM\RL\TCPnet\Java文件里面)文件。
2.25.png
现在就可以全编译了,全编译后,将生成的Web.c文件(关于此文件的添加和相关问题看第44章)也添加进来:
2.26.png
这个Web.c文件务必要添加进来,否则会出现Web服务器网页无法访问的情况:
2.27.png
最后,下载程序到开发板之前,最好再全编译一遍,防止Web.c文件中的网页内容没有参与编译。

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

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-17 16:48:13 | 显示全部楼层
52.5 访问开发板Web服务器的方法
      (强烈推荐将网线接到路由器或者交换机上面测试,因为已经使能了DHCP,可以自动获取IP地址)
      用户可在浏览器中直接输入IP地址访问Web服务器,跟大家访问路由器后台一样,也可以通过NetBIOS Name直接访问,即http://armfly/,这样就无需查看具体IP了。下面我们两种方式都说下。

52.5.1 输入NetBIOS Name访问
1、浏览器输入地址http://armfly/,点击键盘回车键(点击回车后,前面的http://会自动隐藏了)。
2.28.png
2、用户名输入admin,密码输入123456,点击“登录”按钮即可访问。
2.29.png
3、登录Web服务器后的效果如下:
2.30.png
4、点击页面上的“温度监控”超链接,进入温度控制页面。点击“手动更新”按钮,仅更新一次数据。
     选中“自动更新”复选框会每500ms更新一次RTC时间和温度值,取消选中,关闭更新。
2.31.png
5、点击页面上的“无源蜂鸣器控制”超链接,进入蜂鸣器控制页面。点击“蜂鸣器鸣响两次”按钮,会听到蜂鸣器鸣响两次。
2.32.png

52.5.2 输入IP地址访问
      访问Web服务器前,要先获取板子的IP地址。由于已经使能了DHCP,板子可以自动获取IP地址,而且使能了局域网域名NetBIOS,用户只需在电脑端ping armfly就可以获取板子的IP地址,获取方法如下:
       (1)WIN+R组合键打开“运行”窗口,输入cmd。
2.33.png
       (2)弹出的命令窗口中,输入ping armfly。
2.34.png
       (3)输入ping armfly后,回车。
2.35.png
获得IP地址是192.168.1.5。
1、浏览器输入192.168.1.5,点击键盘回车键(IP地址前面加不加http://都没有关系,不加的话,浏览器会自动加上)。
2.36.png
2、用户名输入admin,密码输入123456,点击“登录”按钮即可访问。
2.37.png
3、登录Web服务器后的效果如下:
2.38.png
4、点击页面上的“温度监控”超链接,进入温度控制页面。点击“手动更新”按钮,仅更新一次数据。
      选中“自动更新”复选框会每500ms更新一次RTC时间和温度值,取消选中,关闭更新。
2.39.png
5、点击页面上的“无源蜂鸣器控制”超链接,进入蜂鸣器控制页面。点击“蜂鸣器鸣响两次”按钮,会听到蜂鸣器鸣响两次。
2.40.png

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

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-17 17:59:58 | 显示全部楼层
52.6 实验例程说明(RTX)
52.6.1 STM32F407开发板实验
配套例子:
        V5-1069_RL-TCPnet实验_WebServer之Ajax实现动态网页局部刷新(RTX)
实验目的:
        1.     学习Ajax技术实现动态网页局部刷新的制作方法和RL-TCPnet的Web服务器实现。
实验内容:
      1.      强烈推荐将网线接到路由器或者交换机上面测试,因为已经使能了DHCP,可以自动获取IP地址。
      2.      用户可在浏览器中直接输入IP地址访问Web服务器,跟大家访问路由器后台一样,也可以通过NetBIOS局域网域名直接访问,即http://armfly/,这样就无需查看具体IP了。
      3.      Web服务器的用户名admin,密码123456。
      4.      本例子主要学习Ajax技术(异步JavaScript+XML),做了两个交互功能。
          一个是温度监控页面:
          (1)温度传感器采用的DS18B20,开发板上面没有带此器件,但是有接口,测试例子前务必插上。
          (2)为了保证RTC实时时钟能够正常起振,下载程序后将板子断电然后重新上电再测试。
          另一个是蜂鸣器控制页面:
          (1)如果用的比较老的V5开发板,请查看板子上面是否有无源蜂鸣器,后来出的V5和V6板子都带无源蜂鸣器。
      5.      关于网页的制作和Web服务器的测试方法,务必看本例子配套的教程,有详细讲解!!!
网页制作:
      详见本章节52.4小节。
配置向导文件设置(Net_Config.c):
      详见本章节52.2小节。
调试文件设置(Net_Debug.c):
      详见本章节52.3小节。
Web服务器访问效果:
      详见本章节52.5小节。
RTX配置:
      RTX配置向导详情如下:
2.41.png
                              
Task Configuration
(1)Number of concurrent running tasks
      允许创建6个任务,实际创建了如下5个任务:
      AppTaskUserIF任务   :按键消息处理。
      AppTaskLED任务     :LED闪烁和DS18B20温度读取。
      AppTaskMsgPro任务 :按键和蜂鸣器检测。
      AppTaskTCPMain任务:RL-TCPnet网络主任务。
      AppTaskStart任务  :启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。
(2)Number of tasks with user-provided stack
      创建的5个任务都是采用自定义堆栈方式。
(3)Run in privileged mode
      设置任务运行在非特权级模式。
RTX任务调试信息:
2.42.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类型数据运算会出问题。
系统栈大小分配:
2.43.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.      BEEP_InitHard();    /* 初始化蜂鸣器 */

  23.      bsp_InitDS18B20();  /* 初始化18B20 */

  24.    

  25.      bsp_InitRTC();      /* 初始化RTC时钟 */

  26. }
复制代码

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.                   

  26.                    /* K2键按下 */

  27.                    case KEY_DOWN_K2:

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

  29.                        break;  

  30.                   

  31.                    /* K3键按下 */

  32.                    case KEY_DOWN_K3:

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

  34.                        break;

  35.                                     

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

  37.                    default:                    

  38.                        break;

  39.               }

  40.          }

  41.         

  42.          os_dly_wait(20);

  43.      }

  44. }



  45. /*

  46. *********************************************************************************************************

  47. *    函 数 名: AppTaskLED

  48. *    功能说明: LED闪烁和DS18B20温度读取。

  49. *    形    参: 无

  50. *    返 回 值: 无

  51. *   优 先 级: 2

  52. *********************************************************************************************************

  53. */

  54. __task void AppTaskLED(void)

  55. {

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

  57.      char  buf[50];

  58.      uint8_t ucDS18B20ID[8], i, res;

  59.    

  60.    

  61.      /* 读取DS18B20的ID号,目的是检测DS18B20是否接到开发板上 */

  62.      res = DS18B20_ReadID(ucDS18B20ID);

  63.    

  64.      /* DS18B20未插入到开发板上 */

  65.      if(res == 0)

  66.      {

  67.          printf("DS18B20未插到开发板上面\r\n");

  68.      }

  69.      /* DS18B20插到开发板上面了,并打印其ID号 */

  70.      else

  71.      {

  72.          sprintf(buf, "DS18B20的ID = ");

  73.          for (i = 0; i < 8; i++)

  74.          {

  75.               sprintf(&buf[strlen(buf)], "%02X", ucDS18B20ID[i]);

  76.               if (i == 3)

  77.               {

  78.                    sprintf(&buf[strlen(buf)], " ");

  79.               }

  80.          }

  81.          printf("%s\r\n", buf);

  82.      }

  83.    

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

  85.      os_itv_set(usFrequency);

  86.    

  87.     while(1)

  88.     {

  89.          bsp_LedToggle(4);

  90.          iTemp = DS18B20_ReadTempReg();

  91.         

  92.          //printf("----%4.1fC\r\n", (float)iTemp/16);

  93.         

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

  95.          os_itv_wait();

  96.     }

  97. }



  98. /*

  99. *********************************************************************************************************

  100. *    函 数 名: AppTaskMsgPro

  101. *    功能说明: 按键和蜂鸣器检测

  102. *    形    参: 无

  103. *    返 回 值: 无

  104. *   优 先 级: 3

  105. *********************************************************************************************************

  106. */

  107. __task void AppTaskMsgPro(void)

  108. {

  109.     while(1)

  110.     {

  111.          BEEP_Pro();

  112.          bsp_KeyScan();

  113.          os_dly_wait(10);

  114.     }

  115. }



  116. /*

  117. *********************************************************************************************************

  118. *    函 数 名: AppTaskTCPMain

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

  120. *    形    参: 无

  121. *    返 回 值: 无

  122. *   优 先 级: 4

  123. *********************************************************************************************************

  124. */

  125. __task void AppTaskTCPMain(void)

  126. {

  127.      while (1)

  128.      {

  129.          TCPnetTest();

  130.      }

  131. }



  132. /*

  133. *********************************************************************************************************

  134. *    函 数 名: AppTaskStart

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

  136. *    形    参: 无

  137. *    返 回 值: 无

  138. *   优 先 级: 5

  139. *********************************************************************************************************

  140. */

  141. __task void AppTaskStart(void)

  142. {

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

  144.      init_TcpNet ();

  145.    

  146.      /* 创建任务 */

  147.      AppTaskCreate();

  148.    

  149.      os_itv_set (100);

  150.    

  151.     while(1)

  152.     {

  153.          os_itv_wait ();

  154.         

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

  156.           timer_tick ();

  157.          os_evt_set(0x0001, HandleTaskTCPMain);

  158.     }

  159. }
复制代码

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. }
复制代码

HTTP_CGI.c文件中接口函数的实现
      KEIL官网有提供HTTPCGI的接口文件,名为HTTP_CGI.c。我们就是在这个文件上修改实现,主要是函数cgi_func,其它函数未使用。具体实现内容如下:
  1. #include <Net_Config.h>

  2. #include <stdio.h>

  3. #include <string.h>

  4. #include "bsp.h"





  5. /* ---------------------------------------------------------------------------

  6. * The HTTP server provides a small scripting language.

  7. *

  8. * The script language is simple and works as follows. Each script line starts

  9. * with a command character, either "i", "t", "c", "#" or ".".

  10. *   "i" - command tells the script interpreter to "include" a file from the

  11. *         virtual file system and output it to the web browser.

  12. *   "t" - command should be followed by a line of text that is to be output

  13. *         to the browser.

  14. *   "c" - command is used to call one of the C functions from the this file.

  15. *         It may be followed by the line of text. This text is passed to

  16. *         'cgi_func()' as a pointer to environment variable.

  17. *   "#' - command is a comment line and is ignored (the "#" denotes a comment)

  18. *   "." - denotes the last script line.

  19. *

  20. * --------------------------------------------------------------------------*/



  21. /* at_System.c */

  22. extern  LOCALM localm[];

  23. #define LocM   localm[NETIF_ETH]



  24. /* Net_Config.c */

  25. extern struct tcp_cfg   tcp_config;

  26. extern struct http_cfg  http_config;

  27. #define tcp_NumSocks    tcp_config.NumSocks

  28. #define tcp_socket      tcp_config.Scb

  29. #define http_EnAuth     http_config.EnAuth

  30. #define http_auth_passw http_config.Passw





  31. extern volatile int16_t  iTemp;

  32. extern RTC_TimeTypeDef  RTC_TimeStructure;



  33. /* Local variables. */

  34. U8 LEDControl;





  35. /* My structure of CGI status U32 variable. This variable is private for */

  36. /* each HTTP Session and is not altered by HTTP Server. It is only set to  */

  37. /* zero when the cgi_func() is called for the first time.                  */

  38. typedef struct {

  39.   U16 xcnt;

  40.   U16 unused;

  41. } MY_BUF;

  42. #define MYBUF(p)        ((MY_BUF *)p)



  43. /*----------------------------------------------------------------------------

  44. * HTTP Server Common Gateway Interface Functions

  45. *---------------------------------------------------------------------------*/



  46. /*--------------------------- cgi_process_var -------------------------------*/



  47. void cgi_process_var (U8 *qs) {

  48.   /* This function is called by HTTP server to process the Querry_String   */

  49.   /* for the CGI Form GET method. It is called on SUBMIT from the browser. */

  50.   /*.The Querry_String.is SPACE terminated.                                */

  51.   U8 *var;

  52.   int s[4];



  53.   var = (U8 *)alloc_mem (40);

  54.   do {

  55.     /* Loop through all the parameters. */

  56.     qs = http_get_var (qs, var, 40);

  57.     /* Check the returned string, 'qs' now points to the next. */

  58.     if (var[0] != 0) {

  59.       /* Returned string is non 0-length. */

  60.       if (str_scomp (var, "ip=") == __TRUE) {

  61.         /* My IP address parameter. */

  62.         sscanf ((const char *)&var[3], "%d.%d.%d.%d",&s[0],&s[1],&s[2],&s[3]);

  63.         LocM.IpAdr[0]   = s[0];

  64.         LocM.IpAdr[1]   = s[1];

  65.         LocM.IpAdr[2]   = s[2];

  66.         LocM.IpAdr[3]   = s[3];

  67.       }

  68.       else if (str_scomp (var, "msk=") == __TRUE) {

  69.         /* Net mask parameter. */

  70.         sscanf ((const char *)&var[4], "%d.%d.%d.%d",&s[0],&s[1],&s[2],&s[3]);

  71.         LocM.NetMask[0] = s[0];

  72.         LocM.NetMask[1] = s[1];

  73.         LocM.NetMask[2] = s[2];

  74.         LocM.NetMask[3] = s[3];

  75.       }

  76.       else if (str_scomp (var, "gw=") == __TRUE) {

  77.         /* Default gateway parameter. */

  78.         sscanf ((const char *)&var[3], "%d.%d.%d.%d",&s[0],&s[1],&s[2],&s[3]);

  79.         LocM.DefGW[0]   = s[0];

  80.         LocM.DefGW[1]   = s[1];

  81.         LocM.DefGW[2]   = s[2];

  82.         LocM.DefGW[3]   = s[3];

  83.       }

  84.       else if (str_scomp (var, "pdns=") == __TRUE) {

  85.         /* Default gateway parameter. */

  86.         sscanf ((const char *)&var[5], "%d.%d.%d.%d",&s[0],&s[1],&s[2],&s[3]);

  87.         LocM.PriDNS[0]  = s[0];

  88.         LocM.PriDNS[1]  = s[1];

  89.         LocM.PriDNS[2]  = s[2];

  90.         LocM.PriDNS[3]  = s[3];

  91.       }

  92.       else if (str_scomp (var, "sdns=") == __TRUE) {

  93.         /* Default gateway parameter. */

  94.         sscanf ((const char *)&var[5], "%d.%d.%d.%d",&s[0],&s[1],&s[2],&s[3]);

  95.         LocM.SecDNS[0]  = s[0];

  96.         LocM.SecDNS[1]  = s[1];

  97.         LocM.SecDNS[2]  = s[2];

  98.         LocM.SecDNS[3]  = s[3];

  99.       }

  100.     }

  101.   }while (qs);

  102.   free_mem ((OS_FRAME *)var);

  103. }





  104. /*--------------------------- cgi_process_data ------------------------------*/



  105. void cgi_process_data (U8 code, U8 *dat, U16 len) {

  106.   /* This function is called by HTTP server to process the returned Data    */

  107.   /* for the CGI Form POST method. It is called on SUBMIT from the browser. */

  108.   /* Parameters:                                                            */

  109.   /*   code  - callback context code                                        */

  110.   /*           0 = www-url-encoded form data                                */

  111.   /*           1 = filename for file upload (0-terminated string)           */

  112.   /*           2 = file upload raw data                                     */

  113.   /*           3 = end of file upload (file close requested)                */

  114.   /*           4 = any xml encoded POST data (single or last stream)        */

  115.   /*           5 = the same as 4, but with more xml data to follow          */

  116.   /*               Use http_get_content_type() to check the content type    */

  117.   /*   dat   - pointer to POST received data                                */

  118.   /*   len   - received data length                                         */

  119.   U8 *var;



  120.   switch (code) {

  121.     case 0:

  122.       /* Url encoded form data received. */

  123.       break;



  124.     case 1:

  125.       /* Filename for file upload received as encoded by the browser. */

  126.       /* It might contain an absolute path to a file from the sending */

  127.       /* host. Open a file for writing. */

  128.       return;



  129.     case 2:

  130.       /* File content data received. Write data to a file. */

  131.       /* This function will be called several times with   */

  132.       /* code 2 when a big file is being uploaded.         */

  133.       return;



  134.     case 3:

  135.       /* File upload finished. Close a file. */

  136.       return;



  137.     case 4:

  138.       /* XML encoded content type, last packet. */

  139.      // pType = http_get_content_type ();

  140.       /* check the content type for CGX file request. */

  141.       /* pType is a pointer to a 0-terminated string  */

  142.       /* For example: text/xml; charset=utf-8         */

  143.       return;

  144.    

  145.     case 5:

  146.       /* XML encoded as under 4, but with more to follow. */

  147.       return;



  148.     default:

  149.       /* Ignore all other codes. */

  150.       return;

  151.   }



  152.   if (len == 0) {

  153.     /* No data or all items (radio, checkbox) are off. */

  154.     return;

  155.   }



  156.   var = (U8 *)alloc_mem (40);



  157.   do {

  158.     /* Parse all returned parameters. */

  159.     dat = http_get_var (dat, var, 40);

  160.     if (var[0] != 0) {

  161.         

  162.     }

  163.   }while (dat);

  164.   free_mem ((OS_FRAME *)var);

  165. }



  166. /*--------------------------- cgi_func --------------------------------------*/



  167. U16 cgi_func (U8 *env, U8 *buf, U16 buflen, U32 *pcgi) {

  168.   /* This function is called by HTTP server script interpreter to make a    */

  169.   /* formated output for 'stdout'. It returns the number of bytes written   */

  170.   /* to the output buffer. Hi-bit of return value (len is or-ed with 0x8000)*/

  171.   /* is a repeat flag for the system script interpreter. If this bit is set */

  172.   /* to 1, the system will call the 'cgi_func()' again for the same script  */

  173.   /* line with parameter 'pcgi' pointing to a 4-byte buffer. This buffer    */

  174.   /* can be used for storing different status variables for this function.  */

  175.   /* It is set to 0 by HTTP Server on first call and is not altered by      */

  176.   /* HTTP server for repeated calls. This function should NEVER write more  */

  177.   /* than 'buflen' bytes to the buffer.                                     */

  178.   /* Parameters:                                                            */

  179.   /*   env    - environment variable string                                 */

  180.   /*   buf    - HTTP transmit buffer                                        */

  181.   /*   buflen - length of this buffer (500-1400 bytes - depends on MSS)     */

  182.   /*   pcgi   - pointer to session local buffer used for repeated loops     */

  183.   /*            This is a U32 variable - size is 4 bytes. Value is:         */

  184.   /*            - on 1st call = 0                                           */

  185.   /*            - 2nd call    = as set by this function on first call       */

  186.   U32 len = 0;



  187.   switch (env[0]) {

  188.     /* Analyze the environment string. It is the script 'c' line starting */

  189.     /* at position 2. What you write to the script file is returned here. */

  190.      /* BEEP Input - xml file 'beep.cgx' */

  191.      case 'q':

  192.         switch (env[1]) {

  193.         case '1':

  194.               BEEP_Start(5, 1, 2);

  195.               break;

  196.          }



  197.        len = 0;

  198.       break;

  199.         

  200.      case 'g':

  201.       /* DS18B20 Input - xml file 'ds180b20.cgi' */

  202.       switch (env[2]) {

  203.         case '1':

  204.                 RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);

  205.                 len = sprintf((char *)buf,(const char *)&env[4],  RTC_TimeStructure.RTC_Hours,

  206.                                                                          RTC_TimeStructure.RTC_Minutes,

  207.                                                                          RTC_TimeStructure.RTC_Seconds);

  208.           break;

  209.                

  210.         case '2':

  211.           len = sprintf((char *)buf,(const char *)&env[4],(float)iTemp/16);

  212.           break;

  213.       }

  214.       break;

  215.    

  216.      case 'p':

  217.       /* DS18B20 Input - xml file 'ds180b20.cgx' */

  218.        RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);

  219.       len = sprintf((char *)buf,(const char *)&env[1], RTC_TimeStructure.RTC_Hours,

  220.                                                                 RTC_TimeStructure.RTC_Minutes,

  221.                                                                 RTC_TimeStructure.RTC_Seconds);

  222.       break;

  223.       

  224.     case 'x':

  225.       /* DS18B20 Input - xml file 'ds180b20.cgx' */

  226.       len = sprintf((char *)buf,(const char *)&env[1], (float)iTemp/16);

  227.       break;

  228.       

  229.   }

  230.   return ((U16)len);

  231. }



  232. /*--------------------------- cgx_content_type ------------------------------*/

  233. #if 0

  234. U8 *cgx_content_type (void) {

  235.   /* User configurable Content-type for CGX script files. If this function */

  236.   /* is missing, or returns a NULL pointer, the default 'text/xml' content */

  237.   /* type from the library is used for xml-script file types.              */

  238.   return ("text/xml; charset=utf-8");

  239. }

  240. #endif



  241. /*--------------------------- http_encoding ---------------------------------*/



  242. #if 0

  243. U8 *http_encoding (void) {

  244.   /* User configurable character encoding for text types. If this function */

  245.   /* is missing, or returns a NULL pointer, web browser uses a default     */

  246.   /* character encoding, which is set in the browser configuration.        */

  247.   return ("utf-8");

  248. }

  249. #endif



  250. /*--------------------------- http_accept_host ------------------------------*/

  251. #if 0

  252. BOOL http_accept_host (U8 *rem_ip, U16 rem_port) {

  253.   /* This function checks if a connection from remote host is accepted or  */

  254.   /* not. If this function is missing, all remote hosts are accepted.      */



  255.    if (rem_ip[0] == 192  &&

  256.        rem_ip[1] == 168  &&

  257.        rem_ip[2] == 1    &&

  258.        rem_ip[3] == 1) {

  259.       /* Accept a connection. */

  260.       return (__TRUE);

  261.    }

  262.    /* Deny a connection. */

  263.    return (__FALSE);

  264. }

  265. #endif



  266. /*----------------------------------------------------------------------------

  267. * end of file

  268. *---------------------------------------------------------------------------*/
复制代码


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

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-17 18:07:43 | 显示全部楼层
52.6.2 STM32F429开发板实验
配套例子:
      V6-1069_RL-TCPnet实验_WebServer之Ajax实现动态网页局部刷新(RTX)。
实验目的:
       1.     学习Ajax技术实现动态网页局部刷新的制作方法和RL-TCPnet的Web服务器实现
实验内容:
      1.      强烈推荐将网线接到路由器或者交换机上面测试,因为已经使能了DHCP,可以自动获取IP地址。
      2.      用户可在浏览器中直接输入IP地址访问Web服务器,跟大家访问路由器后台一样,也可以通过NetBIOS局域网域名直接访问,即http://armfly/,这样就无需查看具体IP了。
      3.      Web服务器的用户名admin,密码123456。
      4.      本例子主要学习Ajax技术(异步JavaScript+XML),做了两个交互功能。
          一个是温度监控页面:
          (1)温度传感器采用的DS18B20,开发板上面没有带此器件,但是有接口,测试例子前务必插上。
          (2)为了保证RTC实时时钟能够正常起振,下载程序后将板子断电然后重新上电再测试。
          另一个是蜂鸣器控制页面:
          (1)如果用的比较老的V5开发板,请查看板子上面是否有无源蜂鸣器,后来出的V5和V6板子都带无源蜂鸣器。
      5.      关于网页的制作和Web服务器的测试方法,务必看本例子配套的教程,有详细讲解!!!
网页制作:
      详见本章节52.4小节。
配置向导文件设置(Net_Config.c):
      详见本章节52.2小节。
调试文件设置(Net_Debug.c):
      详见本章节52.3小节。
Web服务器访问效果:
      详见本章节52.5小节。
RTX配置:
      RTX配置向导详情如下:
2.44.png
                              
Task Configuration
(1)Number of concurrent running tasks
      AppTaskUserIF任务 :按键消息处理。
      AppTaskLED任务    :LED闪烁和DS18B20温度读取。
      AppTaskMsgPro任务 :按键和蜂鸣器检测。
      AppTaskTCPMain任务:RL-TCPnet网络主任务
      AppTaskStart任务  :启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。
(2)Number of tasks with user-provided stack
      创建的5个任务都是采用自定义堆栈方式。
(3)Run in privileged mode
      设置任务运行在非特权级模式。
RTX任务调试信息:
2.45.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类型数据运算会出问题。
系统栈大小分配:
2.46.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. BEEP_InitHard();    /* 初始化蜂鸣器 */

  25.      bsp_InitDS18B20();  /* 初始化18B20 */

  26.    

  27.      bsp_InitRTC();      /* 初始化RTC时钟 */

  28. }
复制代码

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.                   

  26.                    /* K2键按下 */

  27.                    case KEY_DOWN_K2:

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

  29.                        break;  

  30.                   

  31.                    /* K3键按下 */

  32.                    case KEY_DOWN_K3:

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

  34.                        break;

  35.                                     

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

  37.                    default:                    

  38.                        break;

  39.               }

  40.          }

  41.         

  42.          os_dly_wait(20);

  43.      }

  44. }



  45. /*

  46. *********************************************************************************************************

  47. *    函 数 名: AppTaskLED

  48. *    功能说明: LED闪烁和DS18B20温度读取。

  49. *    形    参: 无

  50. *    返 回 值: 无

  51. *   优 先 级: 2

  52. *********************************************************************************************************

  53. */

  54. __task void AppTaskLED(void)

  55. {

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

  57.      char  buf[50];

  58.      uint8_t ucDS18B20ID[8], i, res;

  59.    

  60.    

  61.      /* 读取DS18B20的ID号,目的是检测DS18B20是否接到开发板上 */

  62.      res = DS18B20_ReadID(ucDS18B20ID);

  63.    

  64.      /* DS18B20未插入到开发板上 */

  65.      if(res == 0)

  66.      {

  67.          printf("DS18B20未插到开发板上面\r\n");

  68.      }

  69.      /* DS18B20插到开发板上面了,并打印其ID号 */

  70.      else

  71.      {

  72.          sprintf(buf, "DS18B20的ID = ");

  73.          for (i = 0; i < 8; i++)

  74.          {

  75.               sprintf(&buf[strlen(buf)], "%02X", ucDS18B20ID[i]);

  76.               if (i == 3)

  77.               {

  78.                    sprintf(&buf[strlen(buf)], " ");

  79.               }

  80.          }

  81.          printf("%s\r\n", buf);

  82.      }

  83.    

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

  85.      os_itv_set(usFrequency);

  86.    

  87.     while(1)

  88.     {

  89.          bsp_LedToggle(4);

  90.          iTemp = DS18B20_ReadTempReg();

  91.         

  92.          //printf("----%4.1fC\r\n", (float)iTemp/16);

  93.         

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

  95.          os_itv_wait();

  96.     }

  97. }



  98. /*

  99. *********************************************************************************************************

  100. *    函 数 名: AppTaskMsgPro

  101. *    功能说明: 按键和蜂鸣器检测

  102. *    形    参: 无

  103. *    返 回 值: 无

  104. *   优 先 级: 3

  105. *********************************************************************************************************

  106. */

  107. __task void AppTaskMsgPro(void)

  108. {

  109.     while(1)

  110.     {

  111.          BEEP_Pro();

  112.          bsp_KeyScan();

  113.          os_dly_wait(10);

  114.     }

  115. }



  116. /*

  117. *********************************************************************************************************

  118. *    函 数 名: AppTaskTCPMain

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

  120. *    形    参: 无

  121. *    返 回 值: 无

  122. *   优 先 级: 4

  123. *********************************************************************************************************

  124. */

  125. __task void AppTaskTCPMain(void)

  126. {

  127.      while (1)

  128.      {

  129.          TCPnetTest();

  130.      }

  131. }



  132. /*

  133. *********************************************************************************************************

  134. *    函 数 名: AppTaskStart

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

  136. *    形    参: 无

  137. *    返 回 值: 无

  138. *   优 先 级: 5

  139. *********************************************************************************************************

  140. */

  141. __task void AppTaskStart(void)

  142. {

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

  144.      init_TcpNet ();

  145.    

  146.      /* 创建任务 */

  147.      AppTaskCreate();

  148.    

  149.      os_itv_set (100);

  150.    

  151.     while(1)

  152.     {

  153.          os_itv_wait ();

  154.         

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

  156.          timer_tick ();

  157.          os_evt_set(0x0001, HandleTaskTCPMain);

  158.     }

  159. }
复制代码

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. }
复制代码

HTTP_CGI.c文件中接口函数的实现
      KEIL官网有提供HTTPCGI的接口文件,名为HTTP_CGI.c。我们就是在这个文件上修改实现,主要是函数cgi_func,其它函数未使用。具体实现内容如下:
  1. #include <Net_Config.h>

  2. #include <stdio.h>

  3. #include <string.h>

  4. #include "bsp.h"





  5. /* ---------------------------------------------------------------------------

  6. * The HTTP server provides a small scripting language.

  7. *

  8. * The script language is simple and works as follows. Each script line starts

  9. * with a command character, either "i", "t", "c", "#" or ".".

  10. *   "i" - command tells the script interpreter to "include" a file from the

  11. *         virtual file system and output it to the web browser.

  12. *   "t" - command should be followed by a line of text that is to be output

  13. *         to the browser.

  14. *   "c" - command is used to call one of the C functions from the this file.

  15. *         It may be followed by the line of text. This text is passed to

  16. *         'cgi_func()' as a pointer to environment variable.

  17. *   "#' - command is a comment line and is ignored (the "#" denotes a comment)

  18. *   "." - denotes the last script line.

  19. *

  20. * --------------------------------------------------------------------------*/



  21. /* at_System.c */

  22. extern  LOCALM localm[];

  23. #define LocM   localm[NETIF_ETH]



  24. /* Net_Config.c */

  25. extern struct tcp_cfg   tcp_config;

  26. extern struct http_cfg  http_config;

  27. #define tcp_NumSocks    tcp_config.NumSocks

  28. #define tcp_socket      tcp_config.Scb

  29. #define http_EnAuth     http_config.EnAuth

  30. #define http_auth_passw http_config.Passw





  31. extern volatile int16_t  iTemp;

  32. extern RTC_TimeTypeDef  RTC_TimeStructure;



  33. /* Local variables. */

  34. U8 LEDControl;





  35. /* My structure of CGI status U32 variable. This variable is private for */

  36. /* each HTTP Session and is not altered by HTTP Server. It is only set to  */

  37. /* zero when the cgi_func() is called for the first time.                  */

  38. typedef struct {

  39.   U16 xcnt;

  40.   U16 unused;

  41. } MY_BUF;

  42. #define MYBUF(p)        ((MY_BUF *)p)



  43. /*----------------------------------------------------------------------------

  44. * HTTP Server Common Gateway Interface Functions

  45. *---------------------------------------------------------------------------*/



  46. /*--------------------------- cgi_process_var -------------------------------*/



  47. void cgi_process_var (U8 *qs) {

  48.   /* This function is called by HTTP server to process the Querry_String   */

  49.   /* for the CGI Form GET method. It is called on SUBMIT from the browser. */

  50.   /*.The Querry_String.is SPACE terminated.                                */

  51.   U8 *var;

  52.   int s[4];



  53.   var = (U8 *)alloc_mem (40);

  54.   do {

  55.     /* Loop through all the parameters. */

  56.     qs = http_get_var (qs, var, 40);

  57.     /* Check the returned string, 'qs' now points to the next. */

  58.     if (var[0] != 0) {

  59.       /* Returned string is non 0-length. */

  60.       if (str_scomp (var, "ip=") == __TRUE) {

  61.         /* My IP address parameter. */

  62.         sscanf ((const char *)&var[3], "%d.%d.%d.%d",&s[0],&s[1],&s[2],&s[3]);

  63.         LocM.IpAdr[0]   = s[0];

  64.         LocM.IpAdr[1]   = s[1];

  65.         LocM.IpAdr[2]   = s[2];

  66.         LocM.IpAdr[3]   = s[3];

  67.       }

  68.       else if (str_scomp (var, "msk=") == __TRUE) {

  69.         /* Net mask parameter. */

  70.         sscanf ((const char *)&var[4], "%d.%d.%d.%d",&s[0],&s[1],&s[2],&s[3]);

  71.         LocM.NetMask[0] = s[0];

  72.         LocM.NetMask[1] = s[1];

  73.         LocM.NetMask[2] = s[2];

  74.         LocM.NetMask[3] = s[3];

  75.       }

  76.       else if (str_scomp (var, "gw=") == __TRUE) {

  77.         /* Default gateway parameter. */

  78.         sscanf ((const char *)&var[3], "%d.%d.%d.%d",&s[0],&s[1],&s[2],&s[3]);

  79.         LocM.DefGW[0]   = s[0];

  80.         LocM.DefGW[1]   = s[1];

  81.         LocM.DefGW[2]   = s[2];

  82.         LocM.DefGW[3]   = s[3];

  83.       }

  84.       else if (str_scomp (var, "pdns=") == __TRUE) {

  85.         /* Default gateway parameter. */

  86.         sscanf ((const char *)&var[5], "%d.%d.%d.%d",&s[0],&s[1],&s[2],&s[3]);

  87.         LocM.PriDNS[0]  = s[0];

  88.         LocM.PriDNS[1]  = s[1];

  89.         LocM.PriDNS[2]  = s[2];

  90.         LocM.PriDNS[3]  = s[3];

  91.       }

  92.       else if (str_scomp (var, "sdns=") == __TRUE) {

  93.         /* Default gateway parameter. */

  94.         sscanf ((const char *)&var[5], "%d.%d.%d.%d",&s[0],&s[1],&s[2],&s[3]);

  95.         LocM.SecDNS[0]  = s[0];

  96.         LocM.SecDNS[1]  = s[1];

  97.         LocM.SecDNS[2]  = s[2];

  98.         LocM.SecDNS[3]  = s[3];

  99.       }

  100.     }

  101.   }while (qs);

  102.   free_mem ((OS_FRAME *)var);

  103. }





  104. /*--------------------------- cgi_process_data ------------------------------*/



  105. void cgi_process_data (U8 code, U8 *dat, U16 len) {

  106.   /* This function is called by HTTP server to process the returned Data    */

  107.   /* for the CGI Form POST method. It is called on SUBMIT from the browser. */

  108.   /* Parameters:                                                            */

  109.   /*   code  - callback context code                                        */

  110.   /*           0 = www-url-encoded form data                                */

  111.   /*           1 = filename for file upload (0-terminated string)           */

  112.   /*           2 = file upload raw data                                     */

  113.   /*           3 = end of file upload (file close requested)                */

  114.   /*           4 = any xml encoded POST data (single or last stream)        */

  115.   /*           5 = the same as 4, but with more xml data to follow          */

  116.   /*               Use http_get_content_type() to check the content type    */

  117.   /*   dat   - pointer to POST received data                                */

  118.   /*   len   - received data length                                         */

  119.   U8 *var;



  120.   switch (code) {

  121.     case 0:

  122.       /* Url encoded form data received. */

  123.       break;



  124.     case 1:

  125.       /* Filename for file upload received as encoded by the browser. */

  126.       /* It might contain an absolute path to a file from the sending */

  127.       /* host. Open a file for writing. */

  128.       return;



  129.     case 2:

  130.       /* File content data received. Write data to a file. */

  131.       /* This function will be called several times with   */

  132.       /* code 2 when a big file is being uploaded.         */

  133.       return;



  134.     case 3:

  135.       /* File upload finished. Close a file. */

  136.       return;



  137.     case 4:

  138.       /* XML encoded content type, last packet. */

  139.      // pType = http_get_content_type ();

  140.       /* check the content type for CGX file request. */

  141.       /* pType is a pointer to a 0-terminated string  */

  142.       /* For example: text/xml; charset=utf-8         */

  143.       return;

  144.    

  145.     case 5:

  146.       /* XML encoded as under 4, but with more to follow. */

  147.       return;



  148.     default:

  149.       /* Ignore all other codes. */

  150.       return;

  151.   }



  152.   if (len == 0) {

  153.     /* No data or all items (radio, checkbox) are off. */

  154.     return;

  155.   }



  156.   var = (U8 *)alloc_mem (40);



  157.   do {

  158.     /* Parse all returned parameters. */

  159.     dat = http_get_var (dat, var, 40);

  160.     if (var[0] != 0) {

  161.         

  162.     }

  163.   }while (dat);

  164.   free_mem ((OS_FRAME *)var);

  165. }



  166. /*--------------------------- cgi_func --------------------------------------*/



  167. U16 cgi_func (U8 *env, U8 *buf, U16 buflen, U32 *pcgi) {

  168.   /* This function is called by HTTP server script interpreter to make a    */

  169.   /* formated output for 'stdout'. It returns the number of bytes written   */

  170.   /* to the output buffer. Hi-bit of return value (len is or-ed with 0x8000)*/

  171.   /* is a repeat flag for the system script interpreter. If this bit is set */

  172.   /* to 1, the system will call the 'cgi_func()' again for the same script  */

  173.   /* line with parameter 'pcgi' pointing to a 4-byte buffer. This buffer    */

  174.   /* can be used for storing different status variables for this function.  */

  175.   /* It is set to 0 by HTTP Server on first call and is not altered by      */

  176.   /* HTTP server for repeated calls. This function should NEVER write more  */

  177.   /* than 'buflen' bytes to the buffer.                                     */

  178.   /* Parameters:                                                            */

  179.   /*   env    - environment variable string                                 */

  180.   /*   buf    - HTTP transmit buffer                                        */

  181.   /*   buflen - length of this buffer (500-1400 bytes - depends on MSS)     */

  182.   /*   pcgi   - pointer to session local buffer used for repeated loops     */

  183.   /*            This is a U32 variable - size is 4 bytes. Value is:         */

  184.   /*            - on 1st call = 0                                           */

  185.   /*            - 2nd call    = as set by this function on first call       */

  186.   U32 len = 0;



  187.   switch (env[0]) {

  188.     /* Analyze the environment string. It is the script 'c' line starting */

  189.     /* at position 2. What you write to the script file is returned here. */

  190.      /* BEEP Input - xml file 'beep.cgx' */

  191.      case 'q':

  192.         switch (env[1]) {

  193.         case '1':

  194.               BEEP_Start(5, 1, 2);

  195.               break;

  196.          }



  197.        len = 0;

  198.       break;

  199.         

  200.      case 'g':

  201.       /* DS18B20 Input - xml file 'ds180b20.cgi' */

  202.       switch (env[2]) {

  203.         case '1':

  204.                 RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);

  205.                 len = sprintf((char *)buf,(const char *)&env[4],  RTC_TimeStructure.RTC_Hours,

  206.                                                                          RTC_TimeStructure.RTC_Minutes,

  207.                                                                          RTC_TimeStructure.RTC_Seconds);

  208.           break;

  209.                

  210.         case '2':

  211.           len = sprintf((char *)buf,(const char *)&env[4],(float)iTemp/16);

  212.           break;

  213.       }

  214.       break;

  215.    

  216.      case 'p':

  217.       /* DS18B20 Input - xml file 'ds180b20.cgx' */

  218.        RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);

  219.       len = sprintf((char *)buf,(const char *)&env[1], RTC_TimeStructure.RTC_Hours,

  220.                                                                 RTC_TimeStructure.RTC_Minutes,

  221.                                                                 RTC_TimeStructure.RTC_Seconds);

  222.       break;

  223.       

  224.     case 'x':

  225.       /* DS18B20 Input - xml file 'ds180b20.cgx' */

  226.       len = sprintf((char *)buf,(const char *)&env[1], (float)iTemp/16);

  227.       break;

  228.       

  229.   }

  230.   return ((U16)len);

  231. }



  232. /*--------------------------- cgx_content_type ------------------------------*/

  233. #if 0

  234. U8 *cgx_content_type (void) {

  235.   /* User configurable Content-type for CGX script files. If this function */

  236.   /* is missing, or returns a NULL pointer, the default 'text/xml' content */

  237.   /* type from the library is used for xml-script file types.              */

  238.   return ("text/xml; charset=utf-8");

  239. }

  240. #endif



  241. /*--------------------------- http_encoding ---------------------------------*/



  242. #if 0

  243. U8 *http_encoding (void) {

  244.   /* User configurable character encoding for text types. If this function */

  245.   /* is missing, or returns a NULL pointer, web browser uses a default     */

  246.   /* character encoding, which is set in the browser configuration.        */

  247.   return ("utf-8");

  248. }

  249. #endif



  250. /*--------------------------- http_accept_host ------------------------------*/

  251. #if 0

  252. BOOL http_accept_host (U8 *rem_ip, U16 rem_port) {

  253.   /* This function checks if a connection from remote host is accepted or  */

  254.   /* not. If this function is missing, all remote hosts are accepted.      */



  255.    if (rem_ip[0] == 192  &&

  256.        rem_ip[1] == 168  &&

  257.        rem_ip[2] == 1    &&

  258.        rem_ip[3] == 1) {

  259.       /* Accept a connection. */

  260.       return (__TRUE);

  261.    }

  262.    /* Deny a connection. */

  263.    return (__FALSE);

  264. }

  265. #endif



  266. /*----------------------------------------------------------------------------

  267. * end of file

  268. *---------------------------------------------------------------------------*/
复制代码


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

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2018-1-17 18:08:10 | 显示全部楼层
52.7 总结
       本章节就为大家讲解这么多,其中网页的制作比较麻烦,希望大家实际动手操作一遍,并将其熟练掌握

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-29 20:58 , Processed in 0.340114 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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