搜索
bottom↓
回复: 16

各位用过w5100的前辈,能不能帮我看下这段程序有问题否?

[复制链接]

出0入0汤圆

发表于 2013-2-9 10:56:19 | 显示全部楼层 |阅读模式
首先,先贴代码
#include"W5100.h"                                        /* 定义W5100的寄存器地址、状态 */
#include"REG51.h"
typedef unsigned char SOCKET;
#define S_RX_SIZE        2048                //定义Socket接收缓冲区的大小,可以根据W5100_RMSR的设置修改
#define S_TX_SIZE        2048                  //定义Socket发送缓冲区的大小,可以根据W5100_TMSR的设置修改
#define FALSE 0
#define TRUE 1
sbit     SPI_SCS= P1^5;
sbit     SPI_SCK= P1^2;
sbit     SPI_SO= P1^3;
sbit     SPI_SI= P1^4;
sbit     KEY= P1^7;
/* 端口数据缓冲区 */
unsigned char Rx_Buffer[16];                        /* 端口接收数据缓冲区 */
unsigned char Tx_Buffer[16];                        /* 端口发送数据缓冲区 */

/* 网络参数寄存器 */
unsigned char Gateway_IP[4]={192,168,10,1};                             /* Gateway IP Address */
unsigned char Sub_Mask[4]={255,255,255,0};                                /* Subnet Mask */
unsigned char Phy_Addr[6]={0x00,0x08,0xDC,0x01,0x02,0x03};                          /* Physical Address */
unsigned char IP_Addr[4]={192,168,10,40};                                /* Loacal IP Address */

unsigned char S0_Port[2]={0x1F,0x40};                         /* Socket0 Port number 5000 */
unsigned char S0_DIP[4]={192,168,10,41};                                /* Socket0 Destination IP Address */
unsigned char S0_DPort[2]={0x1F,0x40};                                 /* Socket0 Destination Port number 5000*/



unsigned char S0_State=0;                                /* Socket0 state recorder */


unsigned char S0_Data;                        /* Socket0 receive data and transmit OK */
unsigned char S_CONN=1;
unsigned char S_TRANSMITOK=2;
unsigned char S_RECEIVE=3        ;
unsigned char W5100_Interrupt;

/* UDP Destionation IP address and Port number */
unsigned char UDP_DIPR[4];
unsigned char UDP_DPORT[2];

void delayx10ms(unsigned int c)
{
        unsigned int i,j,k;
        for(i=0;i<c;i++)
                for(j=0;j<10;j++)
                        for(k=0;k<120;k++);
}


void SPI_SendByte(unsigned char dat)
{
   unsigned char i;

  for(i=0;i<8;i++)
  {
    if(dat&0x80)
      {
        SPI_SI=1;
      }
    else
      {
       SPI_SI=0;
     }
    SPI_SCK=1;
    dat<<=1;
    SPI_SCK=0;
  
  }
}
unsigned char Read_W5100(unsigned short addr)
{
        unsigned char i,j;

        /* 置W5100的CS为低电平 */
        SPI_SCS=0;

        /* 发送读命令 */
        SPI_SendByte(0x0f);

        /* 发送地址 */
        SPI_SendByte(addr/256);
        SPI_SendByte(addr);

        /* 读取数据 */
        j=0;
        for(i=0;i<8;i++)
        {
                SPI_SCK=1;
                j<<=1;
                if(SPI_SO)
                {
                        j|=0x01;
                        SPI_SCK=0;
                }               
        }

        /* 置W5100的CS为高电平 */
        SPI_SCS=1;
        return j;
}

void Write_W5100(unsigned short addr, unsigned char dat)
{
        /* 置W5100的CS为低电平 */
        SPI_SCS=0;
        /* 发送写命令 */
        SPI_SendByte(0xf0);
        /* 发送地址 */
        SPI_SendByte(addr/256);
        SPI_SendByte(addr);

        /* 写入数据 */
        SPI_SendByte(dat);
        /* 置W5100的CS为高电平 */
        SPI_SCS=1;
}

