打印
[技术讨论]

W5500的SPI控制程序问题(调试不通)

[复制链接]
3283|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
taozhaogy|  楼主 | 2019-1-13 17:39 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
tyw| | 2019-1-13 19:08 | 只看该作者
基于STM32与W5500的嵌入式以太网系统.pdf (70.25 KB)
W5500使用手册V2.0.pdf (1.8 MB)
W5500高清晰中文数据手册.pdf (1.83 MB)
W5500数据手册.pdf (8.93 MB)
W5500网络扩展板原理图.pdf (254.5 KB)
W5500问题集锦.pdf (868.06 KB)
w5500带协议栈以太网芯片原理图.pdf (106.8 KB)
以太网接口芯片W5500与ENC28J60对比.pdf (1.57 MB)
关于W5500和CC2530之间的通信.pdf (1.91 MB)
ENC28J60中文网络芯片教程.pdf (19.88 MB)
W5500驱动函数库.pdf (30.1 KB)
单片机C8051F 网口W5500电机驱动原理图.pdf (422.66 KB)
W5500(socket)寄存器使用说明.pdf (208.27 KB)
W5500网络扩展板教程.pdf (7.52 MB)
W5500KeepAlive功能调试经验.pdf (4.87 KB)
STM32F103驱动W5500网络程序.pdf (39.37 KB)
w5500带协议栈以太网芯片手册.pdf (1.91 MB)


使用特权

评论回复
板凳
lvface123654| | 2019-1-14 11:45 | 只看该作者
示波器,单次同时抓SDO SCK 的数据波形,分析数据先

使用特权

评论回复
地板
iDiy| | 2019-1-14 11:56 | 只看该作者
W5500_READBYTE
{
    spi_write_byte
    spi_read_byte
}

W5500_WRITEBYTE
{
    spi_write_byte
    spi_read_byte
}

使用特权

评论回复
5
taozhaogy|  楼主 | 2019-1-14 19:57 | 只看该作者
谢谢大家,经过昨晚一晚上不懈努力,终于调试通了。先把主要代码贴出来,开源感谢大家(单片机为MC9S08DZ60),不知道怎么上传文件,只能贴上主要代码了(都有注释的)
-----------------------------------------------------------------------------------
SPI初始化:

PTED_PTED1=0;                                           //初始化PE1连接W5500模块的Reset脚( W5500.h中定义)
          PTEDD_PTEDD1=1;                                     //输出使能
          
          PTED_PTED2=1;                                           //初始化PE2连接W5500模块的SCS脚   ( W5500.h中定义)
          PTEDD_PTEDD2=1;
          PTEDS_PTEDS2=1;                 
                                                                              //SPI模块功能初始化
          SPIC1 = 0x50;                                                 //轮询模式、SPI使能、主SPI SPI串行数据传输始于最高位
          SPIC2 = 0x02;  
--------------------------------------------------------------------------------------
W5500.c中

/*******************************************************************************
* 函数名  : SPI_ReadByte
* 描述    : 读取一个字节SPI返回的数据
* 输入    : 无
* 输出    : 无
* 返回值  : 读取到的寄存器数据
* 说明    : 无
*******************************************************************************/
unsigned char SPI_Read_Byte(void)
{   
   //SPI通信方式一(I/O口模拟SPI)
   /*
        unsigned char i,rByte=0;
       
        W5500_SCLK=0;
        for(i=0;i<8;i++)
        {
                W5500_SCLK=1;
                rByte<<=1;
                rByte|=W5500_MISO;
                W5500_SCLK=0;       
        }
        return rByte;
        */
       
        //SPI通信方式二(直接使用单片机的SPI模块)
        unsigned char rByte=0;
        INT8U tmp;            
        while(!( SPIS & 0x80 ));       //必须,否则输出的数据乱码              
        rByte = SPID;
        tmp=SPIS;
        return  rByte;
}

/*******************************************************************************
* 函数名  : SPI_SendByte
* 描述    : SPI发送一个字节数据
* 输入    : dt:待发送的数据
* 输出    : 无
* 返回值  : 无
* 说明    : 无
*******************************************************************************/
void SPI_Send_Byte(unsigned char dt)
{   
    //SPI通信方式一(I/O口模拟SPI)
    /*
        unsigned char i;
               
        for(i=0;i<8;i++)
        {       
                W5500_SCLK=0;
                if((dt<<i)&0x80)
                        W5500_MOSI=1;
                else
                        W5500_MOSI=0;                                       
                W5500_SCLK=1;
        }
        W5500_SCLK=0;
        */
       
        //SPI通信方式二(直接使用单片机的SPI模块)         
        INT8U tmp;
        tmp=SPIS;                             //必须             
        SPID=dt;
        while(!( SPIS & 0x20 ));       //必须,否则不输出   
}


