基于CH395的组播应用

---------------------------------------------------------------------------------------------------------------------------------------------------

   组播(Multicast)是一种在计算机网络中实现一对多通信的技术。在传统的单播(Unicast)通信中,一台计算机发送数据,只有特定的目标计算机可以接收到数据。而在组播中,一台计算机可以同时发送数据给一个组播组中的多个计算机,只有属于该组的计算机才能接收到数据。组播技术可以有效地减少数据在网络中的传输量,提高网络的效率。

  CH395Q/L芯片是一款以太网协议栈芯片,它支持组播应用,同时可以通过MAC过滤模式来接受组播数据包。

  本文通过使用沁恒CH32V307单片机SPI驱动CH395Q,编译软件为MRS。

  首先,在主函数中对CH395进行初始化(注意主程序开始时先延时200ms时间以上和初始化延时),IP和网关及相关变量信息不在这边复述,程序代码见文章链接地址。

    CH395CMDReset();                                    /* 复位CH395芯片 */
    Delay_Ms(1000);                                     /* 延时1000毫秒,要分开写,否则无效 */
    Delay_Ms(1000);
    i = CH395CMDGetVer();                               /*获取芯片以及固件版本号 */
    printf("CH395CMDGetVer:%x\n",i);
    InitCH395InfParam();                                /* 初始化CH395相关变量 */
    i = CH395Init();                                    /* 初始化CH395芯片 ,200Ms以上*/
    printf("CH395Init:%x\n",i);
    mStopIfError(i);                                    /*调试使用,显示错误代码,并停机*/

  初始化完成后,根据CH395相关例程和手册(5.11节)描述,通过CMD_SET_MAC_FILT设置MAC过滤模式,该命令共9个字节数据。第一个字节用来设置过滤模式(图1示该字节的各位含义),芯片复位后默认是开启第0、3、4位的。程序中开启接收组播包,因此第一位写入0x1d。

   图1 CH395MAC过滤模式第一字节各位含义

  第 2 至第 5 字节为 HASH0(哈希表 0),第 6 至第 9 字节为 HASH1(哈希表 1),仅在多播开启有效。哈希表算法可以通过目的地址MAC地址计算出32位的CRC值,使用此 CRC 值的高 6 位作为索引值,将 HASH 表对应的位写 1。哈希算法可根据实际优化,通过该种算法可以过滤大部分无效帧,减少芯片处理负荷。

    MacCrc32 =  CH395CRCRet6Bit(MultiMac_1);   //该命令详细内容可以参考官网提供的例程CH395CMD中
    printf("MacCrc32 : %2x\n",(uint16_t)MacCrc32);
    if(MacCrc32 > 31)
    {
        MacCrc32 -=32;
        printf("MacCrc32_1 : %2x\n",(uint16_t)MacCrc32);
        Hash1 = Hash1|((uint32_t)1<<MacCrc32);
    }
    else
    {
        Hash0 |= ((uint32_t)1<<MacCrc32);
    }
    printf("Hash0:%lx\r\n",(uint32_t)Hash0);
    printf("Hash1:%lx\r\n",(uint32_t)Hash1);
    CH395CMDSetMACFilt(0x1d, Hash0, Hash1);//开启接收多播包

MacCrc32
= CH395CRCRet6Bit(MultiMac_2); printf("MacCrc32 : %2x\n",(uint16_t)MacCrc32); if(MacCrc32 > 31) { MacCrc32 -=32; printf("MacCrc32_2 : %2x\n",(uint16_t)MacCrc32); Hash1 = Hash1|((uint32_t)1<<MacCrc32); } else { Hash0 |= ((uint32_t)1<<MacCrc32); } printf("Hash0:%lx\r\n",(uint32_t)Hash0); printf("Hash1:%lx\r\n",(uint32_t)Hash1); CH395CMDSetMACFilt(0x1d, Hash0, Hash1);

   完成这些配置后,则对相应的scoket进行初始化和打开,注意socket要配置为UDP模式下。