void W5100_Init(void)
{
        unsigned char i;
    SPI_SCK=0;SPI_SCS=1;SPI_SO=1;
        Write_W5100(W5100_MODE,MODE_RST);                /*软复位W5100*/

        delayx10ms(10);                                        /*延时100ms,自己定义该函数*/

        /*设置网关(Gateway)的IP地址,4字节 */
        /*使用网关可以使通信突破子网的局限,通过网关可以访问到其它子网或进入Internet*/
        for(i=0;i<4;i++)
                Write_W5100(W5100_GAR+i,Gateway_IP[i]);                        /*Gateway_IP为4字节unsigned char数组,自己定义*/
        for(i=0;i<4;i++)
                Gateway_IP[i]=Read_W5100(W5100_GAR+i);
        /*设置子网掩码(MASK)值,4字节。子网掩码用于子网运算*/
        for(i=0;i<4;i++)
                Write_W5100(W5100_SUBR+i,Sub_Mask[i]);                        /*SUB_MASK为4字节unsigned char数组,自己定义*/

        /*设置物理地址,6字节,用于唯一标识网络设备的物理地址值
        该地址值需要到IEEE申请,按照OUI的规定,前3个字节为厂商代码,后三个字节为产品序号
        如果自己定义物理地址,注意第一个字节必须为偶数*/
        for(i=0;i<6;i++)
                Write_W5100(W5100_SHAR+i,Phy_Addr[i]);                        /*PHY_ADDR6字节unsigned char数组,自己定义*/

        /*设置本机的IP地址,4个字节
        注意,网关IP必须与本机IP属于同一个子网,否则本机将无法找到网关*/
        for(i=0;i<4;i++)
                Write_W5100(W5100_SIPR+i,IP_Addr[i]);                        /*IP_ADDR为4字节unsigned char数组,自己定义*/

        /*设置发送缓冲区和接收缓冲区的大小,参考W5100数据手册*/
        Write_W5100(W5100_RMSR,0x55);                /*Socket Rx memory size=2k*/
        Write_W5100(W5100_TMSR,0x55);                /*Socket Tx mempry size=2k*/

        /* 设置重试时间,默认为2000(200ms) */
        Write_W5100(W5100_RTR,0x07);
        Write_W5100(W5100_RTR+1,0xd0);

        /* 设置重试次数,默认为8次 */
        Write_W5100(W5100_RCR,8);

        /* 启动中断,参考W5100数据手册确定自己需要的中断类型
        IMR_CONFLICT是IP地址冲突异常中断
        IMR_UNREACH是UDP通信时,地址无法到达的异常中断
        其它是Socket事件中断,根据需要添加 */
        Write_W5100(W5100_IMR,(IMR_CONFLICT|IMR_UNREACH|IMR_S0_INT));
}


void Socket_Init(SOCKET s)
{
        unsigned int i;

        /*设置分片长度,参考W5100数据手册,该值可以不修改*/
        Write_W5100((W5100_S0_MSS+s*0x100),0x00);                /*最大分片字节数=16*/
        Write_W5100((W5100_S0_MSS+s*0x100+1),0x10);

        /* Set Socket Port number */
        switch(s)
        {
                case 0:
                        Write_W5100(W5100_S0_PORT,S0_Port[0]);        /* Set Local Socket Port number */
                        Write_W5100(W5100_S0_PORT+1,S0_Port[1]);

                        Write_W5100(W5100_S0_DPORT,S0_DPort[0]);        /* Set Destination port number */
                        Write_W5100(W5100_S0_DPORT+1,S0_DPort[1]);

                        for(i=0;i<4;i++)
                                Write_W5100(W5100_S0_DIPR+i,S0_DIP[i]);        /* Set Destination IP Address */
                        break;
                case 1:
                        break;
                case 2:

                        break;
                case 3:

                        break;
                default:
                        break;
        }
}

