1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// ******* UDP *******
#define UDP_HEADER_LEN 8 //源端口位置 #define UDP_SRC_PORT_H_P 0x22 #define UDP_SRC_PORT_L_P 0x23 //目標端口位置 #define UDP_DST_PORT_H_P 0x24 #define UDP_DST_PORT_L_P 0x25 //UDP數據長度位置 #define UDP_LEN_H_P 0x26 #define UDP_LEN_L_P 0x27 //UDP校驗和位置 #define UDP_CHECKSUM_H_P 0x28 #define UDP_CHECKSUM_L_P 0x29 //UDP數據起始地址 #define UDP_DATA_P 0x2a |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
void make_udp_reply_from_request(unsigned char *buf, char *data, unsigned int datalen, unsigned int port)
{ unsigned int i = 0, tol_len; unsigned int ck; //如前面的ARP和ICMP一樣的 make_eth(buf); // total length field in the IP header must be set: //如IP Header tol_len = IP_HEADER_LEN + UDP_HEADER_LEN + datalen; buf[IP_TOTLEN_H_P] = tol_len >> 8; buf[IP_TOTLEN_L_P] = tol_len; //如ICMP make_ip(buf); //本地UDP的端口號 buf[UDP_DST_PORT_H_P] = port >> 8; buf[UDP_DST_PORT_L_P] = port & 0xff; // source port does not matter and is what the sender used. // calculte the udp length:最大16bit長度,即65535-14-20-8,但一般會設置的較小,原因麼,上文裏面講過。 buf[UDP_LEN_H_P] = datalen >> 8; buf[UDP_LEN_L_P] = UDP_HEADER_LEN + datalen; // zero the checksum buf[UDP_CHECKSUM_H_P] = 0; buf[UDP_CHECKSUM_L_P] = 0; // copy the data: while(i < datalen) { buf[UDP_DATA_P + i] = data[i]; i++; } //UDP_DEBUG插入此處 //這裏的16字節是UDP的僞首部,即IP的源地址-0x1a+目標地址-0x1e(和標準的有差異), //+UDP首部=4+4+8=16 ck = checksum(&buf[IP_SRC_P], 16 + datalen, 1); buf[UDP_CHECKSUM_H_P] = ck >> 8; buf[UDP_CHECKSUM_L_P] = ck & 0xff; enc28j60PacketSend(UDP_HEADER_LEN + IP_HEADER_LEN + ETH_HEADER_LEN + datalen, buf); } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/*--------------------- udp server start, we listen on udp port 1200=0x4B0 -----------------------------*/
if (buf[IP_PROTO_P]==IP_PROTO_UDP_V&&buf[UDP_DST_PORT_H_P]==4&&buf[UDP_DST_PORT_L_P]==0xb0) { //UDP數據長度 udpdatalen=buf[UDP_LEN_H_P]; udpdatalen=udpdatalen<<8; udpdatalen=(udpdatalen+buf[UDP_LEN_L_P])-UDP_HEADER_LEN; //udpdatalen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN; //獲取pc端的udp port pcudpport=buf[UDP_SRC_PORT_H_P]<<8 | buf[UDP_SRC_PORT_L_P];
//將udp客戶端得到的數據buf寫入buf1,因爲下面的實驗需要輸入的信息來做出相應的動作for(i1=0; i1<udpdatalen; i1++) buf1[i1]=buf[UDP_DATA_P+i1]; make_udp_reply_from_request(buf,buf1,udpdatalen,pcudpport); } /*----------------------------------------udp end -----------------------------------------------*/ |
- 通過串口輸出UDP客戶端的IP地址及端口號
- 通過串口和UDP輸出UDP的輸入數據,即USART ECHO和UDP ECHO
- 實現UDP命令控制STM32板子上面的LED
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
void make_udp_reply_from_request(unsigned char *buf, char *data, unsigned int datalen, unsigned int port)
{ unsigned int i = 0, tol_len; unsigned int ck; //如前面的ARP和ICMP一樣的 make_eth(buf); // total length field in the IP header must be set: //如IP Header tol_len = IP_HEADER_LEN + UDP_HEADER_LEN + datalen; buf[IP_TOTLEN_H_P] = tol_len >> 8; buf[IP_TOTLEN_L_P] = tol_len; //如ICMP make_ip(buf); //本地UDP的端口號 buf[UDP_DST_PORT_H_P] = port >> 8; buf[UDP_DST_PORT_L_P] = port & 0xff; // source port does not matter and is what the sender used. // calculte the udp length:最大16bit長度,即65535-14-20-8,但一般會設置的較小,原因麼,上文裏面講過。 buf[UDP_LEN_H_P] = datalen >> 8; buf[UDP_LEN_L_P] = UDP_HEADER_LEN + datalen; // zero the checksum buf[UDP_CHECKSUM_H_P] = 0; buf[UDP_CHECKSUM_L_P] = 0; // copy the data: while(i < datalen) { buf[UDP_DATA_P + i] = data[i]; i++; } #ifdef UDP_DEBUG i = 0; printf("UDP Server Test. \r\n"); printf("udp客戶端的IP地址及端口號 : \r\n"); while(i < sizeof(ipv4_addr)) { //注意這裏我們建立的是UDP Server,輸出UDP Client的IP地址 printf("%d", buf[IP_DST_P + i]); if(i != sizeof(ipv4_addr) - 1) { printf("."); } i++; } i = 0; //輸出pc端的udp port
printf(":%d \r\n", port);
//串口打印UDP Client發過來的數據 printf("udp客戶端發送的數據 : \r\n"); printf("%s \r\n", data); //實現UDP Server來響應UDP Client的控制LED命令 //如:led1=on,led1=off if(strcmp(data, "led1=on") == 0) { GPIO_ResetBits(GPIOA, GPIO_Pin_8); } if(strcmp(data, "led1=off") == 0) { GPIO_SetBits(GPIOA, GPIO_Pin_8); } //如:led2=on,led2=off if(strcmp(data, "led2=on") == 0) { GPIO_ResetBits(GPIOD, GPIO_Pin_2); } if(strcmp(data, "led2=off") == 0) { GPIO_SetBits(GPIOD, GPIO_Pin_2); } #endif //這裏的16字節是UDP的僞首部,即IP的源地址-0x1a+目標地址-0x1e(和標準的有差異), //+UDP首部=4+4+8=16 ck = checksum(&buf[IP_SRC_P], 16 + datalen, 1); buf[UDP_CHECKSUM_H_P] = ck >> 8; buf[UDP_CHECKSUM_L_P] = ck & 0xff; enc28j60PacketSend(UDP_HEADER_LEN + IP_HEADER_LEN + ETH_HEADER_LEN + datalen, buf); } |