[技术讨论] W5500的SPI控制程序问题(调试不通)

[复制链接]
5194|7
 楼主| taozhaogy 发表于 2019-1-13 17:39 | 显示全部楼层 |阅读模式
各位高人,本人使用网上的W5500程序(模拟SPI),W5500模块能连上TCP调试助手,通信正常,但改成SPI通信(不模拟),则W5500就始终链接不上TCP调试助手,但能ping通模块,使用单片机为 MC9S08DZ60。我是新手,谢谢大家帮助呵
tyw 发表于 2019-1-13 19:08 | 显示全部楼层



















本帖子中包含更多资源

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

×
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
}

 楼主| 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
**************************************/
//==========================================================================
yueguang3048 发表于 2019-1-16 09:41 | 显示全部楼层
taozhaogy 发表于 2019-1-14 19:57
谢谢大家,经过昨晚一晚上不懈努力,终于调试通了。先把主要代码贴出来,开源感谢大家(单片机为MC9S08DZ60 ...

感谢分享经验
playxzy 发表于 2019-7-15 17:26 | 显示全部楼层
刚好在 做这个
haitianhappy 发表于 2019-12-15 22:45 来自手机 | 显示全部楼层
socket发送数据有没有乱码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

29

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部