/**
* @brief  设置Socket为客户端与远程服务器连接
*当本机Socket工作在客户端模式时,引用该程序,与远程服务器建立连接
*
*如果启动连接后出现超时中断,则与服务器连接失败,需要重新调用该程序连接
*该程序每调用一次,就与服务器产生一次连接
**/

unsigned char Socket_Connect(SOCKET s)
{
        Write_W5100((W5100_S0_MR+s*0x100), S_MR_TCP);                /*设置socket为TCP模式 */
        Write_W5100((W5100_S0_CR+s*0x100), S_CR_OPEN);                /*打开Socket*/

        if(Read_W5100(W5100_S0_SSR+s*0x100)!=S_SSR_INIT)
        {
                Write_W5100(W5100_S0_CR+s*0x100,S_CR_CLOSE);        /*打开不成功,关闭Socket,然后返回*/
                return FALSE;
        }

        Write_W5100((W5100_S0_CR+s*0x100),S_CR_CONNECT);                /*设置Socket为Connect模式*/

        return TRUE;

        /*至此完成了Socket的打开连接工作,至于它是否与远程服务器建立连接,则需要等待Socket中断,
        以判断Socket的连接是否成功。参考W5100数据手册的Socket中断状态*/
}

/**
* @brief  设置Socket作为服务器等待远程主机的连接
*当本机Socket工作在服务器模式时,引用该程序,等等远程主机的连接
*
*该程序只调用一次,就使W5100设置为服务器模式
* @return 如果设置成功则返回true, 否则返回false
**/

unsigned char Socket_Listen(SOCKET s)
{
        Write_W5100((W5100_S0_MR+s*0x100), S_MR_TCP);                /*设置socket为TCP模式 */
    Write_W5100(W5100_S0_PORT,S0_Port[0]);        /* Set source Socket Port number */
        Write_W5100(W5100_S0_PORT+1,S0_Port[1]);
        Write_W5100((W5100_S0_CR+s*0x100), S_CR_OPEN);                /*打开Socket*/

        if(Read_W5100(W5100_S0_SSR+s*0x100)!=S_SSR_INIT)
        {
                Write_W5100((W5100_S0_CR+s*0x100),S_CR_CLOSE);        /*打开不成功,关闭Socket,然后返回*/
                return FALSE;
        }

        Write_W5100((W5100_S0_CR+s*0x100), S_CR_LISTEN);                /*设置Socket为侦听模式*/

        if(Read_W5100(W5100_S0_SSR+s*0x100)!=S_SSR_LISTEN)
        {
                Write_W5100((W5100_S0_CR+s*0x100), S_CR_CLOSE);                /*设置不成功,关闭Socket,然后返回*/
                return FALSE;
        }

        return TRUE;

        /*至此完成了Socket的打开和设置侦听工作,至于远程客户端是否与它建立连接,则需要等待Socket中断,
        以判断Socket的连接是否成功。参考W5100数据手册的Socket中断状态
        在服务器侦听模式不需要设置目的IP和目的端口号*/
}

/**
* @brief          设置Socket为UDP模式
*如果Socket工作在UDP模式,引用该程序。在UDP模式下,Socket通信不需要建立连接
*该程序只调用一次,就使W5100设置为UDP模式
* @return 如果设置成功则返回true, 否则返回false
**/




