CH579 以太网 DHCP+DNS+MQTT

一、前言

好久没写博客了,最近比较忙,这次分享一个CH579的组合例子
其实也觉得比较奇怪。。。DHCP感觉是必须的,DNS感觉也是,应该和TCP应用组合在一起才对。。分开来给例子,挺那个的。


二、为何选CH579

  1. 价格太香了,随便放个图片,不是打广告
    CH579 以太网 DHCP+DNS+MQTT_第1张图片
  2. 看一下外设情况
    CH579 以太网 DHCP+DNS+MQTT_第2张图片
  3. 总结一下,6鸡,白菜价,引脚多,外设强,就拿来搞以太网都比W5500香

三、资料获取

  1. 软件(官网地址):https://www.wch.cn/products/CH579.html
  2. 硬件(立创开源了原厂的开发板):https://oshwhub.com/staunchheart/ch579
    这里注意一下:用以太网,必须使用外部32M;若不使用DC-DC,电感部分电路可以直接短接;2个网口灯注意使用EVK的引脚;
    所以只用以太网的最小系统就出来了:(注意3.3V的10UF电容必须有,否则在获取DHCP时会不停复位,上电也会复位几次,应该是电压被拉低导致的)
    CH579 以太网 DHCP+DNS+MQTT_第3张图片

四、参考程序

  1. 先看看example的目录,对于我们来说,平时都是DHCP搭配DNS搭配使用的,这里分开来,所以我整合了一下
    CH579 以太网 DHCP+DNS+MQTT_第4张图片
  2. 分别使用了 DHCP_ClientMQTTDNS 这3个例子

五、程序重点

  • 对于库的使用,可以参考CH57xNET协议栈库说明.pdf

  • main.c里面跑了协议栈的主任务函数,并且使用了一个10ms的定时器,这里例子就有对应的注释

    /*******************************************************************************
    * Function Name  : main
    * Description    : 主函数
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    int main(void) 
    {
        UINT8 ip[4],i = 0;
        UINT8 dns_flag = 0;
    		
    	SystemClock_UART1_init();
    	GetMacAddr(MACAddr);	
        i = CH57xNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr);                       /* 库初始化 */
        mStopIfError(i);                                                            /* 检查错误 */
        PRINT("CH57xNETLibInit Success\r\n");  
    	Timer0Init( 10000 );		                                                /*初始化定时器:10ms*/
    	NVIC_EnableIRQ(ETH_IRQn);
    	while ( CH57xInf.PHYStat < 2 ) {
    		DelayMs(50);
    	}
        PRINT("CH579 DNS client create!\r\n"); 
    	
        while(1)
        {   	
            CH57xNET_MainTask();                                                    /* CH57xNET库主任务函数,需要在主循环中不断调用 */
            if(CH57xNET_QueryGlobalInt())CH57xNET_HandleGlobalInt();                /* 查询中断,如果有中断,则调用全局中断处理函数 */
            if( dns_flag == 0 ){
                i = DnsQuery(SocketId,url_dn3,ip);                                         /* 查询 */
                 if(i){ 
                    dns_flag = 1;
                    if( i == 1 ){
                        PRINT("Domain name:%s \n",url_dn3);
                        PRINT(" HTTPs_IP=%d.%d.%d.%d\n\n",ip[0],ip[1],ip[2],ip[3]);
                    }  
                }
            }     
    	}
    }
    
  • 上电后的逻辑:上电后建立DNS的UDP(只需调用一次)–>开启DHCP–>DNS拿到IP–>将此IP复制到TCP的Socket参数中–>建立TCP–>建立MQTT
    这里比较需要注意的是:SOCKET建立后,其实并不需要自己重新关闭什么的,例子已经帮我们做好了重连操作了DNS也是,对于插入网口后,只需要使用一次DNS即可,所以在程序中,DNS的SOCKET和MQTT的SOCKET,都是建立了一次后,就不需要自己操作断开什么的了。

  • 插拔网口逻辑:拔网口–>GINT_STAT_PHY_CHANGE 01–>使用CH57xNET_DHCPStop()关闭DHCP–>插入网口–>GINT_STAT_PHY_CHANGE 02–>使用CH57xNET_DHCPStart(CH57xNET_DHCPCallBack)重新开启DHCP–>TCPtimeout或者disconnect–>DHCP完成–>TCPtimeout或者disconnect–>自动重连
    没太理解的,可以看下这个LOG
    CH579 以太网 DHCP+DNS+MQTT_第5张图片

六、源码

