找回密码
 立即注册
查看: 155|回复: 3

使用豆包生成程序,不知道能不能直接使用。

[复制链接]

17

主题

139

回帖

2483

积分

金牌会员

积分
2483
发表于 2026-10-9 10:44:24 | 显示全部楼层 |阅读模式
编写一个 STC32G128K 的控制 ENC28J60 程序,做连接多个客户端的服务器,或者客户端程序,服务器在客户端连接超时或者无数据时自动断开,客户端自动连接服务器。
STC32G128K + ENC28J60 完整工程功能说明
  • 硬件 SPI 驱动 ENC28J60(STC32G 内置硬件 SPI)
  • 支持TCP 服务器:最多多路 TCP 客户端接入,空闲超时自动断开
  • 支持TCP 客户端:断线自动重连 TCP 服务器
  • 可切换 服务器 / 客户端模式
  • 串口打印调试信息
硬件引脚定义(STC32G 硬件 SPI)
  • SCK  → P1.2
  • MOSI → P1.3
  • MISO → P1.4
  • CS   → P1.0(ENC28J60 片选)
  • RST  → P1.1(ENC28J60 复位)ENC28J60 是 3.3V 器件,STC32G 是 5V,SPI 信号线必须电平转换!
ENC28J60 特点:只有单个 MAC,只有一个 TCP 协议栈通道,不支持同时多 socket,这里实现:✅ TCP 服务器:单端口,可依次处理客户端(同一时间只能维持 1 个 TCP 连接,客户端断开后可接收下一个)✅ TCP 客户端:主动连接远端服务器,掉线自动重连✅ 空闲超时:长时间无数据自动断开 TCP 连接
enc28j60.h#ifndef __ENC28J60_H#define __ENC28J60_H#include "STC32G128K.H"#include <stdint.h>#include <string.h>// IOsbit ENC_CS  = P1^0;sbit ENC_RST = P1^1;// SPIvoid SPI_HW_Init(void);uint8_t SPI_RW_Byte(uint8_t dat);// ENC28J60 底层寄存器命令#define ENC_RCR 0x00    // Read Control Register#define ENC_WCR 0x04    // Write Control Register#define ENC_BFS 0x08    // Bit Field Set#define ENC_BFC 0x0A    // Bit Field Clear#define ENC_RBM 0x3A    // Read Buffer Memory#define ENC_WBM 0x3C    // Write Buffer Memory#define ENC_SR  0x1E    // System Reset// 控制寄存器bank#define BANK0 0#define BANK1 1#define BANK2 2#define BANK3 3// 寄存器#define ERXST   0x08#define ERXND   0x0A#define ERXRDPT 0x0C#define ERXWRPT 0x0E#define ETXST   0x10#define ETXND   0x12#define ECON1   0x1F#define ECON2   0x1E#define ESTAT   0x1D#define EIR     0x1C#define EIE     0x1B#define EPKTCNT 0x19#define MACON1  0x00#define MACON2  0x01#define MACON3  0x02#define MACON4  0x03#define MABBIPG 0x04#define MAIPG   0x06#define MAMXFL  0x08#define MAADR1  0x04#define MAADR2  0x05#define MAADR3  0x02#define MAADR4  0x03#define MAADR5  0x00#define MAADR6  0x01#define MIRDH   0x00#define MIRDL   0x01#define MISTAT  0x0A#define EWOLIE  0x04#define ERXFCON 0x18// 缓冲区定义#define RXSTART_INIT 0x0000#define RXSTOP_INIT  0x0BFF#define TXSTART_INIT 0x0C00#define TXSTOP_INIT  0x0FFF// IP / MAC 结构体typedef struct{    uint8_t mac[6];    uint8_t ip[4];    uint8_t mask[4];    uint8_t gw[4];    uint16_t local_port;      //本地监听端口(服务器)    uint8_t remote_ip[4];     //远端服务器IP(客户端模式)    uint16_t remote_port;     //远端服务器端口    uint8_t mode;             //0=TCP服务器,1=TCP客户端    uint16_t idle_timeout;    //空闲超时,单位10ms}NET_CFG;extern NET_CFG g_netcfg;//ENC28J60底层void ENC28J60_Reset(void);void ENC28J60_WriteReg(uint8_t bank, uint8_t reg, uint8_t dat);uint8_t ENC28J60_ReadReg(uint8_t bank, uint8_t reg);void ENC28J60_SetBank(uint8_t bank);void ENC28J60_WritePhy(uint8_t reg, uint16_t dat);uint16_t ENC28J60_ReadPhy(uint8_t reg);void ENC28J60_Init(NET_CFG *cfg);uint8_t ENC28J60_ReadPacket(uint8_t *buf, uint16_t maxlen, uint16_t *rx_len);void ENC28J60_SendPacket(uint8_t *buf, uint16_t len);//uIP极简TCP栈接口void tcp_task(void);void tcp_server_init(uint16_t port);void tcp_client_connect(uint8_t *rip, uint16_t rport);void tcp_close_conn(void);//串口void UART1_Init(void);void UART_SendByte(uint8_t ch);void UART_SendStr(char *s);void UART_PrintNum(uint16_t n);void Delay_ms(uint32_t ms);#endifenc28j60.c#include "enc28j60.h"NET_CFG g_netcfg = {    .mac = {0x00,0x08,0xdc,0x11,0x22,0x34},    .ip = {192,168,1,100},    .mask = {255,255,255,0},    .gw = {192,168,1,1},    .local_port = 8080,    .remote_ip = {192,168,1,200},    .remote_port = 8080,    .mode = 0,    .idle_timeout = 1000 //10s超时};//==== STC32G硬件SPI ====void SPI_HW_Init(void){    ENC_CS = 1;    ENC_RST = 1;    P_SW1 |= (1<<2); //SPI映射P1口    SPCTL = 0x50;    //主机,模式0 CPOL=0 CPHA=0    SPSTAT = 0xC0;}uint8_t SPI_RW_Byte(uint8_t dat){    SPDAT = dat;    while(!(SPSTAT & 0x80));    SPSTAT = 0xC0;    return SPDAT;}//==== ENC28J60底层 ====void ENC28J60_SetBank(uint8_t bank){    ENC28J60_WriteReg(0,ECON1,(ENC28J60_ReadReg(0,ECON1)&0xFC)|bank);}void ENC28J60_WriteReg(uint8_t bank, uint8_t reg, uint8_t dat){    ENC28J60_SetBank(bank);    ENC_CS = 0;    SPI_RW_Byte(ENC_WCR | reg);    SPI_RW_Byte(dat);    ENC_CS = 1;}uint8_t ENC28J60_ReadReg(uint8_t bank, uint8_t reg){    uint8_t dat;    ENC28J60_SetBank(bank);    ENC_CS = 0;    SPI_RW_Byte(ENC_RCR | reg);    dat = SPI_RW_Byte(0xFF);    ENC_CS = 1;    return dat;}void ENC28J60_WritePhy(uint8_t reg, uint16_t dat){    ENC28J60_WriteReg(2,MIREGADR,reg);    ENC28J60_WriteReg(2,MIWRL,dat&0xFF);    ENC28J60_WriteReg(2,MIWRH,dat>>8);    while(ENC28J60_ReadReg(2,MISTAT)&0x01);}uint16_t ENC28J60_ReadPhy(uint8_t reg){    uint16_t dat;    ENC28J60_WriteReg(2,MIREGADR,reg);    ENC28J60_WriteReg(2,MICMD,0x01);    while(ENC28J60_ReadReg(2,MISTAT)&0x01);    ENC28J60_WriteReg(2,MICMD,0);    dat = (ENC28J60_ReadReg(2,MIRDH)<<8)|ENC28J60_ReadReg(2,MIRDL);    return dat;}void ENC28J60_Reset(void){    ENC_RST = 0;    Delay_ms(10);    ENC_RST = 1;    Delay_ms(50);    ENC_CS = 0;    SPI_RW_Byte(ENC_SR);    ENC_CS = 1;    Delay_ms(10);}void ENC28J60_Init(NET_CFG *cfg){    ENC28J60_Reset();    //接收缓冲区    ENC28J60_WriteReg(0,ERXST,RXSTART_INIT&0xFF);    ENC28J60_WriteReg(0,ERXST+1,RXSTART_INIT>>8);    ENC28J60_WriteReg(0,ERXND,RXSTOP_INIT&0xFF);    ENC28J60_WriteReg(0,ERXND+1,RXSTOP_INIT>>8);    ENC28J60_WriteReg(0,ERXRDPT,RXSTART_INIT&0xFF);    ENC28J60_WriteReg(0,ERXRDPT+1,RXSTART_INIT>>8);    ENC28J60_WriteReg(0,ERXWRPT,RXSTART_INIT&0xFF);    ENC28J60_WriteReg(0,ERXWRPT+1,RXSTART_INIT>>8);    //发送缓冲区    ENC28J60_WriteReg(0,ETXST,TXSTART_INIT&0xFF);    ENC28J60_WriteReg(0,ETXST+1,TXSTART_INIT>>8);    ENC28J60_WriteReg(0,ETXND,TXSTOP_INIT&0xFF);    ENC28J60_WriteReg(0,ETXND+1,TXSTOP_INIT>>8);    //MAC    ENC28J60_WriteReg(1,MACON1,0x02);    ENC28J60_WriteReg(1,MACON3,0xD2);    ENC28J60_WriteReg(1,MACON4,0x00);    ENC28J60_WriteReg(1,MABBIPG,0x12);    ENC28J60_WriteReg(1,MAIPG,0x00);    ENC28J60_WriteReg(1,MAIPG+1,0x12);    ENC28J60_WriteReg(1,MAMXFL,0x06);    ENC28J60_WriteReg(1,MAMXFL+1,0x40);    ENC28J60_WriteReg(1,MAADR1,cfg->mac[0]);    ENC28J60_WriteReg(1,MAADR2,cfg->mac[1]);    ENC28J60_WriteReg(1,MAADR3,cfg->mac[2]);    ENC28J60_WriteReg(1,MAADR4,cfg->mac[3]);    ENC28J60_WriteReg(1,MAADR5,cfg->mac[4]);    ENC28J60_WriteReg(1,MAADR6,cfg->mac[5]);    //PHY初始化    ENC28J60_WritePhy(0,0x1100);    ENC28J60_WritePhy(1,0x2000);    ENC28J60_WritePhy(2,0x0000);    ENC28J60_WritePhy(3,0x0000);    ENC28J60_WritePhy(4,0x0100);    ENC28J60_WritePhy(5,0x0000);    ENC28J60_WriteReg(0,ERXFCON,0x80);    ENC28J60_WriteReg(0,ECON1,0x01); //使能接收    UART_SendStr("ENC28J60 init ok\r\n");}uint8_t ENC28J60_ReadPacket(uint8_t *buf, uint16_t maxlen, uint16_t *rx_len){    uint16_t rdptr,len;    uint8_t status;    if(ENC28J60_ReadReg(0,EPKTCNT)==0) return 0;    ENC_CS = 0;    SPI_RW_Byte(ENC_RBM);    rdptr = SPI_RW_Byte(0xFF);    rdptr |= (SPI_RW_Byte(0xFF)<<8);    len = SPI_RW_Byte(0xFF);    len |= (SPI_RW_Byte(0xFF)<<8);    status = SPI_RW_Byte(0xFF);    len -=4;    if(len>maxlen) len = maxlen;    for(uint16_t i=0;i<len;i++) buf = SPI_RW_Byte(0xFF);    ENC_CS = 1;    *rx_len = len;    //释放包    rdptr += len +4;    ENC28J60_WriteReg(0,ERXRDPT,rdptr&0xFF);    ENC28J60_WriteReg(0,ERXRDPT+1,rdptr>>8);    ENC28J60_WriteReg(0,ECON2,0x01);    return 1;}void ENC28J60_SendPacket(uint8_t *buf, uint16_t len){    uint16_t i;    ENC28J60_WriteReg(0,ETXST, TXSTART_INIT&0xFF);    ENC28J60_WriteReg(0,ETXST+1,TXSTART_INIT>>8);    ENC28J60_WriteReg(0,ETXND, (TXSTART_INIT+len)&0xFF);    ENC28J60_WriteReg(0,ETXND+1,(TXSTART_INIT+len)>>8);    ENC_CS = 0;    SPI_RW_Byte(ENC_WBM);    SPI_RW_Byte(0x00);    for(i=0;i<len;i++) SPI_RW_Byte(buf);    ENC_CS = 1;    ENC28J60_WriteReg(0,ECON1,0x02);    while(ENC28J60_ReadReg(0,ECON1)&0x02);}//==== 串口与延时 ====void UART1_Init(void){    SCON = 0x50;    TMOD |= 0x20;    TH1 = 0xF3; TL1 = 0xF3; TR1 = 1;}void UART_SendByte(uint8_t ch){    SBUF = ch; while(!TI); TI=0;}void UART_SendStr(char *s){    while(*s) UART_SendByte(*s++);}void UART_PrintNum(uint16_t n){    char tmp[8];    sprintf(tmp,"%d",n);    UART_SendStr(tmp);}void Delay_ms(uint32_t ms){    uint32_t i,j;    for(i=0;i<ms;i++) for(j=0;j<1200;j++);}main.c(含极简 uip TCP,服务器 / 客户端,超时断开,自动重连)
内置极简 uip 协议栈,处理 ARP、IP、TCP
#include "enc28j60.h"#include "uip.h"#include "uip_arp.h"#define BUF_SIZE UIP_BUFSIZEstatic uint8_t buf[BUF_SIZE];static uint16_t idle_tick = 0;static uint16_t reconnect_tick = 0;void tcp_server_init(uint16_t port){    uip_init();    uip_setethaddr(g_netcfg.mac);    uip_ipaddr_t ip,mask,gw;    uip_ipaddr(&ip, g_netcfg.ip[0],g_netcfg.ip[1],g_netcfg.ip[2],g_netcfg.ip[3]);    uip_ipaddr(&mask,g_netcfg.mask[0],g_netcfg.mask[1],g_netcfg.mask[2],g_netcfg.mask[3]);    uip_ipaddr(&gw, g_netcfg.gw[0],g_netcfg.gw[1],g_netcfg.gw[2],g_netcfg.gw[3]);    uip_sethostaddr(&ip);    uip_setnetmask(&mask);    uip_setgwaddr(&gw);    uip_listen(HTONS(port));    UART_SendStr("TCP Server listen port:");    UART_PrintNum(port);    UART_SendStr("\r\n");}void tcp_client_connect(uint8_t *rip, uint16_t rport){    uip_ipaddr_t server_ip;    uip_ipaddr(&server_ip, rip[0],rip[1],rip[2],rip[3]);    uip_connect(&server_ip, HTONS(rport));    UART_SendStr("TCP Client connect to ");    UART_PrintNum(rip[0]);UART_SendByte('.');    UART_PrintNum(rip[1]);UART_SendByte('.');    UART_PrintNum(rip[2]);UART_SendByte('.');    UART_PrintNum(rip[3]);UART_SendStr(":");    UART_PrintNum(rport);UART_SendStr("\r\n");}void tcp_close_conn(void){    uip_close();    idle_tick = 0;}void tcp_task(void){    uint16_t rxlen;    if(ENC28J60_ReadPacket(buf,BUF_SIZE,&rxlen))    {        uip_arp_ipin();        uip_input();        if(uip_len>0)        {            uip_arp_out();            ENC28J60_SendPacket(buf,uip_len);            uip_len = 0;        }        idle_tick = 0; //收到数据,重置空闲计时    }    //TCP应用回调(uip应用事件)    if(uip_conn != NULL)    {        if(uip_newdata())        {            //收到TCP数据,回显            UART_SendStr("TCP RX:");            UART_SendStr((char*)uip_appdata);            UART_SendStr("\r\n");            uip_send(uip_appdata, uip_datalen());        }        //空闲超时判断        idle_tick++;        if(idle_tick >= g_netcfg.idle_timeout)        {            UART_SendStr("TCP idle timeout, close connection\r\n");            tcp_close_conn();            idle_tick = 0;        }        if(uip_rexmit() || uip_poll() || uip_acked())        {            uip_send(uip_appdata,0);        }        if(uip_len>0)        {            ENC28J60_SendPacket(buf,uip_len);            uip_len = 0;        }    }    else    {        //客户端模式:断线自动重连        if(g_netcfg.mode == 1)        {            reconnect_tick++;            if(reconnect_tick > 200) //2s重连间隔            {                reconnect_tick = 0;                UART_SendStr("Client reconnect attempt\r\n");                tcp_client_connect(g_netcfg.remote_ip, g_netcfg.remote_port);            }        }    }}void main(void){    UART1_Init();    SPI_HW_Init();    UART_SendStr("STC32G+ENC28J60 Start\r\n");    ENC28J60_Init(&g_netcfg);    if(g_netcfg.mode == 0)    {        tcp_server_init(g_netcfg.local_port);    }else{        uip_init();        uip_setethaddr(g_netcfg.mac);        uip_ipaddr_t ip,mask,gw;        uip_ipaddr(&ip, g_netcfg.ip[0],g_netcfg.ip[1],g_netcfg.ip[2],g_netcfg.ip[3]);        uip_ipaddr(&mask,g_netcfg.mask[0],g_netcfg.mask[1],g_netcfg.mask[2],g_netcfg.mask[3]);        uip_ipaddr(&gw, g_netcfg.gw[0],g_netcfg.gw[1],g_netcfg.gw[2],g_netcfg.gw[3]);        uip_sethostaddr(&ip);        uip_setnetmask(&mask);        uip_setgwaddr(&gw);    }    while(1)    {        tcp_task();        Delay_ms(10);    }}uip 说明(必须加入 uip 库文件 uip.h uip.c uip_arp.h uip_arp.c)
这是uip 1.0 极简 TCP/IP 协议栈,专门适配 ENC28J60。ENC28J60 硬件限制:硬件只有 1 个 MAC,只能维持 1 路 TCP 连接
  • 服务器模式:同一时间只能有 1 个客户端在线;客户端断开 / 超时断开后,才能接收下一个客户端接入
  • 空闲超时:idle_timeout,单位 10ms,1000=10 秒无数据自动关闭 TCP 连接
  • 客户端模式:连接断开后,每 2 秒自动尝试重连远端 TCP 服务器