unsigned short S_rx_process(SOCKET s)
{
        unsigned short i,j;
        unsigned short rx_size,rx_offset;

        /*读取接收数据的字节数*/
        rx_size=Read_W5100(W5100_S0_RX_RSR+s*0x100);
        rx_size*=256;
        rx_size+=Read_W5100(W5100_S0_RX_RSR+s*0x100+1);

        /*读取接收缓冲区的偏移量*/
        rx_offset=Read_W5100(W5100_S0_RX_RR+s*0x100);
        rx_offset*=256;
        rx_offset+=Read_W5100(W5100_S0_RX_RR+s*0x100+1);

        i=rx_offset/S_RX_SIZE;                                /*计算实际的物理偏移量,S0_RX_SIZE需要在前面#define中定义*/
                                                                /*注意S_RX_SIZE的值在W5100_Init()函数的W5100_RMSR中确定*/
        rx_offset=rx_offset-i*S_RX_SIZE;

        j=W5100_RX+s*S_RX_SIZE+rx_offset;                /*实际物理地址为W5100_RX+rx_offset*/
        for(i=0;i<rx_size;i++)
        {
                if(rx_offset>=S_RX_SIZE)
                {
                        j=W5100_RX+s*S_RX_SIZE;
                        rx_offset=0;
                }
                Rx_Buffer[i]=Read_W5100(j);                /*将数据缓存到Rx_buffer数组中*/
                j++;
                rx_offset++;
        }

        /*计算下一次偏移量*/
        rx_offset=Read_W5100(W5100_S0_RX_RR+s*0x100);
        rx_offset*=256;
        rx_offset+=Read_W5100(W5100_S0_RX_RR+s*0x100+1);

        rx_offset+=rx_size;
        Write_W5100((W5100_S0_RX_RR+s*0x100), (rx_offset/256));
        Write_W5100((W5100_S0_RX_RR+s*0x100+1), rx_offset);

        Write_W5100((W5100_S0_CR+s*0x100), S_CR_RECV);                        /*设置RECV命令,等等下一次接收*/

        return rx_size;                                                                /*返回接收的数据字节数*/
}
/**
* @brief          如果要通过Socket发送数据,则引用该程序
*要发送的数据缓存在Tx_buffer中, size则是要发送的字节长度
* @author  stmsky
* @param[in] socket nummber
* @param[out] none
* @return
* @note
**/

unsigned char S_tx_process(SOCKET s, unsigned int size)
{
        unsigned short i,j;
        unsigned short tx_free_size,tx_offset;

        /*如果是UDP模式,可以在此设置目的主机的IP和端口号*/
        if((Read_W5100(W5100_S0_MR+s*0x100)&0x0f)==0x02)
        {
                for(i=0;i<4;i++)                        /* 设置目的主机IP*/
                        Write_W5100((W5100_S0_DIPR+s*0x100+i), UDP_DIPR[i]);

                Write_W5100((W5100_S0_DPORT+s*0x100), UDP_DPORT[0]);
                Write_W5100((W5100_S0_DPORT+s*0x100+1), UDP_DPORT[1]);
        }

        /*读取缓冲区剩余的长度*/
        tx_free_size=Read_W5100(W5100_S0_TX_FSR+s*0x100);
        tx_free_size*=256;
        tx_free_size+=Read_W5100(W5100_S0_TX_FSR+s*0x100+1);
        if(tx_free_size<size)                                                /*如果剩余的字节长度小于发送字节长度,则返回*/
                return FALSE;

        /*读取发送缓冲区的偏移量*/
        tx_offset=Read_W5100(W5100_S0_TX_WR+s*0x100);
        tx_offset*=256;
        tx_offset+=Read_W5100(W5100_S0_TX_WR+s*0x100+1);

        i=tx_offset/S_TX_SIZE;                                        /*计算实际的物理偏移量,S0_TX_SIZE需要在前面#define中定义*/
                                                                        /*注意S0_TX_SIZE的值在W5100_Init()函数的W5100_TMSR中确定*/
        tx_offset=tx_offset-i*S_TX_SIZE;
        j=W5100_TX+s*S_TX_SIZE+tx_offset;                /*实际物理地址为W5100_TX+tx_offset*/

        for(i=0;i<size;i++)
        {
                if(tx_offset>=S_TX_SIZE)
                {
                        j=W5100_TX+s*S_TX_SIZE;
                        tx_offset=0;
                }
                Write_W5100(j,Tx_Buffer[i]);                                                /*将Tx_buffer缓冲区中的数据写入到发送缓冲区*/
                j++;
                tx_offset++;
        }

        /*计算下一次的偏移量*/
        tx_offset=Read_W5100(W5100_S0_TX_WR+s*0x100);
        tx_offset*=256;
        tx_offset+=Read_W5100(W5100_S0_TX_WR+s*0x100+1);


        tx_offset+=size;
        Write_W5100((W5100_S0_TX_WR+s*0x100),(tx_offset/256));
        Write_W5100((W5100_S0_TX_WR+s*0x100+1),tx_offset);

        Write_W5100((W5100_S0_CR+s*0x100), S_CR_SEND);                        /*设置SEND命令,启动发送*/

        return TRUE;                                                                /*返回成功*/
}

