搜索
bottom↓
回复: 9

裸机STM32+LWIP1.3.2+DM9000A数据收发一段时间后卡住的问题

[复制链接]

出0入0汤圆

发表于 2013-11-2 20:42:06 | 显示全部楼层 |阅读模式
一、硬件平台及配置情况
CPU:STM32F103ZET
ETH:DM9000A
LWIP版本:1.3.2
开发板运行TCP服务端,IP为192.168.1.10端口为1026,PC运行TCP客户端,IP为192.168.1.2。
PC端测试软件为:网络调试助手 V3.7
软件运行时选择tcpclient模式,连接到服务器的IP为192.168.1.10端口为1026,能够连接成功。
然后以十六进制数据流(发送间隔500ms)发送0xaa 0x01 0x02 0x03,没法送一次以上数据,接收端就会收到4096字节数据。

二、问题描述
问题是运行几分钟后就只有发送没有接收了,也ping不通了。

三、上代码

//-----------------------------------------------------------------------------
// 入口
//-----------------------------------------------------------------------------
int main(void)
{
        SystemInit();
        LED_Config();
        InitUsart(115200);
        LwIpInit();
        LED_Loop();
        Tcp_Server_Init();
        SysTick_Config(72000000/1000);
        printf(        "Lwip TcpServer Started
"\n                        "Server IP:192.168.1.10
"\n                        "Server Port:1026

"
                  );
        while (1)
        {
                ethernetif_input(&netif);// 读取eth的数据包
                LwIP_Periodic_Handle(SystermTime);// tcp老化处理(250ms跟5000ms的tcp老化程序)
                if(1 == ETH_RX_CMP)
                {
                        ETH_RX_CMP = 0;
                        Eth_Data_Handle();
                }
        }
}

//-----------------------------------------------------------------------------
// 接收到数据解析
//-----------------------------------------------------------------------------
static void Eth_Data_Handle(void)
{
        if(eth_rev_buff[1] == 0x01)
        {
                if(eth_send_ok == 1)
                {
                        Eth_Send(eth_send_buff,4096);
                        eth_send_ok = 0;
                }
        }
        th_rev_buff[1] = 0;
}

//-----------------------------------------------------------------------------
// 初始化
//-----------------------------------------------------------------------------
void Tcp_Server_Init(void)
{
   struct tcp_pcb *pcb;

   /* Create a new TCP control block  */
   pcb = tcp_new();
   
   /* Bind the pcb to the port */
   /* Using IP_ADDR_ANY allow the pcb to be used by any local interface */
   tcp_bind(pcb, IP_ADDR_ANY, 1026);
                                                                                     
   pcb = tcp_listen(pcb);                                // 将此tcp连接移至侦听tcp队列中去        
   tcp_accept(pcb, tcp_server_accept);        // 初始化pcb->accept
}

//-----------------------------------------------------------------------------
// 回调函数 连接响应
//-----------------------------------------------------------------------------
err_t tcp_server_accept(void *arg, struct tcp_pcb *pcb,err_t err)
{
        tcp_server_pcb = pcb;                                // 将此PCB保存
        tcp_setprio(pcb,TCP_PRIO_MIN);
        tcp_recv(pcb,tcp_server_recv);
        tcp_write(pcb,Connect_data,sizeof(Connect_data),0);
        tcp_output(pcb);                                        // 立即发送数据
        tcp_sent(tcp_server_pcb,tcp_sended);// 发送成功后本函数的回调函数会被调用
        err = ERR_OK;
        return err;
}

//-----------------------------------------------------------------------------
// 回调函数 接收数据
//-----------------------------------------------------------------------------
err_t tcp_server_recv(void *arg, struct tcp_pcb *pcb,struct pbuf *p,err_t err)
{
        unsigned int i;
        tcp_server_pcb = pcb;                                // 将此PCB保存
        if(p != NULL)
        {
                eth_rev_len = p->len;
                if(eth_rev_len <= 1024)
                {
                        for(i=0;i<eth_rev_len;i++)
                        {
                                eth_rev_buff=*((char *)p->payload+i);
                        }                         
                        tcp_recved(pcb,eth_rev_len);
                        ETH_RX_CMP = 1;        // 收到数据了
                }   
        }
        pbuf_free(p);                         // 释放PBUF
        err = ERR_OK;
        return err;
}

//-----------------------------------------------------------------------------
// 回调函数 数据发送成功
//-----------------------------------------------------------------------------
err_t tcp_sended(void *arg, struct tcp_pcb *pcb,u16_t len)
{
//        printf("Data Sended Len = %d
",len);
        Init_Data();
        eth_send_ok = 1;
        return ERR_OK;
}

//-----------------------------------------------------------------------------
// ETH发送
//-----------------------------------------------------------------------------
void Eth_Send(unsigned char *p,unsigned int len)
{
        tcp_write(tcp_server_pcb,p,len,0);                // 放入队列 最大字节在“lwipopt.h”中设置
        tcp_output(tcp_server_pcb);                                // 立即发送
        tcp_sent(tcp_server_pcb,tcp_sended);        // 发送成功后本函数的回调函数会被调用
}

