1. 前言
??在當(dāng)今的計(jì)算機(jī)網(wǎng)絡(luò)環(huán)境中,TCP(傳輸控制協(xié)議)是一種非常重要的通信協(xié)議。TCP提供了一種可靠、有序和錯(cuò)誤控制的數(shù)據(jù)傳輸方式,被廣泛應(yīng)用于各種網(wǎng)絡(luò)應(yīng)用中。在TCP通信中,TCP Client是客戶端的角色,它負(fù)責(zé)建立連接、發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。
??本文以TCP Client為核心,讓設(shè)備在TCP Client模式下進(jìn)行數(shù)據(jù)回環(huán)測試。
??W5100S/W5500是一款集成全硬件 TCP/IP 協(xié)議棧的嵌入式以太網(wǎng)控制器,同時(shí)也是一顆工業(yè)級(jí)以太網(wǎng)控制芯片。在以太網(wǎng)應(yīng)用中使用 W5100S/W5500 讓用戶可以更加方便地在設(shè)備之間實(shí)現(xiàn)遠(yuǎn)程連接和通信。
2. 協(xié)議簡介
2.1 簡述
??TCP (Transmission Control Protocol) 是一種面向連接的、可靠的、基于字節(jié)流的傳輸協(xié)議,用于在計(jì)算機(jī)網(wǎng)絡(luò)上傳輸數(shù)據(jù)。TCP Client是指TCP網(wǎng)絡(luò)服務(wù)的客戶端連接,主動(dòng)向服務(wù)器發(fā)起連接請(qǐng)求并建立連接,用于實(shí)現(xiàn)串口數(shù)據(jù)和服務(wù)器數(shù)據(jù)的交互,保證數(shù)據(jù)的可靠交換。TCP Clent通常用于設(shè)備與服務(wù)器之間的數(shù)據(jù)交互,是最常用的聯(lián)網(wǎng)通信方式。
??TCP Client的主要作用是建立和管理與TCP服務(wù)器之間的連接,實(shí)現(xiàn)數(shù)據(jù)的可靠傳輸。通過TCP Client,設(shè)備可以向服務(wù)器發(fā)送數(shù)據(jù)并從服務(wù)器接收數(shù)據(jù),從而實(shí)現(xiàn)設(shè)備與服務(wù)器之間的數(shù)據(jù)交互。
??在TCP Client中,客戶端程序需要指定服務(wù)器的IP地址和端口號(hào),并使用TCP協(xié)議與服務(wù)器建立連接。一旦連接建立成功,客戶端程序就可以通過數(shù)據(jù)流對(duì)象 (NetworkStream) 與服務(wù)器進(jìn)行數(shù)據(jù)交互。
??因此,TCP Client可以幫助設(shè)備實(shí)現(xiàn)與服務(wù)器之間的可靠數(shù)據(jù)交換,是設(shè)備聯(lián)網(wǎng)通信的重要方式之一。在工業(yè)自動(dòng)化、物聯(lián)網(wǎng)、智能家居等應(yīng)用中,TCP Client被廣泛使用。
2.2 優(yōu)點(diǎn)
- 可靠性:TCP Client在數(shù)據(jù)傳輸過程中,通過TCP協(xié)議的確認(rèn)機(jī)制、重傳機(jī)制、擁塞控制機(jī)制等來確保數(shù)據(jù)的準(zhǔn)確性和完整性,避免數(shù)據(jù)丟失或亂序。
- 穩(wěn)定性:TCP Client在建立連接時(shí),需要經(jīng)過三次握手過程,確保連接的穩(wěn)定性和可靠性。在數(shù)據(jù)傳輸完成后,還會(huì)斷開連接,以節(jié)約系統(tǒng)資源。
- 效率:TCP的全雙工傳輸模式使得TCP Client具有很高的數(shù)據(jù)傳輸效率。
- 有序:TCP的字節(jié)流傳輸方式可以保證數(shù)據(jù)的順序性和完整性。
- 應(yīng)用友好性:TcpClient類為應(yīng)用層協(xié)議如FTP、HTTP等提供了更簡單、更友好的接口,降低了應(yīng)用層協(xié)議開發(fā)維護(hù)的成本。
2.3 應(yīng)用
- 網(wǎng)絡(luò)數(shù)據(jù)庫連接:許多數(shù)據(jù)庫系統(tǒng),如MySQL和PostgreSQL等,都支持使用TCP連接來接收客戶端的連接請(qǐng)求并處理數(shù)據(jù)請(qǐng)求。
- 遠(yuǎn)程桌面連接:使用TCP連接來遠(yuǎn)程控制另一臺(tái)計(jì)算機(jī)的桌面或通過另一臺(tái)計(jì)算機(jī)的操作進(jìn)行網(wǎng)絡(luò)瀏覽等。例如,RDP、VNC和SSH等協(xié)議都是使用TCP連接進(jìn)行遠(yuǎn)程控制和操作的例子。
- 文件傳輸:許多FTP和TFTP等文件傳輸協(xié)議使用TCP連接來傳輸文件。
- 郵件服務(wù)器:SMTP、POP和IMAP等電子郵件協(xié)議都使用TCP連接來發(fā)送和接收電子郵件。
- 網(wǎng)絡(luò)游戲:許多網(wǎng)絡(luò)游戲使用TCP連接來傳輸游戲數(shù)據(jù)和控制指令,以實(shí)現(xiàn)實(shí)時(shí)交互和同步。
- 即時(shí)通訊:許多即時(shí)通訊應(yīng)用程序使用TCP連接來傳輸音頻、視頻和文本消息。
- 電子商務(wù):TCP也可以用于電子商務(wù)應(yīng)用中,例如處理用戶登錄、支付和購物車等。
3. WIZnet以太網(wǎng)芯片
WIZnet 主流硬件協(xié)議棧以太網(wǎng)芯片參數(shù)對(duì)比
Model | Embedded Core | Host I/F | TX/RX Buffer | HW Socket | Network Performance |
---|---|---|---|---|---|
W5100S | TCP/IPv4, MAC & PHY | 8bit BUS, SPI | 16KB | 4 | Max.25Mbps |
W6100 | TCP/IPv4/IPv6, MAC & PHY | 8bit BUS, Fast SPI | 32KB | 8 | Max.25Mbps |
W5500 | TCP/IPv4, MAC & PHY | Fast SPI | 32KB | 8 | Max 15Mbps |
- W5100S/W6100 支持 8bit數(shù)據(jù)總線接口,網(wǎng)絡(luò)傳輸速度會(huì)優(yōu)于W5500。
- W6100 支持IPV6,與W5100S 硬件兼容,若已使用W5100S的用戶需要支持IPv6,可以Pin to Pin兼容。
- W5500 擁有比 W5100S更多的 Socket數(shù)量以及發(fā)送與接收緩存。
4. TCP Client數(shù)據(jù)回環(huán)測試
4.1 程序流程圖
4.2 測試準(zhǔn)備
軟件:
- Visual Studio Code
- WIZnet UartTool
- SocketTester
硬件:
- W5100SIO模塊 + RP2040 樹莓派Pico開發(fā)板 或者 WIZnet W5100S-EVB-Pico開發(fā)板
- Micro USB 接口的數(shù)據(jù)線
- TTL 轉(zhuǎn) USB
- 網(wǎng)線
4.3 連接方式
- 通過數(shù)據(jù)線連接PC的USB口(主要用于燒錄程序,也可以虛擬出串口使用)
- 通過TTL串口轉(zhuǎn)USB,連接UART0 的默認(rèn)引腳:
- RP2040 GPIO 0(UART0 TX) <----> USB_TTL_RX
- RP2040 GPIO 1(UART0 RX) <----> USB_TTL_TX
- 使用模塊連接RP2040進(jìn)行連線時(shí)
- RP2040 GPIO 16 <----> W5100S MISO
- RP2040 GPIO 17 <----> W5100S CS
- RP2040 GPIO 18 <----> W5100S SCK
- RP2040 GPIO 19 <----> W5100S MOSI
- RP2040 GPIO 20 <----> W5100S RST
- 通過網(wǎng)線直接連接PC網(wǎng)口(或:PC和設(shè)備都通過網(wǎng)線連接交換機(jī)或路由器LAN口)
4.4 相關(guān)代碼
??我們直接打開tcp_client.c文件(路徑:examples/tcp_client/tcp_client.c)看下具體實(shí)現(xiàn):
??可以看到這里是以dhcp模式配置網(wǎng)絡(luò)信息的,因此在主控和W5100S初始化完成后,會(huì)進(jìn)行DHCP初始化,然后增加一個(gè)定時(shí)器初始化,用來做dhcp過程中的計(jì)時(shí)以進(jìn)行超時(shí)處理;接著進(jìn)入dhcp配置網(wǎng)絡(luò)信息,成功則直接進(jìn)入循環(huán)調(diào)用回環(huán)測試函數(shù),失敗則用我們初始化的靜態(tài)網(wǎng)絡(luò)信息進(jìn)行配置,然后再進(jìn)入循環(huán)調(diào)用回環(huán)測試函數(shù),如下所示:
/* Network information to be configured. */
wiz_NetInfo net_info = {
.mac = {0x00, 0x08, 0xdc, 0x1e, 0xed, 0x2e}, // Configured MAC address
.ip = {192, 168, 1, 10}, // Configured IP address
.sn = {255, 255, 255, 0}, // Configured subnet mask
.gw = {192, 168, 1, 1}, // Configured gateway
.dns = {8, 8, 8, 8}, // Configured domain address
.dhcp = NETINFO_DHCP}; // Configured dhcp model,NETINFO_DHCP:use dhcp; NETINFO_STATIC: use static ip.
wiz_NetInfo get_info;
static uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {
0,
}; // Send and receive cache
static uint8_t des_ip[4] = {192, 168, 1, 2}; // Server IP address
static uint16_t des_port = 8080; // Server port
static uint16_t local_port = 8000; // Local port
static uint8_t dhcp_get_ip_flag = 0; // Define the DHCP acquisition flag
int main()
{
struct repeating_timer timer; // Define the timer structure
/* MCU init */
stdio_init_all(); // Initialize the main control peripheral
wizchip_initialize(); // Initialize the chip interface
/*dhcp init*/
DHCP_init(SOCKET_ID, ethernet_buf); // DHCP initialization
add_repeating_timer_ms(1000, repeating_timer_callback, NULL, &timer); // Add DHCP 1s Tick Timer handler
printf("wiznet chip tcp client example.\r\n");
network_init(&net_info); // Configuring Network Information
print_network_information(&get_info); // Read back the configuration information and print it
while (true)
{
loopback_tcpc(SOCKET_ID, ethernet_buf, des_ip, des_port, local_port); // tcp client data loop test
}
}
??跳進(jìn)回環(huán)測試?yán)锩婵聪缕渚唧w實(shí)現(xiàn): 該函數(shù)有這幾個(gè)參數(shù),socket端口號(hào)、數(shù)據(jù)收發(fā)緩存、目標(biāo)IP地址、目標(biāo)端口;可根據(jù)需要自行填入?yún)?shù)。其整體通過一個(gè)Swatch狀態(tài)機(jī)輪詢socket狀態(tài),根據(jù)不同進(jìn)行相應(yīng)的處理,依次完成了初始化、打開端口、連接服務(wù)器、收到數(shù)據(jù)后回傳的操作 ;其中本地端口直接在函數(shù)內(nèi)初始化了。如下所示:
/**
* @brief tcp client loopback test
* @param sn: socket number
* @param buf: Data sending and receiving cache
* @param destip: Destination IP address
* @param destport: Destination port
* @return value for SOCK_ERRORs,return 1:no error
*/
int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport)
{
int32_t ret; // return value for SOCK_ERRORs
uint16_t size = 0, sentsize=0;
// Destination (TCP Server) IP info (will be connected)
// >> loopback_tcpc() function parameter
// >> Ex)
// uint8_t destip[4] = {192, 168, 0, 214};
// uint16_t destport = 5000;
// Port number for TCP client (will be increased)
uint16_t any_port = 50000;
// Socket Status Transitions
// Check the W5500 Socket n status register (Sn_SR, The 'Sn_SR' controlled by Sn_CR command or Packet send/recv status)
switch(getSn_SR(sn))
{
case SOCK_ESTABLISHED :
if(getSn_IR(sn) & Sn_IR_CON) // Socket n interrupt register mask; TCP CON interrupt = connection with peer is successful
{
#ifdef _LOOPBACK_DEBUG_
printf("%d:Connected to - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
#endif
setSn_IR(sn, Sn_IR_CON); // this interrupt should be write the bit cleared to '1'
}
//
// Data Transaction Parts; Handle the [data receive and send] process
//
if((size = getSn_RX_RSR(sn)) > 0) // Sn_RX_RSR: Socket n Received Size Register, Receiving data length
{
if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE; // DATA_BUF_SIZE means user defined buffer size (array)
ret = recv(sn, buf, size); // Data Receive process (H/W Rx socket buffer -> User's buffer)
buf[ret]=0x00; // Add a string terminator
printf("recv: %s\n",buf); // print the receive data
if(ret <= 0) return ret; // If the received data length <= 0, receive failed and process end
size = (uint16_t) ret;
sentsize = 0;
// Data sentsize control
while(size != sentsize)
{
ret = send(sn, buf+sentsize, size-sentsize); // Data send process (User's buffer -> Destination through H/W Tx socket buffer)
if(ret < 0) // Send Error occurred (sent data length < 0)
{
close(sn); // socket close
return ret;
}
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
}
}
//
break;
case SOCK_CLOSE_WAIT :
#ifdef _LOOPBACK_DEBUG_
//printf("%d:CloseWait\r\n",sn);
#endif
if((ret=disconnect(sn)) != SOCK_OK) return ret;
#ifdef _LOOPBACK_DEBUG_
printf("%d:Socket Closed\r\n", sn);
#endif
break;
case SOCK_INIT :
#ifdef _LOOPBACK_DEBUG_
printf("%d:Try to connect to the %d.%d.%d.%d : %d\r\n", sn, destip[0], destip[1], destip[2], destip[3], destport);
#endif
if( (ret = connect(sn, destip, destport)) != SOCK_OK) return ret; // Try to TCP connect to the TCP server (destination)
break;
case SOCK_CLOSED:
close(sn);
if((ret=socket(sn, Sn_MR_TCP, any_port++, 0x00)) != sn){
if(any_port == 0xffff) any_port = 50000;
return ret; // TCP socket open with 'any_port' port number
}
#ifdef _LOOPBACK_DEBUG_
//printf("%d:TCP client loopback start\r\n",sn);
//printf("%d:Socket opened\r\n",sn);
#endif
break;
default:
break;
}
return 1;
}
4.5 測試現(xiàn)象
??硬件連接無誤后,編譯燒錄程序(具體可參考第一章節(jié)),打開WIZ UartTool,選擇對(duì)應(yīng)的COM口,填入?yún)?shù):波特率115200,8位數(shù)據(jù)位,1位停止位,無校驗(yàn)位,無流控,填完參數(shù)后點(diǎn)擊open打開,觀察串口打印的信息以獲取設(shè)備運(yùn)行狀態(tài);打開SocketTester,在左列填入相對(duì)應(yīng)的參數(shù),選擇TCP server模式,本地IP和監(jiān)聽端口根據(jù)串口打印的信息填入,完成后點(diǎn)擊Listen監(jiān)聽,連接成功后發(fā)送數(shù)據(jù)觀察現(xiàn)象;可以看到數(shù)據(jù)成功發(fā)送并成功回傳,如下圖所示:
5. 注意事項(xiàng)
- 不要混淆服務(wù)器IP和客戶端IP。
- 連接后交互過程不要突然斷開網(wǎng)線,造成假鏈接。
- 如果想用WIZnet的W5500來實(shí)現(xiàn)本章的示例,我們只需修改兩個(gè)地方即可:
- 在library/ioLibrary_Driver/Ethernet/下找到wizchip_conf.h這個(gè)頭文件,將_WIZCHIP_ 宏定義修改為W5500。
- 在library下找到CMakeLists.txt文件,將COMPILE_SEL設(shè)置為ON即可,OFF為W5100S,ON為W5500。
6. 相關(guān)鏈接
WIZnet官網(wǎng)
WIZnet官方庫鏈接
本章例程鏈接文章來源:http://www.zghlxwxcb.cn/news/detail-716833.html
想了解更多,評(píng)論留言哦!文章來源地址http://www.zghlxwxcb.cn/news/detail-716833.html
到了這里,關(guān)于三、W5100S/W5500+RP2040樹莓派Pico<TCP Client數(shù)據(jù)回環(huán)測試>的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!