/**
* @brief          W5100中断处理程序框架
* @note
**/
void vPrintString(unsigned char *ucpString)
{
   unsigned int  i=0;
   while(ucpString[i]!=0x00)
           {
              Tx_Buffer[i]=ucpString[i];
              i++;
           }
   S_tx_process(0,i);
}
void W5100_Interrupt_Process(void)
{
        unsigned char i,j;

        W5100_Interrupt=0;

        i=Read_W5100(W5100_IR);
        Write_W5100(W5100_IR, (i&0xf0));                                        /*回写清除中断标志*/
//GPIO_SetBits(GPIOB, GPIO_Pin_0);
        if((i & IR_CONFLICT) == IR_CONFLICT)                 /*IP地址冲突异常处理,自己添加代码*/
        {

        }

        if((i & IR_UNREACH) == IR_UNREACH)                        /*UDP模式下地址无法到达异常处理,自己添加代码*/

        {
        }

        /* Socket事件处理 */
        if((i & IR_S0_INT) == IR_S0_INT)
        {
                j=Read_W5100(W5100_S0_IR);
                Write_W5100(W5100_S0_IR, j);                /* 回写清中断标志 */

                if(j&S_IR_CON)                                /* 在TCP模式下,Socket0成功连接 */
                {
                        S0_State|=S_CONN;
                }
                if(j&S_IR_DISCON)                                /* 在TCP模式下Socket断开连接处理,自己添加代码 */
                {
                        Write_W5100(W5100_S0_CR, S_CR_CLOSE);                /* 关闭端口,等待重新打开连接 */
                        S0_State=0;
                }
                if(j&S_IR_SENDOK)                                /* Socket0数据发送完成,可以再次启动S_tx_process()函数发送数据 */
                {
                        S0_Data|=S_TRANSMITOK;
                }
                if(j&S_IR_RECV)                                /* Socket接收到数据,可以启动S_rx_process()函数 */
                {
                        S0_Data|=S_RECEIVE;
                }
                if(j&S_IR_TIMEOUT)                        /* Socket连接或数据传输超时处理 */
                {
                        Write_W5100(W5100_S0_CR, S_CR_CLOSE);                /* 关闭端口,等待重新打开连接 */
                        S0_State=0;
                }
        }

        /* Socket1事件处理 */
        if((i&IR_S1_INT)==IR_S1_INT)
        {
                j=Read_W5100(W5100_S1_IR);
                Write_W5100(W5100_S1_IR, j);                /* 回写清中断标志 */
        }

        /* Socket2事件处理 */
        if((i&IR_S2_INT)==IR_S2_INT)
        {
                j=Read_W5100(W5100_S2_IR);
                Write_W5100(W5100_S2_IR, j);                /*回写清中断标志 */

        }

        /* Socket3事件处理 */
        if((i&IR_S3_INT)==IR_S3_INT)
        {
                j=Read_W5100(W5100_S3_IR);
                Write_W5100(W5100_S3_IR, j);                /* 回写清中断标志 */
        }
}







