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 **********************************/

 

posted @ 2020-03-05 13:54  kingboy100  阅读(1057)  评论(0编辑  收藏  举报