//-----------------------------------------------------------------------------
// 生成数据
//-----------------------------------------------------------------------------
void Init_Data(void)
{
        unsigned int i;

        for(i=0;i<4096;i++)
        {
                eth_send_buff = i;
        }
        eth_send_buff[0] = 0xAA;
        eth_send_buff[1] = 0xAA;
        eth_send_buff[2] = 0x10;
        eth_send_buff[3] = 0x00;
}

//-----------------------------------------------------------------------------
// 系统滴答
//-----------------------------------------------------------------------------
void SysTick_Handler(void)
{
        SystermTime++;       
}

//-----------------------------------------------------------------------------
// TCP老化
//-----------------------------------------------------------------------------
void LwIP_Periodic_Handle(__IO uint32_t localtime)
{
        /* TCP periodic process every 250 ms */
          if ((localtime - TCPTimer) >= 250)//TCP_TMR_INTERVAL)               
          {
            TCPTimer =  localtime;
//                printf("TCPTimer = %d\n",TCPTimer);
            tcp_tmr();
                        /* ARP periodic process every 5s */
                  if ((localtime - ARPTimer) >= 5000)//ARP_TMR_INTERVAL)
                  {
                    ARPTimer =  localtime;
//                        printf("ARPTimer = %d\n",ARPTimer);
                    etharp_tmr();
                  }
          }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2013-11-3 14:10:14 | 显示全部楼层
希望我的帖子不要沉了

出0入0汤圆

发表于 2013-11-4 08:35:10 | 显示全部楼层
楼主你的tcp老化是什么意思

收发都是靠eth_send_buff、eth_rev_buff吗   

建议驱动参考rtt的,那个驱动写的还可以  我移植过freertos下lwip很稳定的说

出0入0汤圆

 楼主| 发表于 2013-11-4 12:55:05 | 显示全部楼层
lyzhangxiang 发表于 2013-11-4 08:35
楼主你的tcp老化是什么意思

收发都是靠eth_send_buff、eth_rev_buff吗   

1、TCP老化是指每250ms 调用tcp_tmr();每5000ms调用etharp_tmr();
2、收发都是用的eth_send_buff、eth_rev_buff,不拷贝。

出0入0汤圆

发表于 2013-11-10 22:10:24 | 显示全部楼层
请问 我做的 Dm9000AEP  为什么读取MRCMDX中的数据  数据帧的长度信息是高地址在前,低地址在后?   可是从数据手册上看  是低地址在前呀?

出0入0汤圆

发表于 2013-11-11 05:56:00 | 显示全部楼层
建议使用MICREL KSZ8851SNL 。

做2个实验:
1. 不插网线,系统启动完成之后,插网线,拔网线,连续插拔100次,看看网络link 成功次数。
2. 2KV 4KV静电打击测试

比较一下你使用的芯片与MICREL  SMSC公司网络接口芯片的区别。

出0入0汤圆

发表于 2013-11-13 07:13:23 | 显示全部楼层
研究学习用台系芯片可以,但真正做产品,推荐用micrel ksz8851snl  ,SPI 接口,线路简单,接口稳定性好。或者选用SMSC LAN9221之类的。
在稳定性及可用性方面比台系芯片强很多。并且相应的软件资源更丰富.

做出来的产品  4KV 静电干扰测试,台系芯片抗静电性能与美系芯片性能比较?
不插网线,系统加电启动完成后,再插网线,看是否能正常连接,反复插拔网线,看看哪一家芯片每次都可以正常连接 ?

工控产品选美系的绝对是节约成本,减少系统维护成本。

出100入101汤圆

发表于 2013-11-13 09:40:51 | 显示全部楼层
qftek 发表于 2013-11-13 07:13
研究学习用台系芯片可以,但真正做产品,推荐用micrel ksz8851snl  ,SPI 接口,线路简单,接口稳定性好。或 ...

micrel ksz8851snl,选工业级的话,有点贵。

出0入0汤圆

发表于 2013-11-14 10:51:40 | 显示全部楼层
fengyunyu 发表于 2013-11-13 09:40
micrel ksz8851snl,选工业级的话,有点贵。

工业级选哪家的会便宜呢 ? 再说台系的所谓工业级芯片根本就是与商用芯片同一条产品线生产出来的,你实际测试真的能达到工业级吗 ?

美系芯片 工业级一定是工业级,不会忽悠的。

严重建议:
MICREL KSZ8851SNL 性能、价格比台系芯片强很多,特别插拔不能link的bug不存在。另外SPI接口,硬件线路及软件驱动都容易。

WIZNET W5500 ,硬件集成TCP/IP协议栈。不要哪么费心费力去调试uIP lwIP之类的东东,硬件SPI接口,线路简单。

还有SMSC的相关芯片,性能超强。

哪些用台系芯片的,要好好考虑一下芯片BUG,及原厂及代理商是否能出质量承诺书,及硬件软件的复杂程度。有更好的,为什么选它 ?

出0入0汤圆

发表于 2015-9-2 10:22:42 | 显示全部楼层
qftek 发表于 2013-11-13 07:13
研究学习用台系芯片可以,但真正做产品,推荐用micrel ksz8851snl  ,SPI 接口,线路简单,接口稳定性好。或 ...

我用的是DM9000,4KV 静电干扰测试OK了,100次插拔也可以PING ,系统上电后再插也OK。求给个解释。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-25 20:12

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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