void main(void)
{

    W5100_Init();
    Socket_Init(0);
        Socket_Listen(0);
        KEY=0;
    while(1)
            {               
               W5100_Interrupt_Process();
               if(S0_State==S_CONN) break;
                  
            }
                vPrintString("SOCKET0 opened.");
                KEY=1;
    while(1)
            {
             if(KEY==1)
             {
             vPrintString("Switch is on!");
             }
             else vPrintString("Switch is off!");
            }

}
说明下:很明显我是用spi 的w5100 进行读写。里面的KEY是用来找程序运行到哪里的,没实际意义。
问题是:现在程序直接卡在第一个 while(1)里面。我利用网络助手连接一直连接不上,但是能ping通192.168.10.40 ,能不能前辈抽空帮我看下是哪里出错了?小的不胜感激。
另外付电脑设置截图

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

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

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

出0入0汤圆

 楼主| 发表于 2013-2-15 14:23:46 | 显示全部楼层
没人能看吗?

出0入0汤圆

发表于 2013-5-2 21:47:45 | 显示全部楼层
中二525 发表于 2013-2-15 14:23
没人能看吗?

楼主是否已解决问题???

出0入0汤圆

发表于 2013-5-2 21:57:16 | 显示全部楼层
好长,学习 一下

出0入0汤圆

发表于 2013-5-19 17:28:51 | 显示全部楼层
我也出现了同样的问题,有时候能连接上,有时候就连接不上。郁闷

出0入0汤圆

发表于 2013-8-8 16:56:18 | 显示全部楼层
linbaoluo3 发表于 2013-5-19 17:28
我也出现了同样的问题,有时候能连接上,有时候就连接不上。郁闷


解决了吗 我也碰到了,但是连不上的几率大

出0入0汤圆

发表于 2013-8-8 16:57:59 | 显示全部楼层
解决了吗 问题很相识

出0入0汤圆

发表于 2013-8-10 17:05:19 | 显示全部楼层
yangzi8000 发表于 2013-8-8 16:57
解决了吗 问题很相识

已经解决了,因为我做的是可以作为服务端和客户端的,所以有时候切换不过来,比如当系统进入服务端状态时,要再进入客户端,那必须先断掉原来的链接,重新再链接才行了。

出0入0汤圆

发表于 2013-10-28 17:20:32 | 显示全部楼层
MARK

出0入0汤圆

发表于 2013-11-24 16:02:23 | 显示全部楼层
群主,能加个好友请教点问题么?!QQ:2518836651

出0入0汤圆

发表于 2013-11-24 16:04:22 | 显示全部楼层
想请问下群主,我是新手,这个网络参数寄存器这块的设置是根据什么设置的呢?!我看芯片手册上貌似除了设置的格式以外,内容的设置并没有什么说明啊^……谢谢

出0入0汤圆

发表于 2013-11-27 16:55:57 | 显示全部楼层
mark..............

出0入0汤圆

发表于 2014-3-22 11:24:06 | 显示全部楼层
正在使用W5500……

出0入0汤圆

发表于 2014-3-28 14:49:15 | 显示全部楼层
a06040051 发表于 2014-3-22 11:24
正在使用W5500……

5500比5100贵多少?

出0入0汤圆

发表于 2014-4-6 17:02:14 | 显示全部楼层
powerdruy 发表于 2014-3-28 14:49
5500比5100贵多少?

不多,开发板的话价格一样,只不过芯片的话应该差不多吧!!!

出0入0汤圆

发表于 2014-4-24 16:21:28 | 显示全部楼层
a06040051 发表于 2014-4-6 17:02
不多,开发板的话价格一样,只不过芯片的话应该差不多吧!!!

你用W5500调试通过了TCP客户端发送数据了么,我用官方的DEMO里的程序,但是那些函数连个注释都没有,都不知道调用什么来发送数据,能否交流一下,QQ289146049

出0入0汤圆

发表于 2014-9-14 19:47:43 | 显示全部楼层
新出W5500模块,WIZnet最新型号,有需要的坛友购买前说是在论坛上看到信息的,一律50元包邮,有兴趣请点击一下链接,谢谢支持。
http://item.taobao.com/item.htm? ... &id=40933615687
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-8-26 02:13

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

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