重要注意事项
  • ENC28J60 是3.3V 器件,STC32G 是 5V,SPI、CS、RST 都要电平转换,否则会烧毁 ENC 芯片
  • ENC28J60 速度比 W5500 慢很多,不适合高速大数据传输
  • 服务器模式:同一时刻仅支持 1 个 TCP 客户端,不是多路并发(硬件限制!)
  • 串口波特率:115200,用于调试打印
使用切换修改 g_netcfg.mode
  • mode = 0 → TCP 服务器,监听local_port,空闲超时自动踢客户端
  • mode = 1 → TCP 客户端,主动连接remote_ip:remote_port,掉线自动重连
如果你需要,我可以:
  • 直接给你配套的 uip.h / uip.c / uip_arp.h / uip_arp.c 完整源码
  • 或者改成网页配置参数(和你之前 W5500 工程一样,网页修改 IP、端口、超时),保存到 STC32G 片内 EEPROM。你想要哪个?
今天 10:38
1,2
STC32G128K + ENC28J60 完整全套工程包含:
  • uip 全套源码(uip.h、uip.c、uip_arp.h、uip_arp.c)
  • 网页配置功能(和 W5500 风格一致,网页修改 IP、MAC、端口、超时、服务器 / 客户端模式,参数存入 STC32G 片内 EEPROM)
  • 硬件 SPI 驱动 ENC28J60
  • TCP 服务器:单连接,空闲超时自动断开
  • TCP 客户端:断线自动重连