//=============================================================================
/**************************************
注意:以下为读取W5500资源的函数(与I/O口模拟 SPI 情况不同,主要添加了空读语句和写哑数据语句)---陶  2019-1-10
**************************************/
/*******************************************************************************
* 函数名  : Read_W5500_1Byte
* 描述    : 读W5500指定地址寄存器的1个字节数据
* 输入    : reg:16位寄存器地址
* 输出    : 无
* 返回值  : 读取到寄存器的1个字节数据
* 说明    : 无
*******************************************************************************/
unsigned char Read_W5500_1Byte(unsigned short reg)
{
        unsigned char i;

        W5500_SCS=0;//置W5500的SCS为低电平
                       
        SPI_Send_Short(reg);//通过SPI写16位寄存器地址
        SPI_Send_Byte(FDM1|RWB_READ|COMMON_R);//通过SPI写控制字节,1个字节数据长度,读数据,选择通用寄存器
       
        SPI_Read_Byte();      //陶  添加 空读语句,主要是把上一条写语句时,从设备发送过来的数据读取掉,以便不影响后续读数据
        SPI_Send_Byte(0xff);//陶  添加 哑数据,为读取有效数据提供时钟信号(因为spi是全双工的,只有在发送数据的时候才会产生时钟,让从机返回数据)
       
        i=SPI_Read_Byte();     //读取有效数据

        W5500_SCS=1;//置W5500的SCS为高电平
        return i;//返回读取到的寄存器数据
}

/*******************************************************************************
* 函数名  : Read_W5500_SOCK_1Byte
* 描述    : 读W5500指定端口寄存器的1个字节数据
* 输入    : s:端口号,reg:16位寄存器地址
* 输出    : 无
* 返回值  : 读取到寄存器的1个字节数据
* 说明    : 无
*******************************************************************************/
unsigned char Read_W5500_SOCK_1Byte(SOCKET s, unsigned short reg)
{
        unsigned char i;

        W5500_SCS=0;//置W5500的SCS为低电平
                       
        SPI_Send_Short(reg);//通过SPI写16位寄存器地址
        SPI_Send_Byte(FDM1|RWB_READ|(s*0x20+0x08));//通过SPI写控制字节,1个字节数据长度,读数据,选择端口s的寄存器

          SPI_Read_Byte();      //陶  添加 空读语句,主要是把上一条写语句时,从设备发送过来的数据读取掉,以便不影响后续读数据
        SPI_Send_Byte(0xff);//陶  添加 哑数据,为读取有效数据提供时钟信号(因为spi是全双工的,只有在发送数据的时候才会产生时钟,让从机返回数据)
       
        i=SPI_Read_Byte();

        W5500_SCS=1;//置W5500的SCS为高电平
        return i;//返回读取到的寄存器数据
}

/*******************************************************************************
* 函数名  : Read_W5500_SOCK_2Byte
* 描述    : 读W5500指定端口寄存器的2个字节数据
* 输入    : s:端口号,reg:16位寄存器地址
* 输出    : 无
* 返回值  : 读取到寄存器的2个字节数据(16位)
* 说明    : 无
*******************************************************************************/
unsigned short Read_W5500_SOCK_2Byte(SOCKET s, unsigned short reg)
{
        unsigned short i;

        W5500_SCS=0;//置W5500的SCS为低电平
                       
        SPI_Send_Short(reg);//通过SPI写16位寄存器地址
        SPI_Send_Byte(FDM2|RWB_READ|(s*0x20+0x08));//通过SPI写控制字节,2个字节数据长度,读数据,选择端口s的寄存器

    SPI_Read_Byte();      //陶  添加 空读语句,主要是把上一条写语句时,从设备发送过来的数据读取掉,以便不影响后续读数据
        SPI_Send_Byte(0xff);//陶  添加 哑数据,为读取有效数据提供时钟信号(因为spi是全双工的,只有在发送数据的时候才会产生时钟,让从机返回数据)
   
        i=SPI_Read_Byte();
       
        SPI_Send_Byte(0xff);//陶  添加 哑数据,为读取有效数据提供时钟信号(因为spi是全双工的,只有在发送数据的时候才会产生时钟,让从机返回数据)
       
        i*=256;
        i+=SPI_Read_Byte();//读取低位数据

        W5500_SCS=1;//置W5500的SCS为高电平
        return i;//返回读取到的寄存器数据
}

