W5500例程的不严谨造成的网络不正常通讯的问题。
本帖最后由 dontium 于 2019-7-13 08:53 编辑W5500使用简单、方便,对资源要求低,非常喜欢。刚开始用它,在www.w5500.cn网站下载了例程,-------不知道这个网站是不是官网。
在使用TCP服务器程序时,遇到了问题:W5500接收多数情况正常,发送少数情况正常。
因为是刚接触此芯片,所以就找自己的原因,开始怀疑SPI的相位不正确,
又怀疑SPI的速度太快,又怀疑硬件电路有问题,……。搞了几天也不知道问题所在。
后来长时间监视发送接收,发现,接收的数据的正确与错误有一定规律,即有周期性。
这时想到的是,寄存器的读写问题,是不是地址修改不正确造成对2048的存储器从头至尾来回读写?
但检查程序,又认真地学习芯片手册,并没有发现问题,后来想想,是不是程序问题 ----一般不这样怀疑的
因为经询问是“反复实验正常”的程序。但还是要检查的,或者是自己在修改什么参数时不小心动到哪儿了?
检查到收发函数时,突然觉得好象有点问题。
原程序是这样的:
void send_data_processing(SOCKET s, uint8 *data, uint16 len)
{
uint16 ptr =0;
uint32 addrbsb =0;
if(len == 0)
{
printf(" CH: %d Unexpected1 length 0\r\n", s);
return;
}
ptr = IINCHIP_READ( Sn_TX_WR0(s) );
ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_TX_WR1(s));
addrbsb = (uint32)(ptr<<8) + (s<<5) + 0x10;
wiz_write_buf(addrbsb, data, len);
ptr += len;
IINCHIP_WRITE( Sn_TX_WR0(s) ,(uint8)((ptr & 0xff00) >> 8));
IINCHIP_WRITE( Sn_TX_WR1(s),(uint8)(ptr & 0x00ff));
}
这里的:
addrbsb = (uint32)(ptr<<8) + (s<<5) + 0x10;
中的ptr为16位,而在左移8位后再强制转换成32位,
这样在轮换前它的高8位就被移出去了,丢失了。再强制转换成32位就没有意义了。
将它改一下:
addrbsb = ((uint32)ptr<<8) + (s<<5) + 0x10;
并对其它相似的地方作同样修改。
烧写后程序运行正常!
另外,我有个疑问:
IINCHIP_WRITE( Sn_TX_WR0(s) ,(uint8)((ptr & 0xff00) >> 8));
这句中的,(uint8)((ptr & 0xff00) >> 8),对于ptr,先将低8位屏蔽掉再移出,
与直接移出低8位,在结果上有什么区别?如果没有区别,多加这个不是给程序带来负担吗?
相同的如(uint8)(ptr & 0x00ff),如果编译器有强制类型转换功能,就会把高8位丢弃,语句中再加入与运算有什么好处呢?
不错不错,好经验分享。 你那个明显不是官网,例程还是找原厂或者代理那边索取,随便下的,就只能折腾自己了 我也有你那个原厂程序,不过,已经更新成你说的这样了。 另外,请教楼主几个问题,能否给说明一下socket n的发送过程。主要是TX_WR是怎么变化的。
如果TX_WR大于他分配给他的空间(例如2k-4k是分给他的地址范围),这个变量是变成2k,还是变成0? 这一般是由编程习惯造成。
如果纯粹屏蔽的和移动位数一样,而且是被移出去的,则完全可以不需要这个屏蔽命令。
页:
[1]