谢谢大家,经过昨晚一晚上不懈努力,终于调试通了。先把主要代码贴出来,开源感谢大家(单片机为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
**************************************/
//==========================================================================
|