CH579-LAN-DHCP-DNS-TCP-UDP
DHCP
1 /********************************** (C) COPYRIGHT ****************************** 2 * File Name : DHCP_Client.C 3 * Author : WCH 4 * Version : V1.0 5 * Date : 2018/12/01 6 * Description : CH57xNET库演示文件 7 * (1)、CH579 Examples by KEIL; 8 * (2)、串口1输出监控信息,115200bps; 9 * (3)、本程序用于演示DHCP客户端从网关获取IP地址 10 *******************************************************************************/ 11 12 13 14 /******************************************************************************/ 15 /* 头文件包含*/ 16 #include <stdio.h> 17 #include <string.h> 18 #include "CH57x_common.h" 19 #include "core_cm0.h" 20 #include "CH57xNET.H" 21 22 #define KEEPLIVE_ENABLE 1 // 开启KEEPLIVE功能 23 24 /* 下面的缓冲区和全局变量必须要定义,库中调用 */ 25 __align(16)UINT8 CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16]; //MAC接收描述符缓冲区,16字节对齐 26 __align(4) UINT8 CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE]; //MAC接收缓冲区,4字节对齐 27 __align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM]; //Socket信息表,4字节对齐 28 29 UINT16 MemNum[8] = {CH57xNET_NUM_IPRAW, 30 CH57xNET_NUM_UDP, 31 CH57xNET_NUM_TCP, 32 CH57xNET_NUM_TCP_LISTEN, 33 CH57xNET_NUM_TCP_SEG, 34 CH57xNET_NUM_IP_REASSDATA, 35 CH57xNET_NUM_PBUF, 36 CH57xNET_NUM_POOL_BUF 37 }; 38 UINT16 MemSize[8] = {CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IPRAW_PCB), 39 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_UDP_PCB), 40 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB), 41 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB_LISTEN), 42 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_SEG), 43 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IP_REASSDATA), 44 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(0), 45 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_POOL_BUF) 46 }; 47 __align(4)UINT8 Memp_Memory[CH57xNET_MEMP_SIZE]; 48 __align(4)UINT8 Mem_Heap_Memory[CH57xNET_RAM_HEAP_SIZE]; 49 __align(4)UINT8 Mem_ArpTable[CH57xNET_RAM_ARP_TABLE_SIZE]; 50 /******************************************************************************/ 51 /* 本演示程序的相关宏 */ 52 #define RECE_BUF_LEN 536 //接收缓冲区的大小 53 /* CH57xNET库TCP的MSS长度为536字节,即一个TCP包里的数据部分最长为536字节 */ 54 /* TCP协议栈采用滑动窗口进行流控,窗口最大值为socket的接收缓冲区长度。在设定 */ 55 /* RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系,例如窗口值为4*MSS,则远端一次会发送 */ 56 /* 4个TCP包,如果RX_QUEUE_ENTRIES小于4,则必然会导致数据包丢失,从而导致通讯效率降低 */ 57 /* 建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据,则 */ 58 /* 建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 */ 59 /* 为了节约RAM,请将接收缓冲区的长度设置为MSS */ 60 61 /* CH579相关定义 */ 62 UINT8 MACAddr[6] = {0x84,0xc2,0xe4,0x02,0x03,0x04}; //CH579MAC地址 63 UINT8 IPAddr[4] = {0}; //CH579IP地址 64 UINT8 GWIPAddr[4] = {192,168,1,1}; //CH579网关 65 UINT8 IPMask[4] = {255,255,255,0}; //CH579子网掩码 66 UINT8 DESIP[4] = {192,168,1,100}; //目的IP地址 67 68 UINT8 SocketId; //保存socket索引,可以不用定义 69 UINT8 SocketRecvBuf[RECE_BUF_LEN]; //socket接收缓冲区 70 UINT8 MyBuf[RECE_BUF_LEN]; //定义一个临时缓冲区 71 72 73 //extern const UINT16 *memp_num; 74 75 /******************************************************************************* 76 * Function Name : IRQ_Handler 77 * Description : IRQ中断服务函数 78 * Input : None 79 * Output : None 80 * Return : None 81 *******************************************************************************/ 82 void ETH_IRQHandler( void ) //以太网中断 83 { 84 CH57xNET_ETHIsr(); //以太网中断中断服务函数 85 } 86 87 void TMR0_IRQHandler( void ) //定时器中断 88 { 89 CH57xNET_TimeIsr(CH57xNETTIMEPERIOD); //定时器中断服务函数 90 R8_TMR0_INT_FLAG |= 0xff; //清除定时器中断标志 91 } 92 93 94 95 /******************************************************************************* 96 * Function Name : mStopIfError 97 * Description : 调试使用,显示错误代码 98 * Input : iError 错误代码 99 * Output : None 100 * Return : None 101 *******************************************************************************/ 102 void mStopIfError(UINT8 iError) 103 { 104 if (iError == CH57xNET_ERR_SUCCESS) return; //操作成功 105 PRINT("mStopIfError: %02X\r\n", (UINT16)iError); //显示错误 106 } 107 108 109 /******************************************************************************* 110 * Function Name : CH57xNET_CreatTcpSocket 111 * Description : 创建TCP Client socket 112 * Input : None 113 * Output : None 114 * Return : None 115 *******************************************************************************/ 116 void CH57xNET_CreatTcpSocket(void) 117 { 118 UINT8 i; 119 SOCK_INF TmpSocketInf;//创建临时socket变量 */ 120 121 memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); //库内部会将此变量复制,所以最好将临时变量先全部清零 122 memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); //设置目的IP地址 123 TmpSocketInf.DesPort = 1000; 124 TmpSocketInf.SourPort = 2000; //设置源端口 125 TmpSocketInf.ProtoType = PROTO_TYPE_TCP; //设置socekt类型 126 TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf; //设置接收缓冲区的接收缓冲区 127 TmpSocketInf.RecvBufLen = RECE_BUF_LEN;//设置接收缓冲区的接收长度 128 i = CH57xNET_SocketCreat(&SocketId,&TmpSocketInf);//创建socket,将返回的socket索引保存在SocketId中 129 mStopIfError(i);//检查错误 130 #ifdef KEEPLIVE_ENABLE 131 CH57xNET_SocketSetKeepLive( SocketId, 1 ); //开启socket的KEEPLIVE功能(V06版本支持) 132 #endif 133 134 i = CH57xNET_SocketConnect(SocketId); //TCP连接 135 mStopIfError(i); // 检查错误 136 i = CH57xNET_SetSocketTTL( SocketId,10 ); 137 mStopIfError(i); //检查错误 138 } 139 140 141 /******************************************************************************* 142 * Function Name : net_initkeeplive 143 * Description : keeplive初始化 144 * Input : None 145 * Output : None 146 * Return : None 147 *******************************************************************************/ 148 #ifdef KEEPLIVE_ENABLE 149 void net_initkeeplive(void) 150 { 151 struct _KEEP_CFG klcfg; 152 klcfg.KLIdle = 20000; //空闲 153 klcfg.KLIntvl = 10000; //间隔 154 klcfg.KLCount = 5; //次数 155 CH57xNET_ConfigKeepLive(&klcfg); 156 } 157 #endif 158 159 /******************************************************************************* 160 * Function Name : CH57xNET_LibInit 161 * Description : 库初始化操作 162 * Input : ip ip地址指针 163 * :gwip 网关ip地址指针 164 * : mask 掩码指针 165 * : macaddr MAC地址指针 166 * Output : None 167 * Return : 执行状态 168 *******************************************************************************/ 169 UINT8 CH57xNET_LibInit(UINT8 *ip,UINT8 *gwip,UINT8 *mask,UINT8 *macaddr) 170 { 171 UINT8 i; 172 struct _CH57x_CFG cfg; 173 174 if(CH57xNET_GetVer() != CH57xNET_LIB_VER)return 0xfc; //获取库的版本号,检查是否和头文件一致 175 CH57xNETConfig = LIB_CFG_VALUE; //将配置信息传递给库的配置变量 176 cfg.RxBufSize = RX_BUF_SIZE; 177 cfg.TCPMss = CH57xNET_TCP_MSS; 178 cfg.HeapSize = CH57x_MEM_HEAP_SIZE; 179 cfg.ARPTableNum = CH57xNET_NUM_ARP_TABLE; 180 cfg.MiscConfig0 = CH57xNET_MISC_CONFIG0; 181 CH57xNET_ConfigLIB(&cfg); 182 i = CH57xNET_Init(ip,gwip,mask,macaddr); 183 #ifdef KEEPLIVE_ENABLE 184 net_initkeeplive( ); 185 #endif 186 return (i); 187 } 188 189 /******************************************************************************* 190 * Function Name : CH57xNET_HandleSockInt 191 * Description : Socket中断处理函数 192 * Input : sockeid socket索引 193 * :initstat 中断状态 194 * Output : None 195 * Return : None 196 *******************************************************************************/ 197 void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat) 198 { 199 UINT32 len; 200 UINT32 totallen; 201 UINT8 *p = MyBuf; 202 203 if(initstat & SINT_STAT_RECV) //接收中断 204 { 205 len = CH57xNET_SocketRecvLen(sockeid,NULL); //查询长度 206 PRINT("Receive Len = %d\r\n",len); 207 totallen = len; 208 CH57xNET_SocketRecv(sockeid,MyBuf,&len); //将接收缓冲区的数据读到MyBuf中 209 while(1) 210 { 211 len = totallen; 212 CH57xNET_SocketSend(sockeid,p,&len); //将MyBuf中的数据发送 213 totallen -= len; //将总长度减去以及发送完毕的长度 214 p += len; //将缓冲区指针偏移 215 if(totallen)continue; //如果数据未发送完毕,则继续发送 216 break; //发送完毕,退出 217 } 218 } 219 if(initstat & SINT_STAT_CONNECT) //TCP连接中断 220 { //产生此中断表示TCP已经连接,可以进行收发数据 221 PRINT("TCP Connect Success\n"); 222 } 223 if(initstat & SINT_STAT_DISCONNECT)//TCP断开中断 224 { //产生此中断,CH579库内部会将此socket清除,置为关闭 225 PRINT("TCP Disconnect\n"); //应用曾需可以重新创建连接 226 } 227 if(initstat & SINT_STAT_TIM_OUT) //TCP超时中断 228 { //产生此中断,CH579库内部会将此socket清除,置为关闭 229 PRINT("TCP Timout\n"); //应用曾需可以重新创建连接 230 } 231 } 232 233 234 /******************************************************************************* 235 * Function Name : CH57xNET_HandleGloableInt 236 * Description : 全局中断处理函数 237 * Input : None 238 * Output : None 239 * Return : None 240 *******************************************************************************/ 241 void CH57xNET_HandleGlobalInt(void) 242 { 243 UINT8 initstat; 244 UINT8 i; 245 UINT8 socketinit; 246 initstat = CH57xNET_GetGlobalInt(); //读全局中断状态并清除 247 if(initstat & GINT_STAT_UNREACH) //不可达中断 248 { 249 PRINT("UnreachCode :%d\n",CH57xInf.UnreachCode); //查看不可达代码 250 PRINT("UnreachProto :%d\n",CH57xInf.UnreachProto);//查看不可达协议类型 251 PRINT("UnreachPort :%d\n",CH57xInf.UnreachPort); //查询不可达端口 252 } 253 if(initstat & GINT_STAT_IP_CONFLI) //IP冲突中断 254 { 255 256 } 257 if(initstat & GINT_STAT_PHY_CHANGE) //PHY改变中断 258 { 259 i = CH57xNET_GetPHYStatus(); //获取PHY状态 260 PRINT("GINT_STAT_PHY_CHANGE %02x\n",i); 261 } 262 if(initstat & GINT_STAT_SOCKET) //Socket中断 263 { 264 for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++) 265 { 266 socketinit = CH57xNET_GetSocketInt(i); //读socket中断并清零 267 if(socketinit)CH57xNET_HandleSockInt(i,socketinit); //如果有中断则清零 268 } 269 } 270 } 271 272 /******************************************************************************* 273 * Function Name : Timer0Init 274 * Description : 定时器1初始化 275 * Input : time 定时时间 276 * Output : None 277 * Return : None 278 *******************************************************************************/ 279 void Timer0Init(UINT32 time) 280 { 281 R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;//清除所有计数值 282 R8_TMR0_CTRL_MOD = 0; //设置定时器模式 283 R32_TMR0_CNT_END = FREQ_SYS/1000000*time; //设置定时时间 284 R8_TMR0_INT_FLAG = R8_TMR0_INT_FLAG;//清除标志 285 R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END;//定时中断 286 R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN; 287 NVIC_EnableIRQ(TMR0_IRQn); 288 } 289 290 291 /******************************************************************************* 292 * Function Name : CH57xNET_DHCPCallBack 293 * Description : DHCP回调函数 294 * Input : None 295 * Output : None 296 * Return : 执行状态 297 *******************************************************************************/ 298 UINT8 CH57xNET_DHCPCallBack(UINT8 status,void *arg) 299 { 300 UINT8 *p; 301 302 if(!status){ //成功 303 p = arg; //产生此中断,CH57xNET库内部会将此socket清除,置为关闭 304 PRINT("DHCP Success\n"); 305 memcpy(IPAddr,p,4); 306 memcpy(GWIPAddr,&p[4],4); 307 memcpy(IPMask,&p[8],4); //产生此中断,CH57xNET库内部会将此socket清除,置为关闭 308 PRINT("IPAddr = %d.%d.%d.%d \n",(UINT16)IPAddr[0],(UINT16)IPAddr[1], 309 (UINT16)IPAddr[2],(UINT16)IPAddr[3]); 310 PRINT("GWIPAddr = %d.%d.%d.%d \n",(UINT16)GWIPAddr[0],(UINT16)GWIPAddr[1], 311 (UINT16)GWIPAddr[2],(UINT16)GWIPAddr[3]); 312 PRINT("IPAddr = %d.%d.%d.%d \n",(UINT16)IPMask[0],(UINT16)IPMask[1], 313 (UINT16)IPMask[2],(UINT16)IPMask[3]); 314 PRINT("DNS1: %d.%d.%d.%d\n",p[12],p[13],p[14],p[15]); 315 PRINT("DNS2: %d.%d.%d.%d\n",p[16],p[17],p[18],p[19]); 316 // CH57xNET_CreatTcpSocket(); //可以在此处,在DHCP完成后进行TCP连接 317 // PRINT("creat tcp sockrt!\r\n"); 318 } 319 else{ //产生此中断,CH57xNET库内部会将此socket清除,置为关闭 320 PRINT("DHCP Fail %02x\n",status); 321 } 322 return 0; 323 } 324 325 /******************************************************************************* 326 * Function Name : SystemClock_UART1_init 327 * Description : 系统时钟和串口1初始化,串口1用于打印输出 328 * Input : None 329 * Output : None 330 * Return : None 331 *******************************************************************************/ 332 void SystemClock_UART1_init(void) 333 { 334 PWR_UnitModCfg(ENABLE, UNIT_SYS_PLL); //PLL上电 335 DelsyMs(3); 336 SetSysClock(CLK_SOURCE_HSE_32MHz); //外部晶振 PLL 输出32MHz 337 GPIOA_SetBits( GPIO_Pin_9 ); 338 GPIOA_ModeCfg( GPIO_Pin_9, GPIO_ModeOut_PP_5mA ); //串口1的IO口设置 339 UART1_DefInit( ); //串口1初始化 340 } 341 342 /******************************************************************************* 343 * Function Name : main 344 * Description : 主函数 345 * Input : None 346 * Output : None 347 * Return : None 348 *******************************************************************************/ 349 int main(void) 350 { 351 UINT8 i = 0; 352 353 SystemClock_UART1_init(); 354 i = CH57xNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr); //库初始化 355 mStopIfError(i); //检查错误 356 PRINT("CH57xNETLibInit Success\r\n"); 357 Timer0Init( 10000 ); //初始化定时器:10ms 358 NVIC_EnableIRQ(ETH_IRQn); 359 while ( CH57xInf.PHYStat < 2 ) DelsyMs(50); 360 if(!i)CH57xNET_DHCPStart(CH57xNET_DHCPCallBack); //启动DHCP 361 PRINT("CH579 dhcp client create!\r\n"); 362 while(1) 363 { 364 CH57xNET_MainTask();//CH57xNET库主任务函数,需要在主循环中不断调用 365 if(CH57xNET_QueryGlobalInt())CH57xNET_HandleGlobalInt(); //查询中断,如果有中断,则调用全局中断处理函数 366 } 367 } 368 /*********************************** endfile **********************************/
CH57xNETLibInit Success CH579 dhcp client create! GINT_STAT_PHY_CHANGE 02 DHCP Success IPAddr = 192.168.1.11 GWIPAddr = 192.168.1.1 IPAddr = 255.255.255.0 DNS1: 168.126.63.1 DNS2: 168.126.63.2
DNS
dns.c//库函数
1 /********************************** (C) COPYRIGHT ****************************** 2 * File Name : DNS.c 3 * Author : WCH 4 * Version : V1.0 5 * Date : 2018/12/05 6 * Description : CH579 NET库DNS应用演示 7 *******************************************************************************/ 8 9 10 11 /******************************************************************************/ 12 /* 头文件包含 */ 13 #include <stdio.h> 14 #include <string.h> 15 #include <stdlib.h> 16 #include "CH57x_common.h" 17 #include "core_cm0.h" 18 #include "CH57xNET.H" 19 #include "DNS.H" 20 21 22 #define CH57xNET_DBG 1 23 /* 变量定义 */ 24 UINT8 DNS_SERVER_IP[4]={114,114,114,114}; //DNS服务器 25 #define IPPORT_DOMAIN 53 //DNS默认端口 26 UINT16 MSG_ID = 0x1100; //标识 27 UINT32 count = 0; 28 UINT8 dns_buf[MAX_DNS_BUF_SIZE]; 29 30 /******************************************************************************* 31 * Function Name : get16 32 * Description : 将缓冲区UINT8数据转为UINT16格式数据 33 * Input : s -UINT8类型数据 34 * Output : None 35 * Return : 转化后的UINT16类型数据 36 *******************************************************************************/ 37 UINT16 get16(UINT8 * s) 38 { 39 UINT16 i; 40 41 i = *s++ << 8; 42 i = i + *s; 43 return i; 44 } 45 46 /******************************************************************************* 47 * Function Name : ParseName 48 * Description : 分析完整的域名 49 * Input : msg -指向报文的指针 50 compressed -指向报文中主域名的指针 51 buf -缓冲区指针,用于存放转化后域名 52 * Output : None 53 * Return : 压缩报文的长度 54 *******************************************************************************/ 55 int ParseName(UINT8 * msg, UINT8 * compressed, char * buf) 56 { 57 UINT16 slen; //当前片段长度 58 UINT8 * cp; 59 int clen = 0; //压缩域名长度 60 int indirect = 0; 61 int nseg = 0; //域名被分割的片段总数 62 63 cp = compressed; 64 for (;;){ 65 slen = *cp++; //首字节的计数值 66 if (!indirect) clen++; 67 if ((slen & 0xc0) == 0xc0){ //计数字节高两比特为1,用于压缩格式 68 if (!indirect) clen++; 69 indirect = 1; 70 cp = &msg[((slen & 0x3f)<<8) + *cp];//按计数字节数值指针偏移到指定位置 71 slen = *cp++; 72 } 73 if (slen == 0) break; //计数为0,结束 74 if (!indirect) clen += slen; 75 while (slen-- != 0) *buf++ = (char)*cp++; 76 *buf++ = '.'; 77 nseg++; 78 } 79 if (nseg == 0){ 80 /* 根域名; */ 81 *buf++ = '.'; 82 } 83 *buf++ = '\0'; 84 return clen; //压缩报文长度 85 } 86 87 /******************************************************************************* 88 * Function Name : DnsQuestion 89 * Description : 分析响应报文中的问题记录部分 90 * Input : msg -指向响应报文的指针 91 cp -指向问题记录的指针 92 * Output : None 93 * Return : 指向下一记录的指针 94 *******************************************************************************/ 95 UINT8 * DnsQuestion(UINT8 * msg, UINT8 * cp) 96 { 97 int len; 98 char name[MAX_DNS_BUF_SIZE]; 99 100 len = ParseName(msg, cp, name); 101 cp += len; 102 cp += 2; //类型 103 cp += 2; //类 104 return cp; 105 } 106 107 /******************************************************************************* 108 * Function Name : DnsAnswer 109 * Description : 分析响应报文中的回答记录部分 110 * Input : msg -指向响应报文的指针 111 cp -指向回答记录的指针 112 psip 113 * Output : None 114 * Return :指向下一记录的指针 115 *******************************************************************************/ 116 UINT8 * DnsAnswer(UINT8 * msg, UINT8 * cp, UINT8 * pSip) 117 { 118 int len, type; 119 char name[MAX_DNS_BUF_SIZE]; 120 121 len = ParseName(msg, cp, name); 122 cp += len; 123 type = get16(cp); 124 cp += 2; //类型 125 cp += 2; //类 126 cp += 4; //生存时间 127 cp += 2; //资源数据长度 128 switch ( type ){ 129 case TYPE_A: 130 pSip[0] = *cp++; 131 pSip[1] = *cp++; 132 pSip[2] = *cp++; 133 pSip[3] = *cp++; 134 break; 135 case TYPE_CNAME: 136 case TYPE_MB: 137 case TYPE_MG: 138 case TYPE_MR: 139 case TYPE_NS: 140 case TYPE_PTR: 141 len = ParseName(msg, cp, name); 142 cp += len; 143 break; 144 case TYPE_HINFO: 145 case TYPE_MX: 146 case TYPE_SOA: 147 case TYPE_TXT: 148 break; 149 default: 150 break; 151 } 152 return cp; 153 } 154 155 /******************************************************************************* 156 * Function Name : parseMSG 157 * Description : 分析响应报文中的资源记录部分 158 * Input : msg -指向DNS报文头部的指针 159 cp -指向响应报文的指针 160 * Output : None 161 * Return :成功返回1,否则返回0 162 *******************************************************************************/ 163 164 UINT8 parseMSG(struct dhdr * pdhdr, UINT8 * pbuf, UINT8 * pSip) 165 { 166 UINT16 tmp; 167 UINT16 i; 168 UINT8 * msg; 169 UINT8 * cp; 170 171 msg = pbuf; 172 memset(pdhdr, 0, sizeof(pdhdr)); 173 pdhdr->id = get16(&msg[0]); 174 tmp = get16(&msg[2]); 175 if (tmp & 0x8000) pdhdr->qr = 1; 176 pdhdr->opcode = (tmp >> 11) & 0xf; 177 if (tmp & 0x0400) pdhdr->aa = 1; 178 if (tmp & 0x0200) pdhdr->tc = 1; 179 if (tmp & 0x0100) pdhdr->rd = 1; 180 if (tmp & 0x0080) pdhdr->ra = 1; 181 pdhdr->rcode = tmp & 0xf; 182 pdhdr->qdcount = get16(&msg[4]); 183 pdhdr->ancount = get16(&msg[6]); 184 pdhdr->nscount = get16(&msg[8]); 185 pdhdr->arcount = get16(&msg[10]); 186 /* 分析可变数据长度部分*/ 187 cp = &msg[12]; 188 /* 查询问题 */ 189 for (i = 0; i < pdhdr->qdcount; i++) 190 { 191 cp = DnsQuestion(msg, cp); 192 } 193 /* 回答 */ 194 for (i = 0; i < pdhdr->ancount; i++) 195 { 196 cp = DnsAnswer(msg, cp, pSip); 197 } 198 /*授权 */ 199 for (i = 0; i < pdhdr->nscount; i++) 200 { 201 /*待解析*/ ; 202 } 203 /* 附加信息 */ 204 for (i = 0; i < pdhdr->arcount; i++) 205 { 206 /*待解析*/ ; 207 } 208 if(pdhdr->rcode == 0) return 1; //rcode = 0:成功 209 else return 0; 210 } 211 212 /******************************************************************************* 213 * Function Name : put16 214 * Description :UINT16 格式数据按UINT8格式存到缓冲区 215 * Input : s -缓冲区首地址 216 i -UINT16数据 217 * Output : None 218 * Return : 偏移指针 219 *******************************************************************************/ 220 UINT8 * put16(UINT8 * s, UINT16 i) 221 { 222 *s++ = i >> 8; 223 *s++ = i; 224 return s; 225 } 226 227 /******************************************************************************* 228 * Function Name : MakeDnsQuery 229 * Description : 制作DNS查询报文 230 input : op - 递归 231 * name - 指向待查域名指针 232 * buf - DNS缓冲区. 233 * len - 缓冲区最大长度. 234 * Output : None 235 * Return : 指向DNS报文指针 236 *******************************************************************************/ 237 UINT16 MakeDnsQueryMsg(UINT16 op, char * name, UINT8 * buf, UINT16 len) 238 { 239 UINT8 *cp; 240 char *cp1; 241 char tmpname[MAX_DNS_BUF_SIZE]; 242 char *dname; 243 UINT16 p; 244 UINT16 dlen; 245 246 //printf("Domain name:%s \n",name); 247 cp = buf; 248 MSG_ID++; 249 cp = put16(cp, MSG_ID); //标识 250 p = (op << 11) | 0x0100; 251 cp = put16(cp, p); //0x0100:Recursion desired 252 cp = put16(cp, 1); //问题数:1 253 cp = put16(cp, 0); //资源记录数:0 254 cp = put16(cp, 0); //资源记录数:0 255 cp = put16(cp, 0); //额外资源记录数:0 256 257 strcpy(tmpname, name); 258 dname = tmpname; 259 dlen = strlen(dname); 260 for (;;){ //按照DNS请求报文域名格式,把URI写入到buf里面去 261 cp1 = strchr(dname, '.'); 262 if (cp1 != NULL) len = cp1 - dname; 263 else len = dlen; 264 *cp++ = len; 265 if (len == 0) break; 266 strncpy((char *)cp, dname, len); 267 cp += len; 268 if (cp1 == NULL) 269 { 270 *cp++ = 0; 271 break; 272 } 273 dname += len+1; //dname首地址后移 274 dlen -= len+1; //dname长度减小 275 } 276 cp = put16(cp, 0x0001); //type :1------ip地址 277 cp = put16(cp, 0x0001); //class:1-------互联网地址 278 return ((UINT16)(cp - buf)); 279 } 280 281 /******************************************************************************* 282 * Function Name : DnsQuery 283 * Description : 进行DNS查询 284 input : s -socket索引 285 * name - 指向待查域名指针 286 pSip -查询结果 287 * Output : None 288 * Return : 查询结果。成功返回1,失败返回-1 289 *******************************************************************************/ 290 UINT8 DnsQuery(UINT8 s, UINT8 * name, UINT8 * pSip) 291 { 292 struct dhdr dhp; 293 294 UINT8 ret; 295 UINT32 len; 296 if(status >1 ){ 297 count++; 298 DelsyMs(10); 299 if( count>20000 ){ 300 #if CH57xNET_DBG 301 printf("DNS Fail!!!!!\n"); 302 #endif 303 count=0; 304 status = 0; 305 return 2; 306 } 307 } 308 if(status == 1) 309 { 310 UDPSocketParamInit(s,DNS_SERVER_IP,4000,IPPORT_DOMAIN); 311 status = 2; 312 #if CH57xNET_DBG 313 printf(" 2 status = %d!\n",status); 314 #endif 315 } 316 if(status ==2) 317 { 318 len = MakeDnsQueryMsg(0,(char *)name, dns_buf, MAX_DNS_BUF_SIZE); 319 ret = CH57xNET_SocketSend(s,dns_buf,&len); 320 if ( ret ) return(0); 321 else{ 322 status = 3; 323 #if CH57xNET_DBG 324 printf("status = 3!\n"); 325 #endif 326 } 327 } 328 if(status ==4) 329 { 330 return(parseMSG(&dhp, dns_buf, pSip)); //解析响应报文并返回结果 331 332 } 333 return 0; 334 } 335 336 /*********************************** endfile **********************************/
DNS_Client.c
1 /********************************** (C) COPYRIGHT ****************************** 2 * File Name : DNS_Client.c 3 * Author : WCH 4 * Version : V1.0 5 * Date : 2018/12/01 6 * Description : CH57xNET库演示文件 7 * (1)、CH579 Examples by KEIL; 8 * (2)、串口0输出监控信息,115200bps; 9 * (3)、本程序用于演示UDP 客户端通讯,单片机收到数据后,回传给目标IP上位机 10 *******************************************************************************/ 11 12 13 14 /******************************************************************************/ 15 /* 头文件包含*/ 16 #include <stdio.h> 17 #include <string.h> 18 #include "CH57x_common.h" 19 #include "core_cm0.h" 20 #include "CH57xNET.H" 21 22 #define KEEPLIVE_ENABLE 1 //开启KEEPLIVE功能 23 24 /* 下面的缓冲区和全局变量必须要定义,库中调用 */ 25 __align(16)UINT8 CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16]; //MAC接收描述符缓冲区,16字节对齐 26 __align(4) UINT8 CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE];//MAC接收缓冲区,4字节对齐 27 __align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM]; //Socket信息表,4字节对齐 28 29 const UINT16 MemNum[8] = {CH57xNET_NUM_IPRAW, 30 CH57xNET_NUM_UDP, 31 CH57xNET_NUM_TCP, 32 CH57xNET_NUM_TCP_LISTEN, 33 CH57xNET_NUM_TCP_SEG, 34 CH57xNET_NUM_IP_REASSDATA, 35 CH57xNET_NUM_PBUF, 36 CH57xNET_NUM_POOL_BUF 37 }; 38 const UINT16 MemSize[8] = {CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IPRAW_PCB), 39 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_UDP_PCB), 40 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB), 41 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB_LISTEN), 42 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_SEG), 43 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IP_REASSDATA), 44 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(0), 45 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_POOL_BUF) 46 }; 47 __align(4)UINT8 Memp_Memory[CH57xNET_MEMP_SIZE]; 48 __align(4)UINT8 Mem_Heap_Memory[CH57xNET_RAM_HEAP_SIZE]; 49 __align(4)UINT8 Mem_ArpTable[CH57xNET_RAM_ARP_TABLE_SIZE]; 50 /******************************************************************************/ 51 /* 本演示程序的相关宏 */ 52 #define RECE_BUF_LEN 536 //接收缓冲区的大小 53 /* CH57xNET库TCP的MSS长度为536字节,即一个TCP包里的数据部分最长为536字节 */ 54 /* TCP协议栈采用滑动窗口进行流控,窗口最大值为socket的接收缓冲区长度。在设定 */ 55 /* RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系,例如窗口值为4*MSS,则远端一次会发送 */ 56 /* 4个TCP包,如果RX_QUEUE_ENTRIES小于4,则必然会导致数据包丢失,从而导致通讯效率降低 */ 57 /* 建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据,则 */ 58 /* 建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 */ 59 /* 为了节约RAM,请将接收缓冲区的长度设置为MSS */ 60 61 /* CH579相关定义 */ 62 UINT8 MACAddr[6] = {0x84,0xc2,0xe4,0x02,0x03,0x04};//CH579MAC地址 63 UINT8 IPAddr[4] = {192,168,1,200}; //CH579IP地址 64 UINT8 GWIPAddr[4] = {192,168,1,1}; //CH579网关 65 UINT8 IPMask[4] = {255,255,255,0}; //CH579子网掩码 66 67 UINT8 SocketId; //保存socket索引,可以不用定义 68 UINT8 SocketRecvBuf[RECE_BUF_LEN]; //socket接收缓冲区 69 UINT8 MyBuf[RECE_BUF_LEN]; //定义一个临时缓冲区 70 71 extern UINT8 dns_buf[512]; 72 73 UINT8 status; 74 #define MAX_URL_SIZE 128 75 76 UINT8 url_dn1[MAX_URL_SIZE] = "www.baidu.com"; 77 UINT8 url_dn2[MAX_URL_SIZE] = "www.tencent.com"; 78 UINT8 url_dn3[MAX_URL_SIZE] = "www.wch.cn"; 79 80 81 //extern const UINT16 *memp_num; 82 83 /******************************************************************************* 84 * Function Name : IRQ_Handler 85 * Description : IRQ中断服务函数 86 * Input : None 87 * Output : None 88 * Return : None 89 *******************************************************************************/ 90 void ETH_IRQHandler( void ) //以太网中断 91 { 92 CH57xNET_ETHIsr(); //以太网中断中断服务函数 93 } 94 95 void TMR0_IRQHandler( void ) //定时器中断 96 { 97 CH57xNET_TimeIsr(CH57xNETTIMEPERIOD); //定时器中断服务函数 98 R8_TMR0_INT_FLAG |= 0xff; //清除定时器中断标志 99 } 100 101 102 103 /******************************************************************************* 104 * Function Name : mStopIfError 105 * Description : 调试使用,显示错误代码 106 * Input : iError 错误代码 107 * Output : None 108 * Return : None 109 *******************************************************************************/ 110 void mStopIfError(UINT8 iError) 111 { 112 if (iError == CH57xNET_ERR_SUCCESS) return; //操作成功 113 PRINT("mStopIfError: %02X\r\n", (UINT16)iError);//显示错误 114 } 115 116 /******************************************************************************* 117 * Function Name : net_initkeeplive 118 * Description : keeplive初始化 119 * Input : None 120 * Output : None 121 * Return : None 122 *******************************************************************************/ 123 #ifdef KEEPLIVE_ENABLE 124 void net_initkeeplive(void) 125 { 126 struct _KEEP_CFG klcfg; 127 128 klcfg.KLIdle = 20000; //空闲 129 klcfg.KLIntvl = 10000; //间隔 130 klcfg.KLCount = 5; //次数 131 CH57xNET_ConfigKeepLive(&klcfg); 132 } 133 #endif 134 135 /******************************************************************************* 136 * Function Name : CH57xNET_LibInit 137 * Description : 库初始化操作 138 * Input : ip ip地址指针 139 * :gwip 网关ip地址指针 140 * : mask 掩码指针 141 * : macaddr MAC地址指针 142 * Output : None 143 * Return : 执行状态 144 *******************************************************************************/ 145 UINT8 CH57xNET_LibInit( UINT8 *ip, UINT8 *gwip, UINT8 *mask,UINT8 *macaddr) 146 { 147 UINT8 i; 148 struct _CH57x_CFG cfg; 149 150 if(CH57xNET_GetVer() != CH57xNET_LIB_VER)return 0xfc;//获取库的版本号,检查是否和头文件一致 151 CH57xNETConfig = LIB_CFG_VALUE; //将配置信息传递给库的配置变量 152 cfg.RxBufSize = RX_BUF_SIZE; 153 cfg.TCPMss = CH57xNET_TCP_MSS; 154 cfg.HeapSize = CH57x_MEM_HEAP_SIZE; 155 cfg.ARPTableNum = CH57xNET_NUM_ARP_TABLE; 156 cfg.MiscConfig0 = CH57xNET_MISC_CONFIG0; 157 CH57xNET_ConfigLIB(&cfg); 158 i = CH57xNET_Init(ip,gwip,mask,macaddr); 159 #ifdef KEEPLIVE_ENABLE 160 net_initkeeplive( ); 161 #endif 162 return (i); //库初始化 163 } 164 165 /******************************************************************************* 166 * Function Name : CH57xNET_HandleSockInt 167 * Description : Socket中断处理函数 168 * Input : sockeid socket索引 169 * :initstat 中断状态 170 * Output : None 171 * Return : None 172 *******************************************************************************/ 173 void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat) 174 { 175 UINT32 len; 176 UINT8 i; 177 178 if(initstat & SINT_STAT_RECV) //接收中断 179 { 180 len = CH57xNET_SocketRecvLen(sockeid,NULL); //会将当前接收指针传递给precv 181 PRINT("Receive Len = %02x\n",len); 182 if (len > 0) 183 { 184 if((sockeid==0)&&(status ==3)) 185 { 186 PRINT("enter rece int!STATUS=3\r\n"); 187 CH57xNET_SocketRecv(sockeid,dns_buf,&len); 188 status = 4; 189 i = CH57xNET_SocketClose( sockeid,TCP_CLOSE_NORMAL ); 190 mStopIfError(i); 191 PRINT("status = 4!\n"); 192 } 193 else 194 CH57xNET_SocketRecv(sockeid,MyBuf,&len); //将接收缓冲区的数据读到MyBuf中 195 } 196 } 197 if(initstat & SINT_STAT_CONNECT) //TCP连接中断 198 { //产生此中断表示TCP已经连接,可以进行收发数据 199 PRINT("TCP Connect Success\n"); 200 } 201 if(initstat & SINT_STAT_DISCONNECT) //TCP断开中断 202 { //产生此中断,CH579库内部会将此socket清除,置为关闭 203 PRINT("TCP Disconnect\n"); //应用曾需可以重新创建连接 204 } 205 if(initstat & SINT_STAT_TIM_OUT) //TCP超时中断 206 { //产生此中断,CH579库内部会将此socket清除,置为关闭 207 PRINT("TCP Timout\n"); //应用曾需可以重新创建连接 208 } 209 } 210 211 212 /******************************************************************************* 213 * Function Name : CH57xNET_HandleGloableInt 214 * Description : 全局中断处理函数 215 * Input : None 216 * Output : None 217 * Return : None 218 *******************************************************************************/ 219 void CH57xNET_HandleGlobalInt(void) 220 { 221 UINT8 initstat; 222 UINT8 i; 223 UINT8 socketinit; 224 initstat = CH57xNET_GetGlobalInt(); //读全局中断状态并清除 225 if(initstat & GINT_STAT_UNREACH) //不可达中断 226 { 227 PRINT("UnreachCode :%d\n",CH57xInf.UnreachCode); //查看不可达代码 228 PRINT("UnreachProto :%d\n",CH57xInf.UnreachProto); //查看不可达协议类型 229 PRINT("UnreachPort :%d\n",CH57xInf.UnreachPort); //查询不可达端口 230 } 231 if(initstat & GINT_STAT_IP_CONFLI) //IP冲突中断 232 { 233 234 } 235 if(initstat & GINT_STAT_PHY_CHANGE) //PHY改变中断 236 { 237 i = CH57xNET_GetPHYStatus(); //获取PHY状态 238 if(i>=0x02) status = 1; 239 PRINT("status = 1!\n"); 240 PRINT("GINT_STAT_PHY_CHANGE %02x\n",i); 241 } 242 if(initstat & GINT_STAT_SOCKET) //Socket中断 243 { 244 for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++) 245 { 246 socketinit = CH57xNET_GetSocketInt(i); //读socket中断并清零 247 if(socketinit)CH57xNET_HandleSockInt(i,socketinit);//如果有中断则清零 248 } 249 } 250 } 251 252 /******************************************************************************* 253 * Function Name : UDPSocketParamInit 254 * Description : 创建UDP socket 255 * Input : socket索引值,源端口,目的端口及目的IP 256 * Output : None 257 * Return : None 258 *******************************************************************************/ 259 void UDPSocketParamInit(UINT8 S,UINT8 *addr,UINT16 SourPort,UINT16 DesPort ) 260 { 261 UINT8 i; 262 SOCK_INF TmpSocketInf; //创建临时socket变量 263 264 memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); //库内部会将此变量复制,所以最好将临时变量先全部清零 265 memcpy((void *)TmpSocketInf.IPAddr,addr,4); //设置目的IP地址 266 267 TmpSocketInf.DesPort = DesPort; //设置目的端口 268 TmpSocketInf.SourPort = SourPort; //设置源端口 269 TmpSocketInf.ProtoType = PROTO_TYPE_UDP; //设置socekt类型 270 TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf; //设置接收缓冲区的接收缓冲区 271 TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; //设置接收缓冲区的接收长度 272 i = CH57xNET_SocketCreat(&S,&TmpSocketInf); //创建socket,将返回的socket索引保存在SocketId中 273 mStopIfError(i); //检查错误 274 } 275 276 277 /******************************************************************************* 278 * Function Name : Timer0Init 279 * Description : 定时器1初始化 280 * Input : time 定时时间 281 * Output : None 282 * Return : None 283 *******************************************************************************/ 284 void Timer0Init(UINT32 time) 285 { 286 R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; //清除所有计数值 287 R8_TMR0_CTRL_MOD = 0; //设置定时器模式 288 R32_TMR0_CNT_END = FREQ_SYS/1000000*time; //设置定时时间 289 R8_TMR0_INT_FLAG = R8_TMR0_INT_FLAG; //清除标志 290 R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END; //定时中断 291 R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN; 292 NVIC_EnableIRQ(TMR0_IRQn); 293 } 294 295 /******************************************************************************* 296 * Function Name : SystemClock_UART1_init 297 * Description : 系统时钟和串口1初始化,串口1用于打印输出 298 * Input : None 299 * Output : None 300 * Return : None 301 *******************************************************************************/ 302 void SystemClock_UART1_init(void) 303 { 304 PWR_UnitModCfg(ENABLE, UNIT_SYS_PLL); //PLL上电 305 DelsyMs(3); 306 SetSysClock(CLK_SOURCE_HSE_32MHz); //外部晶振 PLL 输出32MHz 307 GPIOA_SetBits( GPIO_Pin_9 ); 308 GPIOA_ModeCfg( GPIO_Pin_9, GPIO_ModeOut_PP_5mA ); //串口1的IO口设置 309 UART1_DefInit( ); //串口1初始化 310 } 311 312 /******************************************************************************* 313 * Function Name : main 314 * Description : 主函数 315 * Input : None 316 * Output : None 317 * Return : None 318 *******************************************************************************/ 319 int main(void) 320 { 321 UINT8 ip[4],i = 0; 322 UINT8 dns_flag = 0; 323 324 SystemClock_UART1_init(); 325 i = CH57xNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr); //库初始化 326 mStopIfError(i); //检查错误 327 PRINT("CH57xNETLibInit Success\r\n"); 328 Timer0Init( 10000 ); //初始化定时器:10ms 329 NVIC_EnableIRQ(ETH_IRQn); 330 while ( CH57xInf.PHYStat < 2 ) { 331 DelsyMs(50); 332 } 333 PRINT("CH579 DNS client create!\r\n"); 334 335 while(1) 336 { 337 CH57xNET_MainTask(); //CH57xNET库主任务函数,需要在主循环中不断调用 338 if(CH57xNET_QueryGlobalInt())CH57xNET_HandleGlobalInt();//查询中断,如果有中断,则调用全局中断处理函数 339 if( dns_flag == 0 ){ 340 i = DnsQuery(SocketId,url_dn3,ip); //查询 341 if(i){ 342 dns_flag = 1; 343 if( i == 1 ){ 344 PRINT("Domain name:%s \n",url_dn3); 345 PRINT(" HTTPs_IP=%d.%d.%d.%d\n\n",ip[0],ip[1],ip[2],ip[3]); 346 } 347 } 348 } 349 } 350 } 351 352 /*********************************** endfile **********************************/
CH57xNETLibInit Success CH579 DNS client create! status = 1! GINT_STAT_PHY_CHANGE 02 2 status = 2! status = 3! Receive Len = 2c enter rece int!STATUS=3 status = 4! Domain name:www.wch.cn HTTPs_IP=58.213.45.186
TCP_Client
1 /********************************** (C) COPYRIGHT ****************************** 2 * File Name : TCP_Client.c 3 * Author : WCH 4 * Version : V1.0 5 * Date : 2018/12/01 6 * Description : CH57xNET库演示文件 7 * (1)、CH579 Examples by KEIL; 8 * (2)、串口1输出监控信息,115200bps,打开或者关闭调试信息输出在IDE宏定义中设置; 9 * (3)、本程序用于演示TCP 客户端通讯,单片机收到数据后,回传给目标IP上位机 10 *******************************************************************************/ 11 12 13 14 /******************************************************************************/ 15 /* 头文件包含*/ 16 #include <stdio.h> 17 #include <string.h> 18 #include "CH57x_common.h" 19 #include "core_cm0.h" 20 #include "CH57xNET.h" 21 22 #define KEEPLIVE_ENABLE 1 //开启KEEPLIVE功能 23 24 /* 下面的缓冲区和全局变量必须要定义,库中调用 */ 25 __align(16)UINT8 CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16]; //MAC接收描述符缓冲区,16字节对齐 26 __align(4) UINT8 CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE]; //MAC接收缓冲区,4字节对齐 27 __align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM]; //Socket信息表,4字节对齐 28 29 UINT16 MemNum[8] = {CH57xNET_NUM_IPRAW, 30 CH57xNET_NUM_UDP, 31 CH57xNET_NUM_TCP, 32 CH57xNET_NUM_TCP_LISTEN, 33 CH57xNET_NUM_TCP_SEG, 34 CH57xNET_NUM_IP_REASSDATA, 35 CH57xNET_NUM_PBUF, 36 CH57xNET_NUM_POOL_BUF 37 }; 38 UINT16 MemSize[8] = {CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IPRAW_PCB), 39 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_UDP_PCB), 40 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB), 41 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB_LISTEN), 42 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_SEG), 43 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IP_REASSDATA), 44 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(0), 45 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_POOL_BUF) 46 }; 47 __align(4)UINT8 Memp_Memory[CH57xNET_MEMP_SIZE]; 48 __align(4)UINT8 Mem_Heap_Memory[CH57xNET_RAM_HEAP_SIZE]; 49 __align(4)UINT8 Mem_ArpTable[CH57xNET_RAM_ARP_TABLE_SIZE]; 50 /******************************************************************************/ 51 /* 本演示程序的相关宏 */ 52 #define RECE_BUF_LEN 536 // 接收缓冲区的大小 53 /* CH57xNET库TCP的MSS长度为536字节,即一个TCP包里的数据部分最长为536字节 */ 54 /* TCP协议栈采用滑动窗口进行流控,窗口最大值为socket的接收缓冲区长度。在设定 */ 55 /* RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系,例如窗口值为4*MSS,则远端一次会发送 */ 56 /* 4个TCP包,如果RX_QUEUE_ENTRIES小于4,则必然会导致数据包丢失,从而导致通讯效率降低 */ 57 /* 建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据,则 */ 58 /* 建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 */ 59 /* 为了节约RAM,请将接收缓冲区的长度设置为MSS */ 60 61 /* CH579相关定义 */ 62 UINT8 MACAddr[6] ={0x84,0xc2,0xe4,0x02,0x03,0x04}; //CH579MAC地址 63 UINT8 IPAddr[4] = {192,168,1,200}; //CH579IP地址 64 UINT8 GWIPAddr[4]={192,168,1,1}; //CH579网关 65 UINT8 IPMask[4] = {255,255,255,0}; //CH579子网掩码 66 UINT8 DESIP[4] = {192,168,1,19}; //目的IP地址 67 68 UINT8 SocketId; //保存socket索引,可以不用定义 69 UINT8 SocketRecvBuf[RECE_BUF_LEN]; //socket接收缓冲区 70 UINT8 MyBuf[RECE_BUF_LEN]; //定义一个临时缓冲区 71 72 73 //extern const UINT16 *memp_num; 74 75 /******************************************************************************* 76 * Function Name : IRQ_Handler 77 * Description : IRQ中断服务函数 78 * Input : None 79 * Output : None 80 * Return : None 81 *******************************************************************************/ 82 void ETH_IRQHandler( void ) //以太网中断 83 { 84 CH57xNET_ETHIsr(); //以太网中断中断服务函数 85 } 86 87 void TMR0_IRQHandler( void ) //定时器中断 88 { 89 CH57xNET_TimeIsr(CH57xNETTIMEPERIOD); //定时器中断服务函数 90 R8_TMR0_INT_FLAG |= 0xff; //清除定时器中断标志 91 } 92 93 94 95 /******************************************************************************* 96 * Function Name : mStopIfError 97 * Description : 调试使用,显示错误代码 98 * Input : iError 错误代码 99 * Output : None 100 * Return : None 101 *******************************************************************************/ 102 void mStopIfError(UINT8 iError) 103 { 104 if (iError == CH57xNET_ERR_SUCCESS) return; //操作成功 105 PRINT("mStopIfError: %02X\r\n", (UINT16)iError); //显示错误 106 } 107 108 /******************************************************************************* 109 * Function Name : CH57xNET_CreatTcpSocket 110 * Description : 创建TCP Client socket 111 * Input : None 112 * Output : None 113 * Return : None 114 *******************************************************************************/ 115 void CH57xNET_CreatTcpSocket(void) 116 { 117 UINT8 i; 118 SOCK_INF TmpSocketInf; //创建临时socket变量 119 memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); //库内部会将此变量复制,所以最好将临时变量先全部清零 120 memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); //设置目的IP地址 121 TmpSocketInf.DesPort = 1000; 122 TmpSocketInf.SourPort = 2000; //设置源端口 123 TmpSocketInf.ProtoType = PROTO_TYPE_TCP; //设置socekt类型 124 TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf;//设置接收缓冲区的接收缓冲区 125 TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; //设置接收缓冲区的接收长度 126 i = CH57xNET_SocketCreat(&SocketId,&TmpSocketInf); //创建socket,将返回的socket索引保存在SocketId中 127 mStopIfError(i); //检查错误 128 #ifdef KEEPLIVE_ENABLE 129 CH57xNET_SocketSetKeepLive( SocketId, 1 ); //开启socket的KEEPLIVE功能(V06版本支持) 130 #endif 131 132 i = CH57xNET_SocketConnect(SocketId); //TCP连接 133 mStopIfError(i); //检查错误 134 i = CH57xNET_SetSocketTTL( SocketId,10 ); 135 mStopIfError(i); //检查错误 136 } 137 138 139 /******************************************************************************* 140 * Function Name : net_initkeeplive 141 * Description : keeplive初始化 142 * Input : None 143 * Output : None 144 * Return : None 145 *******************************************************************************/ 146 #ifdef KEEPLIVE_ENABLE 147 void net_initkeeplive(void) 148 { 149 struct _KEEP_CFG klcfg; 150 151 klcfg.KLIdle = 20000; //空闲 152 klcfg.KLIntvl = 10000; //间隔 153 klcfg.KLCount = 5; //次数 154 CH57xNET_ConfigKeepLive(&klcfg); 155 } 156 #endif 157 158 /******************************************************************************* 159 * Function Name : CH57xNET_LibInit 160 * Description : 库初始化操作 161 * Input : ip ip地址指针 162 * :gwip 网关ip地址指针 163 * : mask 掩码指针 164 * : macaddr MAC地址指针 165 * Output : None 166 * Return : 执行状态 167 *******************************************************************************/ 168 UINT8 CH57xNET_LibInit(UINT8 *ip,UINT8 *gwip,UINT8 *mask, UINT8 *macaddr) 169 { 170 UINT8 i; 171 struct _CH57x_CFG cfg; 172 173 if(CH57xNET_GetVer() != CH57xNET_LIB_VER)return 0xfc; //获取库的版本号,检查是否和头文件一致 174 CH57xNETConfig = LIB_CFG_VALUE; //将配置信息传递给库的配置变量 175 cfg.RxBufSize = RX_BUF_SIZE; 176 cfg.TCPMss = CH57xNET_TCP_MSS; 177 cfg.HeapSize = CH57x_MEM_HEAP_SIZE; 178 cfg.ARPTableNum = CH57xNET_NUM_ARP_TABLE; 179 cfg.MiscConfig0 = CH57xNET_MISC_CONFIG0; 180 CH57xNET_ConfigLIB(&cfg); 181 i = CH57xNET_Init(ip,gwip,mask,macaddr); 182 #ifdef KEEPLIVE_ENABLE 183 net_initkeeplive( ); 184 #endif 185 return (i); 186 } 187 188 /******************************************************************************* 189 * Function Name : CH57xNET_HandleSockInt 190 * Description : Socket中断处理函数 191 * Input : sockeid socket索引 192 * :initstat 中断状态 193 * Output : None 194 * Return : None 195 *******************************************************************************/ 196 void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat) 197 { 198 UINT32 len; 199 UINT32 totallen; 200 UINT8 *p = MyBuf; 201 202 if(initstat & SINT_STAT_RECV) //接收中断 203 { 204 len = CH57xNET_SocketRecvLen(sockeid,NULL); //查询长度 205 PRINT("Receive Len = %d\r\n",len); 206 totallen = len; 207 CH57xNET_SocketRecv(sockeid,MyBuf,&len); //将接收缓冲区的数据读到MyBuf中 208 while(1) 209 { 210 len = totallen; 211 CH57xNET_SocketSend(sockeid,p,&len); //将MyBuf中的数据发送 212 totallen -= len; //将总长度减去以及发送完毕的长度 213 p += len; //将缓冲区指针偏移 214 if(totallen)continue; //如果数据未发送完毕,则继续发送 215 break; //发送完毕,退出 216 } 217 } 218 if(initstat & SINT_STAT_CONNECT) //TCP连接中断 219 { //产生此中断表示TCP已经连接,可以进行收发数据 220 PRINT("TCP Connect Success\n"); 221 } 222 if(initstat & SINT_STAT_DISCONNECT) //TCP断开中断 223 { //产生此中断,CH579库内部会将此socket清除,置为关闭 224 PRINT("TCP Disconnect\n"); //应用曾需可以重新创建连接 225 226 } 227 if(initstat & SINT_STAT_TIM_OUT) //TCP超时中断 228 { //产生此中断,CH579库内部会将此socket清除,置为关闭 229 PRINT("TCP Timout\n"); //应用曾需可以重新创建连接 230 231 } 232 } 233 234 235 /******************************************************************************* 236 * Function Name : CH57xNET_HandleGloableInt 237 * Description : 全局中断处理函数 238 * Input : None 239 * Output : None 240 * Return : None 241 *******************************************************************************/ 242 void CH57xNET_HandleGlobalInt(void) 243 { 244 UINT8 initstat; 245 UINT8 i; 246 UINT8 socketinit; 247 initstat = CH57xNET_GetGlobalInt(); //读全局中断状态并清除 248 if(initstat & GINT_STAT_UNREACH) //不可达中断 249 { 250 PRINT("UnreachCode :%d\n",CH57xInf.UnreachCode); //查看不可达代码 251 PRINT("UnreachProto :%d\n",CH57xInf.UnreachProto); //查看不可达协议类型 252 PRINT("UnreachPort :%d\n",CH57xInf.UnreachPort); //查询不可达端口 253 } 254 if(initstat & GINT_STAT_IP_CONFLI) //IP冲突中断 255 { 256 257 } 258 if(initstat & GINT_STAT_PHY_CHANGE) //PHY改变中断 259 { 260 i = CH57xNET_GetPHYStatus(); //获取PHY状态 261 PRINT("GINT_STAT_PHY_CHANGE %02x\n",i); 262 } 263 if(initstat & GINT_STAT_SOCKET) //Socket中断 264 { 265 for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++) 266 { 267 socketinit = CH57xNET_GetSocketInt(i); //读socket中断并清零 268 if(socketinit)CH57xNET_HandleSockInt(i,socketinit);//如果有中断则清零 269 } 270 } 271 } 272 273 /******************************************************************************* 274 * Function Name : Timer0Init 275 * Description : 定时器1初始化 276 * Input : time 定时时间 277 * Output : None 278 * Return : None 279 *******************************************************************************/ 280 void Timer0Init(UINT32 time) 281 { 282 R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; //清除所有计数值 283 R8_TMR0_CTRL_MOD = 0; //设置定时器模式 284 R32_TMR0_CNT_END = FREQ_SYS/1000000*time; //设置定时时间 285 R8_TMR0_INT_FLAG = R8_TMR0_INT_FLAG; //清除标志 286 R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END; //定时中断 287 R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN; 288 NVIC_EnableIRQ(TMR0_IRQn); 289 } 290 291 /******************************************************************************* 292 * Function Name : SystemClock_UART1_init 293 * Description : 系统时钟和串口1初始化,串口1用于打印输出 294 * Input : None 295 * Output : None 296 * Return : None 297 *******************************************************************************/ 298 void SystemClock_UART1_init(void) 299 { 300 PWR_UnitModCfg(ENABLE, UNIT_SYS_PLL); //PLL上电 301 DelsyMs(3); 302 SetSysClock(CLK_SOURCE_HSE_32MHz); //外部晶振 PLL 输出32MHz 303 GPIOA_SetBits( GPIO_Pin_9 ); 304 GPIOA_ModeCfg( GPIO_Pin_9, GPIO_ModeOut_PP_5mA );//串口1的IO口设置 305 UART1_DefInit( ); //串口1初始化 306 } 307 308 /******************************************************************************* 309 * Function Name : main 310 * Description : 主函数 311 * Input : None 312 * Output : None 313 * Return : None 314 *******************************************************************************/ 315 int main(void) 316 { 317 UINT8 i = 0; 318 319 SystemClock_UART1_init(); 320 i = CH57xNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr); //库初始化 321 mStopIfError(i); //检查错误 322 PRINT("CH57xNETLibInit Success\r\n"); 323 Timer0Init( 10000 ); //初始化定时器:10ms 324 NVIC_EnableIRQ(ETH_IRQn); 325 while ( CH57xInf.PHYStat < 2 ) { 326 DelsyMs(50); 327 } 328 CH57xNET_CreatTcpSocket(); //创建TCP Socket 329 PRINT("CH579 TCP client create!\r\n"); 330 while(1) 331 { 332 CH57xNET_MainTask(); //CH57xNET库主任务函数,需要在主循环中不断调用 333 if(CH57xNET_QueryGlobalInt())CH57xNET_HandleGlobalInt();//查询中断,如果有中断,则调用全局中断处理函数 334 } 335 } 336 337 /*********************************** endfile **********************************/
TCP_MultipleClients
4个单片机的Socket 同时连接到 电脑服务端
1 /********************************** (C) COPYRIGHT ****************************** 2 * File Name : TCP_Client_X.c 3 * Author : WCH 4 * Version : V1.0 5 * Date : 2018/12/01 6 * Description : CH57xNET库演示文件 7 * (1)、CH579 Examples by KEIL; 8 * (2)、串口1输出监控信息,115200bps,打开或者关闭调试打印信息输出请修改CH57xNET_DBG宏定义; 9 * (3)、本程序用于演示TCP 多客户端通讯(示例为4个),单片机收到数据后,回传给目标IP上位机 10 *******************************************************************************/ 11 12 13 14 /******************************************************************************/ 15 /* 头文件包含*/ 16 #include <stdio.h> 17 #include <string.h> 18 #include "CH57x_common.h" 19 #include "core_cm0.h" 20 #include "CH57xNET.H" 21 22 #define CH57xNET_DBG 1 23 #define KEEPLIVE_ENABLE 1 //开启KEEPLIVE功能 24 25 /* 下面的缓冲区和全局变量必须要定义,库中调用 */ 26 __align(16)UINT8 CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16]; //MAC接收描述符缓冲区,16字节对齐 27 __align(4) UINT8 CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE];//MAC接收缓冲区,4字节对齐 28 __align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM]; //Socket信息表,4字节对齐 29 30 UINT16 MemNum[8] = {CH57xNET_NUM_IPRAW, 31 CH57xNET_NUM_UDP, 32 CH57xNET_NUM_TCP, 33 CH57xNET_NUM_TCP_LISTEN, 34 CH57xNET_NUM_TCP_SEG, 35 CH57xNET_NUM_IP_REASSDATA, 36 CH57xNET_NUM_PBUF, 37 CH57xNET_NUM_POOL_BUF 38 }; 39 UINT16 MemSize[8] = {CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IPRAW_PCB), 40 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_UDP_PCB), 41 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB), 42 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB_LISTEN), 43 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_SEG), 44 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IP_REASSDATA), 45 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(0), 46 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_POOL_BUF) 47 }; 48 __align(4)UINT8 Memp_Memory[CH57xNET_MEMP_SIZE]; 49 __align(4)UINT8 Mem_Heap_Memory[CH57xNET_RAM_HEAP_SIZE]; 50 __align(4)UINT8 Mem_ArpTable[CH57xNET_RAM_ARP_TABLE_SIZE]; 51 /******************************************************************************/ 52 /* 本演示程序的相关宏 */ 53 #define RECE_BUF_LEN 536 //接收缓冲区的大小 54 /* CH57xNET库TCP的MSS长度为536字节,即一个TCP包里的数据部分最长为536字节 */ 55 /* TCP协议栈采用滑动窗口进行流控,窗口最大值为socket的接收缓冲区长度。在设定 */ 56 /* RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系,例如窗口值为4*MSS,则远端一次会发送 */ 57 /* 4个TCP包,如果RX_QUEUE_ENTRIES小于4,则必然会导致数据包丢失,从而导致通讯效率降低 */ 58 /* 建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据,则 */ 59 /* 建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 */ 60 /* 为了节约RAM,请将接收缓冲区的长度设置为MSS */ 61 62 /* CH579相关定义 */ 63 UINT8 MACAddr[6]= {0x84,0xc2,0xe4,0x02,0x03,0x04};//CH579MAC地址 64 UINT8 IPAddr[4] = {192,168,1,200};//CH579IP地址 65 UINT8 GWIPAddr[4]={192,168,1,1}; //CH579网关 66 UINT8 IPMask[4] = {255,255,255,0};// CH579子网掩码 67 UINT8 DESIP[4] = {192,168,1,19}; //目的IP地址 68 69 UINT8 SocketId1;//保存socket索引,可以不用定义 70 UINT8 SocketId2;//保存socket索引,可以不用定义 71 UINT8 SocketId3;//保存socket索引,可以不用定义 72 UINT8 SocketId4; 73 74 UINT8 Socket1RecvBuf[RECE_BUF_LEN];//socket1接收缓冲区 75 UINT8 Socket2RecvBuf[RECE_BUF_LEN];//socket2接收缓冲区 76 UINT8 Socket3RecvBuf[RECE_BUF_LEN];//socket3接收缓冲区 77 UINT8 Socket4RecvBuf[RECE_BUF_LEN];//socket4接收缓冲区 78 UINT8 MyBuf[RECE_BUF_LEN];//定义一个临时缓冲区 79 80 81 82 /******************************************************************************* 83 * Function Name : IRQ_Handler 84 * Description : IRQ中断服务函数 85 * Input : None 86 * Output : None 87 * Return : None 88 *******************************************************************************/ 89 void ETH_IRQHandler( void )//以太网中断 90 { 91 CH57xNET_ETHIsr();//以太网中断中断服务函数 92 } 93 94 void TMR0_IRQHandler( void ) //定时器中断 95 { 96 CH57xNET_TimeIsr(CH57xNETTIMEPERIOD);//定时器中断服务函数 97 R8_TMR0_INT_FLAG |= 0xff;//清除定时器中断标志 98 } 99 100 101 102 /******************************************************************************* 103 * Function Name : mStopIfError 104 * Description : 调试使用,显示错误代码 105 * Input : iError 错误代码 106 * Output : None 107 * Return : None 108 *******************************************************************************/ 109 void mStopIfError(UINT8 iError) 110 { 111 if (iError == CH57xNET_ERR_SUCCESS) return; // 操作成功 112 #if CH57xNET_DBG 113 printf("mStopIfError: %02X\r\n", (UINT16)iError); //显示错误 114 #endif 115 } 116 117 118 /******************************************************************************* 119 * Function Name : CH57xNET_CreatTcpSocket 120 * Description : 创建第一个TCP Client socket 121 * Input : None 122 * Output : None 123 * Return : None 124 *******************************************************************************/ 125 void CH57xNET_CreatTcpSocket1(void) 126 { 127 UINT8 i; 128 SOCK_INF TmpSocketInf;//创建临时socket变量 129 130 memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); //库内部会将此变量复制,所以最好将临时变量先全部清零 131 memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); //设置目的IP地址 132 TmpSocketInf.DesPort = 1000; 133 TmpSocketInf.SourPort = 2000; //设置源端口 134 TmpSocketInf.ProtoType = PROTO_TYPE_TCP;//设置socekt类型 135 TmpSocketInf.RecvStartPoint = (UINT32)Socket1RecvBuf; //设置接收缓冲区的接收缓冲区 136 TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; //设置接收缓冲区的接收长度 137 i = CH57xNET_SocketCreat(&SocketId1,&TmpSocketInf);//创建socket,将返回的socket索引保存在SocketId中 138 mStopIfError(i); // 检查错误 */ 139 #ifdef KEEPLIVE_ENABLE 140 CH57xNET_SocketSetKeepLive( SocketId1, 1 ); //开启socket的KEEPLIVE功能(V06版本支持) 141 #endif 142 143 i = CH57xNET_SocketConnect(SocketId1); //TCP连接 144 mStopIfError(i); //检查错误 145 i = CH57xNET_SetSocketTTL( SocketId1,10 ); 146 mStopIfError(i); //检查错误 147 } 148 149 /******************************************************************************* 150 * Function Name : CH57xNET_CreatTcpSocket 151 * Description : 创建第二个TCP Client socket 152 * Input : None 153 * Output : None 154 * Return : None 155 *******************************************************************************/ 156 void CH57xNET_CreatTcpSocket2(void) 157 { 158 UINT8 i; 159 SOCK_INF TmpSocketInf; //创建临时socket变量 */ 160 161 memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); //库内部会将此变量复制,所以最好将临时变量先全部清零 162 memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); //设置目的IP地址 163 TmpSocketInf.DesPort = 1000; 164 TmpSocketInf.SourPort = 4000; //设置源端口 165 TmpSocketInf.ProtoType = PROTO_TYPE_TCP; //设置socekt类型 166 TmpSocketInf.RecvStartPoint = (UINT32)Socket2RecvBuf;//设置接收缓冲区的接收缓冲区 167 TmpSocketInf.RecvBufLen = RECE_BUF_LEN ;//设置接收缓冲区的接收长度 168 i = CH57xNET_SocketCreat(&SocketId2,&TmpSocketInf); // 创建socket,将返回的socket索引保存在SocketId中 169 mStopIfError(i);// 检查错误 */ 170 #ifdef KEEPLIVE_ENABLE 171 CH57xNET_SocketSetKeepLive( SocketId2, 1 ); //开启socket的KEEPLIVE功能 172 #endif 173 i = CH57xNET_SocketConnect(SocketId2); //TCP连接 174 mStopIfError(i); //检查错误 175 i = CH57xNET_SetSocketTTL( SocketId2,10 ); 176 mStopIfError(i);//检查错误 177 } 178 179 180 /******************************************************************************* 181 * Function Name : CH57xNET_CreatTcpSocket 182 * Description : 创建第二个TCP Client socket 183 * Input : None 184 * Output : None 185 * Return : None 186 *******************************************************************************/ 187 void CH57xNET_CreatTcpSocket3(void) 188 { 189 UINT8 i; 190 SOCK_INF TmpSocketInf; //创建临时socket变量 191 192 memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); //库内部会将此变量复制,所以最好将临时变量先全部清零 193 memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); //设置目的IP地址 194 TmpSocketInf.DesPort = 1000; 195 TmpSocketInf.SourPort = 6000; //设置源端口 196 TmpSocketInf.ProtoType = PROTO_TYPE_TCP;//设置socekt类型 197 TmpSocketInf.RecvStartPoint = (UINT32)Socket3RecvBuf; //设置接收缓冲区的接收缓冲区 198 TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; //设置接收缓冲区的接收长度 199 i = CH57xNET_SocketCreat(&SocketId3,&TmpSocketInf); //创建socket,将返回的socket索引保存在SocketId中 200 mStopIfError(i); //检查错误 */ 201 #ifdef KEEPLIVE_ENABLE 202 CH57xNET_SocketSetKeepLive( SocketId3, 1 ); //开启socket的KEEPLIVE功能 203 #endif 204 205 i = CH57xNET_SocketConnect(SocketId3); //TCP连接 206 mStopIfError(i); //检查错误 207 i = CH57xNET_SetSocketTTL( SocketId3,10 ); 208 mStopIfError(i);//检查错误 209 } 210 211 void CH57xNET_CreatTcpSocket4(void) 212 { 213 UINT8 i; 214 SOCK_INF TmpSocketInf; //创建临时socket变量 */ 215 216 memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF));//库内部会将此变量复制,所以最好将临时变量先全部清零 217 memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); //设置目的IP地址 218 TmpSocketInf.DesPort = 1000; 219 TmpSocketInf.SourPort = 8000; //设置源端口 220 TmpSocketInf.ProtoType = PROTO_TYPE_TCP; //设置socekt类型 221 TmpSocketInf.RecvStartPoint = (UINT32)Socket3RecvBuf; //设置接收缓冲区的接收缓冲区 222 TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; //设置接收缓冲区的接收长度 223 i = CH57xNET_SocketCreat(&SocketId4,&TmpSocketInf); //创建socket,将返回的socket索引保存在SocketId中 224 mStopIfError(i); //检查错误 */ 225 #ifdef KEEPLIVE_ENABLE 226 CH57xNET_SocketSetKeepLive( SocketId4, 1 ); //开启socket的KEEPLIVE功能 227 #endif 228 229 i = CH57xNET_SocketConnect(SocketId4); // TCP连接 230 mStopIfError(i); //检查错误 231 i = CH57xNET_SetSocketTTL( SocketId4,10 ); 232 mStopIfError(i); //检查错误 233 } 234 235 /******************************************************************************* 236 * Function Name : net_initkeeplive 237 * Description : keeplive初始化 238 * Input : None 239 * Output : None 240 * Return : None 241 *******************************************************************************/ 242 #ifdef KEEPLIVE_ENABLE 243 void net_initkeeplive(void) 244 { 245 struct _KEEP_CFG klcfg; 246 247 klcfg.KLIdle = 20000;//空闲 248 klcfg.KLIntvl = 10000;//间隔 249 klcfg.KLCount = 5; //次数 250 CH57xNET_ConfigKeepLive(&klcfg); 251 } 252 #endif 253 254 /******************************************************************************* 255 * Function Name : CH57xNET_LibInit 256 * Description : 库初始化操作 257 * Input : ip ip地址指针 258 * :gwip 网关ip地址指针 259 * : mask 掩码指针 260 * : macaddr MAC地址指针 261 * Output : None 262 * Return : 执行状态 263 *******************************************************************************/ 264 UINT8 CH57xNET_LibInit(UINT8 *ip, UINT8 *gwip, UINT8 *mask, UINT8 *macaddr) 265 { 266 UINT8 i; 267 struct _CH57x_CFG cfg; 268 269 if(CH57xNET_GetVer() != CH57xNET_LIB_VER)return 0xfc;//获取库的版本号,检查是否和头文件一致 270 CH57xNETConfig = LIB_CFG_VALUE;//将配置信息传递给库的配置变量 271 cfg.RxBufSize = RX_BUF_SIZE; 272 cfg.TCPMss = CH57xNET_TCP_MSS; 273 cfg.HeapSize = CH57x_MEM_HEAP_SIZE; 274 cfg.ARPTableNum = CH57xNET_NUM_ARP_TABLE; 275 cfg.MiscConfig0 = CH57xNET_MISC_CONFIG0; 276 CH57xNET_ConfigLIB(&cfg); 277 i = CH57xNET_Init(ip,gwip,mask,macaddr); 278 #ifdef KEEPLIVE_ENABLE 279 net_initkeeplive( ); 280 #endif 281 return (i); //库初始化 282 } 283 284 /******************************************************************************* 285 * Function Name : CH57xNET_HandleSockInt 286 * Description : Socket中断处理函数 287 * Input : sockeid socket索引 288 * :initstat 中断状态 289 * Output : None 290 * Return : None 291 *******************************************************************************/ 292 void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat) 293 { 294 UINT32 len; 295 UINT32 totallen; 296 UINT8 *p = MyBuf; 297 298 if(initstat & SINT_STAT_RECV)//接收中断 299 { 300 len = CH57xNET_SocketRecvLen(sockeid,NULL);//查询长度 301 #if CH57xNET_DBG 302 printf("Receive Len = %d\r\n",len); 303 #endif 304 totallen = len; 305 CH57xNET_SocketRecv(sockeid,MyBuf,&len);//将接收缓冲区的数据读到MyBuf中 306 while(1) 307 { 308 len = totallen; 309 CH57xNET_SocketSend(sockeid,p,&len); //将MyBuf中的数据发送 310 totallen -= len; //将总长度减去以及发送完毕的长度 311 p += len; //将缓冲区指针偏移 312 if(totallen)continue;//如果数据未发送完毕,则继续发送 313 break; //发送完毕,退出 314 } 315 } 316 if(initstat & SINT_STAT_CONNECT) //TCP连接中断 317 {//产生此中断表示TCP已经连接,可以进行收发数据 318 #if CH57xNET_DBG 319 printf("TCP Connect Success\n"); 320 #endif 321 } 322 if(initstat & SINT_STAT_DISCONNECT)//TCP断开中断 323 {//产生此中断,CH579库内部会将此socket清除,置为关闭 324 #if CH57xNET_DBG 325 printf("TCP Disconnect\n"); // 应用曾需可以重新创建连接 326 #endif 327 } 328 if(initstat & SINT_STAT_TIM_OUT) //TCP超时中断 329 {//产生此中断,CH579库内部会将此socket清除,置为关闭 330 #if CH57xNET_DBG 331 printf("TCP Timout\n"); //应用曾需可以重新创建连接 332 #endif 333 // if(sockeid==SocketId1) 334 // CH57xNET_CreatTcpSocket1(); 335 // if(sockeid==SocketId2) 336 // CH57xNET_CreatTcpSocket2(); 337 // if(sockeid==SocketId3) 338 // CH57xNET_CreatTcpSocket3(); 339 // 340 } 341 } 342 343 344 /******************************************************************************* 345 * Function Name : CH57xNET_HandleGloableInt 346 * Description : 全局中断处理函数 347 * Input : None 348 * Output : None 349 * Return : None 350 *******************************************************************************/ 351 void CH57xNET_HandleGlobalInt(void) 352 { 353 UINT8 initstat; 354 UINT8 i; 355 UINT8 socketinit; 356 initstat = CH57xNET_GetGlobalInt(); //读全局中断状态并清除 357 if(initstat & GINT_STAT_UNREACH) //不可达中断 358 { 359 #if CH57xNET_DBG 360 printf("UnreachCode :%d\n",CH57xInf.UnreachCode); //查看不可达代码 361 printf("UnreachProto :%d\n",CH57xInf.UnreachProto);//查看不可达协议类型 362 printf("UnreachPort :%d\n",CH57xInf.UnreachPort); //查询不可达端口 363 #endif 364 } 365 if(initstat & GINT_STAT_IP_CONFLI)//IP冲突中断 366 { 367 368 } 369 if(initstat & GINT_STAT_PHY_CHANGE)//PHY改变中断 370 { 371 i = CH57xNET_GetPHYStatus();//获取PHY状态 372 #if CH57xNET_DBG 373 printf("GINT_STAT_PHY_CHANGE %02x\n",i); 374 #endif 375 } 376 if(initstat & GINT_STAT_SOCKET) //Socket中断 377 { 378 for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++) 379 { 380 socketinit = CH57xNET_GetSocketInt(i);//读socket中断并清零 381 if(socketinit)CH57xNET_HandleSockInt(i,socketinit);//如果有中断则清零 382 } 383 } 384 } 385 386 387 /******************************************************************************* 388 * Function Name : Timer0Init 389 * Description : 定时器1初始化 390 * Input : time 定时时间 391 * Output : None 392 * Return : None 393 *******************************************************************************/ 394 void Timer0Init(UINT32 time) 395 { 396 R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; //清除所有计数值 397 R8_TMR0_CTRL_MOD = 0; //设置定时器模式 398 R32_TMR0_CNT_END = FREQ_SYS/1000000*time; //设置定时时间 399 R8_TMR0_INT_FLAG = R8_TMR0_INT_FLAG; //清除标志 400 R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END; //定时中断 401 R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN; 402 NVIC_EnableIRQ(TMR0_IRQn); 403 } 404 405 /******************************************************************************* 406 * Function Name : Timer0Init 407 * Description : 系统时钟和串口1初始化,串口1用于打印输出 408 * Input : None 409 * Output : None 410 * Return : None 411 *******************************************************************************/ 412 void SystemClock_UART1_init(void) 413 { 414 PWR_UnitModCfg(ENABLE, UNIT_SYS_PLL); //PLL上电 415 DelsyMs(3); 416 SetSysClock(CLK_SOURCE_HSE_32MHz);//外部晶振 PLL 输出32MHz 417 GPIOA_SetBits( GPIO_Pin_9 ); 418 GPIOA_ModeCfg( GPIO_Pin_9, GPIO_ModeOut_PP_5mA );//串口1的IO口设置 419 UART1_DefInit( ); //串口1初始化 420 } 421 422 423 /******************************************************************************* 424 * Function Name : main 425 * Description : 主函数 426 * Input : None 427 * Output : None 428 * Return : None 429 *******************************************************************************/ 430 int main(void) 431 { 432 UINT8 i = 0; 433 434 SystemClock_UART1_init(); 435 i = CH57xNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr); //库初始化 436 mStopIfError(i); //检查错误 437 438 #if CH57xNET_DBG 439 printf("CH57xNETLibInit Success\r\n"); 440 #endif 441 Timer0Init( 10000 ); //初始化定时器:10ms 442 NVIC_EnableIRQ(ETH_IRQn); //打开以太网中断 443 while ( CH57xInf.PHYStat < 2 ) DelsyMs(50); 444 CH57xNET_CreatTcpSocket1(); //创建第一个TCP Socket 445 CH57xNET_CreatTcpSocket2(); //创建第二个TCP Socket 446 CH57xNET_CreatTcpSocket3(); 447 CH57xNET_CreatTcpSocket4(); 448 449 #if CH57xNET_DBG 450 printf("CH579 TCP clients created!\r\n"); 451 #endif 452 while(1) 453 { 454 CH57xNET_MainTask(); //CH57xNET库主任务函数,需要在主循环中不断调用 455 if(CH57xNET_QueryGlobalInt())CH57xNET_HandleGlobalInt(); //查询中断,如果有中断,则调用全局中断处理函数 456 } 457 } 458 459 /*********************************** endfile **********************************/
TCP-Server
1 /********************************** (C) COPYRIGHT ****************************** 2 * File Name : TCP_server.c 3 * Author : WCH 4 * Version : V1.0 5 * Date : 2018/12/01 6 * Description : CH57xNET库演示文件 7 * (1)、CH579 Examples by KEIL; 8 * (2)、串口1输出监控信息,115200bps,打开或者关闭调试信息打印在IDE宏定义中设置; 9 * (3)、本程序用于演示TCP客户端通讯,单片机收到数据后,回传给目标IP上位机 10 *******************************************************************************/ 11 12 13 14 /******************************************************************************/ 15 /* 头文件包含*/ 16 #include <stdio.h> 17 #include <string.h> 18 #include "CH57x_common.h" 19 #include "core_cm0.h" 20 #include "CH57xNET.H" 21 22 #define KEEPLIVE_ENABLE 1 //开启KEEPLIVE功能 23 24 /* 下面的缓冲区和全局变量必须要定义,库中调用 */ 25 __align(16)UINT8 CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16]; //MAC接收描述符缓冲区,16字节对齐 26 __align(4) UINT8 CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE];//MAC接收缓冲区,4字节对齐 27 __align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM]; //Socket信息表,4字节对齐 28 29 UINT16 MemNum[8] = {CH57xNET_NUM_IPRAW, 30 CH57xNET_NUM_UDP, 31 CH57xNET_NUM_TCP, 32 CH57xNET_NUM_TCP_LISTEN, 33 CH57xNET_NUM_TCP_SEG, 34 CH57xNET_NUM_IP_REASSDATA, 35 CH57xNET_NUM_PBUF, 36 CH57xNET_NUM_POOL_BUF 37 }; 38 UINT16 MemSize[8] = {CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IPRAW_PCB), 39 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_UDP_PCB), 40 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB), 41 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB_LISTEN), 42 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_SEG), 43 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IP_REASSDATA), 44 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(0), 45 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_POOL_BUF) 46 }; 47 __align(4)UINT8 Memp_Memory[CH57xNET_MEMP_SIZE]; 48 __align(4)UINT8 Mem_Heap_Memory[CH57xNET_RAM_HEAP_SIZE]; 49 __align(4)UINT8 Mem_ArpTable[CH57xNET_RAM_ARP_TABLE_SIZE]; 50 /******************************************************************************/ 51 /* 本演示程序的相关宏 */ 52 #define RECE_BUF_LEN 536 //接收缓冲区的大小 53 /* CH57xNET库TCP的MSS长度为536字节,即一个TCP包里的数据部分最长为536字节 */ 54 /* TCP协议栈采用滑动窗口进行流控,窗口最大值为socket的接收缓冲区长度。在设定 */ 55 /* RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系,例如窗口值为4*MSS,则远端一次会发送 */ 56 /* 4个TCP包,如果RX_QUEUE_ENTRIES小于4,则必然会导致数据包丢失,从而导致通讯效率降低 */ 57 /* 建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据,则 */ 58 /* 建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 */ 59 /* 为了节约RAM,请将接收缓冲区的长度设置为MSS */ 60 61 /* CH579相关定义 */ 62 UINT8 MACAddr[6]= {0x84,0xc2,0xe4,0x02,0x03,0x04}; //CH579MAC地址 63 UINT8 IPAddr[4] = {192,168,1,200}; //CH579IP地址 64 UINT8 GWIPAddr[4]={192,168,1,1}; //CH579网关 65 UINT8 IPMask[4] = {255,255,255,0}; //CH579子网掩码 66 UINT8 DESIP[4] = {0,0,0,0}; //目的IP地址(随便填写,但不能没有) 67 68 UINT8 SocketId; //保存socket索引,可以不用定义 69 UINT8 SocketRecvBuf[4][RECE_BUF_LEN]; //socket接收缓冲区 70 UINT8 MyBuf[RECE_BUF_LEN]; //定义一个临时缓冲区 71 72 73 74 /******************************************************************************* 75 * Function Name : IRQ_Handler 76 * Description : IRQ中断服务函数 77 * Input : None 78 * Output : None 79 * Return : None 80 *******************************************************************************/ 81 void ETH_IRQHandler( void ) //以太网中断 82 { 83 CH57xNET_ETHIsr(); //以太网中断中断服务函数 84 } 85 86 void TMR0_IRQHandler( void ) //定时器中断 87 { 88 CH57xNET_TimeIsr(CH57xNETTIMEPERIOD);//定时器中断服务函数 89 R8_TMR0_INT_FLAG |= 0xff; //清除定时器中断标志 90 } 91 92 /******************************************************************************* 93 * Function Name : mStopIfError 94 * Description : 调试使用,显示错误代码 95 * Input : iError 错误代码 96 * Output : None 97 * Return : None 98 *******************************************************************************/ 99 void mStopIfError(UINT8 iError) 100 { 101 if (iError == CH57xNET_ERR_SUCCESS) return; //操作成功 102 PRINT("mStopIfError: %02X\r\n", (UINT16)iError); //显示错误 103 } 104 105 /******************************************************************************* 106 * Function Name : CH57xNET_CreatTcpSocket 107 * Description : 创建TCP Client socket 108 * Input : None 109 * Output : None 110 * Return : None 111 *******************************************************************************/ 112 void CH57xNET_CreatTcpSocket(void) 113 { 114 UINT8 i; 115 SOCK_INF TmpSocketInf; //创建临时socket变量 116 117 memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); //库内部会将此变量复制,所以最好将临时变量先全部清零 118 memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); //设置目的IP地址 119 TmpSocketInf.SourPort = 2000; //设置源端口 120 TmpSocketInf.ProtoType = PROTO_TYPE_TCP; //设置socekt类型 121 TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf;//设置接收缓冲区的接收缓冲区 122 TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; //设置接收缓冲区的接收长度 123 i = CH57xNET_SocketCreat(&SocketId,&TmpSocketInf); //创建socket,将返回的socket索引保存在SocketId中 124 mStopIfError(i); //检查错误 125 126 #ifdef KEEPLIVE_ENABLE 127 CH57xNET_SocketSetKeepLive( SocketId, 1 ); //开启socket的KEEPLIVE功能(V06版本支持) 128 #endif 129 130 i = CH57xNET_SocketListen(SocketId); //TCP连接 131 mStopIfError(i); //检查错误 132 i = CH57xNET_SetSocketTTL( SocketId,10 ); 133 mStopIfError(i); //检查错误 134 } 135 136 137 /******************************************************************************* 138 * Function Name : net_initkeeplive 139 * Description : keeplive初始化 140 * Input : None 141 * Output : None 142 * Return : None 143 *******************************************************************************/ 144 #ifdef KEEPLIVE_ENABLE 145 void net_initkeeplive(void) 146 { 147 struct _KEEP_CFG klcfg; 148 149 klcfg.KLIdle = 20000; //空闲 150 klcfg.KLIntvl = 10000; //间隔 151 klcfg.KLCount = 5; //次数 152 CH57xNET_ConfigKeepLive(&klcfg); 153 } 154 #endif 155 156 /******************************************************************************* 157 * Function Name : CH57xNET_LibInit 158 * Description : 库初始化操作 159 * Input : ip ip地址指针 160 * :gwip 网关ip地址指针 161 * : mask 掩码指针 162 * : macaddr MAC地址指针 163 * Output : None 164 * Return : 执行状态 165 *******************************************************************************/ 166 UINT8 CH57xNET_LibInit(UINT8 *ip, UINT8 *gwip,UINT8 *mask, UINT8 *macaddr) 167 { 168 UINT8 i; 169 struct _CH57x_CFG cfg; 170 171 if(CH57xNET_GetVer() != CH57xNET_LIB_VER)return 0xfc; //获取库的版本号,检查是否和头文件一致 172 CH57xNETConfig = LIB_CFG_VALUE; //将配置信息传递给库的配置变量 173 cfg.RxBufSize = RX_BUF_SIZE; 174 cfg.TCPMss = CH57xNET_TCP_MSS; 175 cfg.HeapSize = CH57x_MEM_HEAP_SIZE; 176 cfg.ARPTableNum = CH57xNET_NUM_ARP_TABLE; 177 cfg.MiscConfig0 = CH57xNET_MISC_CONFIG0; 178 CH57xNET_ConfigLIB(&cfg); 179 i = CH57xNET_Init(ip,gwip,mask,macaddr); 180 #ifdef KEEPLIVE_ENABLE 181 net_initkeeplive( ); 182 #endif 183 return (i); 184 } 185 186 /******************************************************************************* 187 * Function Name : CH57xNET_HandleSockInt 188 * Description : Socket中断处理函数 189 * Input : sockeid socket索引 190 * :initstat 中断状态 191 * Output : None 192 * Return : None 193 *******************************************************************************/ 194 void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat) 195 { 196 UINT32 len; 197 UINT32 totallen; 198 UINT8 *p = MyBuf; 199 200 if(initstat & SINT_STAT_RECV) //接收中断 201 { 202 len = CH57xNET_SocketRecvLen(sockeid,NULL);//查询长度 203 PRINT("Receive Len = %d\r\n",len); 204 totallen = len; 205 CH57xNET_SocketRecv(sockeid,MyBuf,&len);//将接收缓冲区的数据读到MyBuf中 206 while(1) 207 { 208 len = totallen; 209 CH57xNET_SocketSend(sockeid,p,&len); //将MyBuf中的数据发送 210 totallen -= len; //将总长度减去以及发送完毕的长度 211 p += len; //将缓冲区指针偏移 212 if(totallen)continue; //如果数据未发送完毕,则继续发送 213 break; //发送完毕,退出 214 } 215 } 216 if(initstat & SINT_STAT_CONNECT) //TCP连接中断 217 { //产生此中断表示TCP已经连接,可以进行收发数据 218 PRINT("TCP Connect Success\n"); 219 CH57xNET_ModifyRecvBuf(sockeid,(UINT32)SocketRecvBuf[sockeid],RECE_BUF_LEN); 220 } 221 if(initstat & SINT_STAT_DISCONNECT) //TCP断开中断 222 { //产生此中断,CH579库内部会将此socket清除,置为关闭 223 PRINT("TCP Disconnect\n"); //应用曾需可以重新创建连接 224 225 } 226 if(initstat & SINT_STAT_TIM_OUT) //TCP超时中断 227 { //产生此中断,CH579库内部会将此socket清除,置为关闭 228 PRINT("TCP Timout\n"); //应用曾需可以重新创建连接 229 230 } 231 } 232 233 /******************************************************************************* 234 * Function Name : CH57xNET_HandleGloableInt 235 * Description : 全局中断处理函数 236 * Input : None 237 * Output : None 238 * Return : None 239 *******************************************************************************/ 240 void CH57xNET_HandleGlobalInt(void) 241 { 242 UINT8 initstat; 243 UINT8 i; 244 UINT8 socketinit; 245 initstat = CH57xNET_GetGlobalInt(); //读全局中断状态并清除 246 if(initstat & GINT_STAT_UNREACH) //不可达中断 247 { 248 PRINT("UnreachCode :%d\n",CH57xInf.UnreachCode); //查看不可达代码 249 PRINT("UnreachProto :%d\n",CH57xInf.UnreachProto); //查看不可达协议类型 250 PRINT("UnreachPort :%d\n",CH57xInf.UnreachPort); //查询不可达端口 251 } 252 if(initstat & GINT_STAT_IP_CONFLI) //IP冲突中断 253 { 254 255 } 256 if(initstat & GINT_STAT_PHY_CHANGE) //PHY改变中断 257 { 258 i = CH57xNET_GetPHYStatus(); //获取PHY状态 259 PRINT("GINT_STAT_PHY_CHANGE %02x\n",i); 260 } 261 if(initstat & GINT_STAT_SOCKET) //Socket中断 262 { 263 for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++) 264 { 265 socketinit = CH57xNET_GetSocketInt(i); //读socket中断并清零 266 if(socketinit)CH57xNET_HandleSockInt(i,socketinit);//如果有中断则清零 267 } 268 } 269 } 270 271 /******************************************************************************* 272 * Function Name : Timer0Init 273 * Description : 定时器1初始化 274 * Input : time 定时时间 275 * Output : None 276 * Return : None 277 *******************************************************************************/ 278 void Timer0Init(UINT32 time) 279 { 280 R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; //清除所有计数值 281 R8_TMR0_CTRL_MOD = 0; //设置定时器模式 282 R32_TMR0_CNT_END = FREQ_SYS/1000000*time; //设置定时时间 283 R8_TMR0_INT_FLAG = R8_TMR0_INT_FLAG; //清除标志 284 R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END; //定时中断 285 R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN; 286 NVIC_EnableIRQ(TMR0_IRQn); 287 } 288 289 /******************************************************************************* 290 * Function Name : SystemClock_UART1_init 291 * Description : 系统时钟和串口1初始化,串口1用于打印输出 292 * Input : None 293 * Output : None 294 * Return : None 295 *******************************************************************************/ 296 void SystemClock_UART1_init(void) 297 { 298 PWR_UnitModCfg(ENABLE, UNIT_SYS_PLL); //PLL上电 299 DelsyMs(3); 300 SetSysClock(CLK_SOURCE_HSE_32MHz); //外部晶振 PLL 输出32MHz 301 GPIOA_SetBits( GPIO_Pin_9 ); 302 GPIOA_ModeCfg( GPIO_Pin_9, GPIO_ModeOut_PP_5mA ); //串口1的IO口设置 303 UART1_DefInit( ); //串口1初始化 304 } 305 306 /******************************************************************************* 307 * Function Name : main 308 * Description : 主函数 309 * Input : None 310 * Output : None 311 * Return : None 312 *******************************************************************************/ 313 int main(void) 314 { 315 UINT8 i = 0; 316 317 SystemClock_UART1_init(); //系统时钟和串口1初始化 318 i = CH57xNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr); //库初始化 319 mStopIfError(i); //检查错误 320 PRINT("CH57xNETLibInit Success\r\n"); 321 Timer0Init( 10000 ); //初始化定时器:10ms 322 NVIC_EnableIRQ(ETH_IRQn); 323 while ( CH57xInf.PHYStat < 2 ) { 324 DelsyMs(50); 325 } 326 CH57xNET_CreatTcpSocket(); //创建TCP Socket 327 PRINT("CH579 TCP server create!\r\n"); 328 while(1) 329 { 330 CH57xNET_MainTask(); //CH57xNET库主任务函数,需要在主循环中不断调用 331 if(CH57xNET_QueryGlobalInt())CH57xNET_HandleGlobalInt(); //查询中断,如果有中断,则调用全局中断处理函数 332 } 333 } 334 /*********************************** endfile **********************************/
udp-Client
1 /********************************** (C) COPYRIGHT ****************************** 2 * File Name : UDP_Client.c 3 * Author : WCH 4 * Version : V1.0 5 * Date : 2018/12/01 6 * Description : CH57xNET库演示文件 7 * (1)、CH579 Examples by KEIL; 8 * (2)、串口1输出监控信息,115200bps; 9 * (3)、本程序用于演示UDP 客户端通讯,单片机收到数据后,回传给目标IP上位机 10 * (4)、打开\关闭调试信息打印在IDE宏定义中设置 11 *******************************************************************************/ 12 13 14 15 /******************************************************************************/ 16 /* 头文件包含*/ 17 #include <stdio.h> 18 #include <string.h> 19 #include "CH57x_common.h" 20 #include "core_cm0.h" 21 #include "CH57xNET.H" 22 23 #define KEEPLIVE_ENABLE 1 //开启KEEPLIVE功能 24 25 /* 下面的缓冲区和全局变量必须要定义,库中调用 */ 26 __align(16)UINT8 CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16]; //MAC接收描述符缓冲区,16字节对齐 27 __align(4) UINT8 CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE];//MAC接收缓冲区,4字节对齐 28 __align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM]; //Socket信息表,4字节对齐 29 30 UINT16 MemNum[8] = {CH57xNET_NUM_IPRAW, 31 CH57xNET_NUM_UDP, 32 CH57xNET_NUM_TCP, 33 CH57xNET_NUM_TCP_LISTEN, 34 CH57xNET_NUM_TCP_SEG, 35 CH57xNET_NUM_IP_REASSDATA, 36 CH57xNET_NUM_PBUF, 37 CH57xNET_NUM_POOL_BUF 38 }; 39 UINT16 MemSize[8] = {CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IPRAW_PCB), 40 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_UDP_PCB), 41 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB), 42 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB_LISTEN), 43 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_SEG), 44 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IP_REASSDATA), 45 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(0), 46 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_POOL_BUF) 47 }; 48 __align(4)UINT8 Memp_Memory[CH57xNET_MEMP_SIZE]; 49 __align(4)UINT8 Mem_Heap_Memory[CH57xNET_RAM_HEAP_SIZE]; 50 __align(4)UINT8 Mem_ArpTable[CH57xNET_RAM_ARP_TABLE_SIZE]; 51 /******************************************************************************/ 52 /* 本演示程序的相关宏 */ 53 #define RECE_BUF_LEN 536 //接收缓冲区的大小 54 /* CH57xNET库TCP的MSS长度为536字节,即一个TCP包里的数据部分最长为536字节 */ 55 /* TCP协议栈采用滑动窗口进行流控,窗口最大值为socket的接收缓冲区长度。在设定 */ 56 /* RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系,例如窗口值为4*MSS,则远端一次会发送 */ 57 /* 4个TCP包,如果RX_QUEUE_ENTRIES小于4,则必然会导致数据包丢失,从而导致通讯效率降低 */ 58 /* 建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据,则 */ 59 /* 建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 */ 60 /* 为了节约RAM,请将接收缓冲区的长度设置为MSS */ 61 62 /* CH579相关定义 */ 63 UINT8 MACAddr[6] = {0x84,0xc2,0xe4,0x02,0x03,0x04}; //CH579MAC地址 64 UINT8 IPAddr[4] = {192,168,1,200}; //CH579IP地址 65 UINT8 GWIPAddr[4]= {192,168,1,1}; //CH579网关 66 UINT8 IPMask[4] = {255,255,255,0}; //CH579子网掩码 67 UINT8 DESIP[4] = {192,168,1,19}; //目的IP地址 电脑 68 69 UINT8 SocketId; //保存socket索引,可以不用定义 70 UINT8 SocketRecvBuf[RECE_BUF_LEN]; //socket接收缓冲区 71 UINT8 MyBuf[RECE_BUF_LEN]; //定义一个临时缓冲区 72 73 74 75 /******************************************************************************* 76 * Function Name : IRQ_Handler 77 * Description : IRQ中断服务函数 78 * Input : None 79 * Output : None 80 * Return : None 81 *******************************************************************************/ 82 void ETH_IRQHandler( void ) //以太网中断 83 { 84 CH57xNET_ETHIsr(); //以太网中断中断服务函数 85 } 86 87 void TMR0_IRQHandler( void ) //定时器中断 88 { 89 CH57xNET_TimeIsr(CH57xNETTIMEPERIOD); //定时器中断服务函数 90 R8_TMR0_INT_FLAG |= 0xff; //清除定时器中断标志 91 } 92 93 94 95 /******************************************************************************* 96 * Function Name : mStopIfError 97 * Description : 调试使用,显示错误代码 98 * Input : iError 错误代码 99 * Output : None 100 * Return : None 101 *******************************************************************************/ 102 void mStopIfError(UINT8 iError) 103 { 104 if (iError == CH57xNET_ERR_SUCCESS) return; //操作成功 105 PRINT("mStopIfError: %02X\r\n", (UINT16)iError); //显示错误 106 } 107 108 /******************************************************************************* 109 * Function Name : CH57xNET_CreatUpdSocket 110 * Description : 创建UDP socket 111 * Input : None 112 * Output : None 113 * Return : None 114 *******************************************************************************/ 115 void CH57xNET_CreatUdpSocket(void) 116 { 117 UINT8 i; 118 SOCK_INF TmpSocketInf; //创建临时socket变量 119 120 memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); //库内部会将此变量复制,所以最好将临时变量先全部清零 121 memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); //设置目的IP地址 122 TmpSocketInf.DesPort = 1000; //设置目的端口 123 TmpSocketInf.SourPort = 2000; //设置源端口 124 TmpSocketInf.ProtoType = PROTO_TYPE_UDP; //设置socekt类型 125 TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf; //设置接收缓冲区的接收缓冲区 126 TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; //设置接收缓冲区的接收长度 127 i = CH57xNET_SocketCreat(&SocketId,&TmpSocketInf); //创建socket,将返回的socket索引保存在SocketId中 128 mStopIfError(i); //检查错误 129 } 130 131 /******************************************************************************* 132 * Function Name : net_initkeeplive 133 * Description : keeplive初始化 134 * Input : None 135 * Output : None 136 * Return : None 137 *******************************************************************************/ 138 #ifdef KEEPLIVE_ENABLE 139 void net_initkeeplive(void) 140 { 141 struct _KEEP_CFG klcfg; 142 143 klcfg.KLIdle = 20000; //空闲 144 klcfg.KLIntvl = 10000; //间隔 145 klcfg.KLCount = 5; //次数 146 CH57xNET_ConfigKeepLive(&klcfg); 147 } 148 #endif 149 150 /******************************************************************************* 151 * Function Name : CH57xNET_LibInit 152 * Description : 库初始化操作 153 * Input : ip ip地址指针 154 * :gwip 网关ip地址指针 155 * : mask 掩码指针 156 * : macaddr MAC地址指针 157 * Output : None 158 * Return : 执行状态 159 *******************************************************************************/ 160 UINT8 CH57xNET_LibInit(UINT8 *ip,UINT8 *gwip,UINT8 *mask,UINT8 *macaddr) 161 { 162 UINT8 i; 163 struct _CH57x_CFG cfg; 164 165 if(CH57xNET_GetVer() != CH57xNET_LIB_VER)return 0xfc; //获取库的版本号,检查是否和头文件一致 166 CH57xNETConfig = LIB_CFG_VALUE; //将配置信息传递给库的配置变量 167 cfg.RxBufSize = RX_BUF_SIZE; 168 cfg.TCPMss = CH57xNET_TCP_MSS; 169 cfg.HeapSize = CH57x_MEM_HEAP_SIZE; 170 cfg.ARPTableNum = CH57xNET_NUM_ARP_TABLE; 171 cfg.MiscConfig0 = CH57xNET_MISC_CONFIG0; 172 CH57xNET_ConfigLIB(&cfg); 173 i = CH57xNET_Init(ip,gwip,mask,macaddr); 174 #ifdef KEEPLIVE_ENABLE 175 net_initkeeplive( ); 176 #endif 177 return (i); 178 } 179 180 /******************************************************************************* 181 * Function Name : CH57xNET_HandleSockInt 182 * Description : Socket中断处理函数 183 * Input : sockeid socket索引 184 * :initstat 中断状态 185 * Output : None 186 * Return : None 187 *******************************************************************************/ 188 void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat) 189 { 190 UINT32 len; 191 UINT32 totallen; 192 UINT8 *p = MyBuf; 193 194 if(initstat & SINT_STAT_RECV) //接收中断 195 { 196 len = CH57xNET_SocketRecvLen(sockeid,NULL);//查询长度 197 PRINT("Receive Len = %d\r\n",len); 198 totallen = len; 199 CH57xNET_SocketRecv(sockeid,MyBuf,&len); //将接收缓冲区的数据读到MyBuf中 200 while(1) 201 { 202 len = totallen; 203 CH57xNET_SocketSend(sockeid,p,&len); //将MyBuf中的数据发送 204 totallen -= len; //将总长度减去以及发送完毕的长度 205 p += len; //将缓冲区指针偏移 206 if(totallen)continue; //如果数据未发送完毕,则继续发送 207 break; //发送完毕,退出 208 } 209 } 210 if(initstat & SINT_STAT_CONNECT) //TCP连接中断 211 { //产生此中断表示TCP已经连接,可以进行收发数据 212 PRINT("TCP Connect Success\n"); 213 } 214 if(initstat & SINT_STAT_DISCONNECT) //TCP断开中断 215 { //产生此中断,CH579库内部会将此socket清除,置为关闭 216 PRINT("TCP Disconnect\n"); //应用曾需可以重新创建连接 217 } 218 if(initstat & SINT_STAT_TIM_OUT) //TCP超时中断 219 { //产生此中断,CH579库内部会将此socket清除,置为关闭 220 PRINT("TCP Timout\n"); //应用曾需可以重新创建连接 221 } 222 } 223 224 225 /******************************************************************************* 226 * Function Name : CH57xNET_HandleGloableInt 227 * Description : 全局中断处理函数 228 * Input : None 229 * Output : None 230 * Return : None 231 *******************************************************************************/ 232 void CH57xNET_HandleGlobalInt(void) 233 { 234 UINT8 initstat; 235 UINT8 i; 236 UINT8 socketinit; 237 initstat = CH57xNET_GetGlobalInt(); //读全局中断状态并清除 238 if(initstat & GINT_STAT_UNREACH) //不可达中断 239 { 240 PRINT("UnreachCode :%d\n",CH57xInf.UnreachCode); //查看不可达代码 241 PRINT("UnreachProto :%d\n",CH57xInf.UnreachProto); //查看不可达协议类型 242 PRINT("UnreachPort :%d\n",CH57xInf.UnreachPort); //查询不可达端口 243 } 244 if(initstat & GINT_STAT_IP_CONFLI) //IP冲突中断 245 { 246 247 } 248 if(initstat & GINT_STAT_PHY_CHANGE) //PHY改变中断 249 { 250 i = CH57xNET_GetPHYStatus(); //获取PHY状态 251 PRINT("GINT_STAT_PHY_CHANGE %02x\n",i); 252 } 253 if(initstat & GINT_STAT_SOCKET) //Socket中断 254 { 255 for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++) 256 { 257 socketinit = CH57xNET_GetSocketInt(i); //读socket中断并清零 258 if(socketinit)CH57xNET_HandleSockInt(i,socketinit); //如果有中断则清零 259 } 260 } 261 } 262 263 /******************************************************************************* 264 * Function Name : Timer0Init 265 * Description : 定时器1初始化 266 * Input : time 定时时间 267 * Output : None 268 * Return : None 269 *******************************************************************************/ 270 void Timer0Init(UINT32 time) 271 { 272 R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; //清除所有计数值 273 R8_TMR0_CTRL_MOD = 0; //设置定时器模式 274 R32_TMR0_CNT_END = FREQ_SYS/1000000*time; //设置定时时间 275 R8_TMR0_INT_FLAG = R8_TMR0_INT_FLAG; //清除标志 276 R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END; //定时中断 277 R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN; 278 NVIC_EnableIRQ(TMR0_IRQn); 279 } 280 281 /******************************************************************************* 282 * Function Name : SystemClock_UART1_init 283 * Description : 系统时钟和串口1初始化,串口1用于打印输出 284 * Input : None 285 * Output : None 286 * Return : None 287 *******************************************************************************/ 288 void SystemClock_UART1_init(void) 289 { 290 PWR_UnitModCfg(ENABLE, UNIT_SYS_PLL); //PLL上电 291 DelsyMs(3); 292 SetSysClock(CLK_SOURCE_HSE_32MHz); //外部晶振 PLL 输出32MHz 293 GPIOA_SetBits( GPIO_Pin_9 ); 294 GPIOA_ModeCfg( GPIO_Pin_9, GPIO_ModeOut_PP_5mA );//串口1的IO口设置 295 UART1_DefInit( ); //串口1初始化 296 } 297 298 /******************************************************************************* 299 * Function Name : main 300 * Description : 主函数 301 * Input : None 302 * Output : None 303 * Return : None 304 *******************************************************************************/ 305 int main(void) 306 { 307 UINT8 i = 0; 308 309 SystemClock_UART1_init(); 310 i = CH57xNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr); //库初始化 311 mStopIfError(i); //检查错误 312 PRINT("CH57xNETLibInit Success\r\n"); 313 Timer0Init( 10000 ); //初始化定时器:10ms 314 NVIC_EnableIRQ(ETH_IRQn); 315 while ( CH57xInf.PHYStat < 2 ) { 316 DelsyMs(50); 317 } 318 CH57xNET_CreatUdpSocket(); //创建TCP Socket 319 PRINT("CH579 UDP socket create!\r\n"); 320 while(1) 321 { 322 CH57xNET_MainTask(); //CH57xNET库主任务函数,需要在主循环中不断调用 323 if(CH57xNET_QueryGlobalInt())CH57xNET_HandleGlobalInt(); //查询中断,如果有中断,则调用全局中断处理函数 324 } 325 } 326 327 /*********************************** endfile **********************************/
UDP_Server
1 /********************************** (C) COPYRIGHT ****************************** 2 * File Name : UDP_Server.c 3 * Author : WCH 4 * Version : V1.0 5 * Date : 2018/12/01 6 * Description : CH57xNET库演示文件 7 * (1)、CH579 Examples by KEIL; 8 * (2)、串口1输出监控信息,115200bps,打开或关闭调试信息打印在IDE宏定义中设置; 9 * (3)、本程序用于演示UDP 服务器通讯,单片机收到数据后,回传给数据源IP地址的上位机 10 *******************************************************************************/ 11 12 13 14 /******************************************************************************/ 15 /* 头文件包含*/ 16 #include <stdio.h> 17 #include <string.h> 18 #include "CH57x_common.h" 19 #include "core_cm0.h" 20 #include "CH57xNET.h" 21 22 #define KEEPLIVE_ENABLE 1 //开启KEEPLIVE功能 23 24 /* 下面的缓冲区和全局变量必须要定义,库中调用 */ 25 __align(16)UINT8 CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16]; //MAC接收描述符缓冲区,16字节对齐 26 __align(4) UINT8 CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE];//MAC接收缓冲区,4字节对齐 27 __align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM]; //Socket信息表,4字节对齐 28 29 UINT16 MemNum[8] = {CH57xNET_NUM_IPRAW, 30 CH57xNET_NUM_UDP, 31 CH57xNET_NUM_TCP, 32 CH57xNET_NUM_TCP_LISTEN, 33 CH57xNET_NUM_TCP_SEG, 34 CH57xNET_NUM_IP_REASSDATA, 35 CH57xNET_NUM_PBUF, 36 CH57xNET_NUM_POOL_BUF 37 }; 38 UINT16 MemSize[8] = {CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IPRAW_PCB), 39 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_UDP_PCB), 40 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB), 41 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB_LISTEN), 42 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_SEG), 43 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IP_REASSDATA), 44 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(0), 45 CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_POOL_BUF) 46 }; 47 __align(4)UINT8 Memp_Memory[CH57xNET_MEMP_SIZE]; 48 __align(4)UINT8 Mem_Heap_Memory[CH57xNET_RAM_HEAP_SIZE]; 49 __align(4)UINT8 Mem_ArpTable[CH57xNET_RAM_ARP_TABLE_SIZE]; 50 /******************************************************************************/ 51 /* 本演示程序的相关宏 */ 52 #define RECE_BUF_LEN 536 //接收缓冲区的大小 53 /* CH57xNET库TCP的MSS长度为536字节,即一个TCP包里的数据部分最长为536字节 */ 54 /* TCP协议栈采用滑动窗口进行流控,窗口最大值为socket的接收缓冲区长度。在设定 */ 55 /* RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系,例如窗口值为4*MSS,则远端一次会发送 */ 56 /* 4个TCP包,如果RX_QUEUE_ENTRIES小于4,则必然会导致数据包丢失,从而导致通讯效率降低 */ 57 /* 建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据,则 */ 58 /* 建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 */ 59 /* 为了节约RAM,请将接收缓冲区的长度设置为MSS */ 60 61 /* CH579相关定义 */ 62 UINT8 MACAddr[6] = {0x84,0xc2,0xe4,0x02,0x03,0x04}; //CH579MAC地址 63 UINT8 IPAddr[4] = {192,168,1,200}; //CH579IP地址 64 UINT8 GWIPAddr[4]= {192,168,1,1}; //CH579网关 65 UINT8 IPMask[4] = {255,255,255,0}; //CH579子网掩码 66 UINT8 DESIP[4] = {255,255,255,255}; //接收广播包,此地址不应更变 67 68 UINT8 SocketId; //保存socket索引,可以不用定义 69 UINT8 SocketRecvBuf[RECE_BUF_LEN]; //socket接收缓冲区 70 UINT8 MyBuf[RECE_BUF_LEN]; //定义一个临时缓冲区 71 72 73 74 /******************************************************************************* 75 * Function Name : IRQ_Handler 76 * Description : IRQ中断服务函数 77 * Input : None 78 * Output : None 79 * Return : None 80 *******************************************************************************/ 81 void ETH_IRQHandler( void ) //以太网中断 82 { 83 CH57xNET_ETHIsr(); //以太网中断中断服务函数 84 } 85 86 void TMR0_IRQHandler( void ) //定时器中断 87 { 88 CH57xNET_TimeIsr(CH57xNETTIMEPERIOD); //定时器中断服务函数 89 R8_TMR0_INT_FLAG |= 0xff; //清除定时器中断标志 90 } 91 92 /******************************************************************************* 93 * Function Name : mStopIfError 94 * Description : 调试使用,显示错误代码 95 * Input : iError 错误代码 96 * Output : None 97 * Return : None 98 *******************************************************************************/ 99 void mStopIfError(UINT8 iError) 100 { 101 if (iError == CH57xNET_ERR_SUCCESS) return; //操作成功 102 PRINT("mStopIfError: %02X\r\n", (UINT16)iError); //显示错误 103 } 104 105 /******************************************************************************* 106 * Function Name : CH57xNET_CreatUdpSocket 107 * Description : 接收udp数据并处理 108 * Input : None 109 * Output : None 110 * Return : None 111 *******************************************************************************/ 112 void CH57xNET_UdpServerRecv(struct _SCOK_INF *socinf,UINT32 ipaddr,UINT16 port,UINT8 *buf,UINT32 len) 113 { 114 UINT8 ip_addr[4],i; 115 PRINT("ipaddr=%-8x port=%-8d len=%-8d socketid=%-4d\r\n",ipaddr,port,len,socinf->SockIndex); 116 for(i=0;i<4;i++){ 117 ip_addr[i] = ipaddr&0xff; 118 PRINT("%-4d",ip_addr[i]); 119 ipaddr = ipaddr>>8; 120 } 121 CH57xNET_SocketUdpSendTo( socinf->SockIndex,buf,&len,ip_addr,port); 122 } 123 124 /******************************************************************************* 125 * Function Name : CH57xNET_CreatUpdSocket 126 * Description : 创建UDP socket 127 * Input : None 128 * Output : None 129 * Return : None 130 *******************************************************************************/ 131 void CH57xNET_CreatUdpSocket(void) 132 { 133 UINT8 i; 134 SOCK_INF TmpSocketInf; //创建临时socket变量 135 memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); //库内部会将此变量复制,所以最好将临时变量先全部清零 136 memcpy((void *)TmpSocketInf.IPAddr,DESIP,4); //设置目的IP地址 137 TmpSocketInf.DesPort = 2000; //设置目的端口 138 TmpSocketInf.SourPort = 2000; //设置源端口 139 TmpSocketInf.ProtoType = PROTO_TYPE_UDP; //设置socekt类型 140 TmpSocketInf.AppCallBack = CH57xNET_UdpServerRecv; //接收回调函数 141 TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf;//设置接收缓冲区的接收缓冲区 142 TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; //设置接收缓冲区的接收长度 143 i = CH57xNET_SocketCreat(&SocketId,&TmpSocketInf); //创建socket,将返回的socket索引保存在SocketId中 144 mStopIfError(i); //检查错误 145 } 146 147 /******************************************************************************* 148 * Function Name : net_initkeeplive 149 * Description : keeplive初始化 150 * Input : None 151 * Output : None 152 * Return : None 153 *******************************************************************************/ 154 #ifdef KEEPLIVE_ENABLE 155 void net_initkeeplive(void) 156 { 157 struct _KEEP_CFG klcfg; 158 159 klcfg.KLIdle = 20000; //空闲 160 klcfg.KLIntvl = 10000; //间隔 161 klcfg.KLCount = 5; //次数 162 CH57xNET_ConfigKeepLive(&klcfg); 163 } 164 #endif 165 166 /******************************************************************************* 167 * Function Name : CH57xNET_LibInit 168 * Description : 库初始化操作 169 * Input : ip ip地址指针 170 * :gwip 网关ip地址指针 171 * : mask 掩码指针 172 * : macaddr MAC地址指针 173 * Output : None 174 * Return : 执行状态 175 *******************************************************************************/ 176 UINT8 CH57xNET_LibInit(UINT8 *ip,UINT8 *gwip,UINT8 *mask,UINT8 *macaddr) 177 { 178 UINT8 i; 179 struct _CH57x_CFG cfg; 180 181 if(CH57xNET_GetVer() != CH57xNET_LIB_VER)return 0xfc;//获取库的版本号,检查是否和头文件一致 182 CH57xNETConfig = LIB_CFG_VALUE; //将配置信息传递给库的配置变量 183 cfg.RxBufSize = RX_BUF_SIZE; 184 cfg.TCPMss = CH57xNET_TCP_MSS; 185 cfg.HeapSize = CH57x_MEM_HEAP_SIZE; 186 cfg.ARPTableNum = CH57xNET_NUM_ARP_TABLE; 187 cfg.MiscConfig0 = CH57xNET_MISC_CONFIG0; 188 CH57xNET_ConfigLIB(&cfg); 189 i = CH57xNET_Init(ip,gwip,mask,macaddr); 190 #ifdef KEEPLIVE_ENABLE 191 net_initkeeplive( ); 192 #endif 193 return (i); 194 } 195 196 /******************************************************************************* 197 * Function Name : CH57xNET_HandleSockInt 198 * Description : Socket中断处理函数 199 * Input : sockeid socket索引 200 * :initstat 中断状态 201 * Output : None 202 * Return : None 203 *******************************************************************************/ 204 void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat) 205 { 206 UINT32 len; 207 UINT32 totallen; 208 UINT8 *p = MyBuf; 209 210 if(initstat & SINT_STAT_RECV) //接收中断 211 { 212 len = CH57xNET_SocketRecvLen(sockeid,NULL);//会将当前接收指针传递给precv 213 PRINT("Receive Len = %02x\n",len); 214 totallen = len; 215 CH57xNET_SocketRecv(sockeid,MyBuf,&len); //将接收缓冲区的数据读到MyBuf中 216 while(1) 217 { 218 len = totallen; 219 CH57xNET_SocketSend(sockeid,p,&len); //将MyBuf中的数据发送 220 totallen -= len; //将总长度减去以及发送完毕的长度 221 p += len; //将缓冲区指针偏移 222 if(totallen)continue; //如果数据未发送完毕,则继续发送 223 break; //发送完毕,退出 224 } 225 } 226 if(initstat & SINT_STAT_CONNECT) //TCP连接中断 227 { //产生此中断表示TCP已经连接,可以进行收发数据 228 PRINT("TCP Connect Success\n"); 229 } 230 if(initstat & SINT_STAT_DISCONNECT) //TCP断开中断 231 { //产生此中断,CH579库内部会将此socket清除,置为关闭 232 PRINT("TCP Disconnect\n"); //应用曾需可以重新创建连接 233 } 234 if(initstat & SINT_STAT_TIM_OUT) //TCP超时中断 235 { //产生此中断,CH579库内部会将此socket清除,置为关闭 236 PRINT("TCP Timout\n"); //应用曾需可以重新创建连接 237 } 238 } 239 240 /******************************************************************************* 241 * Function Name : CH57xNET_HandleGloableInt 242 * Description : 全局中断处理函数 243 * Input : None 244 * Output : None 245 * Return : None 246 *******************************************************************************/ 247 void CH57xNET_HandleGlobalInt(void) 248 { 249 UINT8 initstat; 250 UINT8 i; 251 UINT8 socketinit; 252 initstat = CH57xNET_GetGlobalInt(); //读全局中断状态并清除 253 if(initstat & GINT_STAT_UNREACH) //不可达中断 254 { 255 PRINT("UnreachCode :%d\n",CH57xInf.UnreachCode); //查看不可达代码 256 PRINT("UnreachProto :%d\n",CH57xInf.UnreachProto);//查看不可达协议类型 257 PRINT("UnreachPort :%d\n",CH57xInf.UnreachPort); //查询不可达端口 258 } 259 if(initstat & GINT_STAT_IP_CONFLI) //IP冲突中断 260 { 261 262 } 263 if(initstat & GINT_STAT_PHY_CHANGE) //PHY改变中断 264 { 265 i = CH57xNET_GetPHYStatus(); //获取PHY状态 266 PRINT("GINT_STAT_PHY_CHANGE %02x\n",i); 267 } 268 if(initstat & GINT_STAT_SOCKET) //Socket中断 269 { 270 for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++) 271 { 272 socketinit = CH57xNET_GetSocketInt(i); //读socket中断并清零 273 if(socketinit)CH57xNET_HandleSockInt(i,socketinit); //如果有中断则清零 274 } 275 } 276 } 277 278 /******************************************************************************* 279 * Function Name : Timer0Init 280 * Description : 定时器1初始化 281 * Input : time 定时时间 282 * Output : None 283 * Return : None 284 *******************************************************************************/ 285 void Timer0Init(UINT32 time) 286 { 287 R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; //清除所有计数值 288 R8_TMR0_CTRL_MOD = 0; //设置定时器模式 289 R32_TMR0_CNT_END = FREQ_SYS/1000000*time;//设置定时时间 290 R8_TMR0_INT_FLAG = R8_TMR0_INT_FLAG; //清除标志 291 R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END; //定时中断 292 R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN; 293 NVIC_EnableIRQ(TMR0_IRQn); 294 } 295 296 /******************************************************************************* 297 * Function Name : SystemClock_UART1_init 298 * Description : 系统时钟和串口1初始化,串口1用于打印输出 299 * Input : None 300 * Output : None 301 * Return : None 302 *******************************************************************************/ 303 void SystemClock_UART1_init(void) 304 { 305 PWR_UnitModCfg(ENABLE, UNIT_SYS_PLL); //PLL上电 306 DelsyMs(3); 307 SetSysClock(CLK_SOURCE_HSE_32MHz); //外部晶振 PLL 输出32MHz 308 GPIOA_SetBits( GPIO_Pin_9 ); 309 GPIOA_ModeCfg( GPIO_Pin_9, GPIO_ModeOut_PP_5mA ); //串口1的IO口设置 310 UART1_DefInit( ); //串口1初始化 311 } 312 313 /******************************************************************************* 314 * Function Name : main 315 * Description : 主函数 316 * Input : None 317 * Output : None 318 * Return : None 319 *******************************************************************************/ 320 int main(void) 321 { 322 UINT8 i = 0; 323 324 SystemClock_UART1_init(); //系统时钟和串口1初始化 325 i = CH57xNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr); //库初始化 326 mStopIfError(i); //检查错误 327 PRINT("CH57xNETLibInit Success\r\n"); 328 Timer0Init( 10000 ); //初始化定时器:10ms 329 NVIC_EnableIRQ(ETH_IRQn); 330 331 while ( CH57xInf.PHYStat < 2 ) { 332 DelsyMs(50); 333 } 334 CH57xNET_CreatUdpSocket(); //创建TCP Socket 335 PRINT("CH579 UDP socket create!\r\n"); 336 while(1) 337 { 338 CH57xNET_MainTask(); //CH57xNET库主任务函数,需要在主循环中不断调用 339 if(CH57xNET_QueryGlobalInt())CH57xNET_HandleGlobalInt(); //查询中断,如果有中断,则调用全局中断处理函数 340 } 341 } 342 /*********************************** endfile **********************************/