void InitSocketParam(void)
{
  memset(&sockinf[0],0,sizeof(sockinf[0])); /* 将SockInf[0]全部清零*/
  memcpy(&sockinf[0].IPAddr, BroadcastIP,sizeof(BroadcastIP)); /* 如果启用UDP SERVER功能,需将目的IP设为广播地址255.255.255.255 */
  // sockinf[0].DesPort = Socket0DesPort; /* 目的端口 */
  sockinf[0].SourPort= Socket0SourPort; /* 源端口 */
  sockinf[0].ProtoType=PROTO_TYPE_UDP; /* UDP模式 */

  memset(&sockinf[1],0,sizeof(sockinf[1])); /* 将SockInf[0]全部清零*/
  memcpy(&sockinf[1].IPAddr, BroadcastIP,sizeof(BroadcastIP)); /* 如果启用UDP SERVER功能,需将目的IP设为广播地址255.255.255.255 */
  // sockinf[1].DesPort = Socket1DesPort; /* 目的端口 */
  sockinf[1].SourPort= Socket1SourPort; /* 源端口 */
  sockinf[1].ProtoType=PROTO_TYPE_UDP; /* UDP模式 */
}

void CH395SocketInitOpen(void)
{
UINT8 i;

/* socket 0为UDP模式 */
  CH395SetSocketDesIP(0,sockinf[0].IPAddr); /* 设置socket 0目标IP地址 */
  CH395SetSocketProtType(0,sockinf[0].ProtoType); /* 设置socket 0协议类型 */
  // CH395SetSocketDesPort(0,sockinf[0].DesPort); /* 设置socket 0目的端口 */
  CH395SetSocketSourPort(0,sockinf[0].SourPort); /* 设置socket 0源端口 */
  i = CH395OpenSocket(0); /* 打开socket 0 */
  mStopIfError(i);

  CH395SetSocketDesIP(1,sockinf[1].IPAddr); /* 设置socket 0目标IP地址 */
  CH395SetSocketProtType(1,sockinf[1].ProtoType); /* 设置socket 0协议类型 */
  // CH395SetSocketDesPort(1,sockinf[1].DesPort); /* 设置socket 0目的端口 */
  CH395SetSocketSourPort(1,sockinf[1].SourPort); /* 设置socket 0源端口 */
  i = CH395OpenSocket(1); /* 打开socket 0 */
  mStopIfError(i);
}

 

  到这里的CH395的配置信息就满足组播应用需求了,注意使用时需要对CH395全局和Socket中断信息的读写,这里不再描述,可以参考例程代码。

---------------------------------------------------------------------------------------------------------------------------------------------------

  配置完成后,我们可以通过网络测试工具和wireshark进行数据测试和抓包。

  首先,通过网络测试工具建立一个UDP,目标IP为224.1.1.4,目标端口为6000,定时向224.1.1.4地址发送数据,图2示。

图2 网络测试工具配置

  可以通过wireshark抓取网络数据包和单片机串口打印信息来判断CH395是否接受到该数据,图3示网络抓包和串口打印信息。

 图3 数据监控

  图中可以看出,电脑端192.168.1.21向224.1.1.4地址发送数据后,因程序里对socket的目的IP设置为广播地址,所以CH395接收到该数据包后会打印带有主机地址信息。其中len长为22的原因是程序设置socket为UDP Server模式,该模式下会带有信源的8个字节地址信息。为了更直观的判断CH395是否收到该数据,在该例程中调用了UDPSendto函数,CH395接受到该组播数据后会向原主机地址进行数据回传。可以在wires hark抓包图中第216行可以清晰看到CH395会向主机地址回传数据。

  该例程测试是在直连电脑的情况下进行的,所以能够直观的接收到组播数据。但在更多的应用时,会发现我们电脑会时常发送一个组播请求的报文IGMP,而CH395并没有发送该报文,导致使用此例程可能无法在路由等网络环境对组播数据进行收发。

  针对这个应用,我会在下一篇文章中做一个简单例程测试,让CH395在接入路由的环境下可以通过发送请求报文来加入组播段,解决无法接受组播数据的问题。

   (测试例程)https://files.cnblogs.com/files/blogs/805237/Socket-UdpMulticast.rar?t=1700655709&download=true

 

posted on 2023-11-22 20:28  sw2222  阅读(331)  评论(0编辑  收藏  举报