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