感谢wxj1952前辈~!BasicCAN通信实验成功~!
下午以及晚上上完课后,就一直开始查错查到现在,终于发现问题之所在~!!!(中午已经认真计算过波特率,但还是没有效果)<br /> 原来是所使用的SJA驱动的接收与发送函数有问题!<br /><br />请先看接收与发送缓冲区的数据结构:<br /><br />struct BASICCAN_BUFstruct{<br /> unsigned char FrameID_H ; //帧ID高8位<br /> unsigned char FrameLENTH ; //帧数据长度<br /> unsigned char FrameKIND ; //数据帧或远程帧(0:数据;1:远程)<br /> unsigned char FrameID_L3 ; //帧ID低3位<br /> unsigned char Frame_Data; //数据缓冲区<br /> };<br /><br />再看以下发送函数里的关于发送一帧信号中的第二个字节(即低3位ID,PTR,四位长度标志)的写法:<br /><br /><br />///////////////////////////////////////////////////////////////////////<br /> if((CANREG_read(0x02)&0x10)==0)<br /> {<br /> if((CANREG_read(0x02)&0x04)!=0)<br /> {<br /> CANREG_write(0x10,send_BUF.FrameID_H);<br /> CANREG_write(0x11,(send_BUF.FrameLENTH)||(send_BUF.FrameKIND<<4)||(send_BUF.FrameID_L3<<5));//注意这一句,问题出在这里!<br /> <br /> if(send_BUF.FrameKIND==0)<br /> {<br /> for(i=0;i<send_BUF.FrameLENTH,i<8;i++)<br /> CANREG_write(0x12+i,send_BUF.Frame_Data);<br /> P1_7 = !P1_7;<br /> }<br /> //发送寄存器写成功<br /> setting_success=1;<br /> }<br /> }<br />//////////////////////////////////////////////////////////////////////<br /><br />就是因为第二个字节的数据不正确,以至接收模块根本不能接收到正确的数据(接收函数也采用类似的写法,但发送都不正确了,接收的正确与否也无从谈起)。<br />如原驱动所采用的逻辑或的方法根本是得不到设想的结果的。后来根据陈明计前辈的一本关于smallRTOS的书中所展示的BasicCAN实验例子的接收与发送函数进行改写,最后终于成功了~!<br /><br />通过本次实验,再次感到自己的C语言的运用能力的不足,如果是真的熟练的话,相信这个错误可以一眼就可以看出,之前太过相信这些下载而来的程序的正确性了。<br />虽然本次实验只是一个开始,不过有了这个成功的开始,后面的实验的开展相信会相对容易一些,毕竟有了一个成功的参考例子~!<br />在这里感谢各位网友提供的资料,特别是周工网站以及陈明计前辈写的一本关于smallRTOS的书中所提到的BasicCAN总线的例子,特别感谢wxj1952前辈提供热心的支持~~!<br /><br />恭喜!
比我强多了。我是那种离不开仿真器和书本的人。谢谢~!
我也是离不开书本的人,没有书根本是无从下手~~还是多得前辈鼓励呀~!有时候并不需什么有多具体的指导,方向的指导以及鼓励更是像我们这种菜鸟所需要的~<br />/////////////////////////////////////////////////////<br /><br />重新看了原来的发送与接收部分函数,确实问题多多:<br />1,发送函数那个第二个节字的整合(低3位ID,PTR,四位长度标志)应该使用位或的(“|”)而不是逻辑或(||);<br />2,发送与接收函数的SJA上面的缓冲地址原来用的是十六进制的表示法,但写的却是十进制的地址(如本应为0x0a的,却写了0x10);<br /><br />这两个就是导致之前一直得不到正确的数据的原因。从侧面反映了C语言功底还需提高~~<br />嗯,我会加油的~~对了,还有一问题
你之前发过的SJA1000标准发送/接收程序中,所使用到的是函数指针吗?那个PA是不是unsigned char 之类的数据类型?<br /><br />函数指针我前段时间刚接触,高阶应用得比较多,如uc/os等的系统,还有《时间触发的嵌入式系统》这本书也用得很多。<br />你能给个完整一点的例子看看吗?<br /><br />我试过直接定义一个void类型的函数指针,但当时没有编译通过~桂电飞天鼠
哈哈,你的程序好像和我参考的一样,是不是应该这样写,我是发现这个问题了,但是我的BasicCAN 还是调试不成功,<br />关于数组拷贝
PA是一个typedef用户定义的类型,保留答案,看看谁有更精彩的另解,即:如何实现2个同类型数组的相互拷贝? 数组1=数组2。(当然不是调用函数/显式按字节拷贝。)<br />寻求答案的过程中能发现好多过去忽略的精彩,例如:到底什么叫变量?什么叫对象?一个数组是一个对象?还是一个变量?要知道,无论变量还是对象,同类型之间是可以互相拷贝的。~~
to 五楼的兄弟:<br />一步一步搞掂它<br />1,首先将屏蔽设为0xff先,让它不管是什么,验收代码有没有设对,让发来的都能产生接收中断。(当然波特率要设为一致,我用了可以的:BTR0=0x0c,BTR1=0x0a)。<br />2,然后检查发送与接收的中断都正不正常。<br />3,如果这些都行了,再细心检查检查哪里的值有没有设对。<br /><br />对了,你跟我用的是同一个SJA的驱动,那原驱动的接收与发送函数都有问题的(上面有说了)你改改再试一下<br /><br />to wxj1952前辈:<br />使用的应该就是函数指针吧?愿闻其详呀~~书上的告诫。
感谢桂天飞鼠网友,他使我以后不会忽略&&与&,||与|的运算区别。<br />书本中的“告诫强调”能够使我们加深印象,特别是我们经历过的事情。可惜我们上C语言课时,老师从没给我们强调过这一点。<br /><br />“运算符&&和运算符||在左侧操作数的值能够确定最终结果时,根本不会对右侧操作数求值!例如10||f ( )=1,无论f ( )是什么。”<br /> ---- 摘自《C陷阱与缺陷》<br /><br />再看下面C51的编译结果,正符合上面的编程原则。<br /><br />CANREG_write(0x11,(send_BUF.FrameLENTH)||(send_BUF.FrameKIND<<4)||(send_BUF.FrameID_L3<<5));<br /> ; SOURCE LINE # 36<br /> MOV A,send_BUF+01H<br /> JNZ ?C0005<br /> MOV A,send_BUF+02H<br /> SWAP A<br /> ANL A,#0F0H<br /> JNZ ?C0005<br /> MOV A,send_BUF+03H<br /> SWAP A<br /> RLC A<br /> ANL A,#0E0H<br /> JZ ?C0003<br />?C0005:<br /> MOV R7,#01H<br /> SJMP ?C0004<br />?C0003:<br /> MOV R7,#00H<br /><br /><br /><br />而运算符&或运算符| 两侧的操作数都必须被求值。 --- 摘自《C陷阱与缺陷》<br />确实~
那本书的电子版也有,不过没有认真看过~~<br /><br />是的,确实做这个实验,遇到问题,然后解决问题,这种过程确实能让学习更有效。<br /><br />wxj1952前辈,我还想听听你的关于发送与接收的数组拷贝呢~TO 桂电飞天鼠
最近没有时间调试,忙的很<br />先谢过,等调试时再请教有没有第二个人想到
公开就没价值了。?
这么神秘?<br />拿板凳坐好看答案~坐好板凳静观研究生的水平
记得当时我以500元求索答案,一直没有。现在涨价了,2000元,仍然有效,谁有同解或另解?有偿求索。<br /><br />没什么玩笑,请版主做中间人好了。<br /><br />楼主大哥:能发一个最简单的测试程序给我吗?
我的CAN不知为何收发一直不正常。谢谢!lyonlu@tom.comrt
不好意思,最近比较忙且我手头上没有最小测试程序,而且我更希望你自己独立完成。<br /><br />你可以参考wxj1952前辈的帖子,已经说得很详细了,希望能细心耐心点先把资料,特别是寄存器的功能了解清楚。另外我也在本坛上共享了Basic的驱动(我自己用的),希望对你有帮助。CAN总线难点不在程序
那个什么 的CAN开发板的程序也够烂的了。CAN总线难点不在程序,CAN的程序简单的要死,关键是如何组网,如何调整硬件使CAN可靠的通讯。所以不要急着写程序,先把CAN理解透。rt
确实是呀,楼上的前辈说得很对~!
页:
[1]