zoukankan      html  css  js  c++  java
  • 【RL-TCPnet网络教程】第28章 RL-TCPnet之DNS应用

    第28章      RL-TCPnet之DNS应用

    本章节为大家讲解RL-TCPnet的DNS应用,学习本章节前,务必要优先学习第27章的DNS基础知识。有了这些基础知识之后,再搞本章节会有事半功倍的效果。

    本章教程含STM32F407开发板和STM32F429开发板。

    28.1  初学者重要提示

    28.2  DNS函数

    28.3  DNS配置说明(Net_Config.c)

    28.4  DNS调试说明(Net_Debug.c)

    28.5  DNS检测过程

    28.6  网络调试助手和板子的操作步骤

    28.7  实验例程说明(裸机)

    28.8  实验例程说明(RTX)

    28.9  总结

    28.1  初学者重要提示

    1. 学习本章节前,务必保证已经学习了第27章的基础知识。
    2. 本章相对比较简单,通过函数get_host_by_name实现对域名的解析,从而获得实际的IP地址。另外注意,一些大型的网站都有多个服务器的,通过此函数获取的IP地址不同,是正常的。
    3. 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。

    28.2  DNS函数

    涉及到DNS的,仅有如下一个函数:

    • get_host_by_name

    关于这个函数的讲解及其使用方法可以看教程第 3 章 3.4 小节里面说的参考资料 rlarm.chm 文件:

     

    注意,这个函数不支持重入,也就是不支持多任务调用。

    28.2.1  函数get_host_by_name

    函数原型:

    U8 get_host_by_name (
    
        U8* hostn,                                /* 域名指针变量 */
    
        void (*cbfunc)(U8 event, U8* host_ip) );  /* 回调函数 */

    函数描述:

    函数get_host_by_name用于获取网址的IP地址。

    1. 第1个参数是域名。
    2. 第2个参数是DNS Client的回调函数。回调函数有两个参数:
      • 回调函数第1个参数是回调消息类型:
      • 回调函数第2个参数,如果解析成功的话,解析出的IP地址的缓冲区地址会保存到这个指针变量里面。
    3. 返回值有以下三种:
     

    使用这个函数要注意以下问题:

    1. 如果用户将此函数的第1个参数填写成“192.168.1.1”等无需解析的IP地址,调用此函数后,DNS Client会立即调用此函数的回调函数。

    使用举例:

      1 /*
      2 
      3 *********************************************************************************************************
      4 
      5 *                                          变量
      6 
      7 *********************************************************************************************************
      8 
      9 */
     10 
     11 char const *hosts[3] =
     12 
     13 {
     14 
     15      "www.armfly.com",
     16 
     17      "www.baidu.com",
     18 
     19      "www.qq.com",
     20 
     21 };
     22 
     23  
     24 
     25 /*
     26 
     27 *********************************************************************************************************
     28 
     29 *    函 数 名: dns_cbfunc
     30 
     31 *    功能说明: 函数get_host_by_name的调函数。
     32 
     33 *    形    参: event  事件类型
     34 
     35 *             ip     如果事件类型是DNS_EVT_SUCCESS,此指针变量指向返回的IP地址缓冲区。
     36 
     37 *    返 回 值: 无
     38 
     39 *********************************************************************************************************
     40 
     41 */
     42 
     43 static void dns_cbfunc (unsigned char event, unsigned char *ip)
     44 
     45 {
     46 
     47      switch (event)
     48 
     49      {
     50 
     51          /* 成功解析地址 */
     52 
     53          case DNS_EVT_SUCCESS:
     54 
     55               printf_debug("%d.%d.%d.%d
    ",ip[0],ip[1],ip[2],ip[3]);
     56 
     57               break;
     58 
     59         
     60 
     61          /* DNS记录数据库中不存在此地址 */
     62 
     63          case DNS_EVT_NONAME:
     64 
     65               printf_debug("Host Name does not exist in DNS record database.
    ");
     66 
     67               break;
     68 
     69  
     70 
     71          /* 允许的DNS解析重试次数已经用完,仍无法解析,时间超时 */
     72 
     73          case DNS_EVT_TIMEOUT:
     74 
     75               printf_debug("DNS Resolver Timeout expired, Host Address not resolved.
    ");
     76 
     77               break;
     78 
     79  
     80 
     81          /* DNS协议错误,收到无效或者被损坏的回复 */
     82 
     83          case DNS_EVT_ERROR:
     84 
     85               printf_debug("DNS Resolver Protocol Error, Host Address not resolved.
    ");
     86 
     87               return;
     88 
     89      }
     90 
     91 }
     92 
     93  
     94 
     95 /*
     96 
     97 *********************************************************************************************************
     98 
     99 *    函 数 名: tcpnet_poll
    100 
    101 *    功能说明: 使用TCPnet必须要一直调用的函数
    102 
    103 *    形    参: 无
    104 
    105 *    返 回 值: 无
    106 
    107 *********************************************************************************************************
    108 
    109 */
    110 
    111 void tcpnet_poll(void)
    112 
    113 {
    114 
    115      if(bsp_CheckTimer(0))
    116 
    117      {
    118 
    119          bsp_LedToggle(2);
    120 
    121         
    122 
    123          /* 此函数坚决不可以放在中断里面跑 */
    124 
    125          timer_tick ();
    126 
    127      }
    128 
    129     
    130 
    131      main_TcpNet ();
    132 
    133 }
    134 
    135  
    136 
    137 /*
    138 
    139 *********************************************************************************************************
    140 
    141 *    函 数 名: TCPnetTest
    142 
    143 *    功能说明: TCPnet应用
    144 
    145 *    形    参: 无
    146 
    147 *    返 回 值: 无
    148 
    149 *********************************************************************************************************
    150 
    151 */
    152 
    153 void TCPnetTest(void)
    154 
    155 { 
    156 
    157      uint8_t ucKeyCode;
    158 
    159     
    160 
    161     
    162 
    163      /* 初始化网络协议栈 */
    164 
    165      init_TcpNet ();
    166 
    167  
    168 
    169      /* 创建一个周期是100ms的软定时器 */
    170 
    171     bsp_StartAutoTimer(0, 100);
    172 
    173     
    174 
    175      while (1)
    176 
    177      {
    178 
    179          /* TCP轮询 */
    180 
    181          tcpnet_poll();
    182 
    183         
    184 
    185          /* 按键消息的处理 */
    186 
    187          ucKeyCode = bsp_GetKey();
    188 
    189           if ((ucKeyCode != KEY_NONE))
    190 
    191          {
    192 
    193               switch (ucKeyCode)
    194 
    195               {
    196 
    197                    /* 按键K1按下,返回www.armfly.com的IP地址。 */
    198 
    199                    case KEY_DOWN_K1:
    200 
    201                        printf_debug("网址www.armfly.com的IP地址:");
    202 
    203                     get_host_by_name ((U8 *)hosts[0], dns_cbfunc);
    204 
    205                        break;
    206 
    207  
    208 
    209                    /* 按键K2按下,返回www.baidu.com的IP地址 */
    210 
    211                    case KEY_DOWN_K2:
    212 
    213                        printf_debug("网址www.baidu.com的IP地址:");                  
    214 
    215                        get_host_by_name ((U8 *)hosts[1], dns_cbfunc);                  
    216 
    217                        break;
    218 
    219                       
    220 
    221                    /* 按键K3按下,返回www.qq.com的IP地址 */
    222 
    223                    case KEY_DOWN_K3:
    224 
    225                        printf_debug("网址www.qq.com的IP地址:");                          
    226 
    227                        get_host_by_name ((U8 *)hosts[2], dns_cbfunc);                       
    228 
    229                        break;
    230 
    231                   
    232 
    233                     /* 其他的键值不处理 */
    234 
    235                    default:                    
    236 
    237                        break;
    238 
    239               }
    240 
    241          }
    242 
    243      }
    244 
    245 }

    28.3 DNS配置说明(Net_Config.c)

    (本章节配套例子的配置与本小节的说明相同)

    RL-TCPnet的配置工作是通过配置文件Net_Config.c实现。在MDK工程中打开文件Net_Config.c,可以看到下图所示的工程配置向导:

     

    RL-TCPnet要配置的选项非常多,我们这里把几个主要的配置选项简单介绍下。

     

    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。

     

    Ethernet Network Interface

    以太网接口配置,勾选了此选项就可以配置了,如果没有使能DHCP的话,将使用这里配置的固定IP

    (1)MAC Address

    局域网内可以随意配置,只要不跟局域网内其它设备的MAC地址冲突即可。

    (2)IP Address

    IP地址。

    (3)Subnet mask

    子网掩码。

    (4)Default Gateway

    默认网关。

     

    Ethernet Network Interface

    以太网接口配置,这个配置里面还有如下两项比较重要的配置需要说明。

    (1)NetBIOS Name Service

    NetBIOS局域网域名服务,这里打上对勾就使能了。这样我们就可以通过前面配置的Local Host Name局域网域名进行访问,而不需要通过IP地址访问了。

    (2)Dynaminc Host Configuration

    即DHCP,这里打上对勾就使能了。使能了DHCP后,RL-TCPnet就可以从外接的路由器上获得动态IP地址。

     

    UDP Sockets

    UDP Sockets配置,打上对勾就使能了此项功能

    (1)Number of UDP Sockets

    用于配置可创建的UDP Sockets数量,这里配置了5个。

    范围1 – 20。

     

    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接收窗口大小。

     

    DNS Client

    DNS 配置,打上对勾就使能了此项功能

    (1)Cache Table size

    主机名/IP地址的缓存表大小。

    范围5-100。

    28.4 DNS调试说明(Net_Debug.c)

    (重要说明,RL-TCPnet的调试是通过串口打印出来的)

    RL-TCPnet的调试功能是通过配置文件Net_Debug.c实现。在MDK工程中打开文件Net_Debug.c,可以看到下图所示的工程配置向导:

     

    Print Time Stamp

    勾选了此选项的话,打印消息时,前面会附带时间信息。

    其它所有的选项

    默认情况下,所有的调试选项都关闭了,每个选项有三个调试级别可选择,这里我们以DNS Debug为例,点击下拉列表,可以看到里面有Off,Errors only和Full debug三个调试级别可供选择,每个调试选项里面都是这三个级别。

     

    Off:表示关闭此选项的调试功能。

    Errors only:表示仅在此选项出错时,将其错误打印出来。

    Full debug:表示此选项的全功能调试。

    下面是对DNS Debug配置为Full debug时,打印出来的消息(以解析网址www.armfly.com为例):

     

    28.5 DNS域名解析方法

    DNS的域名解析比较简单,用户仅需满足以下几个条件即可:

    • 务必记得使能Net_Config.c文件中DNS。
    • 调用函数get_host_by_name,关于这个函数的使用方法在本章的28.2.1小节有讲解。
    • 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。

    28.6 板子的操作步骤

    本章的操作相对比较简单,用户务必将板子连接到能够联网的路由器或者交换机上。

    1. 按键K1按下,返回www.armfly.com的IP地址。
    2. 按键K2按下,返回www.baidu.com的IP地址。
    3. 按键K3按下,返回www.qq.com的IP地址。

    (串口波特率115200,数据位8,奇偶校验位无,停止位1)

     

    28.7 实验例程说明(裸机)

    28.7.1 STM32F407开发板实验

    配套例子:

    V5-1036_RL-TCPnet实验_DNS应用(裸机)

    实验目的:

    1. 学习RL-TCPnet的DNS使用。

    实验内容:

    1. 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。
    2. 像腾讯,百度等网址都有多个IP地址,如果用户测试DNS返回的地址不同,这种情况是正常的。
    3. 按键K1按下,返回www.armfly.com的IP地址。
    4. 按键K2按下,返回www.baidu.com的IP地址。
    5. 按键K3按下,返回www.qq.com的IP地址。

    实验操作:

    详见本章节28.6小节。

    配置向导文件设置(Net_Config.c):

    详见本章节28.3小节。

    调试文件设置(Net_Debug.c):

    详见本章节28.4小节。

    程序设计:

    主函数初始化

    在main.c文件实现:

    /*
    
    *********************************************************************************************************
    
    *    函 数 名: main
    
    *    功能说明: 标准c程序入口。
    
    *    形    参: 无
    
    *    返 回 值: 无
    
    *********************************************************************************************************
    
    */
    
    int main (void)
    
    {   
    
         /* 初始化外设 */
    
         bsp_Init();
    
     
    
         /* 进入RL-TCPnet测试函数 */
    
         TCPnetTest();
    
    }

    硬件外设初始化

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

     1 /*
     2 
     3 *********************************************************************************************************
     4 
     5 *    函 数 名: bsp_Init
     6 
     7 *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
     8 
     9 *    形    参:无
    10 
    11 *    返 回 值: 无
    12 
    13 *********************************************************************************************************
    14 
    15 */
    16 
    17 void bsp_Init(void)
    18 
    19 {
    20 
    21      /*
    22 
    23          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
    24 
    25          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
    26 
    27  
    28 
    29          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
    30 
    31      */
    32 
    33      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
    34 
    35      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    36 
    37  
    38 
    39      bsp_InitUart();    /* 初始化串口 */
    40 
    41      bsp_InitKey();     /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */
    42 
    43      bsp_InitLed();     /* 初始LED指示灯端口 */
    44 
    45      bsp_InitTimer();   /* 初始化滴答定时器 */
    46 
    47 }

    RL-TCPnet功能测试

    这里专门创建了一个app_tcpnet_lib.c文件用于RL-TCPnet功能的测试,这里通过函数get_host_by_name来解析网址对应的IP地址。

      1 /*
      2 
      3 *********************************************************************************************************
      4 
      5 *                                      用于本文件的调试
      6 
      7 *********************************************************************************************************
      8 
      9 */
     10 
     11 #if 1
     12 
     13      #define printf_debug printf
     14 
     15 #else
     16 
     17      #define printf_debug(...)
     18 
     19 #endif
     20 
     21  
     22 
     23  
     24 
     25 /*
     26 
     27 *********************************************************************************************************
     28 
     29 *                                          变量
     30 
     31 *********************************************************************************************************
     32 
     33 */
     34 
     35 char const *hosts[3] =
     36 
     37 {
     38 
     39      "www.armfly.com",
     40 
     41      "www.baidu.com",
     42 
     43      "www.qq.com",
     44 
     45 };
     46 
     47  
     48 
     49 /*
     50 
     51 *********************************************************************************************************
     52 
     53 *    函 数 名: dns_cbfunc
     54 
     55 *    功能说明: 函数get_host_by_name的调函数。
     56 
     57 *    形    参: event  事件类型
     58 
     59 *             ip     如果事件类型是DNS_EVT_SUCCESS,此指针变量指向返回的IP地址缓冲区。
     60 
     61 *    返 回 值: 无
     62 
     63 *********************************************************************************************************
     64 
     65 */
     66 
     67 static void dns_cbfunc (unsigned char event, unsigned char *ip)
     68 
     69 {
     70 
     71      switch (event)
     72 
     73      {
     74 
     75          /* 成功解析地址 */
     76 
     77          case DNS_EVT_SUCCESS:
     78 
     79               printf_debug("%d.%d.%d.%d
    ",ip[0],ip[1],ip[2],ip[3]);
     80 
     81               break;
     82 
     83         
     84 
     85          /* DNS记录数据库中不存在此地址 */
     86 
     87          case DNS_EVT_NONAME:
     88 
     89               printf_debug("Host Name does not exist in DNS record database.
    ");
     90 
     91               break;
     92 
     93  
     94 
     95          /* 允许的DNS解析重试次数已经用完,仍无法解析,时间超时 */
     96 
     97          case DNS_EVT_TIMEOUT:
     98 
     99               printf_debug("DNS Resolver Timeout expired, Host Address not resolved.
    ");
    100 
    101               break;
    102 
    103  
    104 
    105           /* DNS协议错误,收到无效或者被损坏的回复 */
    106 
    107          case DNS_EVT_ERROR:
    108 
    109               printf_debug("DNS Resolver Protocol Error, Host Address not resolved.
    ");
    110 
    111               return;
    112 
    113      }
    114 
    115 }
    116 
    117  
    118 
    119 /*
    120 
    121 *********************************************************************************************************
    122 
    123 *    函 数 名: tcpnet_poll
    124 
    125 *    功能说明: 使用TCPnet必须要一直调用的函数
    126 
    127 *    形    参: 无
    128 
    129 *    返 回 值: 无
    130 
    131 *********************************************************************************************************
    132 
    133 */
    134 
    135 void tcpnet_poll(void)
    136 
    137 {
    138 
    139      if(bsp_CheckTimer(0))
    140 
    141      {
    142 
    143          /* 此函数坚决不可以放在中断里面跑 */
    144 
    145          timer_tick ();
    146 
    147      }
    148 
    149     
    150 
    151      main_TcpNet ();
    152 
    153 }
    154 
    155  
    156 
    157 /*
    158 
    159 *********************************************************************************************************
    160 
    161 *    函 数 名: TCPnetTest
    162 
    163 *    功能说明: TCPnet应用
    164 
    165 *    形    参: 无
    166 
    167 *    返 回 值: 无
    168 
    169 *********************************************************************************************************
    170 
    171 */
    172 
    173 void TCPnetTest(void)
    174 
    175 { 
    176 
    177      uint8_t ucKeyCode;
    178 
    179     
    180 
    181     
    182 
    183      /* 初始化网络协议栈 */
    184 
    185      init_TcpNet ();
    186 
    187  
    188 
    189      /* 创建一个周期是100ms的软定时器 */
    190 
    191     bsp_StartAutoTimer(0, 100);
    192 
    193     
    194 
    195      while (1)
    196 
    197      {
    198 
    199           /* TCP轮询 */
    200 
    201          tcpnet_poll();
    202 
    203         
    204 
    205           /* 按键消息的处理 */
    206 
    207          ucKeyCode = bsp_GetKey();
    208 
    209          if ((ucKeyCode != KEY_NONE))
    210 
    211          {
    212 
    213               switch (ucKeyCode)
    214 
    215               {
    216 
    217                    /* 按键K1按下,返回www.armfly.com的IP地址。 */
    218 
    219                    case KEY_DOWN_K1:
    220 
    221                        printf_debug("网址www.armfly.com的IP地址:");
    222 
    223                        get_host_by_name ((U8 *)hosts[0], dns_cbfunc);
    224 
    225                        break;
    226 
    227  
    228 
    229                    /* 按键K2按下,返回www.baidu.com的IP地址 */
    230 
    231                    case KEY_DOWN_K2:
    232 
    233                        printf_debug("网址www.baidu.com的IP地址:");                  
    234 
    235                         get_host_by_name ((U8 *)hosts[1], dns_cbfunc);                  
    236 
    237                        break;
    238 
    239                       
    240 
    241                    /* 按键K3按下,返回www.qq.com的IP地址 */
    242 
    243                    case KEY_DOWN_K3:
    244 
    245                        printf_debug("网址www.qq.com的IP地址:");                          
    246 
    247                        get_host_by_name ((U8 *)hosts[1], dns_cbfunc);                       
    248 
    249                        break;
    250 
    251                   
    252 
    253                     /* 其他的键值不处理 */
    254 
    255                    default:                    
    256 
    257                        break;
    258 
    259               }
    260 
    261          }
    262 
    263      }
    264 
    265 }

    28.7.2 STM32F429开发板实验

    配套例子:

    V6-1036_RL-TCPnet实验_DNS应用(裸机)

    实验目的:

    1. 学习RL-TCPnet的DNS使用。

    实验内容:

    1. 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。
    2. 像腾讯,百度等网址都有多个IP地址,如果用户测试DNS返回的地址不同,这种情况是正常的。
    3. 按键K1按下,返回www.armfly.com的IP地址。
    4. 按键K2按下,返回www.baidu.com的IP地址。
    5. 按键K3按下,返回www.qq.com的IP地址。

    实验操作:

    详见本章节28.6小节。

    配置向导文件设置(Net_Config.c):

    详见本章节28.3小节。

    调试文件设置(Net_Debug.c):

    详见本章节28.4小节。

    程序设计:

    主函数初始化

    在main.c文件实现:

    /*
    
    *********************************************************************************************************
    
    *    函 数 名: main
    
    *    功能说明: 标准c程序入口。
    
    *    形    参: 无
    
    *    返 回 值: 无
    
    *********************************************************************************************************
    
    */
    
    int main (void)
    
    {   
    
         /* 初始化外设 */
    
         bsp_Init();
    
     
    
         /* 进入RL-TCPnet测试函数 */
    
         TCPnetTest();
    
    }

    硬件外设初始化

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

     1 /*
     2 
     3 *********************************************************************************************************
     4 
     5 *    函 数 名: bsp_Init
     6 
     7 *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
     8 
     9 *    形    参:无
    10 
    11 *    返 回 值: 无
    12 
    13 *********************************************************************************************************
    14 
    15 */
    16 
    17 void bsp_Init(void)
    18 
    19 {
    20 
    21      /*
    22 
    23          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
    24 
    25          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
    26 
    27  
    28 
    29          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
    30 
    31      */
    32 
    33      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
    34 
    35      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    36 
    37  
    38 
    39      bsp_InitUart();    /* 初始化串口 */
    40 
    41      bsp_InitKey();     /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */
    42 
    43      bsp_InitLed();     /* 初始LED指示灯端口 */
    44 
    45      bsp_InitTimer();   /* 初始化滴答定时器 */
    46 
    47 }

    RL-TCPnet功能测试

    这里专门创建了一个app_tcpnet_lib.c文件用于RL-TCPnet功能的测试,这里通过函数get_host_by_name来解析网址对应的IP地址。

    /*
    
    *********************************************************************************************************
    
    *                                      用于本文件的调试
    
    *********************************************************************************************************
    
    */
    
    #if 1
    
         #define printf_debug printf
    
    #else
    
         #define printf_debug(...)
    
    #endif
    
     
    
     
    
    /*
    
    *********************************************************************************************************
    
    *                                          变量
    
    *********************************************************************************************************
    
    */
    
    char const *hosts[3] =
    
    {
    
         "www.armfly.com",
    
         "www.baidu.com",
    
         "www.qq.com",
    
    };
    
     
    
    /*
    
    *********************************************************************************************************
    
    *    函 数 名: dns_cbfunc
    
    *    功能说明: 函数get_host_by_name的调函数。
    
    *    形    参: event  事件类型
    
    *             ip     如果事件类型是DNS_EVT_SUCCESS,此指针变量指向返回的IP地址缓冲区。
    
    *    返 回 值: 无
    
    *********************************************************************************************************
    
    */
    
    static void dns_cbfunc (unsigned char event, unsigned char *ip)
    
    {
    
         switch (event)
    
         {
    
             /* 成功解析地址 */
    
             case DNS_EVT_SUCCESS:
    
                  printf_debug("%d.%d.%d.%d
    ",ip[0],ip[1],ip[2],ip[3]);
    
                  break;
    
            
    
             /* DNS记录数据库中不存在此地址 */
    
             case DNS_EVT_NONAME:
    
                  printf_debug("Host Name does not exist in DNS record database.
    ");
    
                  break;
    
     
    
             /* 允许的DNS解析重试次数已经用完,仍无法解析,时间超时 */
    
             case DNS_EVT_TIMEOUT:
    
                  printf_debug("DNS Resolver Timeout expired, Host Address not resolved.
    ");
    
                  break;
    
     
    
              /* DNS协议错误,收到无效或者被损坏的回复 */
    
             case DNS_EVT_ERROR:
    
                  printf_debug("DNS Resolver Protocol Error, Host Address not resolved.
    ");
    
                  return;
    
         }
    
    }
    
     
    
    /*
    
    *********************************************************************************************************
    
    *    函 数 名: tcpnet_poll
    
    *    功能说明: 使用TCPnet必须要一直调用的函数
    
    *    形    参: 无
    
    *    返 回 值: 无
    
    *********************************************************************************************************
    
    */
    
    void tcpnet_poll(void)
    
    {
    
         if(bsp_CheckTimer(0))
    
         {
    
             /* 此函数坚决不可以放在中断里面跑 */
    
             timer_tick ();
    
         }
    
        
    
         main_TcpNet ();
    
    }
    
     
    
    /*
    
    *********************************************************************************************************
    
    *    函 数 名: TCPnetTest
    
    *    功能说明: TCPnet应用
    
    *    形    参: 无
    
    *    返 回 值: 无
    
    *********************************************************************************************************
    
    */
    
    void TCPnetTest(void)
    
    { 
    
         uint8_t ucKeyCode;
    
        
    
        
    
         /* 初始化网络协议栈 */
    
         init_TcpNet ();
    
     
    
         /* 创建一个周期是100ms的软定时器 */
    
        bsp_StartAutoTimer(0, 100);
    
        
    
         while (1)
    
         {
    
              /* TCP轮询 */
    
             tcpnet_poll();
    
            
    
              /* 按键消息的处理 */
    
             ucKeyCode = bsp_GetKey();
    
              if ((ucKeyCode != KEY_NONE))
    
             {
    
                  switch (ucKeyCode)
    
                  {
    
                       /* 按键K1按下,返回www.armfly.com的IP地址。 */
    
                       case KEY_DOWN_K1:
    
                           printf_debug("网址www.armfly.com的IP地址:");
    
                           get_host_by_name ((U8 *)hosts[0], dns_cbfunc);
    
                           break;
    
     
    
                       /* 按键K2按下,返回www.baidu.com的IP地址 */
    
                       case KEY_DOWN_K2:
    
                           printf_debug("网址www.baidu.com的IP地址:");                  
    
                           get_host_by_name ((U8 *)hosts[1], dns_cbfunc);                  
    
                           break;
    
                          
    
                       /* 按键K3按下,返回www.qq.com的IP地址 */
    
                       case KEY_DOWN_K3:
    
                           printf_debug("网址www.qq.com的IP地址:");                          
    
                           get_host_by_name ((U8 *)hosts[1], dns_cbfunc);                       
    
                           break;
    
                      
    
                        /* 其他的键值不处理 */
    
                       default:                    
    
                           break;
    
                  }
    
             }
    
         }
    
    }

    28.8 实验例程说明(RTX)

    28.8.1 STM32F407开发板实验

    配套例子:

    V5-1037_RL-TCPnet实验_DNS应用(RTX)

    实验目的:

    1. 学习RL-TCPnet的DNS使用。

    实验内容:

    1. 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。
    2. 像腾讯,百度等网址都有多个IP地址,如果用户测试DNS返回的地址不同,这种情况是正常的。
    3. 按键K1按下,返回www.armfly.com的IP地址。
    4. 按键K2按下,返回www.baidu.com的IP地址。
    5. 按键K3按下,返回www.qq.com的IP地址。

    实验操作:

    详见本章节28.6小节。

    配置向导文件设置(Net_Config.c):

    详见本章节28.3小节。

    调试文件设置(Net_Debug.c):

    详见本章节28.4小节。

    RTX配置:

    RTX配置向导详情如下:

     

    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任务调试信息:

     

    程序设计:

    任务栈大小分配:

    static uint64_t AppTaskUserIFStk[1024/8];   /* 任务栈 */

    static uint64_t AppTaskLEDStk[1024/8];      /* 任务栈 */

    static uint64_t AppTaskMsgProStk[1024/8];  /* 任务栈 */

    static uint64_t AppTaskTCPMainStk[2048/8]; /* 任务栈 */

    static uint64_t AppTaskStartStk[1024/8];     /* 任务栈 */

    将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数、浮点运算和uint64_t类型数据运算会出问题。

    系统栈大小分配:

     

    RTX初始化:

    /*
    
    *********************************************************************************************************
    
    *    函 数 名: main
    
    *    功能说明: 标准c程序入口。
    
    *    形    参: 无
    
    *    返 回 值: 无
    
    *********************************************************************************************************
    
    */
    
    int main (void)
    
    {   
    
         /* 初始化外设 */
    
         bsp_Init();
    
        
    
         /* 创建启动任务 */
    
         os_sys_init_user (AppTaskStart,              /* 任务函数 */
    
                           5,                         /* 任务优先级 */
    
                           &AppTaskStartStk,          /* 任务栈 */
    
                           sizeof(AppTaskStartStk));  /* 任务栈大小,单位字节数 */
    
         while(1);
    
    }

    硬件外设初始化

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

     1 /*
     2 
     3 *********************************************************************************************************
     4 
     5 *    函 数 名: bsp_Init
     6 
     7 *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
     8 
     9 *    形    参:无
    10 
    11 *    返 回 值: 无
    12 
    13 *********************************************************************************************************
    14 
    15 */
    16 
    17 void bsp_Init(void)
    18 
    19 {
    20 
    21      /*
    22 
    23          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
    24 
    25          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
    26 
    27  
    28 
    29          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
    30 
    31      */
    32 
    33      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
    34 
    35      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    36 
    37  
    38 
    39      bsp_InitDWT();     /* 初始化DWT */
    40 
    41      bsp_InitUart();    /* 初始化串口 */
    42 
    43      bsp_InitKey();    /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */
    44 
    45      bsp_InitLed();    /* 初始LED指示灯端口 */
    46 
    47 }

    RTX任务创建:

     1 /*
     2 
     3 *********************************************************************************************************
     4 
     5 *    函 数 名: AppTaskCreate
     6 
     7 *    功能说明: 创建应用任务
     8 
     9 *    形    参: 无
    10 
    11 *    返 回 值: 无
    12 
    13 *********************************************************************************************************
    14 
    15 */
    16 
    17 static void AppTaskCreate (void)
    18 
    19 {
    20 
    21      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
    22 
    23                                            1,                         /* 任务优先级 */
    24 
    25                                            &AppTaskUserIFStk,         /* 任务栈 */
    26 
    27                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
    28 
    29     
    30 
    31      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
    32 
    33                                         2,                       /* 任务优先级 */
    34 
    35                                         &AppTaskLEDStk,          /* 任务栈 */
    36 
    37                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
    38 
    39     
    40 
    41      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
    42 
    43                                            3,                         /* 任务优先级 */
    44 
    45                                            &AppTaskMsgProStk,         /* 任务栈 */
    46 
    47                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
    48 
    49     
    50 
    51     HandleTaskTCPMain = os_tsk_create_user(AppTaskTCPMain,             /* 任务函数 */
    52 
    53                                            4,                         /* 任务优先级 */
    54 
    55                                            &AppTaskTCPMainStk,         /* 任务栈 */
    56 
    57                                            sizeof(AppTaskTCPMainStk)); /* 任务栈大小,单位字节数 */
    58 
    59 }

    五个RTX任务的实现:

      1 /*
      2 
      3 *********************************************************************************************************
      4 
      5 *    函 数 名: AppTaskUserIF
      6 
      7 *    功能说明: 按键消息处理     
      8 
      9 *    形    参: 无
     10 
     11 *    返 回 值: 无
     12 
     13 *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
     14 
     15 *********************************************************************************************************
     16 
     17 */
     18 
     19 __task void AppTaskUserIF(void)
     20 
     21 {
     22 
     23      uint8_t ucKeyCode;
     24 
     25  
     26 
     27     while(1)
     28 
     29     {
     30 
     31          ucKeyCode = bsp_GetKey();
     32 
     33         
     34 
     35          if (ucKeyCode != KEY_NONE)
     36 
     37          {
     38 
     39               switch (ucKeyCode)
     40 
     41               {
     42 
     43                    /* K1键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit0 */
     44 
     45                    case KEY_DOWN_K1:
     46 
     47                        printf("K1键按下,直接发送事件标志给任务AppTaskTCPMain,bit0被设置
    ");
     48 
     49                        os_evt_set (KEY1_BIT0, HandleTaskTCPMain);                      
     50 
     51                        break;  
     52 
     53  
     54 
     55                    /* K2键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit1 */
     56 
     57                    case KEY_DOWN_K2:
     58 
     59                        printf("K2键按下,直接发送事件标志给任务AppTaskTCPMain,bit1被设置
    ");
     60 
     61                        os_evt_set (KEY2_BIT1, HandleTaskTCPMain);
     62 
     63                        break;
     64 
     65                   
     66 
     67                    /* K3键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit2 */
     68 
     69                    case KEY_DOWN_K3:
     70 
     71                        printf("K3键按下,直接发送事件标志给任务AppTaskTCPMain,bit2被设置
    ");
     72 
     73                        os_evt_set (KEY3_BIT2, HandleTaskTCPMain);
     74 
     75                        break;
     76 
     77  
     78 
     79                    /* 其他的键值不处理 */
     80 
     81                    default:                    
     82 
     83                        break;
     84 
     85               }
     86 
     87          }
     88 
     89         
     90 
     91          os_dly_wait(20);
     92 
     93      }
     94 
     95 }
     96 
     97  
     98 
     99 /*
    100 
    101 *********************************************************************************************************
    102 
    103 *    函 数 名: AppTaskLED
    104 
    105 *    功能说明: LED闪烁。
    106 
    107 *    形    参: 无
    108 
    109 *    返 回 值: 无
    110 
    111 *   优 先 级: 2 
    112 
    113 *********************************************************************************************************
    114 
    115 */
    116 
    117 __task void AppTaskLED(void)
    118 
    119 {
    120 
    121      const uint16_t usFrequency = 500; /* 延迟周期 */
    122 
    123     
    124 
    125      /* 设置延迟周期 */
    126 
    127      os_itv_set(usFrequency);
    128 
    129     
    130 
    131     while(1)
    132 
    133     {
    134 
    135          bsp_LedToggle(2);
    136 
    137  
    138 
    139          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
    140 
    141          os_itv_wait();
    142 
    143     }
    144 
    145 }
    146 
    147  
    148 
    149 /*
    150 
    151 *********************************************************************************************************
    152 
    153 *    函 数 名: AppTaskMsgPro
    154 
    155 *    功能说明: 按键检测
    156 
    157 *    形    参: 无
    158 
    159 *    返 回 值: 无
    160 
    161 *   优 先 级: 3 
    162 
    163 *********************************************************************************************************
    164 
    165 */
    166 
    167 __task void AppTaskMsgPro(void)
    168 
    169 {
    170 
    171     while(1)
    172 
    173     {
    174 
    175          bsp_KeyScan();
    176 
    177          os_dly_wait(10);
    178 
    179     }
    180 
    181 }
    182 
    183  
    184 
    185 /*
    186 
    187 *********************************************************************************************************
    188 
    189 *    函 数 名: AppTaskTCPMain
    190 
    191 *    功能说明: RL-TCPnet测试任务
    192 
    193 *    形    参: 无
    194 
    195 *    返 回 值: 无
    196 
    197 *   优 先 级: 4 
    198 
    199 *********************************************************************************************************
    200 
    201 */
    202 
    203 __task void AppTaskTCPMain(void)
    204 
    205 {
    206 
    207      while (1)
    208 
    209      {
    210 
    211          TCPnetTest();
    212 
    213      }
    214 
    215 }
    216 
    217  
    218 
    219 /*
    220 
    221 *********************************************************************************************************
    222 
    223 *    函 数 名: AppTaskStart
    224 
    225 *    功能说明: 启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。
    226 
    227 *    形    参: 无
    228 
    229 *    返 回 值: 无
    230 
    231 *   优 先 级: 5 
    232 
    233 *********************************************************************************************************
    234 
    235 */
    236 
    237 __task void AppTaskStart(void)
    238 
    239 {
    240 
    241      /* 初始化RL-TCPnet */
    242 
    243      init_TcpNet ();
    244 
    245     
    246 
    247      /* 创建任务 */
    248 
    249      AppTaskCreate();
    250 
    251     
    252 
    253      os_itv_set (100);
    254 
    255     
    256 
    257     while(1)
    258 
    259     {
    260 
    261          os_itv_wait ();
    262 
    263         
    264 
    265          /* RL-TCPnet时间基准更新函数 */
    266 
    267          timer_tick ();
    268 
    269     }
    270 
    271 }

    RL-TCPnet功能测试

    这里专门创建了一个app_tcpnet_lib.c文件用于RL-TCPnet功能的测试,这里通过函数get_host_by_name来解析网址对应的IP地址。

      1 #include "includes.h" 
      2 
      3  
      4 
      5  
      6 
      7  
      8 
      9 /*
     10 
     11 *********************************************************************************************************
     12 
     13 *                                      用于本文件的调试
     14 
     15 *********************************************************************************************************
     16 
     17 */
     18 
     19 #if 1
     20 
     21      #define printf_debug printf
     22 
     23 #else
     24 
     25      #define printf_debug(...)
     26 
     27 #endif
     28 
     29  
     30 
     31  
     32 
     33 /*
     34 
     35 *********************************************************************************************************
     36 
     37 *                                          变量
     38 
     39 *********************************************************************************************************
     40 
     41 */
     42 
     43 char const *hosts[3] =
     44 
     45 {
     46 
     47      "www.armfly.com",
     48 
     49      "www.baidu.com",
     50 
     51      "www.qq.com",
     52 
     53 };
     54 
     55  
     56 
     57 /*
     58 
     59 *********************************************************************************************************
     60 
     61 *    函 数 名: dns_cbfunc
     62 
     63 *    功能说明: 函数get_host_by_name的调函数。
     64 
     65 *    形    参: event  事件类型
     66 
     67 *             ip     如果事件类型是DNS_EVT_SUCCESS,此指针变量指向返回的IP地址缓冲区。
     68 
     69 *    返 回 值: 无
     70 
     71 *********************************************************************************************************
     72 
     73 */
     74 
     75 static void dns_cbfunc (unsigned char event, unsigned char *ip)
     76 
     77 {
     78 
     79      switch (event)
     80 
     81      {
     82 
     83          /* 成功解析地址 */
     84 
     85          case DNS_EVT_SUCCESS:
     86 
     87               printf_debug("%d.%d.%d.%d
    ",ip[0],ip[1],ip[2],ip[3]);
     88 
     89               break;
     90 
     91         
     92 
     93          /* DNS记录数据库中不存在此地址 */
     94 
     95          case DNS_EVT_NONAME:
     96 
     97               printf_debug("Host Name does not exist in DNS record database.
    ");
     98 
     99               break;
    100 
    101  
    102 
    103          /* 允许的DNS解析重试次数已经用完,仍无法解析,时间超时 */
    104 
    105          case DNS_EVT_TIMEOUT:
    106 
    107               printf_debug("DNS Resolver Timeout expired, Host Address not resolved.
    ");
    108 
    109               break;
    110 
    111  
    112 
    113          /* DNS协议错误,收到无效或者被损坏的回复 */
    114 
    115          case DNS_EVT_ERROR:
    116 
    117               printf_debug("DNS Resolver Protocol Error, Host Address not resolved.
    ");
    118 
    119               return;
    120 
    121      }
    122 
    123 }
    124 
    125  
    126 
    127 /*
    128 
    129 *********************************************************************************************************
    130 
    131 *    函 数 名: TCPnetTest
    132 
    133 *    功能说明: TCPnet应用
    134 
    135 *    形    参: 无
    136 
    137 *    返 回 值: 无
    138 
    139 *********************************************************************************************************
    140 
    141 */
    142 
    143 void TCPnetTest(void)
    144 
    145 { 
    146 
    147      OS_RESULT xResult;
    148 
    149      const uint16_t usMaxBlockTime = 2; /* 延迟周期 */
    150 
    151  
    152 
    153  
    154 
    155      while (1)
    156 
    157      {
    158 
    159          /* RL-TCPnet处理函数 */
    160 
    161          main_TcpNet();
    162 
    163  
    164 
    165           /* 按键消息的处理 */
    166 
    167          if(os_evt_wait_or(0xFFFF, usMaxBlockTime) == OS_R_EVT)
    168 
    169          {
    170 
    171               xResult = os_evt_get ();
    172 
    173               switch (xResult)
    174 
    175               {
    176 
    177                    /* 接收到按键K1按下消息,返回www.armfly.com的IP地址。 */
    178 
    179                    case KEY1_BIT0:
    180 
    181                        printf_debug("网址www.armfly.com的IP地址:");
    182 
    183                     get_host_by_name ((U8 *)hosts[0], dns_cbfunc);                 
    184 
    185                        break;
    186 
    187  
    188 
    189                    /* 接收到K2键按下消息,返回www.baidu.com的IP地址 */
    190 
    191                    case KEY2_BIT1:   
    192 
    193                        printf_debug("网址www.baidu.com的IP地址:");                  
    194 
    195                        get_host_by_name ((U8 *)hosts[1], dns_cbfunc);
    196 
    197                        break;
    198 
    199                       
    200 
    201                    /* 接收到K3键按下消息,返回www.qq.com的IP地址 */
    202 
    203                    case KEY3_BIT2:
    204 
    205                        printf_debug("网址www.qq.com的IP地址:");                          
    206 
    207                         get_host_by_name ((U8 *)hosts[2], dns_cbfunc);         
    208 
    209                        break;
    210 
    211                   
    212 
    213                     /* 其他的键值不处理 */
    214 
    215                    default:                    
    216 
    217                        break;
    218 
    219               }
    220 
    221          }
    222 
    223      }
    224 
    225 }

    28.8.2 STM32F429开发板实验

    配套例子:

    V6-1037_RL-TCPnet实验_DNS应用(RTX)

    实验目的:

    1. 学习RL-TCPnet的DNS使用。

    实验内容:

    1. 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。
    2. 像腾讯,百度等网址都有多个IP地址,如果用户测试DNS返回的地址不同,这种情况是正常的。
    3. 按键K1按下,返回www.armfly.com的IP地址。
    4. 按键K2按下,返回www.baidu.com的IP地址。
    5. 按键K3按下,返回www.qq.com的IP地址。

    实验操作:

    详见本章节28.6小节。

    配置向导文件设置(Net_Config.c):

    详见本章节28.3小节。

    调试文件设置(Net_Debug.c):

    详见本章节28.4小节。

    RTX配置:

    RTX配置向导详情如下:

     

    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任务调试信息:

     

    程序设计:

    任务栈大小分配:

    static uint64_t AppTaskUserIFStk[1024/8];   /* 任务栈 */

    static uint64_t AppTaskLEDStk[1024/8];      /* 任务栈 */

    static uint64_t AppTaskMsgProStk[1024/8];  /* 任务栈 */

    static uint64_t AppTaskTCPMainStk[2048/8]; /* 任务栈 */

    static uint64_t AppTaskStartStk[1024/8];     /* 任务栈 */

    将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数、浮点运算和uint64_t类型数据运算会出问题。

    系统栈大小分配:

     

    RTX初始化:

    /*
    
    *********************************************************************************************************
    
    *    函 数 名: main
    
    *    功能说明: 标准c程序入口。
    
    *    形    参: 无
    
    *    返 回 值: 无
    
    *********************************************************************************************************
    
    */
    
    int main (void)
    
    {   
    
         /* 初始化外设 */
    
         bsp_Init();
    
        
    
         /* 创建启动任务 */
    
         os_sys_init_user (AppTaskStart,              /* 任务函数 */
    
                           5,                         /* 任务优先级 */
    
                           &AppTaskStartStk,          /* 任务栈 */
    
                           sizeof(AppTaskStartStk));  /* 任务栈大小,单位字节数 */
    
         while(1);
    
    }

    硬件外设初始化

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

     1 /*
     2 
     3 *********************************************************************************************************
     4 
     5 *    函 数 名: bsp_Init
     6 
     7 *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
     8 
     9 *    形    参:无
    10 
    11 *    返 回 值: 无
    12 
    13 *********************************************************************************************************
    14 
    15 */
    16 
    17 void bsp_Init(void)
    18 
    19 {
    20 
    21      /*
    22 
    23          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
    24 
    25          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
    26 
    27  
    28 
    29          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
    30 
    31      */
    32 
    33      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
    34 
    35      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    36 
    37  
    38 
    39      SystemCoreClockUpdate();    /* 根据PLL配置更新系统时钟频率变量 SystemCoreClock */
    40 
    41  
    42 
    43      bsp_InitDWT();      /* 初始化DWT */
    44 
    45      bsp_InitUart();     /* 初始化串口 */
    46 
    47      bsp_InitKey();     /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */
    48 
    49  
    50 
    51      bsp_InitExtIO();    /* FMC总线上扩展了32位输出IO, 操作LED等外设必须初始化 */
    52 
    53      bsp_InitLed();      /* 初始LED指示灯端口 */
    54 
    55 }

    RTX任务创建:

     1 /*
     2 
     3 *********************************************************************************************************
     4 
     5 *    函 数 名: AppTaskCreate
     6 
     7 *    功能说明: 创建应用任务
     8 
     9 *    形    参: 无
    10 
    11 *    返 回 值: 无
    12 
    13 *********************************************************************************************************
    14 
    15 */
    16 
    17 static void AppTaskCreate (void)
    18 
    19 {
    20 
    21      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
    22 
    23                                            1,                         /* 任务优先级 */
    24 
    25                                            &AppTaskUserIFStk,         /* 任务栈 */
    26 
    27                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
    28 
    29     
    30 
    31      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
    32 
    33                                         2,                       /* 任务优先级 */
    34 
    35                                         &AppTaskLEDStk,          /* 任务栈 */
    36 
    37                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
    38 
    39     
    40 
    41      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
    42 
    43                                            3,                         /* 任务优先级 */
    44 
    45                                            &AppTaskMsgProStk,         /* 任务栈 */
    46 
    47                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
    48 
    49     
    50 
    51     HandleTaskTCPMain = os_tsk_create_user(AppTaskTCPMain,             /* 任务函数 */
    52 
    53                                            4,                         /* 任务优先级 */
    54 
    55                                            &AppTaskTCPMainStk,         /* 任务栈 */
    56 
    57                                            sizeof(AppTaskTCPMainStk)); /* 任务栈大小,单位字节数 */
    58 
    59 }

    五个RTX任务的实现:

      1 /*
      2 
      3 *********************************************************************************************************
      4 
      5 *    函 数 名: AppTaskUserIF
      6 
      7 *    功能说明: 按键消息处理     
      8 
      9 *    形    参: 无
     10 
     11 *    返 回 值: 无
     12 
     13 *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
     14 
     15 *********************************************************************************************************
     16 
     17 */
     18 
     19 __task void AppTaskUserIF(void)
     20 
     21 {
     22 
     23      uint8_t ucKeyCode;
     24 
     25  
     26 
     27     while(1)
     28 
     29     {
     30 
     31          ucKeyCode = bsp_GetKey();
     32 
     33         
     34 
     35          if (ucKeyCode != KEY_NONE)
     36 
     37          {
     38 
     39               switch (ucKeyCode)
     40 
     41               {
     42 
     43                    /* K1键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit0 */
     44 
     45                    case KEY_DOWN_K1:
     46 
     47                        printf("K1键按下,直接发送事件标志给任务AppTaskTCPMain,bit0被设置
    ");
     48 
     49                        os_evt_set (KEY1_BIT0, HandleTaskTCPMain);                      
     50 
     51                        break;  
     52 
     53  
     54 
     55                    /* K2键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit1 */
     56 
     57                    case KEY_DOWN_K2:
     58 
     59                        printf("K2键按下,直接发送事件标志给任务AppTaskTCPMain,bit1被设置
    ");
     60 
     61                        os_evt_set (KEY2_BIT1, HandleTaskTCPMain);
     62 
     63                        break;
     64 
     65                   
     66 
     67                    /* K3键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit2 */
     68 
     69                    case KEY_DOWN_K3:
     70 
     71                        printf("K3键按下,直接发送事件标志给任务AppTaskTCPMain,bit2被设置
    ");
     72 
     73                        os_evt_set (KEY3_BIT2, HandleTaskTCPMain);
     74 
     75                        break;
     76 
     77  
     78 
     79                    /* 其他的键值不处理 */
     80 
     81                    default:                    
     82 
     83                        break;
     84 
     85               }
     86 
     87          }
     88 
     89         
     90 
     91          os_dly_wait(20);
     92 
     93      }
     94 
     95 }
     96 
     97  
     98 
     99 /*
    100 
    101 *********************************************************************************************************
    102 
    103 *    函 数 名: AppTaskLED
    104 
    105 *    功能说明: LED闪烁。
    106 
    107 *    形    参: 无
    108 
    109 *    返 回 值: 无
    110 
    111 *   优 先 级: 2 
    112 
    113 *********************************************************************************************************
    114 
    115 */
    116 
    117 __task void AppTaskLED(void)
    118 
    119 {
    120 
    121      const uint16_t usFrequency = 500; /* 延迟周期 */
    122 
    123     
    124 
    125      /* 设置延迟周期 */
    126 
    127      os_itv_set(usFrequency);
    128 
    129     
    130 
    131     while(1)
    132 
    133     {
    134 
    135          bsp_LedToggle(2);
    136 
    137  
    138 
    139          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
    140 
    141          os_itv_wait();
    142 
    143     }
    144 
    145 }
    146 
    147  
    148 
    149 /*
    150 
    151 *********************************************************************************************************
    152 
    153 *    函 数 名: AppTaskMsgPro
    154 
    155 *    功能说明: 按键检测
    156 
    157 *    形    参: 无
    158 
    159 *    返 回 值: 无
    160 
    161 *   优 先 级: 3 
    162 
    163 *********************************************************************************************************
    164 
    165 */
    166 
    167 __task void AppTaskMsgPro(void)
    168 
    169 {
    170 
    171     while(1)
    172 
    173     {
    174 
    175          bsp_KeyScan();
    176 
    177          os_dly_wait(10);
    178 
    179     }
    180 
    181 }
    182 
    183  
    184 
    185 /*
    186 
    187 *********************************************************************************************************
    188 
    189 *    函 数 名: AppTaskTCPMain
    190 
    191 *    功能说明: RL-TCPnet测试任务
    192 
    193 *    形    参: 无
    194 
    195 *    返 回 值: 无
    196 
    197 *   优 先 级: 4 
    198 
    199 *********************************************************************************************************
    200 
    201 */
    202 
    203 __task void AppTaskTCPMain(void)
    204 
    205 {
    206 
    207      while (1)
    208 
    209      {
    210 
    211          TCPnetTest();
    212 
    213      }
    214 
    215 }
    216 
    217  
    218 
    219 /*
    220 
    221 *********************************************************************************************************
    222 
    223 *    函 数 名: AppTaskStart
    224 
    225 *    功能说明: 启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。
    226 
    227 *    形    参: 无
    228 
    229 *    返 回 值: 无
    230 
    231 *   优 先 级: 5 
    232 
    233 *********************************************************************************************************
    234 
    235 */
    236 
    237 __task void AppTaskStart(void)
    238 
    239 {
    240 
    241      /* 初始化RL-TCPnet */
    242 
    243      init_TcpNet ();
    244 
    245     
    246 
    247      /* 创建任务 */
    248 
    249      AppTaskCreate();
    250 
    251     
    252 
    253      os_itv_set (100);
    254 
    255     
    256 
    257     while(1)
    258 
    259     {
    260 
    261          os_itv_wait ();
    262 
    263         
    264 
    265          /* RL-TCPnet时间基准更新函数 */
    266 
    267           timer_tick ();
    268 
    269     }
    270 
    271 }

    RL-TCPnet功能测试

    这里专门创建了一个app_tcpnet_lib.c文件用于RL-TCPnet功能的测试,这里通过函数get_host_by_name来解析网址对应的IP地址。

      1 #include "includes.h" 
      2 
      3  
      4 
      5  
      6 
      7  
      8 
      9 /*
     10 
     11 *********************************************************************************************************
     12 
     13 *                                      用于本文件的调试
     14 
     15 *********************************************************************************************************
     16 
     17 */
     18 
     19 #if 1
     20 
     21      #define printf_debug printf
     22 
     23 #else
     24 
     25      #define printf_debug(...)
     26 
     27 #endif
     28 
     29  
     30 
     31  
     32 
     33 /*
     34 
     35 *********************************************************************************************************
     36 
     37 *                                          变量
     38 
     39 *********************************************************************************************************
     40 
     41 */
     42 
     43 char const *hosts[3] =
     44 
     45 {
     46 
     47      "www.armfly.com",
     48 
     49      "www.baidu.com",
     50 
     51      "www.qq.com",
     52 
     53 };
     54 
     55  
     56 
     57 /*
     58 
     59 *********************************************************************************************************
     60 
     61 *    函 数 名: dns_cbfunc
     62 
     63 *    功能说明: 函数get_host_by_name的调函数。
     64 
     65 *    形    参: event  事件类型
     66 
     67 *             ip     如果事件类型是DNS_EVT_SUCCESS,此指针变量指向返回的IP地址缓冲区。
     68 
     69 *    返 回 值: 无
     70 
     71 *********************************************************************************************************
     72 
     73 */
     74 
     75 static void dns_cbfunc (unsigned char event, unsigned char *ip)
     76 
     77 {
     78 
     79      switch (event)
     80 
     81      {
     82 
     83          /* 成功解析地址 */
     84 
     85          case DNS_EVT_SUCCESS:
     86 
     87               printf_debug("%d.%d.%d.%d
    ",ip[0],ip[1],ip[2],ip[3]);
     88 
     89               break;
     90 
     91         
     92 
     93          /* DNS记录数据库中不存在此地址 */
     94 
     95          case DNS_EVT_NONAME:
     96 
     97               printf_debug("Host Name does not exist in DNS record database.
    ");
     98 
     99               break;
    100 
    101  
    102 
    103          /* 允许的DNS解析重试次数已经用完,仍无法解析,时间超时 */
    104 
    105          case DNS_EVT_TIMEOUT:
    106 
    107               printf_debug("DNS Resolver Timeout expired, Host Address not resolved.
    ");
    108 
    109               break;
    110 
    111  
    112 
    113          /* DNS协议错误,收到无效或者被损坏的回复 */
    114 
    115          case DNS_EVT_ERROR:
    116 
    117               printf_debug("DNS Resolver Protocol Error, Host Address not resolved.
    ");
    118 
    119               return;
    120 
    121      }
    122 
    123 }
    124 
    125  
    126 
    127 /*
    128 
    129 *********************************************************************************************************
    130 
    131 *    函 数 名: TCPnetTest
    132 
    133 *    功能说明: TCPnet应用
    134 
    135 *    形    参: 无
    136 
    137 *    返 回 值: 无
    138 
    139 *********************************************************************************************************
    140 
    141 */
    142 
    143 void TCPnetTest(void)
    144 
    145 { 
    146 
    147      OS_RESULT xResult;
    148 
    149      const uint16_t usMaxBlockTime = 2; /* 延迟周期 */
    150 
    151  
    152 
    153  
    154 
    155      while (1)
    156 
    157      {
    158 
    159          /* RL-TCPnet处理函数 */
    160 
    161          main_TcpNet();
    162 
    163  
    164 
    165           /* 按键消息的处理 */
    166 
    167          if(os_evt_wait_or(0xFFFF, usMaxBlockTime) == OS_R_EVT)
    168 
    169          {
    170 
    171               xResult = os_evt_get ();
    172 
    173               switch (xResult)
    174 
    175               {
    176 
    177                    /* 接收到按键K1按下消息,返回www.armfly.com的IP地址。 */
    178 
    179                    case KEY1_BIT0:
    180 
    181                        printf_debug("网址www.armfly.com的IP地址:");
    182 
    183                     get_host_by_name ((U8 *)hosts[0], dns_cbfunc);                 
    184 
    185                        break;
    186 
    187  
    188 
    189                    /* 接收到K2键按下消息,返回www.baidu.com的IP地址 */
    190 
    191                    case KEY2_BIT1:   
    192 
    193                        printf_debug("网址www.baidu.com的IP地址:");                  
    194 
    195                        get_host_by_name ((U8 *)hosts[1], dns_cbfunc);
    196 
    197                        break;
    198 
    199                       
    200 
    201                    /* 接收到K3键按下消息,返回www.qq.com的IP地址 */
    202 
    203                    case KEY3_BIT2:
    204 
    205                        printf_debug("网址www.qq.com的IP地址:");                          
    206 
    207                        get_host_by_name ((U8 *)hosts[2], dns_cbfunc);         
    208 
    209                        break;
    210 
    211                   
    212 
    213                     /* 其他的键值不处理 */
    214 
    215                    default:                    
    216 
    217                        break;
    218 
    219               }
    220 
    221          }
    222 
    223      }
    224 
    225 }

    28.9 总结

    本章节就为大家讲解这么多,内容相对比较简单,主要是函数get_host_by_name的使用,希望大家熟练掌握。

  • 相关阅读:
    由浅入深之Tensorflow(3)----数据读取之TFRecords
    由浅入深之Tensorflow(2)----logic_regression实现
    由浅入深之Tensorflow(1)----linear_regression实现
    Ubuntu14.04+caffe+cuda7.5 环境搭建以及MNIST数据集的训练与测试
    deeplenrnig学习笔记——什么是特征
    Paper List ABOUT Deep Learning
    C++ vector 用法
    转载:逻辑回归的python实现
    kubernetes 二进制安装1
    kubernetes 二进制安装
  • 原文地址:https://www.cnblogs.com/armfly/p/9566937.html
Copyright © 2011-2022 走看看