Other Parts Discussed in Thread: TMDSCNCD28388D
您好,我使用TI的开发板TMDSCNCD28388D测试网络通信时出现两个问题:
一是 连续发送数据时会有粘包现象
二是 通信一段时间后会断开连接
下面是实验代码:
(1)CM上的主程序和http处理程序
int
main(void)
{
unsigned long ulUser0, ulUser1;
unsigned char pucMACArray[8];
//
// User specific IP Address Configuration.
// Current implementation works with Static IP address only.
//
unsigned long IPAddr = 0xC0A80101;
unsigned long NetMask = 0xFFFFFF00;
unsigned long GWAddr = 0x00000000;
// Initializing the CM. Loading the required functions to SRAM.
CM_init();
SYSTICK_setPeriod(systickPeriodValue);
SYSTICK_enableCounter();
SYSTICK_registerInterruptHandler(SysTickIntHandler);
SYSTICK_enableInterrupt();
//
// Enable processor interrupts.
//
Interrupt_enableInProcessor();
// Set user/company specific MAC octets
// (for this code we are using A8-63-F2-00-00-80)
// 0x00 MACOCT3 MACOCT2 MACOCT1
ulUser0 = 0x00F263A8;
// 0x00 MACOCT6 MACOCT5 MACOCT4
ulUser1 = 0x00800000;
//
// Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
// address needed to program the hardware registers, then program the MAC
// address into the Ethernet Controller registers.
//
pucMACArray[0] = ((ulUser0 >> 0) & 0xff);
pucMACArray[1] = ((ulUser0 >> 8) & 0xff);
pucMACArray[2] = ((ulUser0 >> 16) & 0xff);
pucMACArray[3] = ((ulUser1 >> 0) & 0xff);
pucMACArray[4] = ((ulUser1 >> 8) & 0xff);
pucMACArray[5] = ((ulUser1 >> 16) & 0xff);
//
// Initialize ethernet module.
//
Ethernet_init(pucMACArray);
//
// Initialze the lwIP library, using DHCP.
//
lwIPInit(0, pucMACArray, IPAddr, NetMask, GWAddr, IPADDR_USE_STATIC);
//
// Initialize the HTTP webserver daemon.
//
httpd_init();
IPC_clearFlagLtoR(IPC_CM_L_CPU1_R, IPC_FLAG_ALL);
IPC_sync(IPC_CM_L_CPU1_R, IPC_FLAG31); // 等待远端IPC初始化
//
// Loop forever. All the work is done in interrupt handlers.
//
while(1);
}
static err_t
http_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct http_state *hs = (struct http_state *)arg;
char *data = NULL;
if(err==ERR_OK && p!=NULL)
{
tcp_recved(pcb,p->tot_len);
data = p->payload;
pbuf_free(p);
if(data[0]=='A' && data[1]=='O')
{
tcp_write(pcb,"led1 open",10, 1);
GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);
}
else if(data[0]=='A' && data[1]=='C')
{
tcp_write(pcb,"led1 close",10, 1);
GPIO_writePin(DEVICE_GPIO_PIN_LED1, 1);
}
if(data[0]=='B' && data[1]=='O')
{
tcp_write(pcb,"led2 open",10, 1);
GPIO_writePin(DEVICE_GPIO_PIN_LED2, 0);
}
else if(data[0]=='B' && data[1]=='C')
{
tcp_write(pcb,"led2 close",10, 1);
GPIO_writePin(DEVICE_GPIO_PIN_LED2, 1);
}
else if(data[0]=='P' && data[1]=='L')
{
tcp_write(pcb,"TEST OK",10, 1);
}
}
else
{
pbuf_free(p);
}
if(err==ERR_OK && p==NULL)
{
http_close_conn(pcb,hs);
}
return ERR_OK;
}
(2)CPU1上的主程序
void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();
//
// Boot CM core
//
#ifdef _FLASH
Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
#else
Device_bootCM(BOOTMODE_BOOT_TO_S0RAM);
#endif
//
// Disable pin locks and enable internal pull-ups.
//
Device_initGPIO();
GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);
GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(DEVICE_GPIO_PIN_LED2, GPIO_PIN_TYPE_STD);
GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED2, GPIO_DIR_MODE_OUT);
GPIO_setMasterCore(31, GPIO_CORE_CM);
GPIO_setMasterCore(34, GPIO_CORE_CM);
#ifdef ETHERNET
//
// Set up EnetCLK to use SYSPLL as the clock source and set the
// clock divider to 2.
//
// This way we ensure that the PTP clock is 100 MHz. Note that this value
// is not automatically/dynamically known to the CM core and hence it needs
// to be made available to the CM side code beforehand.
SysCtl_setEnetClk(SYSCTL_ENETCLKOUT_DIV_2, SYSCTL_SOURCE_SYSPLL);
//
// Configure the GPIOs for ETHERNET.
//
//
// MDIO Signals
//
GPIO_setPinConfig(GPIO_105_ENET_MDIO_CLK);
GPIO_setPinConfig(GPIO_106_ENET_MDIO_DATA);
//
// Use this only for RMII Mode
//GPIO_setPinConfig(GPIO_73_ENET_RMII_CLK);
//
//
//MII Signals
//
GPIO_setPinConfig(GPIO_109_ENET_MII_CRS);
GPIO_setPinConfig(GPIO_110_ENET_MII_COL);
GPIO_setPinConfig(GPIO_75_ENET_MII_TX_DATA0);
GPIO_setPinConfig(GPIO_122_ENET_MII_TX_DATA1);
GPIO_setPinConfig(GPIO_123_ENET_MII_TX_DATA2);
GPIO_setPinConfig(GPIO_124_ENET_MII_TX_DATA3);
//
//Use this only if the TX Error pin has to be connected
//GPIO_setPinConfig(GPIO_46_ENET_MII_TX_ERR);
//
GPIO_setPinConfig(GPIO_118_ENET_MII_TX_EN);
GPIO_setPinConfig(GPIO_114_ENET_MII_RX_DATA0);
GPIO_setPinConfig(GPIO_115_ENET_MII_RX_DATA1);
GPIO_setPinConfig(GPIO_116_ENET_MII_RX_DATA2);
GPIO_setPinConfig(GPIO_117_ENET_MII_RX_DATA3);
GPIO_setPinConfig(GPIO_113_ENET_MII_RX_ERR);
GPIO_setPinConfig(GPIO_112_ENET_MII_RX_DV);
GPIO_setPinConfig(GPIO_44_ENET_MII_TX_CLK);
GPIO_setPinConfig(GPIO_111_ENET_MII_RX_CLK);
//
//Power down pin to bring the external PHY out of Power down
//
GPIO_setDirectionMode(108, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(108, GPIO_PIN_TYPE_PULLUP);
GPIO_writePin(108,1);
//
//PHY Reset Pin to be driven High to bring external PHY out of Reset
//
GPIO_setDirectionMode(119, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(119, GPIO_PIN_TYPE_PULLUP);
GPIO_writePin(119,1);
#endif
}
(3)上位机的连接和发送接收函数
#include "DLL_28388.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include <iostream>
#include<winSock2.h>
#include<WS2tcpip.h>
#define WIN32_LEAN_AND_MEAN
#include<windows.h>
#pragma comment(lib,"ws2_32.lib")
SOCKET CDll::F28388D_Lwip_Connect(const std::string& ipAddress, int port)
{
// 初始化Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
return INVALID_SOCKET;
}
// 创建SOCKET
SOCKET ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
WSACleanup();
return INVALID_SOCKET;
}
// 设置服务器地址
sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(port);
// 将IP地址从字符串转换为二进制形式
in_addr addr;
if (inet_pton(AF_INET, ipAddress.c_str(), &addr) <= 0) {
closesocket(ConnectSocket);
WSACleanup();
return INVALID_SOCKET;
}
serverAddress.sin_addr = addr;
// 连接到服务器
iResult = connect(ConnectSocket, (SOCKADDR*)&serverAddress, sizeof(serverAddress));
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
WSACleanup();
return INVALID_SOCKET;
}
return ConnectSocket; // 返回已连接的socket句柄
}
int CDll::F28388D_Lwip_Send(SOCKET sock, const std::string& msg)
{
int bytesSent = send(sock, msg.c_str(), static_cast<int>(msg.size()), 0);
if (bytesSent == SOCKET_ERROR) {
std::cerr << "send failed with error: " << WSAGetLastError() << std::endl;
return 1;
}
return 0;
}
std::string CDll::F28388D_Lwip_Recv(SOCKET sock) {
char recvbuf[512];
int bytesRecvd = recv(sock, recvbuf, sizeof(recvbuf) - 1, 0);
if (bytesRecvd > 0) {
recvbuf[bytesRecvd] = '\0'; // 确保字符串以null终止
return std::string(recvbuf);
}
else if (bytesRecvd == 0) {
std::cout << "Connection closed" << std::endl;
}
else {
std::cerr << "recv failed with error: " << WSAGetLastError() << std::endl;
}
return "";
}
在wireshark软件中,显示的粘包错误:

AC命令对应返回值为led1 close
BC命令对应返回值为led2 close
AO命令对应返回值为led1 open
BO命令对应返回值为led2 open
在上位机程序的定时器中,这些命令分开 依次 发送,但是抓包数据显示,有三个命令是放到一个TCP数据包中发送出去的,请问这可能是什么原因造成的