- 加入了订阅的逻辑,发现了一个BUG,参考下面修改
https://bbs.21ic.com/icview-3016440-1-2.html - 若出现 SINT_STAT_DISCONNECT无法重新联网,改成Transport_Open即可
- 没有发心跳包,所以导致掉线重连,这里周期性调用MQTT_Pingreq即可(我这里主循环里面时间不准,之后可以放定时器)
- 将MAC作为 Client ID ,因为这个CID必须是唯一的,否则会被提下线,username 和密码我就随便设置了
好久没写博客了,最近比较忙,这次分享一个CH579的组合例子
其实也觉得比较奇怪。。。DHCP感觉是必须的,DNS感觉也是,应该和TCP应用组合在一起才对。。分开来给例子,挺那个的。
二、为何选CH579
- 价格太香了,随便放个图片,不是打广告
- 看一下外设情况
- 总结一下,6鸡,白菜价,引脚多,外设强,就拿来搞以太网都比W5500香
三、资料获取
- 软件(官网地址):https://www.wch.cn/products/CH579.html
- 硬件(立创开源了原厂的开发板):https://oshwhub.com/staunchheart/ch579
这里注意一下:用以太网,必须使用外部32M;若不使用DC-DC,电感部分电路可以直接短接;2个网口灯注意使用EVK的引脚;
所以只用以太网的最小系统就出来了:(注意3.3V的10UF电容必须有,否则在获取DHCP时会不停复位,上电也会复位几次,应该是电压被拉低导致的)
四、参考程序
- 先看看example的目录,对于我们来说,平时都是DHCP搭配DNS搭配使用的,这里分开来,所以我整合了一下
- 分别使用了 DHCP_Client ,MQTT,DNS 这3个例子
五、程序重点
-
对于库的使用,可以参考CH57xNET协议栈库说明.pdf
-
main.c里面跑了协议栈的主任务函数,并且使用了一个10ms的定时器,这里例子就有对应的注释
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 Successrn"); Timer0Init( 10000 ); NVIC_EnableIRQ(ETH_IRQn); while ( CH57xInf.PHYStat < 2 ) { DelayMs(50); } PRINT("CH579 DNS client create!rn"); while(1) { CH57xNET_MainTask(); 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.%dnn",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
注意点:
- dns.c和dns.h放到mqtt例子中
- 下面的程序替换掉MQTT_Pub.c
- 将dns.c里面的status替换成dns_status,因为dns.c里面的status和dhcp里面的status冲突了
#include#include #include "CH57x_common.h" #include "core_cm0.h" #include "CH57xNET.H" #include "MQTTPacket.H" #include "dns.h" #define KEEPLIVE_ENABLE 1 __align(16)UINT8 CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16]; __align(4) UINT8 CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE]; __align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM]; 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 UINT8 MACAddr[6] = {0x84,0xc2,0xe4,0x02,0x03,0x04}; UINT8 MACAddr_Str[20]; UINT8 IPAddr[4] = {192,168,1,200}; UINT8 GWIPAddr[4]= {192,168,1,1}; UINT8 IPMask[4] = {255,255,255,0}; UINT8 DESIP[4] = {58,213,74,190}; UINT16 aport=1000; UINT16 CH57xNET_LEDCONN=0x0010; UINT16 CH57xNET_LEDDATA=0x0080; char *username = "123"; char *password = "123"; char *sub_topic = "tt456"; char *pub_topic = "tt123"; UINT8 SocketId; UINT8 SocketRecvBuf[RECE_BUF_LEN]; UINT8 MyBuf[RECE_BUF_LEN]; UINT8 con_flag=0; UINT8 pub_flag=1; UINT8 sub_flag=0; UINT8 tout_flag=0; UINT16 packetid=0; 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"; void ETH_IRQHandler( void ) { CH57xNET_ETHIsr(); } void TMR0_IRQHandler( void ) { CH57xNET_TimeIsr(CH57xNETTIMEPERIOD); R8_TMR0_INT_FLAG |= 0xff; } void mStopIfError(UINT8 iError) { if (iError == CH57xNET_ERR_SUCCESS) return; PRINT("mStopIfError: %02Xrn", (UINT16)iError); } UINT8 Transport_Open() { UINT8 i; SOCK_INF TmpSocketInf; memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); TmpSocketInf.DesPort = 1883; TmpSocketInf.SourPort = aport++; TmpSocketInf.ProtoType = PROTO_TYPE_TCP; TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf; TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; i = CH57xNET_SocketCreat(&SocketId,&TmpSocketInf); mStopIfError(i); i = CH57xNET_SocketConnect(SocketId); mStopIfError(i); return SocketId; } UINT8 Transport_Close() { UINT8 i; i=CH57xNET_SocketClose(SocketId,TCP_CLOSE_NORMAL); mStopIfError(i); return i; } void UDPSocketParamInit(UINT8 S,UINT8 *addr,UINT16 SourPort,UINT16 DesPort ) { UINT8 i; SOCK_INF TmpSocketInf; memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); memcpy((void *)TmpSocketInf.IPAddr,addr,4); TmpSocketInf.DesPort = DesPort; TmpSocketInf.SourPort = SourPort; TmpSocketInf.ProtoType = PROTO_TYPE_UDP; TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf; TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; i = CH57xNET_SocketCreat(&S,&TmpSocketInf); mStopIfError(i); } void Transport_SendPacket(UINT8 *buf,UINT32 len) { UINT32 totallen; UINT8 *p=buf; totallen=len; while(1) { len = totallen; CH57xNET_SocketSend(SocketId,p,&len); totallen -= len; p += len; if(totallen)continue; break; } } void MQTT_Connect(char *username,char *password) { MQTTPacket_connectData data = MQTTPacket_connectData_initializer; UINT32 len; UINT8 buf[200]; data.clientID.cstring = MACAddr_Str; PRINT("MQTT_Connect clientID:%srn",data.clientID.cstring); 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); } 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); } 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); } 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); } void MQTT_Pingreq() { UINT32 len; UINT8 buf[200]; len=MQTTSerialize_pingreq(buf,sizeof(buf)); Transport_SendPacket(buf,len); } void MQTT_Disconnect() { UINT32 len; UINT8 buf[50]; len=MQTTSerialize_disconnect(buf,sizeof(buf)); Transport_SendPacket(buf,len); } void CH57xNET_CreatTcpSocket(void) { UINT8 i; SOCK_INF TmpSocketInf; memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); TmpSocketInf.DesPort = 1000; TmpSocketInf.SourPort = 2000; TmpSocketInf.ProtoType = PROTO_TYPE_TCP; TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf; TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; i = CH57xNET_SocketCreat(&SocketId,&TmpSocketInf); mStopIfError(i); #ifdef KEEPLIVE_ENABLE CH57xNET_SocketSetKeepLive( SocketId, 1 ); #endif i = CH57xNET_SocketConnect(SocketId); mStopIfError(i); i = CH57xNET_SetSocketTTL( SocketId,10 ); mStopIfError(i); } #ifdef KEEPLIVE_ENABLE void net_initkeeplive(void) { struct _KEEP_CFG klcfg; klcfg.KLIdle = 20000; klcfg.KLIntvl = 10000; klcfg.KLCount = 5; CH57xNET_ConfigKeepLive(&klcfg); } #endif UINT8 CH57xNET_LibInit( UINT8 *ip, UINT8 *gwip, UINT8 *mask, 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); } void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat) { UINT32 len; UINT8 i; unsigned char* dup; unsigned short* packetid; int qos;//int* qos; 此处为BUG 改成非指针 unsigned char* retained; MQTTString topicName;//MQTTString* topicName; 此处为BUG 改成指针 unsigned char* payload; int payloadlen; unsigned char *p=payload; if(initstat & SINT_STAT_RECV) { // len = CH57xNET_SocketRecvLen(sockeid,NULL); // CH57xNET_SocketRecv(sockeid,MyBuf,&len); // switch(MyBuf[0]>>4) // { // case FLAG_CONNACK: // PRINT("connackrn"); // con_flag=1; // break; // case FLAG_PUBLISH: // MQTTDeserialize_publish(dup,qos,retained,packetid,topicName,&payload,&payloadlen,MyBuf,len); // PRINT("payloadlen=%drn",(UINT16)payloadlen); // p=payload; // for(i=0;i // PRINT("%c ",(UINT16)*p); // p++; // } // PRINT("rn"); // break; // case FLAG_SUBACK: // sub_flag=1; // PRINT("subackrn"); // break; // default: // break; // } len = CH57xNET_SocketRecvLen(sockeid,NULL); PRINT("Receive Len = %02xrn",len); if (len > 0) { if((sockeid==0)&&(dns_status ==3)) { PRINT("enter rece int!dns_status=3rn"); CH57xNET_SocketRecv(sockeid,dns_buf,&len); dns_status = 4; i = CH57xNET_SocketClose( sockeid,TCP_CLOSE_NORMAL ); mStopIfError(i); PRINT("dns_status = 4!rn"); } else { CH57xNET_SocketRecv(sockeid,MyBuf,&len); PRINT("data:"); for(i=0;i PRINT("%02x ",MyBuf[i]); } PRINT("rn"); switch(MyBuf[0]>>4) { case FLAG_CONNACK: PRINT("connackrn"); MQTT_Subscribe(sub_topic); con_flag=1; break; case FLAG_PUBLISH: MQTTDeserialize_publish(dup,&qos,retained,packetid,&topicName,&payload,&payloadlen,MyBuf,len); PRINT("payloadlen=%drn",(UINT16)payloadlen); p=payload; for(i=0;i PRINT("%c ",(UINT16)*p); p++; } PRINT("rn"); break; case FLAG_SUBACK: sub_flag=1; PRINT("subackrn"); break; default: break; } } } } if(initstat & SINT_STAT_CONNECT) { PRINT("TCP Connect Successrn"); MQTT_Connect(username, password); } if(initstat & SINT_STAT_DISCONNECT) { PRINT("TCP Disconnectn"); //CH57xNET_CreatTcpSocket(); Transport_Open(); } if(initstat & SINT_STAT_TIM_OUT) { PRINT("TCP Timoutn"); Transport_Open(); } } UINT8 CH57xNET_DHCPCallBack(UINT8 status,void *arg) { UINT8 *p; if(!status){ p = arg; PRINT("DHCP Successrn"); memcpy(IPAddr,p,4); memcpy(GWIPAddr,&p[4],4); memcpy(IPMask,&p[8],4); PRINT("IPAddr = %d.%d.%d.%d rn",(UINT16)IPAddr[0],(UINT16)IPAddr[1], (UINT16)IPAddr[2],(UINT16)IPAddr[3]); PRINT("GWIPAddr = %d.%d.%d.%d rn",(UINT16)GWIPAddr[0],(UINT16)GWIPAddr[1], (UINT16)GWIPAddr[2],(UINT16)GWIPAddr[3]); PRINT("IPAddr = %d.%d.%d.%d rn",(UINT16)IPMask[0],(UINT16)IPMask[1], (UINT16)IPMask[2],(UINT16)IPMask[3]); PRINT("DNS1: %d.%d.%d.%drn",p[12],p[13],p[14],p[15]); PRINT("DNS2: %d.%d.%d.%drn",p[16],p[17],p[18],p[19]); // CH57xNET_CreatTcpSocket(); // PRINT("creat tcp sockrt!rn"); dns_status = 1;//可以dns了 } else{ PRINT("DHCP Fail %02xn",status); } return 0; } void CH57xNET_HandleGlobalInt(void) { UINT8 initstat; UINT8 i; UINT8 socketinit; initstat = CH57xNET_GetGlobalInt(); if(initstat & GINT_STAT_UNREACH) { PRINT("UnreachCode :%drn",CH57xInf.UnreachCode); PRINT("UnreachProto :%drn",CH57xInf.UnreachProto); PRINT("UnreachPort :%drn",CH57xInf.UnreachPort); } if(initstat & GINT_STAT_IP_CONFLI) { } if(initstat & GINT_STAT_PHY_CHANGE) { i = CH57xNET_GetPHYStatus(); PRINT("GINT_STAT_PHY_CHANGE %02xrn",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) { for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++) { socketinit = CH57xNET_GetSocketInt(i); 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); } void SystemClock_UART1_init(void) { PWR_UnitModCfg(ENABLE, UNIT_SYS_PLL); DelayMs(3); SetSysClock(CLK_SOURCE_HSE_32MHz); GPIOA_SetBits( GPIO_Pin_9 ); GPIOA_ModeCfg( GPIO_Pin_9, GPIO_ModeOut_PP_5mA ); UART1_DefInit( ); } void GetMacAddr(UINT8 *pMAC) { UINT8 transbuf[6],i; GetMACAddress(transbuf); for(i=0;i<6;i++) { pMAC[5-i]=transbuf[i]; } } 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 Successrn"); sprintf(MACAddr_Str,"%02X%02X%02X%02X%02X",MACAddr[0],MACAddr[1],MACAddr[2],MACAddr[3],MACAddr[4]); PRINT("MAC:%srn",MACAddr_Str); Timer0Init( 10000 ); NVIC_EnableIRQ(ETH_IRQn); //Transport_Open(); while ( CH57xInf.PHYStat < 2 ) { DelayMs(50); } PRINT("CH579 MQTT socket create!Publishingrn"); while(1) { CH57xNET_MainTask(); 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:%srn",url_dn3); PRINT("HTTPs_IP=%d.%d.%d.%drn",ip[0],ip[1],ip[2],ip[3]); memcpy(DESIP,ip,4); Transport_Open(); } } } DelayMs(1); TimeDelay++; if (TimeDelay>20000) { TimeDelay=0; if(con_flag)MQTT_Pingreq(); //MQTT_Publish(pub_topic,payload); } } }