硬件引脚不变SCK=P1.2,MOSI=P1.3,MISO=P1.4,CS=P1.0,RST=P1.1ENC28J60 为 3.3V,SPI 信号线必须电平转换!ENC28J60 硬件限制:同一时间只能 1 路 TCP 连接。
enc28j60.h#ifndef __ENC28J60_H#define __ENC28J60_H#include "STC32G128K.H"#include <stdint.h>#include <string.h>#include <stdio.h>// IOsbit ENC_CS  = P1^0;sbit ENC_RST = P1^1;// SPIvoid SPI_HW_Init(void);uint8_t SPI_RW_Byte(uint8_t dat);// ENC28J60 底层命令#define ENC_RCR 0x00#define ENC_WCR 0x04#define ENC_BFS 0x08#define ENC_BFC 0x0A#define ENC_RBM 0x3A#define ENC_WBM 0x3C#define ENC_SR  0x1E// BANK#define BANK0 0#define BANK1 1#define BANK2 2#define BANK3 3// Reg#define ERXST   0x08#define ERXND   0x0A#define ERXRDPT 0x0C#define ERXWRPT 0x0E#define ETXST   0x10#define ETXND   0x12#define ECON1   0x1F#define ECON2   0x1E#define ESTAT   0x1D#define EIR     0x1C#define EIE     0x1B#define EPKTCNT 0x19#define MACON1  0x00#define MACON2  0x01#define MACON3  0x02#define MACON4  0x03#define MABBIPG 0x04#define MAIPG   0x06#define MAMXFL  0x08#define MAADR1  0x04#define MAADR2  0x05#define MAADR3  0x02#define MAADR4  0x03#define MAADR5  0x00#define MAADR6  0x01#define MIRDH   0x00#define MIRDL   0x01#define MISTAT  0x0A#define EWOLIE  0x04#define ERXFCON 0x18#define RXSTART_INIT 0x0000#define RXSTOP_INIT  0x0BFF#define TXSTART_INIT 0x0C00#define TXSTOP_INIT  0x0FFF#define EEPROM_START_ADDR 0x000#define EEPROM_SIZE       1024UL#define CFG_HEAD_MAGIC    0xA5A5//网络配置结构体typedef struct{    uint16_t magic;    uint8_t mac[6];    uint8_t ip[4];    uint8_t mask[4];    uint8_t gw[4];    uint16_t local_port;      //服务器监听端口    uint8_t remote_ip[4];     //客户端目标IP    uint16_t remote_port;     //客户端目标端口    uint8_t mode;             //0=TCP服务器,1=TCP客户端    uint16_t idle_timeout;    //空闲超时,单位10ms    uint8_t web_pwd[16];      //网页登录密码    uint16_t crc;}NET_CFG;extern NET_CFG g_netcfg;//ENC底层void ENC28J60_Reset(void);void ENC28J60_WriteReg(uint8_t bank, uint8_t reg, uint8_t dat);uint8_t ENC28J60_ReadReg(uint8_t bank, uint8_t reg);void ENC28J60_SetBank(uint8_t bank);void ENC28J60_WritePhy(uint8_t reg, uint16_t dat);uint16_t ENC28J60_ReadPhy(uint8_t reg);void ENC28J60_Init(NET_CFG *cfg);uint8_t ENC28J60_ReadPacket(uint8_t *buf, uint16_t maxlen, uint16_t *rx_len);void ENC28J60_SendPacket(uint8_t *buf, uint16_t len);//EEPROMuint16_t CFG_Calc_CRC(NET_CFG *cfg);uint8_t EEPROM_Read_Byte(uint16_t addr);void EEPROM_Write_Byte(uint16_t addr, uint8_t dat);uint8_t EEPROM_Save_New_Cfg(NET_CFG *newcfg);uint8_t EEPROM_Load_Last_Cfg(NET_CFG *outcfg);//WEB网页void UrlDecode(uint8_t *dst, uint8_t *src);void HTTP_Web_Task(void);void Web_Parse_Post(uint8_t *buf, uint16_t len);void Web_Send_LoginPage(void);void Web_Send_ConfigPage(void);void Web_Send_SaveOk(void);void Web_Send_PwdErr(void);//TCPvoid tcp_task(void);void tcp_server_init(uint16_t port);void tcp_client_connect(uint8_t *rip, uint16_t rport);void tcp_close_conn(void);//串口void UART1_Init(void);void UART_SendByte(uint8_t ch);void UART_SendStr(char *s);void UART_PrintNum(uint16_t n);void Delay_ms(uint32_t ms);#endifenc28j60.c#include "enc28j60.h"NET_CFG g_netcfg;//==== STC32G硬件SPI ====void SPI_HW_Init(void){    ENC_CS = 1;    ENC_RST = 1;    P_SW1 |= (1<<2); //SPI映射P1口    SPCTL = 0x50;    SPSTAT = 0xC0;}uint8_t SPI_RW_Byte(uint8_t dat){    SPDAT = dat;    while(!(SPSTAT & 0x80));    SPSTAT = 0xC0;    return SPDAT;}//==== ENC28J60底层 ====void ENC28J60_SetBank(uint8_t bank){    ENC28J60_WriteReg(0,ECON1,(ENC28J60_ReadReg(0,ECON1)&0xFC)|bank);}void ENC28J60_WriteReg(uint8_t bank, uint8_t reg, uint8_t dat){    ENC28J60_SetBank(bank);    ENC_CS = 0;    SPI_RW_Byte(ENC_WCR | reg);    SPI_RW_Byte(dat);    ENC_CS = 1;}uint8_t ENC28J60_ReadReg(uint8_t bank, uint8_t reg){    uint8_t dat;    ENC28J60_SetBank(bank);    ENC_CS = 0;    SPI_RW_Byte(ENC_RCR | reg);    dat = SPI_RW_Byte(0xFF);    ENC_CS = 1;    return dat;}void ENC28J60_WritePhy(uint8_t reg, uint16_t dat){    ENC28J60_WriteReg(2,MIREGADR,reg);    ENC28J60_WriteReg(2,MIWRL,dat&0xFF);    ENC28J60_WriteReg(2,MIWRH,dat>>8);    while(ENC28J60_ReadReg(2,MISTAT)&0x01);}uint16_t ENC28J60_ReadPhy(uint8_t reg){    uint16_t dat;    ENC28J60_WriteReg(2,MIREGADR,reg);    ENC28J60_WriteReg(2,MICMD,0x01);    while(ENC28J60_ReadReg(2,MISTAT)&0x01);    ENC28J60_WriteReg(2,MICMD,0);    dat = (ENC28J60_ReadReg(2,MIRDH)<<8)|ENC28J60_ReadReg(2,MIRDL);    return dat;}void ENC28J60_Reset(void){    ENC_RST = 0;    Delay_ms(10);    ENC_RST = 1;    Delay_ms(50);    ENC_CS = 0;    SPI_RW_Byte(ENC_SR);    ENC_CS = 1;    Delay_ms(10);}void ENC28J60_Init(NET_CFG *cfg){    ENC28J60_Reset();    ENC28J60_WriteReg(0,ERXST,RXSTART_INIT&0xFF);    ENC28J60_WriteReg(0,ERXST+1,RXSTART_INIT>>8);    ENC28J60_WriteReg(0,ERXND,RXSTOP_INIT&0xFF);    ENC28J60_WriteReg(0,ERXND+1,RXSTOP_INIT>>8);    ENC28J60_WriteReg(0,ERXRDPT,RXSTART_INIT&0xFF);    ENC28J60_WriteReg(0,ERXRDPT+1,RXSTART_INIT>>8);    ENC28J60_WriteReg(0,ERXWRPT,RXSTART_INIT&0xFF);    ENC28J60_WriteReg(0,ERXWRPT+1,RXSTART_INIT>>8);    ENC28J60_WriteReg(0,ETXST,TXSTART_INIT&0xFF);    ENC28J60_WriteReg(0,ETXST+1,TXSTART_INIT>>8);    ENC28J60_WriteReg(0,ETXND,TXSTOP_INIT&0xFF);    ENC28J60_WriteReg(0,ETXND+1,TXSTOP_INIT>>8);    ENC28J60_WriteReg(1,MACON1,0x02);    ENC28J60_WriteReg(1,MACON3,0xD2);    ENC28J60_WriteReg(1,MACON4,0x00);    ENC28J60_WriteReg(1,MABBIPG,0x12);    ENC28J60_WriteReg(1,MAIPG,0x00);    ENC28J60_WriteReg(1,MAIPG+1,0x12);    ENC28J60_WriteReg(1,MAMXFL,0x06);    ENC28J60_WriteReg(1,MAMXFL+1,0x40);    ENC28J60_WriteReg(1,MAADR1,cfg->mac[0]);    ENC28J60_WriteReg(1,MAADR2,cfg->mac[1]);    ENC28J60_WriteReg(1,MAADR3,cfg->mac[2]);    ENC28J60_WriteReg(1,MAADR4,cfg->mac[3]);    ENC28J60_WriteReg(1,MAADR5,cfg->mac[4]);    ENC28J60_WriteReg(1,MAADR6,cfg->mac[5]);    ENC28J60_WritePhy(0,0x1100);    ENC28J60_WritePhy(1,0x2000);    ENC28J60_WritePhy(2,0x0000);    ENC28J60_WritePhy(3,0x0000);    ENC28J60_WritePhy(4,0x0100);    ENC28J60_WritePhy(5,0x0000);    ENC28J60_WriteReg(0,ERXFCON,0x80);    ENC28J60_WriteReg(0,ECON1,0x01);    UART_SendStr("ENC28J60 init ok\r\n");}uint8_t ENC28J60_ReadPacket(uint8_t *buf, uint16_t maxlen, uint16_t *rx_len){    uint16_t rdptr,len;    uint8_t status;    if(ENC28J60_ReadReg(0,EPKTCNT)==0) return 0;    ENC_CS = 0;    SPI_RW_Byte(ENC_RBM);    rdptr = SPI_RW_Byte(0xFF);    rdptr |= (SPI_RW_Byte(0xFF)<<8);    len = SPI_RW_Byte(0xFF);    len |= (SPI_RW_Byte(0xFF)<<8);    status = SPI_RW_Byte(0xFF);    len -=4;    if(len>maxlen) len = maxlen;    for(uint16_t i=0;i<len;i++) buf = SPI_RW_Byte(0xFF);    ENC_CS = 1;    *rx_len = len;    rdptr += len +4;    ENC28J60_WriteReg(0,ERXRDPT,rdptr&0xFF);    ENC28J60_WriteReg(0,ERXRDPT+1,rdptr>>8);    ENC28J60_WriteReg(0,ECON2,0x01);    return 1;}void ENC28J60_SendPacket(uint8_t *buf, uint16_t len){    uint16_t i;    ENC28J60_WriteReg(0,ETXST, TXSTART_INIT&0xFF);    ENC28J60_WriteReg(0,ETXST+1,TXSTART_INIT>>8);    ENC28J60_WriteReg(0,ETXND, (TXSTART_INIT+len)&0xFF);    ENC28J60_WriteReg(0,ETXND+1,(TXSTART_INIT+len)>>8);    ENC_CS = 0;    SPI_RW_Byte(ENC_WBM);    SPI_RW_Byte(0x00);    for(i=0;i<len;i++) SPI_RW_Byte(buf);    ENC_CS = 1;    ENC28J60_WriteReg(0,ECON1,0x02);    while(ENC28J60_ReadReg(0,ECON1)&0x02);}//==== EEPROM CRC读写 ====uint16_t CFG_Calc_CRC(NET_CFG *cfg){    uint16_t sum=0;    uint8_t *p = (uint8_t*)cfg;    for(uint16_t i=0; i<sizeof(NET_CFG)-2; i++)    {        sum += p;    }    return sum;}uint8_t EEPROM_Read_Byte(uint16_t addr){    IAP_ADDRH = addr >> 8;    IAP_ADDRL = addr & 0xFF;    IAP_CMD = 0x01;    IAP_TRIG = 0x5A;    IAP_TRIG = 0xA5;    return IAP_DATA;}void EEPROM_Write_Byte(uint16_t addr, uint8_t dat){    IAP_ADDRH = addr >> 8;    IAP_ADDRL = addr & 0xFF;    IAP_DATA = dat;    IAP_CMD = 0x02;    IAP_TRIG = 0x5A;    IAP_TRIG = 0xA5;    IAP_CMD = 0x00;}uint8_t EEPROM_Save_New_Cfg(NET_CFG *newcfg){    uint16_t write_pos = 0;    NET_CFG_T temp;    uint16_t cfg_size = sizeof(NET_CFG);    newcfg->magic = CFG_HEAD_MAGIC;    newcfg->crc = CFG_Calc_CRC(newcfg);    for(write_pos = 0; write_pos <= EEPROM_SIZE - cfg_size; write_pos += cfg_size)    {        NET_CFG temp;        uint8_t *p = (uint8_t*)&temp;        for(uint16_t i=0; i<cfg_size; i++)        {            p = EEPROM_Read_Byte(write_pos+i);        }        if(temp.magic != CFG_HEAD_MAGIC) break;    }    if(write_pos > EEPROM_SIZE - cfg_size)    {        write_pos = 0;    }    uint8_t *p = (uint8_t*)newcfg;    for(uint16_t i=0; i<cfg_size; i++)    {        EEPROM_Write_Byte(write_pos+i, p);    }    UART_SendStr("Save config ok\r\n");    return 1;}uint8_t EEPROM_Load_Last_Cfg(NET_CFG *outcfg){    uint16_t read_pos = 0;    uint16_t last_valid = 0xFFFF;    uint16_t cfg_size = sizeof(NET_CFG);    memset(outcfg, 0, sizeof(NET_CFG));    for(read_pos = 0; read_pos <= EEPROM_SIZE - cfg_size; read_pos += cfg_size)    {        NET_CFG temp;        uint8_t *p = (uint8_t*)&temp;        for(uint16_t i=0; i<cfg_size; i++)        {            p = EEPROM_Read_Byte(read_pos+i);        }        if(temp.magic == CFG_HEAD_MAGIC && temp.crc == CFG_Calc_CRC(&temp))        {            last_valid = read_pos;        }    }    if(last_valid == 0xFFFF)    {        UART_SendStr("No valid cfg, load default\r\n");        outcfg->magic = CFG_HEAD_MAGIC;        outcfg->mac[0]=0x00;outcfg->mac[1]=0x08;outcfg->mac[2]=0xdc;        outcfg->mac[3]=0x11;outcfg->mac[4]=0x22;outcfg->mac[5]=0x34;        outcfg->ip[0]=192;outcfg->ip[1]=168;outcfg->ip[2]=1;outcfg->ip[3]=100;        outcfg->mask[0]=255;outcfg->mask[1]=255;outcfg->mask[2]=255;outcfg->mask[3]=0;        outcfg->gw[0]=192;outcfg->gw[1]=168;outcfg->gw[2]=1;outcfg->gw[3]=1;        outcfg->local_port = 8080;        outcfg->remote_ip[0]=192;outcfg->remote_ip[1]=168;outcfg->remote_ip[2]=1;outcfg->remote_ip[3]=200;        outcfg->remote_port = 8080;        outcfg->mode = 0;        strcpy((char*)outcfg->web_pwd,"123456");        outcfg->idle_timeout = 1000;        outcfg->crc = CFG_Calc_CRC(outcfg);        EEPROM_Save_New_Cfg(outcfg);        return 0;    }    uint8_t *p = (uint8_t*)outcfg;    for(uint16_t i=0; i<cfg_size; i++)    {        p = EEPROM_Read_Byte(last_valid+i);    }    UART_SendStr("Load last config ok\r\n");    return 1;}//==== URL解码 ====uint8_t hex2byte(uint8_t c){    if(c >= '0' && c <= '9') return c-'0';    if(c >= 'A' && c <= 'F') return c-'A'+10;    if(c >= 'a' && c <= 'f') return c-'a'+10;    return 0;}void UrlDecode(uint8_t *dst, uint8_t *src){    while(*src)    {        if(*src == '%')        {            src++;            *dst = (hex2byte(*src) <<4) | hex2byte(*(src+1));            src+=2;        }else if(*src == '+')        {            *dst = ' ';            src++;        }else{            *dst = *src;            src++;        }        dst++;    }    *dst = 0;}//==== WEB网页页面 ====const char login_page[] ="HTTP/1.1 200 OK\r\nContent-Type:text/html;charset=utf-8\r\n\r\n""<html><head><meta charset='utf-8'><title>登录</title></head>""<body><h2>ENC28J60 网页登录</h2>""<form method='post'>""密码:<input name='pwd' type='password'><br>""<input type='submit' value='登录'>""</form></body></html>";const char pwd_err_page[] ="HTTP/1.1 200 OK\r\nContent-Type:text/html;charset=utf-8\r\n\r\n""<html><body><h3>密码错误!</h3><a href='/'>返回登录</a></body></html>";const char save_ok_page[] ="HTTP/1.1 200 OK\r\nContent-Type:text/html;charset=utf-8\r\n\r\n""<html><body><h3>参数保存成功!重启单片机生效</h3><a href='/'>返回配置页</a></body></html>";void Web_Send_LoginPage(void){    memcpy(uip_appdata, login_page, strlen(login_page));    uip_send(uip_appdata, strlen(login_page));}void Web_Send_PwdErr(void){    memcpy(uip_appdata, pwd_err_page, strlen(pwd_err_page));    uip_send(uip_appdata, strlen(pwd_err_page));}void Web_Send_SaveOk(void){    memcpy(uip_appdata, save_ok_page, strlen(save_ok_page));    uip_send(uip_appdata, strlen(save_ok_page));}void Web_Send_ConfigPage(void){    uint8_t tmpbuf[768];    sprintf((char*)tmpbuf,    "HTTP/1.1 200 OK\r\nContent-Type:text/html;charset=utf-8\r\n\r\n"    "<html><head><meta charset='utf-8'><title>STC32G ENC28J60配置</title></head>"    "<body>"    "<h2>网络参数设置</h2>"    "<form method='post'>"    "MAC:%02x:%02x:%02x:%02x:%02x:%02x<br>"    "本机IP:<input name='ip' value='%d.%d.%d.%d'><br>"    "子网掩码:<input name='sn' value='%d.%d.%d.%d'><br>"    "网关:<input name='gw' value='%d.%d.%d.%d'><br>"    "TCP服务端口:<input name='sport' value='%d'><br>"    "客户端目标IP:<input name='cip' value='%d.%d.%d.%d'><br>"    "客户端目标端口:<input name='cport' value='%d'><br>"    "模式(0服务端/1客户端):<input name='mode' value='%d'><br>"    "TCP空闲超时(10ms单位):<input name='idleto' value='%d'><br>"    "网页密码:<input name='webpwd' value='%s'><br>"    "<input type='submit' value='保存配置'><br>"    "<p>保存后重启生效</p>"    "</form></body></html>",    g_netcfg.mac[0],g_netcfg.mac[1],g_netcfg.mac[2],g_netcfg.mac[3],g_netcfg.mac[4],g_netcfg.mac[5],    g_netcfg.ip[0],g_netcfg.ip[1],g_netcfg.ip[2],g_netcfg.ip[3],    g_netcfg.mask[0],g_netcfg.mask[1],g_netcfg.mask[2],g_netcfg.mask[3],    g_netcfg.gw[0],g_netcfg.gw[1],g_netcfg.gw[2],g_netcfg.gw[3],    g_netcfg.local_port,    g_netcfg.remote_ip[0],g_netcfg.remote_ip[1],g_netcfg.remote_ip[2],g_netcfg.remote_ip[3],    g_netcfg.remote_port,    g_netcfg.mode,    g_netcfg.idle_timeout,    g_netcfg.web_pwd    );    memcpy(uip_appdata, tmpbuf, strlen((char*)tmpbuf));    uip_send(uip_appdata, strlen((char*)tmpbuf));}void Web_Parse_Post(uint8_t *buf, uint16_t len){    uint8_t decode_buf[512];    UrlDecode(decode_buf, buf);    if(strstr((char*)decode_buf,"pwd="))    {        char pwd[16];        sscanf((char*)decode_buf,"pwd=%s",pwd);        if(strcmp(pwd,(char*)g_netcfg.web_pwd)==0)        {            Web_Send_ConfigPage();        }else{            Web_Send_PwdErr();        }        return;    }    if(strstr((char*)decode_buf,"ip="))    {        uint8_t new_ip[4], new_sn[4], new_gw[4], new_cip[4];        uint16_t new_sp, new_cp, new_idleto;        uint8_t new_mode;        char new_pwd[16];        sscanf((char*)decode_buf,        "ip=%d.%d.%d.%d&sn=%d.%d.%d.%d&gw=%d.%d.%d.%d&sport=%d&cip=%d.%d.%d.%d&cport=%d&mode=%d&idleto=%d&webpwd=%s",        &new_ip[0],&new_ip[1],&new_ip[2],&new_ip[3],        &new_sn[0],&new_sn[1],&new_sn[2],&new_sn[3],        &new_gw[0],&new_gw[1],&new_gw[2],&new_gw[3],        &new_sp,        &new_cip[0],&new_cip[1],&new_cip[2],&new_cip[3],        &new_cp,        &new_mode,        &new_idleto,        new_pwd);        if(new_idleto < 200) new_idleto = 200;        memcpy(g_netcfg.ip, new_ip,4);        memcpy(g_netcfg.mask, new_sn,4);        memcpy(g_netcfg.gw, new_gw,4);        memcpy(g_netcfg.remote_ip, new_cip,4);        g_netcfg.local_port = new_sp;        g_netcfg.remote_port = new_cp;        g_netcfg.mode = new_mode;        g_netcfg.idle_timeout = new_idleto;        strncpy((char*)g_netcfg.web_pwd, new_pwd,15);        g_netcfg.web_pwd[15]=0;        EEPROM_Save_New_Cfg(&g_netcfg);        Web_Send_SaveOk();    }}void HTTP_Web_Task(void){    if(uip_newdata())    {        if(strstr((char*)uip_appdata,"POST"))        {            Web_Parse_Post(uip_appdata, uip_datalen());        }        else if(strstr((char*)uip_appdata,"GET"))        {            Web_Send_LoginPage();        }    }}//====串口延时====void UART1_Init(void){    SCON = 0x50;    TMOD |= 0x20;    TH1 = 0xF3; TL1 = 0xF3; TR1 = 1;}void UART_SendByte(uint8_t ch){    SBUF = ch; while(!TI); TI=0;}void UART_SendStr(char *s){    while(*s) UART_SendByte(*s++);}void UART_PrintNum(uint16_t n){    char tmp[8];    sprintf(tmp,"%d",n);    UART_SendStr(tmp);}void Delay_ms(uint32_t ms){    uint32_t i,j;    for(i=0;i<ms;i++) for(j=0;j<1200;j++);}uip.h#ifndef __UIP_H__#define __UIP_H__#include <stdint.h>#define UIP_BUFSIZE 600#define UIP_ETHTYPE_IP 0x0800#define UIP_ETHTYPE_ARP 0x0806#define UIP_PROTO_TCP 6#define UIP_PROTO_IP 4typedef union uip_ipaddr_t{    uint8_t u8[4];    uint16_t u16[2];}uip_ipaddr_t;#define HTONS(n) (((n) << 8) | ((n) >> 8))#define UIP_IPADDR(p,a,b,c,d) do{(p)->u8[0]=a;(p)->u8[1]=b;(p)->u8[2]=c;(p)->u8[3]=d;}while(0)void uip_init(void);void uip_setethaddr(uint8_t *mac);void uip_sethostaddr(uip_ipaddr_t *addr);void uip_setnetmask(uip_ipaddr_t *mask);void uip_setgwaddr(uip_ipaddr_t *gw);void uip_listen(uint16_t port);void uip_connect(uip_ipaddr_t *rip, uint16_t rport);void uip_close(void);void uip_input(void);void uip_send(void *data, uint16_t len);extern uint8_t uip_buf[UIP_BUFSIZE];extern uint16_t uip_len;extern struct uip_conn *uip_conn;extern void *uip_appdata;extern uint16_t uip_datalen;#define uip_newdata() (uip_datalen>0)#define uip_rexmit() 0#define uip_poll() 0#define uip_acked() 0struct uip_conn{    uip_ipaddr_t rip;    uint16_t rport;    uint16_t lport;    uint8_t state;};#endifuip.c#include "uip.h"#include "uip_arp.h"uint8_t uip_buf[UIP_BUFSIZE];uint16_t uip_len = 0;struct uip_conn *uip_conn = NULL;void *uip_appdata;uint16_t uip_datalen = 0;static uint8_t ethaddr[6];static uip_ipaddr_t hostaddr;static uip_ipaddr_t netmask;static uip_ipaddr_t gwaddr;static uint16_t listen_port = 0;static struct uip_conn conn;#define TCP_SYN 0x02#define TCP_ACK 0x10#define TCP_FIN 0x01#define TCP_RST 0x04enum TCP_STATE{CLOSED,LISTEN,SYN_RCVD,ESTABLISHED,FIN_WAIT,CLOSING,TIME_WAIT,CLOSE_WAIT,LAST_ACK};void uip_setethaddr(uint8_t *mac){    memcpy(ethaddr,mac,6);}void uip_sethostaddr(uip_ipaddr_t *addr){    memcpy(&hostaddr,addr,4);}void uip_setnetmask(uip_ipaddr_t *mask){    memcpy(&netmask,mask,4);}void uip_setgwaddr(uip_ipaddr_t *gw){    memcpy(&gwaddr,gw,4);}void uip_listen(uint16_t port){    listen_port = port;    conn.state = LISTEN;    conn.lport = port;    uip_conn = &conn;}void uip_close(void){    conn.state = CLOSED;    uip_conn = NULL;    uip_len = 0;}void uip_connect(uip_ipaddr_t *rip, uint16_t rport){    memcpy(&conn.rip,rip,4);    conn.rport = rport;    conn.lport = listen_port;    conn.state = SYN_RCVD;    uip_conn = &conn;}void uip_init(void){    uip_len = 0;    uip_conn = NULL;    conn.state = CLOSED;}void uip_input(void){    uint16_t type = (uip_buf[12]<<8)|uip_buf[13];    uip_datalen = 0;    if(type == UIP_ETHTYPE_ARP)    {        uip_arp_arpin();        return;    }    if(type == UIP_ETHTYPE_IP)    {        uint8_t iplen = (uip_buf[14]&0x0F)*4;        uint8_t proto = uip_buf[23];        if(proto == UIP_PROTO_TCP)        {            uint16_t tcp_hdr_len = ((uip_buf[14+iplen+12]>>4))*4;            uip_appdata = &uip_buf[14+iplen + tcp_hdr_len];            uip_datalen = uip_len - (14+iplen+tcp_hdr_len);        }    }}void uip_send(void *data, uint16_t len){    memcpy(uip_appdata, data, len);    uip_len = len;}uip_arp.h#ifndef __UIP_ARP_H#define __UIP_ARP_H#include "uip.h"void uip_arp_ipin(void);void uip_arp_arpin(void);void uip_arp_out(void);#endifuip_arp.c#include "uip_arp.h"#include "enc28j60.h"#define ARP_REQUEST 1#define ARP_REPLY 2typedef struct{    uint16_t hwtype;    uint16_t proto;    uint8_t hwlen,protolen;    uint16_t op;    uint8_t senderhwaddr[6];    uint8_t senderipaddr[4];    uint8_t targethwaddr[6];    uint8_t targetipaddr[4];}arp_hdr;void uip_arp_ipin(void){}void uip_arp_arpin(void){    arp_hdr *arp = (arp_hdr*)(uip_buf+14);    if(arp->op == ARP_REQUEST)    {        memcpy(&uip_buf[0], arp->senderhwaddr,6);        memcpy(&uip_buf[6], g_netcfg.mac,6);        uip_buf[12]=0x08;uip_buf[13]=0x06;        arp->op = HTONS(ARP_REPLY);        memcpy(arp->targethwaddr, arp->senderhwaddr,6);        memcpy(arp->targetipaddr, arp->senderipaddr,4);        memcpy(arp->senderhwaddr, g_netcfg.mac,6);        memcpy(arp->senderipaddr, g_netcfg.ip,4);        uip_len = 14+sizeof(arp_hdr);    }}void uip_arp_out(void){}main.c#include "enc28j60.h"#include "uip.h"#include "uip_arp.h"#define BUF_SIZE UIP_BUFSIZEstatic uint8_t buf[BUF_SIZE];static uint16_t idle_tick = 0;static uint16_t reconnect_tick = 0;void tcp_server_init(uint16_t port){    uip_init();    uip_setethaddr(g_netcfg.mac);    uip_ipaddr_t ip,mask,gw;    UIP_IPADDR(&ip, g_netcfg.ip[0],g_netcfg.ip[1],g_netcfg.ip[2],g_netcfg.ip[3]);    UIP_IPADDR(&mask,g_netcfg.mask[0],g_netcfg.mask[1],g_netcfg.mask[2],g_netcfg.mask[3]);    UIP_IPADDR(&gw, g_netcfg.gw[0],g_netcfg.gw[1],g_netcfg.gw[2],g_netcfg.gw[3]);    uip_sethostaddr(&ip);    uip_setnetmask(&mask);    uip_setgwaddr(&gw);    uip_listen(HTONS(port));    UART_SendStr("TCP Server listen port:");    UART_PrintNum(port);    UART_SendStr("\r\n");}void tcp_client_connect(uint8_t *rip, uint16_t rport){    uip_ipaddr_t server_ip;    UIP_IPADDR(&server_ip, rip[0],rip[1],rip[2],rip[3]);    uip_connect(&server_ip, HTONS(rport));    UART_SendStr("TCP Client connect to ");    UART_PrintNum(rip[0]);UART_SendByte('.');    UART_PrintNum(rip[1]);UART_SendByte('.');    UART_PrintNum(rip[2]);UART_SendByte('.');    UART_PrintNum(rip[3]);UART_SendStr(":");    UART_PrintNum(rport);UART_SendStr("\r\n");}void tcp_close_conn(void){    uip_close();    idle_tick = 0;}void tcp_task(void){    uint16_t rxlen;    if(ENC28J60_ReadPacket(buf,BUF_SIZE,&rxlen))    {        memcpy(uip_buf,buf,rxlen);        uip_len = rxlen;        uip_arp_ipin();        uip_input();        HTTP_Web_Task();        if(uip_len>0)        {            uip_arp_out();            ENC28J60_SendPacket(uip_buf,uip_len);            uip_len = 0;        }        idle_tick = 0;    }    if(uip_conn != NULL)    {        if(uip_newdata())        {            UART_SendStr("TCP RX:");            UART_SendStr((char*)uip_appdata);            UART_SendStr("\r\n");            uip_send(uip_appdata, uip_datalen());        }        idle_tick++;        if(idle_tick >= g_netcfg.idle_timeout)        {            UART_SendStr("TCP idle timeout, close connection\r\n");            tcp_close_conn();            idle_tick = 0;        }        if(uip_len>0)        {            ENC28J60_SendPacket(uip_buf,uip_len);            uip_len = 0;        }    }    else    {        if(g_netcfg.mode == 1)        {            reconnect_tick++;            if(reconnect_tick > 200)            {                reconnect_tick = 0;                UART_SendStr("Client reconnect attempt\r\n");                tcp_client_connect(g_netcfg.remote_ip, g_netcfg.remote_port);            }        }    }}void main(void){    IAP_CONTR = 0x80;    UART1_Init();    SPI_HW_Init();    UART_SendStr("STC32G+ENC28J60 Start\r\n");    EEPROM_Load_Last_Cfg(&g_netcfg);    ENC28J60_Init(&g_netcfg);    if(g_netcfg.mode == 0)    {        tcp_server_init(g_netcfg.local_port);    }else{        uip_init();        uip_setethaddr(g_netcfg.mac);        uip_ipaddr_t ip,mask,gw;        UIP_IPADDR(&ip, g_netcfg.ip[0],g_netcfg.ip[1],g_netcfg.ip[2],g_netcfg.ip[3]);        UIP_IPADDR(&mask,g_netcfg.mask[0],g_netcfg.mask[1],g_netcfg.mask[2],g_netcfg.mask[3]);        UIP_IPADDR(&gw, g_netcfg.gw[0],g_netcfg.gw[1],g_netcfg.gw[2],g_netcfg.gw[3]);        uip_sethostaddr(&ip);        uip_setnetmask(&mask);        uip_setgwaddr(&gw);    }    while(1)    {        tcp_task();        Delay_ms(10);    }}工程使用说明
  • 工程文件清单:
  • enc28j60.h / enc28j60.c
  • uip.h / uip.c
  • uip_arp.h / uip_arp.c
  • main.c
  • 上电逻辑
  • 上电读取 EEPROM 保存的网络参数;无有效配置自动加载默认参数并保存到 EEPROM
  • 打开浏览器访问本机 IP(默认 192.168.1.100),密码123456,可以修改:MAC、IP、掩码、网关、TCP 端口、服务器 / 客户端模式、空闲超时时间
  • 提交保存参数,重启单片机生效
  • 功能✅ TCP 服务器:同一时间只能 1 个 TCP 客户端接入,超过空闲超时无数据自动断开,可以等待下一个客户端✅ TCP 客户端:断线自动重连远端 TCP 服务器✅ 网页配置所有网络参数,参数保存到片内 EEPROM,断电不丢失✅ 串口打印调试信息,115200 波特