注意点:

  • dns.c和dns.h放到mqtt例子中

  • 下面的程序替换掉MQTT_Pub.c

  • 将dns.c里面的status替换成dns_status,因为dns.c里面的status和dhcp里面的status冲突了

    /********************************** (C) COPYRIGHT ******************************
    * File Name          : MQTT_Pub.c
    * Author             : WCH
    * Version            : V1.0
    * Date               : 2018/12/01
    * Description        : 基于TCP/IP的MQTT协议通讯例程,实现以MQTT方式,通过百度、阿里云物联网服务器实现设备互通;使用前需设置帐号和密码
    *					(1)、CH579 Examples by KEIL;
    *					(2)、串口1输出监控信息,115200bps,打开或者关闭调试信息输出在IDE宏定义中设置;
    *					(3)、本程序用于演示基于TCP/IP的MQTT协议通讯,
    					     此程序演示PUB的过程
    *******************************************************************************/
    
    
    
    /******************************************************************************/
    /* 头文件包含*/
    #include 
    #include 
    #include "CH57x_common.h"
    #include "core_cm0.h"
    #include "CH57xNET.H"
    #include "MQTTPacket.H"
    #include "dns.h"
    
    #define KEEPLIVE_ENABLE                      1                                  /* 开启KEEPLIVE功能 */
    
    /* 下面的缓冲区和全局变量必须要定义,库中调用 */
    __align(16)UINT8    CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16];                   /* MAC接收描述符缓冲区,16字节对齐 */
    __align(4) UINT8    CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE];                /* MAC接收缓冲区,4字节对齐 */
    __align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM];                         /* Socket信息表,4字节对齐 */
    
    UINT16 MemNum[8] = {CH57xNET_NUM_IPRAW,
                        CH57xNET_NUM_UDP,
                        CH57xNET_NUM_TCP,
                        CH57xNET_NUM_TCP_LISTEN,
                        CH57xNET_NUM_TCP_SEG,
                        CH57xNET_NUM_IP_REASSDATA,
                        CH57xNET_NUM_PBUF,
                        CH57xNET_NUM_POOL_BUF
                        };
    UINT16 MemSize[8] = {CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IPRAW_PCB),
                        CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_UDP_PCB),
                        CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB),
                        CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB_LISTEN),
                        CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_SEG),
                        CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IP_REASSDATA),
                        CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(0),
                        CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_POOL_BUF)
                        };
    __align(4)UINT8 Memp_Memory[CH57xNET_MEMP_SIZE];
    __align(4)UINT8 Mem_Heap_Memory[CH57xNET_RAM_HEAP_SIZE];
    __align(4)UINT8 Mem_ArpTable[CH57xNET_RAM_ARP_TABLE_SIZE];
    /******************************************************************************/
    /* 本演示程序的相关宏 */
    #define RECE_BUF_LEN                          536                               /* 接收缓冲区的大小 */
    /* CH57xNET库TCP的MSS长度为536字节,即一个TCP包里的数据部分最长为536字节 */
    /* TCP协议栈采用滑动窗口进行流控,窗口最大值为socket的接收缓冲区长度。在设定 */
    /* RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系,例如窗口值为4*MSS,则远端一次会发送 */
    /* 4个TCP包,如果RX_QUEUE_ENTRIES小于4,则必然会导致数据包丢失,从而导致通讯效率降低 */
    /* 建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据,则 */ 
    /* 建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 */
    /* 为了节约RAM,请将接收缓冲区的长度设置为MSS */
    
    /* CH579MQTT相关定义,需要根据实际情况修改 */
    UINT8 MACAddr[6] = {0x84,0xc2,0xe4,0x02,0x03,0x04};                              /* CH579MAC地址 */
    UINT8 IPAddr[4]  = {192,168,1,200};                                              /* CH579IP地址 */
    UINT8 GWIPAddr[4]= {192,168,1,1};                                                /* CH579网关 */
    UINT8 IPMask[4]  = {255,255,255,0};                                              /* CH579子网掩码 */
    UINT8 DESIP[4]   = {58,213,74,190};                                              /* 目的IP地址 */
    UINT16 aport=1000;											                     /* CH579源端口 */
    
    /* 网口灯定义 PB口低十六位有效 */
    UINT16 CH57xNET_LEDCONN=0x0010;                                                 /* 连接指示灯 PB4 */
    UINT16 CH57xNET_LEDDATA=0x0080;                                                 /* 通讯指示灯 PB7 */ 
    
    char *username =  "123";							                                 /* 设备名,每个设备唯一,可用”/“做分级 */
    char *password =  "123";								                             /* 服务器登陆密码 */
    char *sub_topic = "tt456";								                             /* 订阅的会话名,为了自发自收,应与发布的会话名相同 */
    char *pub_topic = "tt123";									                         /* 发布的会话*/
    
    UINT8 SocketId;                                                                  /* 保存socket索引,可以不用定义 */
    UINT8 SocketRecvBuf[RECE_BUF_LEN];                                               /* socket接收缓冲区 */
    UINT8 MyBuf[RECE_BUF_LEN];                                                       /* 定义一个临时缓冲区 */
    
    UINT8 con_flag=0;										                         /* 已连接MQTT服务器标志位 */
    UINT8 pub_flag=1;											                     /* 已发布会话消息标志位 */
    UINT8 sub_flag=0;											                     /* 已订阅会话标志位 */
    UINT8 tout_flag=0;											                     /* 超时标志位 */
    UINT16 packetid=0;											                     /* 包ID */
    
    UINT8 dns_status;
    extern UINT8 dns_buf[512];
    UINT8 dhcp_ok = 1;
    UINT8 dns_flag = 0;
    #define   MAX_URL_SIZE 128
    UINT8  url_dn3[MAX_URL_SIZE] = "test.mosquitto.org";  
    
    /*******************************************************************************
    * Function Name  : IRQ_Handler
    * Description    : IRQ中断服务函数
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void ETH_IRQHandler( void )						                             	/* 以太网中断 */
    {
    	CH57xNET_ETHIsr();								                            /* 以太网中断中断服务函数 */
    }
    
    void TMR0_IRQHandler( void ) 						                            /* 定时器中断 */
    {
    	CH57xNET_TimeIsr(CH57xNETTIMEPERIOD);                                       /* 定时器中断服务函数 */
    	R8_TMR0_INT_FLAG |= 0xff;					                             	/* 清除定时器中断标志 */
    }
    
    
    
    /*******************************************************************************
    * Function Name  : mStopIfError
    * Description    : 调试使用,显示错误代码
    * Input          : iError 错误代码
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void mStopIfError(UINT8 iError)
    {
        if (iError == CH57xNET_ERR_SUCCESS) return;                                /* 操作成功 */
        PRINT("mStopIfError: %02X\r\n", (UINT16)iError);                           /* 显示错误 */
    }
    
    /*******************************************************************************
    * Function Name	: Transport_Open
    * Description	: 创建TCP连接
    * Input			: None
    * Output		: None
    * Return		: None
    *******************************************************************************/
    UINT8 Transport_Open()
    {
    	UINT8 i;																														 
    	SOCK_INF TmpSocketInf;								                 	/* 创建临时socket变量 */
    
    	memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF));	                 	/* 库内部会将此变量复制,所以最好将临时变量先全部清零 */
    	memcpy((void *)TmpSocketInf.IPAddr,DESIP,4);		                   	/* 设置目的IP地址 */
    	TmpSocketInf.DesPort = 1883;							                /* 设置目的端口 */
    	TmpSocketInf.SourPort = aport++;						                /* 设置源端口 */
    	TmpSocketInf.ProtoType = PROTO_TYPE_TCP;			                	/* 设置socekt类型 */
    	TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf;	                /* 设置接收缓冲区的接收缓冲区 */
    	TmpSocketInf.RecvBufLen = RECE_BUF_LEN ;			                 	/* 设置接收缓冲区的接收长度 */
    	i = CH57xNET_SocketCreat(&SocketId,&TmpSocketInf);		                /* 创建socket,将返回的socket索引保存在SocketId中 */
    	mStopIfError(i);										                /* 检查错误 */
    	
    	i = CH57xNET_SocketConnect(SocketId);				                	/* TCP连接 */
    	mStopIfError(i);										                /* 检查错误 */
    	return SocketId;
    }
    
    
    /*******************************************************************************
    * Function Name	: Transport_Close
    * Description	: 关闭TCP连接
    * Input			: None
    * Output		: None
    * Return		: None
    *******************************************************************************/
    UINT8 Transport_Close()
    {
    	UINT8 i;
    	i=CH57xNET_SocketClose(SocketId,TCP_CLOSE_NORMAL);
    	mStopIfError(i);
    	return i;
    }
    
    
    
    /*******************************************************************************
    * Function Name  : UDPSocketParamInit
    * Description    : 创建UDP socket
    * Input          : socket索引值,源端口,目的端口及目的IP
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void UDPSocketParamInit(UINT8 S,UINT8 *addr,UINT16 SourPort,UINT16 DesPort )
    {
       UINT8 i;                                                             
       SOCK_INF TmpSocketInf;                                                       /* 创建临时socket变量 */
    
       memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF));                            /* 库内部会将此变量复制,所以最好将临时变量先全部清零 */
       memcpy((void *)TmpSocketInf.IPAddr,addr,4);                                  /* 设置目的IP地址 */
     
       TmpSocketInf.DesPort = DesPort;                                              /* 设置目的端口 */
       TmpSocketInf.SourPort = SourPort;                                            /* 设置源端口 */
       TmpSocketInf.ProtoType = PROTO_TYPE_UDP;                                     /* 设置socekt类型 */
       TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf;                         /* 设置接收缓冲区的接收缓冲区 */
       TmpSocketInf.RecvBufLen = RECE_BUF_LEN ;                                     /* 设置接收缓冲区的接收长度 */
       i = CH57xNET_SocketCreat(&S,&TmpSocketInf);                           /* 创建socket,将返回的socket索引保存在SocketId中 */
       mStopIfError(i);                                                             /* 检查错误 */
    }
    
    /*******************************************************************************
    * Function Name	: Transport_SendPacket
    * Description	: 以太网发送数据
    * Input			: UINT8 *buf 发送数据的首字节地址
    				  UINT32 len 发送数据的长度
    * Output		: None
    * Return		: None
    *******************************************************************************/
    void Transport_SendPacket(UINT8 *buf,UINT32 len)
    {
    	UINT32 totallen;
    	UINT8 *p=buf;
    	
    	totallen=len;
    	while(1)
    	{
    		len = totallen;
    		CH57xNET_SocketSend(SocketId,p,&len);				              	/* 将MyBuf中的数据发送 */
    		totallen -= len;					 					            /* 将总长度减去以及发送完毕的长度 */
    		p += len;											             	/* 将缓冲区指针偏移*/
    		if(totallen)continue;									            /* 如果数据未发送完毕,则继续发送*/
    		break;													            /* 发送完毕,退出 */
    	}
    }
    
    
    /*******************************************************************************
    * Function Name	: MQTT_Connect
    * Description	: 创建MQTT连接
    * Input			: char *username 设备名
    				  char *password 服务器连接密码
    * Output		: None
    * Return		: None
    *******************************************************************************/
    void MQTT_Connect(char *username,char *password)
    {
    	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    	UINT32 len;
    	UINT8 buf[200];
    
    	data.clientID.cstring = "11";
    	data.keepAliveInterval = 20;
    	data.cleansession = 1;
    	data.username.cstring = username;																		
    	data.password.cstring = password;
    	 
    	len=MQTTSerialize_connect(buf,sizeof(buf),&data);											
    	Transport_SendPacket(buf,len);						
    }
    
    
    /*******************************************************************************
    * Function Name	: MQTT_Subscribe
    * Description	: MQTT订阅一个主题
    * Input			: char *topic 订阅的主题名
    * Output		: None
    * Return		: None
    *******************************************************************************/
    void MQTT_Subscribe( char *topic)
    {
    	MQTTString topicString = MQTTString_initializer;
    	int req_qos=0;
    	UINT32 len;
    	UINT32 msgid=1;
    	UINT8 buf[200];
    	
    	topicString.cstring=topic;
    	len=MQTTSerialize_subscribe(buf,sizeof(buf),0,msgid,1,&topicString,&req_qos);
    	Transport_SendPacket(buf,len);
    }
    
    
    /*******************************************************************************
    * Function Name	: MQTT_Unsubscribe
    * Description	: MQTT取消订阅一个主题
    * Input			: char *topic 取消订阅的主题名
    * Output		: None
    * Return		: None
    *******************************************************************************/
    void MQTT_Unsubscribe(char *topic)
    {
    	MQTTString topicString = MQTTString_initializer;
    	UINT32 len;
    	UINT32 msgid=1;
    	UINT8 buf[200];
    	
    	topicString.cstring=topic;
    	len=MQTTSerialize_unsubscribe(buf,sizeof(buf),0,msgid,1,&topicString);
    	Transport_SendPacket(buf,len);
    }
    
    
    /*******************************************************************************
    * Function Name	: MQTT_Subscribe
    * Description	: MQTT订阅一个主题
    * Input			: char *topic 订阅的主题名
    * Output		: None
    * Return		: None
    *******************************************************************************/
    void MQTT_Publish(char *topic,char *payload)
    {
    	MQTTString topicString = MQTTString_initializer;
    	UINT32 payloadlen;
    	UINT32 len;
    	UINT8 buf[1024];
    	
    	topicString.cstring=topic; 
    	payloadlen=strlen(payload);
    	len= MQTTSerialize_publish(buf,sizeof(buf),0,0,0,packetid++,topicString,payload,payloadlen);	
    	Transport_SendPacket(buf,len);
    }
    
    
    /*******************************************************************************
    * Function Name	: MQTT_Pingreq
    * Description	: MQTT发送心跳包
    * Input			: None
    * Output		: None
    * Return		: None
    *******************************************************************************/
    void MQTT_Pingreq()
    {
    	UINT32 len;
    	UINT8 buf[200];
    	
    	len=MQTTSerialize_pingreq(buf,sizeof(buf));
    	Transport_SendPacket(buf,len);
    }
    
    
    /*******************************************************************************
    * Function Name	: MQTT_Disconnect
    * Description	: 断开MQTT连接
    * Input			: None
    * Output		: None
    * Return		: None
    *******************************************************************************/
    void MQTT_Disconnect()
    {
    	UINT32 len;
    	UINT8 buf[50];
    	len=MQTTSerialize_disconnect(buf,sizeof(buf));
    	Transport_SendPacket(buf,len);
    }
    
    
    
    /*******************************************************************************
    * Function Name  : CH57xNET_CreatTcpSocket
    * Description    : 创建TCP Client socket
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void CH57xNET_CreatTcpSocket(void)
    {
       UINT8 i;                                                             
       SOCK_INF TmpSocketInf;                                                       /* 创建临时socket变量 */
    
       memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF));                            /* 库内部会将此变量复制,所以最好将临时变量先全部清零 */
       memcpy((void *)TmpSocketInf.IPAddr,DESIP,4);                                 /* 设置目的IP地址 */
       TmpSocketInf.DesPort = 1000;                     
       TmpSocketInf.SourPort = 2000;                                                /* 设置源端口 */
       TmpSocketInf.ProtoType = PROTO_TYPE_TCP;                                     /* 设置socekt类型 */
       TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf;                         /* 设置接收缓冲区的接收缓冲区 */
       TmpSocketInf.RecvBufLen = RECE_BUF_LEN ;                                     /* 设置接收缓冲区的接收长度 */
       i = CH57xNET_SocketCreat(&SocketId,&TmpSocketInf);                           /* 创建socket,将返回的socket索引保存在SocketId中 */
       mStopIfError(i);                                                             /* 检查错误 */
    #ifdef  KEEPLIVE_ENABLE
       CH57xNET_SocketSetKeepLive( SocketId, 1 );                                   /* 开启socket的KEEPLIVE功能(V06版本支持) */
    #endif
    
       i = CH57xNET_SocketConnect(SocketId);                                        /* TCP连接 */
       mStopIfError(i);                                                             /* 检查错误 */
       i = CH57xNET_SetSocketTTL( SocketId,10 );
       mStopIfError(i);                                                             /* 检查错误 */
    }
    
    
    /*******************************************************************************
    * Function Name  : net_initkeeplive
    * Description    : keeplive初始化
    * Input          : None      
    * Output         : None
    * Return         : None
    *******************************************************************************/
    #ifdef  KEEPLIVE_ENABLE
    void net_initkeeplive(void)
    {
        struct _KEEP_CFG  klcfg;
    
        klcfg.KLIdle = 20000;                                                       /* 空闲 */
        klcfg.KLIntvl = 10000;                                                      /* 间隔 */
        klcfg.KLCount = 5;                                                          /* 次数 */
        CH57xNET_ConfigKeepLive(&klcfg);
    }
    #endif
    
    /*******************************************************************************
    * Function Name  : CH57xNET_LibInit
    * Description    : 库初始化操作
    * Input          : ip      ip地址指针
    *                :gwip    网关ip地址指针
    *                : mask    掩码指针
    *                : macaddr MAC地址指针 
    * Output         : None
    * Return         : 执行状态
    *******************************************************************************/
    UINT8 CH57xNET_LibInit(/*const*/ UINT8 *ip,/*const*/ UINT8 *gwip,/*const*/ UINT8 *mask,/*const*/ UINT8 *macaddr)
    {
        UINT8 i;
        struct _CH57x_CFG cfg;
    
        if(CH57xNET_GetVer() != CH57xNET_LIB_VER)return 0xfc;                       /* 获取库的版本号,检查是否和头文件一致 */
        CH57xNETConfig = LIB_CFG_VALUE;                                             /* 将配置信息传递给库的配置变量 */
        cfg.RxBufSize = RX_BUF_SIZE; 
        cfg.TCPMss   = CH57xNET_TCP_MSS;
        cfg.HeapSize = CH57x_MEM_HEAP_SIZE;
        cfg.ARPTableNum = CH57xNET_NUM_ARP_TABLE;
        cfg.MiscConfig0 = CH57xNET_MISC_CONFIG0;
        CH57xNET_ConfigLIB(&cfg);
        i = CH57xNET_Init(ip,gwip,mask,macaddr);
    #ifdef  KEEPLIVE_ENABLE
        net_initkeeplive( );
    #endif
        return (i);                    
    }
    
    /*******************************************************************************
    * Function Name  : CH57xNET_HandleSockInt
    * Description    : Socket中断处理函数
    * Input          : sockeid  socket索引
    *                :initstat 中断状态
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat)
    {
        UINT32 len;
        UINT8 i;
        unsigned char* dup;
    	unsigned short* packetid;
    
    	int* qos;
    	unsigned char* retained;
    	MQTTString* topicName;
    	unsigned char* payload;
    	int payloadlen;
    	unsigned char *p=payload;
    
        if(initstat & SINT_STAT_RECV)                                             /* 接收中断 */
        {
            // len = CH57xNET_SocketRecvLen(sockeid,NULL);		                      /* 查询长度 */
    		// CH57xNET_SocketRecv(sockeid,MyBuf,&len);			                  /* 将接收缓冲区的数据读到MyBuf中*/
    		// switch(MyBuf[0]>>4)
    		// {
    		// 	case FLAG_CONNACK:
    		// 		PRINT("connack\r\n");
    		// 		con_flag=1;
    		// 		break;
    
    		// 	case FLAG_PUBLISH:
    		// 		MQTTDeserialize_publish(dup,qos,retained,packetid,topicName,&payload,&payloadlen,MyBuf,len);
    		// 		PRINT("payloadlen=%d\r\n",(UINT16)payloadlen);
    		// 		p=payload;
    		// 		for(i=0;i
    		// 		{
    		// 			PRINT("%c ",(UINT16)*p);
    		// 			p++;
    		// 		}
    		// 		PRINT("\r\n");
    		// 		break;
    				
    		// 	case FLAG_SUBACK:
    		// 		sub_flag=1;
    		// 		PRINT("suback\r\n");
    		// 		break;
    
    		// 	default:
    
    		// 		break;
    		// }
            len = CH57xNET_SocketRecvLen(sockeid,NULL);                             /* 会将当前接收指针传递给precv*/
            PRINT("Receive Len = %02x\r\n",len);                           
            if (len > 0)
            {    
                if((sockeid==0)&&(dns_status ==3))
                {
    				PRINT("enter rece int!dns_status=3\r\n");
    				CH57xNET_SocketRecv(sockeid,dns_buf,&len);
    				dns_status = 4;
    				i = CH57xNET_SocketClose( sockeid,TCP_CLOSE_NORMAL );
    				mStopIfError(i);
    				PRINT("dns_status = 4!\r\n");
                }
                else
    			{
                    CH57xNET_SocketRecv(sockeid,MyBuf,&len);  /* 将接收缓冲区的数据读到MyBuf中*/   
    				len = CH57xNET_SocketRecvLen(sockeid,NULL);		                      /* 查询长度 */
    				CH57xNET_SocketRecv(sockeid,MyBuf,&len);			                  /* 将接收缓冲区的数据读到MyBuf中*/
    				switch(MyBuf[0]>>4)
    				{
    					case FLAG_CONNACK:
    						PRINT("connack\r\n");
    						con_flag=1;
    						break;
    
    					case FLAG_PUBLISH:
    						MQTTDeserialize_publish(dup,qos,retained,packetid,topicName,&payload,&payloadlen,MyBuf,len);
    						PRINT("payloadlen=%d\r\n",(UINT16)payloadlen);
    						p=payload;
    						for(i=0;i<payloadlen;i++)
    						{
    							PRINT("%c ",(UINT16)*p);
    							p++;
    						}
    						PRINT("\r\n");
    						break;
    						
    					case FLAG_SUBACK:
    						sub_flag=1;
    						PRINT("suback\r\n");
    						break;
    
    					default:
    
    						break;
    				}
    			}                 
            }
    
        }
        if(initstat & SINT_STAT_CONNECT)                                          /* TCP连接中断 */
        {                                                                         /* 产生此中断表示TCP已经连接,可以进行收发数据 */
            PRINT("TCP Connect Success\r\n");   
            MQTT_Connect(username, password);        
        }
        if(initstat & SINT_STAT_DISCONNECT)                                       /* TCP断开中断 */
        {                                                                         /* 产生此中断,CH579库内部会将此socket清除,置为关闭*/
            PRINT("TCP Disconnect\n");                                            /* 应用曾需可以重新创建连接 */
            CH57xNET_CreatTcpSocket();
        }
        if(initstat & SINT_STAT_TIM_OUT)                                          /* TCP超时中断 */
        {                                                                         /* 产生此中断,CH579库内部会将此socket清除,置为关闭*/
            PRINT("TCP Timout\n");                                                /* 应用曾需可以重新创建连接 */
            Transport_Open();
        }
    }
    /*******************************************************************************
    * Function Name  : CH57xNET_DHCPCallBack
    * Description    : DHCP回调函数
    * Input          : None
    * Output         : None
    * Return         : 执行状态
    *******************************************************************************/
    UINT8 CH57xNET_DHCPCallBack(UINT8 status,void *arg)
    {
       UINT8 *p;
       
       if(!status){                                                                  /* 成功*/
           p = arg;                                                                  /* 产生此中断,CH57xNET库内部会将此socket清除,置为关闭*/
           PRINT("DHCP Success\r\n");
           memcpy(IPAddr,p,4);
           memcpy(GWIPAddr,&p[4],4);
           memcpy(IPMask,&p[8],4);                                                   /* 产生此中断,CH57xNET库内部会将此socket清除,置为关闭*/
           PRINT("IPAddr = %d.%d.%d.%d \r\n",(UINT16)IPAddr[0],(UINT16)IPAddr[1],
                  (UINT16)IPAddr[2],(UINT16)IPAddr[3]);
           PRINT("GWIPAddr = %d.%d.%d.%d \r\n",(UINT16)GWIPAddr[0],(UINT16)GWIPAddr[1],
                  (UINT16)GWIPAddr[2],(UINT16)GWIPAddr[3]);
           PRINT("IPAddr = %d.%d.%d.%d \r\n",(UINT16)IPMask[0],(UINT16)IPMask[1],
                  (UINT16)IPMask[2],(UINT16)IPMask[3]);
           PRINT("DNS1: %d.%d.%d.%d\r\n",p[12],p[13],p[14],p[15]);
           PRINT("DNS2: %d.%d.%d.%d\r\n",p[16],p[17],p[18],p[19]);
    //     CH57xNET_CreatTcpSocket();                                                /* 可以在此处,在DHCP完成后进行TCP连接 */
    //	   PRINT("creat tcp sockrt!\r\n"); 
    		dns_status = 1;//可以dns了
       }
       else{ 
                                                                                     /* 产生此中断,CH57xNET库内部会将此socket清除,置为关闭*/
          PRINT("DHCP Fail %02x\n",status);
       }                                                          
       return 0;
    }
    
    /*******************************************************************************
    * Function Name  : CH57xNET_HandleGloableInt
    * Description    : 全局中断处理函数
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void CH57xNET_HandleGlobalInt(void)
    {
        UINT8 initstat;
        UINT8 i;
        UINT8 socketinit;
        initstat = CH57xNET_GetGlobalInt();                                        /* 读全局中断状态并清除 */
        if(initstat & GINT_STAT_UNREACH)                                           /* 不可达中断 */
        {
            PRINT("UnreachCode :%d\r\n",CH57xInf.UnreachCode);                      /* 查看不可达代码 */
            PRINT("UnreachProto :%d\r\n",CH57xInf.UnreachProto);                    /* 查看不可达协议类型 */
            PRINT("UnreachPort :%d\r\n",CH57xInf.UnreachPort);                      /* 查询不可达端口 */     
        }
       if(initstat & GINT_STAT_IP_CONFLI)                                          /* IP冲突中断 */
       {
       
       }
       if(initstat & GINT_STAT_PHY_CHANGE)                                         /* PHY改变中断 */
       {
           i = CH57xNET_GetPHYStatus();                                            /* 获取PHY状态 */
           PRINT("GINT_STAT_PHY_CHANGE %02x\r\n",i);
           if(i == 2)
    	   {
          	 CH57xNET_DHCPStart(CH57xNET_DHCPCallBack);
    	   }
           else 
           {
               CH57xNET_DHCPStop();
    		   con_flag = 0;
    		//   CH57xNET_SocketClose(SocketId,TCP_CLOSE_ABANDON);
    		   MQTT_Disconnect();
    
    		   ///等插入网线重新走dns
    		 //  dns_flag = 0;
    		//   dns_status = 0;
           }
       }
       if(initstat & GINT_STAT_SOCKET)                                             /* Socket中断 */
       {
           for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++)                     
           {
               socketinit = CH57xNET_GetSocketInt(i);                              /* 读socket中断并清零 */
               if(socketinit)CH57xNET_HandleSockInt(i,socketinit);                 /* 如果有中断则清零 */
           }    
       }
    }
    
    
    void Timer0Init(UINT32 time)
    {
    	R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;		                               /* 清除所有计数值 */
    	R8_TMR0_CTRL_MOD = 0;						                               /* 设置定时器模式 */
    	R32_TMR0_CNT_END = FREQ_SYS/1000000*time;	                               /* 设置定时时间 */
    	R8_TMR0_INT_FLAG = R8_TMR0_INT_FLAG;		                               /* 清除标志 */
    	R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END;	                                   /* 定时中断 */
    	R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN;
    	NVIC_EnableIRQ(TMR0_IRQn);	
    }
    
    /*******************************************************************************
    * Function Name  : SystemClock_UART1_init
    * Description    : 系统时钟和串口1初始化,串口1用于打印输出
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void SystemClock_UART1_init(void)
    {
        PWR_UnitModCfg(ENABLE, UNIT_SYS_PLL);                                      /* PLL上电 */
        DelayMs(3); 
        SetSysClock(CLK_SOURCE_HSE_32MHz);                                          /* 外部晶振 PLL 输出32MHz */
        GPIOA_SetBits( GPIO_Pin_9 );
        GPIOA_ModeCfg( GPIO_Pin_9, GPIO_ModeOut_PP_5mA );                           /* 串口1的IO口设置 */
    	UART1_DefInit( );                                                            /* 串口1初始化 */
    }
    
    /*******************************************************************************
    * Function Name  : GetMacAddr
    * Description    : 系统获取MAC地址
    * Input          : pMAC:指向用来存储Mac地址的缓冲
    * Output         : None
    * Return         : None
    *******************************************************************************/
    void GetMacAddr(UINT8 *pMAC)
    {
    	UINT8 transbuf[6],i;
    	
    	GetMACAddress(transbuf);
    	for(i=0;i<6;i++)
    	{
    		pMAC[5-i]=transbuf[i];
    	
    	}
    }
    
    /*******************************************************************************
    * Function Name  : main
    * Description    : 主函数
    * Input          : None
    * Output         : None
    * Return         : None
    *******************************************************************************/
    int main(void) 
    {
        UINT32 i = 0;
        UINT16 TimeDelay=0;
    	char payload[500];	
    
        UINT8 ip[4];
        
    
    	for(i=0;i<500;i++)
    	payload[i]='a';
    
    	SystemClock_UART1_init();
    	GetMacAddr(MACAddr);
        i = CH57xNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr);                       /* 库初始化 */
        mStopIfError(i);                                                            /* 检查错误 */
        PRINT("CH57xNETLibInit Success\r\n");   
    	Timer0Init( 10000 );		                                                /* 初始化定时器:10ms */
    	NVIC_EnableIRQ(ETH_IRQn);
    	//Transport_Open();    
    	while ( CH57xInf.PHYStat < 2 ) {
    		DelayMs(50);
    	}	                                
        PRINT("CH579 MQTT socket create!Publishing\r\n");   	
        while(1)
        {
            CH57xNET_MainTask();                                                    /* CH57xNET库主任务函数,需要在主循环中不断调用 */
            if(CH57xNET_QueryGlobalInt())CH57xNET_HandleGlobalInt();                /* 查询中断,如果有中断,则调用全局中断处理函数 */
            if( dns_flag == 0 ){
                i = DnsQuery(SocketId,url_dn3,ip);                                         /* 查询 */
                 if(i){ 
                    dns_flag = 1;
                    if( i == 1 ){
                        PRINT("Domain name:%s\r\n",url_dn3);
                        PRINT("HTTPs_IP=%d.%d.%d.%d\r\n",ip[0],ip[1],ip[2],ip[3]);
    					memcpy(DESIP,ip,4);
                        Transport_Open();
                    }  
                }
            } 
    		
    		DelayMs(1);
    		TimeDelay++;
    		if (TimeDelay>2000) {
    			TimeDelay=0;
    			if(con_flag) MQTT_Publish(pub_topic,payload);
    		}   
    		
        }
    }
    /*********************************** endfile **********************************/
    
    

你可能感兴趣的:(CH579,c语言,单片机,CH579,以太网,MQTT)