/*******************************************************************************
* 函数名  : Read_SOCK_Data_Buffer
* 描述    : 从W5500接收数据缓冲区中读取数据
* 输入    : s:端口号,*dat_ptr:数据保存缓冲区指针
* 输出    : 无
* 返回值  : 读取到的数据长度,rx_size个字节
* 说明    : 无
*******************************************************************************/
unsigned short Read_SOCK_Data_Buffer(SOCKET s, unsigned char *dat_ptr)
{
        unsigned short rx_size;
        unsigned short offset, offset1;
        unsigned short i;
        unsigned char j;

        rx_size=Read_W5500_SOCK_2Byte(s,Sn_RX_RSR);
        if(rx_size==0) return 0;//没接收到数据则返回
        if(rx_size>1460) rx_size=1460;

        offset=Read_W5500_SOCK_2Byte(s,Sn_RX_RD);
        offset1=offset;
        offset&=(S_RX_SIZE-1);//计算实际的物理地址

        W5500_SCS=0;//置W5500的SCS为低电平

        SPI_Send_Short(offset);//写16位地址
        SPI_Send_Byte(VDM|RWB_READ|(s*0x20+0x18));//写控制字节,N个字节数据长度,读数据,选择端口s的寄存器
       
        SPI_Read_Byte();      //陶  添加 空读语句,主要是把上一条写语句时,从设备发送过来的数据读取掉,以便不影响后续读数据
       
        if((offset+rx_size)<S_RX_SIZE)//如果最大地址未超过W5500接收缓冲区寄存器的最大地址
        {
                for(i=0;i<rx_size;i++)//循环读取rx_size个字节数据
                {
                             SPI_Send_Byte(0xff);//陶  添加 哑数据,为读取有效数据提供时钟信号(因为spi是全双工的,只有在发送数据的时候才会产生时钟,让从机返回数据)
               
                        j=SPI_Read_Byte();//读取1个字节数据
                        *dat_ptr=j;//将读取到的数据保存到数据保存缓冲区
                        dat_ptr++;//数据保存缓冲区指针地址自增1
                }
        }
        else//如果最大地址超过W5500接收缓冲区寄存器的最大地址
        {
                offset=S_RX_SIZE-offset;
                for(i=0;i<offset;i++)//循环读取出前offset个字节数据
                {
                           SPI_Send_Byte(0xff);//陶  添加 哑数据,为读取有效数据提供时钟信号(因为spi是全双工的,只有在发送数据的时候才会产生时钟,让从机返回数据)
                  
                        j=SPI_Read_Byte();//读取1个字节数据
                        *dat_ptr=j;//将读取到的数据保存到数据保存缓冲区
                        dat_ptr++;//数据保存缓冲区指针地址自增1
                }
                W5500_SCS=1; //置W5500的SCS为高电平

                W5500_SCS=0;//置W5500的SCS为低电平

                SPI_Send_Short(0x00);//写16位地址
                SPI_Send_Byte(VDM|RWB_READ|(s*0x20+0x18));//写控制字节,N个字节数据长度,读数据,选择端口s的寄存器
               
                SPI_Read_Byte();//tao 添加

                for(;i<rx_size;i++)//循环读取后rx_size-offset个字节数据
                {
                           SPI_Send_Byte(0xff);//陶  添加 哑数据,为读取有效数据提供时钟信号(因为spi是全双工的,只有在发送数据的时候才会产生时钟,让从机返回数据)
               
                        j=SPI_Read_Byte();//读取1个字节数据
                        *dat_ptr=j;//将读取到的数据保存到数据保存缓冲区
                        dat_ptr++;//数据保存缓冲区指针地址自增1
                }
        }
        W5500_SCS=1; //置W5500的SCS为高电平

        offset1+=rx_size;//更新实际物理地址,即下次读取接收到的数据的起始地址
        Write_W5500_SOCK_2Byte(s, Sn_RX_RD, offset1);
        Write_W5500_SOCK_1Byte(s, Sn_CR, RECV);//发送启动接收命令
        return rx_size;//返回接收到数据的长度
}     
/**************************************
注意:以上为读取W5500资源的函数(与I/O口模拟 SPI 情况不同)---陶  2019-1-10
**************************************/
//==========================================================================

使用特权

评论回复
6
yueguang3048| | 2019-1-16 09:41 | 只看该作者
taozhaogy 发表于 2019-1-14 19:57
谢谢大家,经过昨晚一晚上不懈努力,终于调试通了。先把主要代码贴出来,开源感谢大家(单片机为MC9S08DZ60 ...

感谢分享经验

使用特权

评论回复
7
playxzy| | 2019-7-15 17:26 | 只看该作者
刚好在 做这个

使用特权

评论回复
8
haitianhappy| | 2019-12-15 22:45 | 只看该作者
socket发送数据有没有乱码

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

29

帖子

3

粉丝