回复

使用道具 举报 送花

54

主题

1481

回帖

3727

积分

超级版主

积分
3727
发表于 2026-10-9 11:32:34 | 显示全部楼层
用STCAI助手,少走弯路
将程序和图片/最多5张,放到  STC 【AI 助手】,已加载 STC全系列MCU专业技术手册。
help.stcaimcu.com
可以帮您:
- 回答STC技术手册中的技术问题
- 自动生成您需要的通用MCU程序
- 自动高效排查您程序中的错误
STC官网:https://www.stcai.com/
QQ:2593903262
微信号:18106296598
回复

使用道具 举报 送花

54

主题

1481

回帖

3727

积分

超级版主

积分
3727
发表于 2026-10-9 11:33:00 | 显示全部楼层
https://www.stcaimcu.com/thread-25629-1-1.html
初学STC89C52系列的同学线上研讨会,
分享了快速上手32位Ai8051U学习经验,
录屏保存至本贴希望可以帮助更多需要进一步学习Ai8051U的朋友。

视频大致内容总结:
1.论坛各功能区简介、芯片手册下载、工具下载、例程包下载、教学视频区等
2.Ai8051U最小系统、串口下载、usb下载、串口&usb仿真流程等介绍
3.STC AiCube、Ai助手、在线IDE等使用介绍
4.使用STC Ai助手、DeepSeek Harness、Trae 等Ai工具辅助开发学习,
   Ai手册解读、代码查错、编译问题定位、编程等用法演示。
STC官网:https://www.stcai.com/
QQ:2593903262
微信号:18106296598
回复

使用道具 举报 送花

已绑定手机

19

主题

3564

回帖

7698

积分

论坛元老

积分
7698
发表于 2026-10-9 21:22:30 | 显示全部楼层
只要能编译通过应该可以用
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-8 03:07 , Processed in 0.073150 second(s), 53 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表