搜索
bottom↓
回复: 69

lnskngdc进来下,关于c8051f040的CAN报文过滤,想向你请教一下,非常感谢

[复制链接]

出0入0汤圆

发表于 2010-3-21 04:01:48 | 显示全部楼层 |阅读模式
在做CAN相关的东西,用的C8051f040,但是在接收的时候,不管消息id多少,总会进CAN中断,好像设置的接收过滤没起作用似的(很可能是我设置的不对,呵呵)
刚接触CAN,找了不少市面上和网上的资料,但关于消息过滤方面的资料还没看到过,你有没有这方面的资料或代码,贴一下参考下,万谢万谢

出0入0汤圆

 楼主| 发表于 2010-3-21 11:19:00 | 显示全部楼层
lnskngdc 救命

出0入0汤圆

发表于 2010-3-21 12:15:54 | 显示全部楼层
呵呵,看了你的问题,我心里只有苦笑~~~为嘛咧?听我细细道来!

出0入0汤圆

发表于 2010-3-21 12:28:33 | 显示全部楼层
silabs的CAN是用博世的核做的,符合CAN2.0标准,但是,他们在嵌入到c8051F040的时候,不知道什么原因,也许是bug或者空间不够或者什么别的.
使得用户在使用的时候,不能完全做到屏蔽CAN中断,也就是说,无论你如何设置屏蔽滤波寄存器,只要总线上有报文出现,这个节点就总会产生CAN中断.
解决的办法就是:在040的CAN寄存器里面找个INTPEND,在产生CAN中断的时候把它读出来,就能知道产生中断的邮箱号,如果里面的值,与你初始化CAN接收所用的mailbox号相同,则是你本身节点应该接收的数据,如果"0",或者你没有初始化的数,则要抛弃本次中断.

------------------------------------------------------------------------------------------------------------
后记:这个问题折磨我将近半个月的时间,国外的Silabs论坛也有讨论这个问题的,但都是没有结果,后来问新华龙总部的一个工程师才知道.

出0入0汤圆

 楼主| 发表于 2010-3-21 14:17:43 | 显示全部楼层
救星,你来得太及时了,我正在单位加班呢,刚刚又把资料好好看了一遍,又把各个寄存器好好设置了一遍,结果依然,正懊恼的抽烟呢···
因为我刚接触CAN,幸亏你告诉我了,不然我还以为是我设置的事,不一定要调多少天呢
你的意思是说,如果接收到的id和本地初始化接收消息时设置的ID不符的话,产生中断的邮箱号不是设定要接收的那个邮箱号,我这么理解对吗

出0入0汤圆

 楼主| 发表于 2010-3-21 14:39:02 | 显示全部楼层
已解决 再次感谢大救星lnskngdc

出0入0汤圆

发表于 2010-3-21 16:52:10 | 显示全部楼层
不客气,只是碰巧知道这个问题罢了,呵呵,互相学习,共同进步.

出0入0汤圆

 楼主| 发表于 2010-3-21 17:57:33 | 显示全部楼层
又遇到一个新问题······
两块板调试 一个发送 一个接收 发送缓冲区的数据正常 8字节 每次接收第六个字节总是0x0A 出过一次0x24 跟踪程序 送到消息里的数据也正常 换了几个通讯速率 故障依然····
你当初调试时遇到过这样的问题吗

出0入0汤圆

发表于 2010-3-21 18:11:04 | 显示全部楼层
这个数据是从AD的寄存器copy过来的还是从XRAM copy的?
印象中出过几次你说的现象,应该数据在转移过程中被修改,可能是操作太快导致数据不完全,也可能是数组越界或者操作失误.
你有总线分析仪么?如果有的话就监听一下总线上的数据,可以分析故障出在发送节点还是接收节点.

出0入0汤圆

 楼主| 发表于 2010-3-21 18:34:16 | 显示全部楼层
从xram拷贝的 是一个大的缓冲池 数组越界和操作失误的可能很小 这里我都仔细跟了
总线分析仪没有··· 我生存在原始社会···
眼泪哗哗的····
我试着加点延时看看吧
刚本着宁错杀不放过的原则 给数组换了个地址···

出0入0汤圆

发表于 2010-3-21 19:08:57 | 显示全部楼层
唉...有了CAN总线分析仪,会提高效率很多...
神兵利器谁不想有?关键是老板抠门啊.
你给数组定位了?个人建议不要定位,这部分用不好就会出问题.
---------------------------------------------------
搞电子的再小心都不为过,往往是你认为百分之百都没问题的地方出问题.
严谨,严谨,再严谨.

出0入0汤圆

 楼主| 发表于 2010-3-21 19:56:13 | 显示全部楼层
故障现象搞清楚了 接收到的数据中第六位和第八位是同一个数 始终都是第八位的数
比如发送端我发12345678 接收端收到就是12345878 发别的数也是一样现象
但故障原因还没找到····
数组定位是为了排除故障 刚刚改回来了 呵呵

出0入0汤圆

发表于 2010-3-21 20:39:17 | 显示全部楼层
这样就容易定位了.
先发送:0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
再发送:0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
这样如果还是data6和data8相同,就是软件问题.如果不相同就是硬件问题(RAM的数据地址线虚焊或者连焊)

出0入0汤圆

 楼主| 发表于 2010-3-21 23:21:52 | 显示全部楼层
lnskngdc老大 你给的这两个数组 data6和data8都是相同的···

出0入0汤圆

发表于 2010-3-22 10:09:26 | 显示全部楼层
呵呵,someone7715 请别叫我“老大”,我担不起啊。
你的XRAM数据地址线是否有虚焊连焊的地方?你仔细检查一下吧。

出0入0汤圆

 楼主| 发表于 2010-3-23 18:51:46 | 显示全部楼层
总算解决了,心情很复杂,疑惑,不解,还有愤怒和鄙视
困扰了两天半,用了各种方法都没好使,无意中看到段代码,里边发数和取数的时候都先从高字节来
照做,然后。。。。
就解决了
疑惑不解的是看资料上说数据收发都是从data0到data7,为什么按正常流程读写就会出data7覆盖data5的现象呢
愤怒和鄙视的是张培仁和孙力这两个RZ
警告,红色警告
后来的兄弟,用c8051系列做开发的,有本书千万别买 清华出版社 张培仁 孙力   c8051系列微控制器原理与应用
一本好书带你上天堂,一堆装订好的废纸可以让你死都不知道怎么死的
奉劝这两位叫兽的RZ,你们好好在学校误人子弟就好了,翻译资料这种事还是交给网上专业的爱好者们吧
要了亲命了,书里有的,新华龙芯片资料里全有,连代码都直接抄的评估板代码

出0入0汤圆

发表于 2010-3-23 20:01:56 | 显示全部楼层
兄弟消消火,你还不明白中国出书的潜规则么?都是翻译说明书而已.
外国人写文档是为了让大家看明白,中国的叫兽出书都是研究生翻译的,让人看不明白.

出0入0汤圆

 楼主| 发表于 2010-3-28 16:29:58 | 显示全部楼层
lnskngdc 还得和你请教一下 怎么把某个节点设置成接收所有id的消息

出0入0汤圆

 楼主| 发表于 2010-3-28 21:23:45 | 显示全部楼层
umask置0了 仍然屏蔽

出0入0汤圆

 楼主| 发表于 2010-3-28 21:24:45 | 显示全部楼层
正在黑夜里彷徨呢 请为我点亮一盏明灯 呵呵

出0入0汤圆

 楼主| 发表于 2010-3-29 08:19:09 | 显示全部楼层
不会是需要接受多少个ID的消息 就定义多少个接收消息吧

出0入0汤圆

发表于 2010-3-29 08:28:41 | 显示全部楼层
MARK

出0入0汤圆

 楼主| 发表于 2010-3-29 08:59:21 | 显示全部楼层
不好用 呵呵 能说一下具体怎么设置吗
现在具体面临的情况是 所有节点中 其中一个节点需要接收别的所有节点发送的数据帧 而剩余的节点要求彼此互不干涉
给新华龙技术支持打电话了 对方说应该可能好像是有这个功能 具体有没有还是说怎么设置说不出来·····

出0入0汤圆

 楼主| 发表于 2010-3-29 09:01:14 | 显示全部楼层
找他要040的勘误表他也说没有 光我用这个CPU不到两个礼拜 就已经发现3个硬件BUG了

出0入0汤圆

发表于 2010-3-29 09:01:55 | 显示全部楼层
void init_msg_object_RX (char MsgNum,uchar id)
{
        uint temp;
           SFRPAGE = CAN0_PAGE;
        CAN0ADR = IF2CMDMSK;
        CAN0DAT = 0x00bb;            
        /*   IF2 Command Mask Registers  =0x00bb
        WR/RD=1,Mask=0,Arb=1,Control=1,ClrIntPnd=1,TxRqst=0,DataA=1,DataB=1,一次发送8字节数据*/
        CAN0ADR = IF2ARB1;           
        CAN0DAT = 0x0000;
        /*IF2 Arbitration Registers1 =0x0000,即ID15-0=0*/            
        temp=id<<2;//标准id为ID28-ID18,所以要左移2位
        temp&=0x1fff;
        temp|=0x8000;
        CAN0DAT = temp;
        /*IF2 Arbitration Registers2=100(id)00b
        MsgVal=1,Xtd=0,为标准模式,扩展ID无效,Dir=0,为接收*/
        CAN0DAT = 0x0488;
        /*IF2 Message Control Registers=0x0488
        NewDat=0,MsgLst=0,IntPnd=0,UMask=0,TxIE=0,RxIE=1,接收中断使能;RmtEn=0,TxRqst=0
        EoB=1,DLC3-0=1000,即数据长度为8*/
        CAN0ADR = IF2CMDRQST;        
        CAN0DATL = MsgNum;           
          /*IF2 Command Request Registers=MsgNum,将以上配置写入MsgNum号消息*/
}

出0入0汤圆

 楼主| 发表于 2010-3-29 09:05:23 | 显示全部楼层
救星 你可算来了 呵呵 我去试试看

出0入0汤圆

 楼主| 发表于 2010-3-29 09:40:41 | 显示全部楼层
代码直接复制粘贴的 还是不行啊
发送ID设2 初始化接收ID的时候设为0
接收失败

出0入0汤圆

 楼主| 发表于 2010-3-29 09:43:01 | 显示全部楼层
数据帧根本就没进消息邮箱
感觉还是被屏蔽了

出0入0汤圆

发表于 2010-3-29 09:45:44 | 显示全部楼层
接收id不能设置为0,0~3一般是给主节点留的地址,“0”尽量不要用,因为不同控制器可能会有bug,不允许使用这个地址。
尽量设置个4以上的。

出0入0汤圆

 楼主| 发表于 2010-3-29 09:46:06 | 显示全部楼层
如果大家都发同一个ID 接收倒是实现了 总线仲裁完蛋了
如果接收方对应不同的ID设置很多接收邮箱 节点少倒是能实现 但灵活性和可扩展性全没了···

出0入0汤圆

 楼主| 发表于 2010-3-29 09:46:36 | 显示全部楼层
收到 嘿嘿嘿 我再去试试

出0入0汤圆

 楼主| 发表于 2010-3-29 09:54:51 | 显示全部楼层
失败····
发送ID 5 接收ID 4
接收失败·····

出0入0汤圆

发表于 2010-3-29 10:33:39 | 显示全部楼层
简单说一下你测试时两个节点的设置及硬件条件,没看到东西没法详细说。

出0入0汤圆

 楼主| 发表于 2010-3-29 12:36:51 | 显示全部楼层
CAN控制器是040内置的 收发器用的vd230 控制器和收发器之间用ps8601光耦隔离
每个节点都有个地址 初始化CAN消息对象的时候 就是用这个地址作为ID初始化的
现在的现象就是 如果两个节点设置成相同地址(也就是相同ID)的话,彼此通信没问题
想让其中一个节点不过滤消息,接收别的所有ID的数据 现在的做法是 把要接收所有ID数据的那个节点 地址设置成和别的节点不一样 然后初始化接收消息对象的时候 设置成不过滤 结果 还是接收不到消息(就是说不能接收不同ID的数据)

出0入0汤圆

 楼主| 发表于 2010-3-29 12:39:17 | 显示全部楼层
初始化接收消息对象的代码是直接复制你上边的代码 呵呵

出0入0汤圆

 楼主| 发表于 2010-3-29 12:40:31 | 显示全部楼层
你在实际工程中用过040CAN的这个功能吗
因为以前的阴影 现在怀疑是不是040内置的CAN控制器实现不了这个功能
因为从网上下了北航那本书的代码 看他的代码里 实现这个功能是靠定义不同ID的接收邮箱实现的·····

出0入0汤圆

发表于 2010-3-29 13:11:18 | 显示全部楼层
我已经用040做了几个项目了,而这几个项目都通过了用户的评估,即使在恶劣环境下也能正常工作。
你可以这样做:在初始化里不要对ARB等寄存器初始化,使用默认值,这样应该是不过滤的。
另:你能收到中断么?如果有中断,再看看Intpend的值是否是本节点的,是否在中断接收的时候给扔掉了?

出0入0汤圆

 楼主| 发表于 2010-3-29 15:37:36 | 显示全部楼层
有中断 但intpend的值为0 说明在ID过滤那块被滤掉了 呵呵
好的 我按默认值试试
我以前用的是F120 很好用 这次本来想F120加SJA1000的
有个同事选了040 选完就把自己掉坑里了 然后就辞职不干了·····

出0入0汤圆

发表于 2010-4-3 16:00:41 | 显示全部楼层
请问下  我想用CAN实现这样功能:

一台主机管理32台从机, 从机能主动任何时刻发送给一台主机

从机之间不会通信(收到也过滤)  主机不会主动轮询从机(负责收32个从机的数据)  但会在收到某ID的从机数据正确后会和这ID地址的从机进行数据收发确认

这时 其他从机 不是主机发送自己的数据滤去接收。不参与通信

从机全是突发性竞争的传送(但不会一直竞争传送),这样用CAN协议过滤配置可以实现吗?

原来用RS485 轮询的太慢了,所以想改用CAN,但CAN还不怎么理解。请指点下

另外 C8051F比较熟悉,原本想用040来做CAN通信

发现你们说的问题不少,所以我想用SJA1000或者SPI接口的CAN等外接,单片机用熟悉的C8051F020.

这样选型怎么样? 价格问题不是考虑很多  谢谢!

出0入0汤圆

发表于 2010-4-3 16:56:39 | 显示全部楼层
用040很好啊,本身中断并不占用多少时间.
可以实现你说的那种竞争,因为CAN总线是自动仲裁的,总线忙的时候会自动重发,只要不是经常竞争就没问题.
020+sja1000我也用过,这样比较占地方而且焊接不良导致的问题也多,040把can集成到cpu内,既省板上空间也提高了可靠性,个人认为集成的好.

出0入0汤圆

发表于 2010-4-4 13:51:29 | 显示全部楼层
谢谢 lnskngdc

还有一个问题请教下  我每次收发都在10字节-32字节之间

对于一次8字节的can
我选择什么CAN协议比较好的处理 这类字节较长的通信 又不会因为

竞争导致 在间隔的数据包中被打乱

出0入0汤圆

发表于 2010-4-4 15:08:09 | 显示全部楼层
不客气,呵呵
多字节传输一般的应用层协议好像都有描述,据我所知的是canopen用的比较多.也有用SDS的.
你可以搜索canopen中文版协议看看,这个可以参考着做,canopen的传输机制还是比较好的.

出0入0汤圆

发表于 2010-5-6 09:55:04 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-29 21:22:01 | 显示全部楼层
好好,支持下

出0入0汤圆

发表于 2010-12-16 15:55:47 | 显示全部楼层
回复【6楼】lnskngdc
-----------------------------------------------------------------------

想问一下,如果一个节点发送一个数据,其他的节点都能接收到数据,这样怎么设置?现在的情况是,数据过来了,节点会产生中断,但是只有ID相符的数据才会被接收,否则数据都为0,我想要的是不管id是否都一样,数据都能被正常的接收

出0入0汤圆

发表于 2010-12-16 16:05:01 | 显示全部楼层
回复【44楼】fzuzwl
回复【6楼】lnskngdc  
-----------------------------------------------------------------------
想问一下,如果一个节点发送一个数据,其他的节点都能接收到数据,这样怎么设置?现在的情况是,数据过来了,节点会产生中断,但是只有id相符的数据才会被接收,否则数据都为0,我想要的是不管id是否都一样,数据都能被正常的接收
-----------------------------------------------------------------------

可以设一个公共ID,比如255.
每个节点除了接收本身固定ID,还设置一个公用ID,
这样用来接收广播报文.每个节点都会认为这个报文是给自己的.

出0入0汤圆

发表于 2010-12-17 11:09:34 | 显示全部楼层
回复【45楼】lnskngdc
-----------------------------------------------------------------------

非常感谢lnskngdc,现在用的是8051F040单片机,本身集成有CAN,我的问题是这样的:
   1.我对can的理解是这样的can本身发送报文就是一个广播式的发送,只要掩码没设置,任何节点都能接收到数据,如果节点设置掩码才能接受到和本身ID一样的报文!我的理解有错吗?还是下面的这种情况,只有ID相同才能接收到数据.
   2.可以设置多个接收体?如果这样接收怎么判断发送方的ID?
   3.受到数据还要判断是哪个ID号发送过来的,如果按照您刚才那样的想,接收到的ID就都是一样的了。

出0入0汤圆

发表于 2010-12-17 14:09:10 | 显示全部楼层
回复【46楼】fzuzwl
-----------------------------------------------------------------------
非常感谢lnskngdc,现在用的是8051f040单片机,本身集成有can,我的问题是这样的:
   1.我对can的理解是这样的can本身发送报文就是一个广播式的发送,只要掩码没设置,任何节点都能接收到数据,如果节点设置掩码才能接受到和本身id一样的报文!我的理解有错吗?还是下面的这种情况,只有id相同才能接收到数据.
   2.可以设置多个接收体?如果这样接收怎么判断发送方的id?
   3.受到数据还要判断是哪个id号发送过来的,如果按照您刚才那样的想,接收到的id就都是一样的了。
-----------------------------------------------------------------------

1.你的理解是对的.
2.仔细看CAN usermanual 2.0 一共可以设置32个mailbox,也就是说除了一个发送的,你可以设置31个不同的接收ID.
3.如果不设置广播,那收到的中断是要判断中断号,不用判断ID,这个是C8051F系列的特例,其他内置CAN的MCU不是这样.
  如果设置了广播,例如ID=255,则所有节点收到的都是同样的ID和DATA.

出0入0汤圆

发表于 2010-12-17 16:19:39 | 显示全部楼层
回复【47楼】lnskngdc
-----------------------------------------------------------------------
再次感谢lnskngdc,我还想问一下:
1.能不能读取发送方的ID,怎么我读取的都是自己的ID?
2.接收滤波过滤设置时在消息控制寄存器中的Umask位吗?清0就可以取消过滤?也就是说任何ID发送过来的数据都能接收到数据!这样对吗?但是我程序中Umask位为0,还是只有ID号相符才能接受到数据。接收体程序如下,希望lnskngdc百忙之中抽空解答一下,甚是感激!
void init_msg_object_RX (char MsgNum,unsigned int id,unsigned int arbi)
{
        unsigned int temp;
        unsigned char SFRPAGE_SAVE = SFRPAGE;
           SFRPAGE = CAN0_PAGE;

        CAN0ADR = IF2CMDMSK;
        CAN0DAT = 0x00BB;            
                       //  IF2 Command Mask Registers  =0x00bb
                       //        WR/RD=1,Mask=0,Arb=1,Control=1,ClrIntPnd=1,TxRqst=0,DataA=1,DataB=1,一次发送8字节数据

                       //  CAN0DAT = 0x0000;
                        //        CAN0DAT = 0x1FFC;  
        CAN0ADR = IF2ARB1;           
//        CAN0DAT = 0x0000;            //IF2 Arbitration Registers1 =0x0000,即ID15-0=0  
    CAN0DAT  = arbi;                // Set arbitration1 ID
//        CAN0DAT = 0xA1B2;
         
//        temp = id<<2;                //标准id为ID28-ID18,所以要左移2位
    temp = id;                   //扩展ID为ID28-ID0,
        temp &= 0x1fff;
//        temp |= 0x8000;
        temp |= 0xC000;
        CAN0DAT = temp;
//  IF2 Arbitration Registers2=100(id)00b
//        MsgVal=1,Xtd=0,为标准模式,扩展ID无效,Dir=0,对应0x8000;
//        MsgVal=1,Xtd=1,为扩展模式,扩展ID有效,Dir=0,对应0xC000;
        CAN0DAT = 0x0488;
//  IF2 Message Control Registers=0x0488
//        NewDat=0,MsgLst=0,IntPnd=0,UMask=0,TxIE=0,RxIE=1,接收中断使能;RmtEn=0,TxRqst=0
//        EoB=1,DLC3-0=1000,即数据长度为8
        CAN0ADR = IF2CMDRQST;        
        CAN0DATL = MsgNum;           //IF2 Command Request Registers=MsgNum,将以上配置写入MsgNum号消息         
        SFRPAGE = SFRPAGE_SAVE;
}

void receive_data (unsigned char MsgNum,unsigned char*p,unsigned char *get_ID)
{
           unsigned char i;
//        unsigned int j;
           SFRPAGE = CAN0_PAGE;

        CAN0ADR = IF2CMDMSK;              
        CAN0DATL = 0x3F;
//        CAN0DATL = 0x0F;         
//  IF1 Command Mask Registers  =0xxx0f
//        WR/RD=0,Mask=0,Arb=0,Control=0,ClrIntPnd=1,NewDat=1,DataA=1,DataB=1,一次发送8字节数据
        CAN0ADR = IF2CMDRQST;             
        CAN0DATL = MsgNum;                       //指向MsgNum号消息     
        CAN0ADR = IF2ARB2; //2008-4-15 NEW ADD ,获取ID
   // get_ID = CAN0DAT;          
        *get_ID = CAN0DATH;
          get_ID++;
    *get_ID = CAN0DATL;
          get_ID++;
          CAN0ADR = IF2ARB1;
        *get_ID = CAN0DATH;
          get_ID++;
    *get_ID = CAN0DATL;                                       
        CAN0ADR = IF2DATA1;              
        for(i=0;i<8;i++)
        {/*
                 r_data[i+1] = CAN0DATH;
                i++;
                r_data[i-1] = CAN0DATL;
           */
            *++p=CAN0DATH;
        p--;
        *p++=CAN0DATL;
        p++;
        }

出0入0汤圆

发表于 2010-12-17 18:19:54 | 显示全部楼层
接收区的11bit或29bit ID,包括了主节点和从节点的ID.
一般在应用层,真正的节点地址部分只占用6个连续的bit,比如最低的bit5~bit0.  其他的bit会有更多的用处,比如bit7代表通讯方向,0:从到主,若是1;主到从.等等一般主节点地址为0~3,因为地址越低,发送优先级越高.
这些都是你自己可以定义的,或者按标准协议来做.

至于UMASK部分,说实话,我已经忘的差不多了,差不多3年前的项目.
只记得对IFARB部分做了修改,你可以多试试,不会把片子写坏的,呵呵.
自己多试试,会很有乐趣,实在行不通再上来问.

出0入0汤圆

发表于 2010-12-21 11:12:34 | 显示全部楼层
回复【49楼】lnskngdc
-----------------------------------------------------------------------
lnskngdc大神又要麻烦你了:
1.远程帧发送,假设A节点向B节点发送远程帧请求数据吗,B节点则是把自己的节点ID和数据帧发送出去,为什么不是把节点A的ID和数据发送出去,这样A节点才能知道是B发给他的。
2.怎么读取发送方的ID,如A节点向B节点发送数据,B节点接收的数据怎么判断是A节点发给它的,我从仲裁寄存器读取ID号都是B自己的ID。要怎么读到A的ID?
3.不知道是不是BUG,当接收到远程帧,节点把自己的节点ID和数据帧发送出去,但是以后发送数据帧的时候,都是自己的ID和数据,而不是数据帧发送体的ID。(总共是两个发送体一个是数据帧的发送体,一个是远程帧的发送体)。是不是只能有一个发送体。
这些我都试了好多次,但是就不知道原因。只能来这里问了。

出0入0汤圆

发表于 2011-5-17 17:33:40 | 显示全部楼层
掩码怎么用啊?
把掩码全设为0,可以接收所有ID

出0入0汤圆

发表于 2011-6-8 21:43:14 | 显示全部楼层
回复【3楼】lnskngdc
silabs的can是用博世的核做的,符合can2.0标准,但是,他们在嵌入到c8051f040的时候,不知道什么原因,也许是bug或者空间不够或者什么别的.
使得用户在使用的时候,不能完全做到屏蔽can中断,也就是说,无论你如何设置屏蔽滤波寄存器,只要总线上有报文出现,这个节点就总会产生can中断.
解决的办法就是:在040的can寄存器里面找个intpend,在产生can中断的时候把它读出来,就能知道产生中断的邮箱号,如果里面的值,与你初始化can接收所用的mailbox号相同,则是你本身节点应该接收的数据,如果"0",或者你没有初始化的数,则要抛弃本次中断.
------------------------------------------------------------------------------------------------------------
后......
-----------------------------------------------------------------------

幸亏看到这个帖子了,lnskngdc好人呐

出0入0汤圆

发表于 2011-6-8 22:50:47 | 显示全部楼层
最近和F500的CAN芯片,好像没有发现这个问题了。

出0入0汤圆

发表于 2011-6-29 16:20:39 | 显示全部楼层
中断号INTPEND这么自动清除啊???

出0入0汤圆

发表于 2011-7-9 09:02:46 | 显示全部楼层
回复【楼主位】someone7715
-----------------------------------------------------------------------

是你设置的不对。可以实现过滤功能。

出0入0汤圆

发表于 2011-7-9 09:39:08 | 显示全部楼层
回复【3楼】lnskngdc
----------------------------------------------------------------------回复【3楼】lnskngdc
-----------------------------------------------------------------------

首先怀疑自己,然后怀疑芯片。

出0入0汤圆

发表于 2011-8-27 10:26:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-5 09:35:50 | 显示全部楼层
回复【53楼】OurWay
最近和f500的can芯片,好像没有发现这个问题了。
-----------------------------------------------------------------------

我最近也在用500单片机的can 有些疑问,能不能加qq277422973

出0入0汤圆

发表于 2013-3-28 01:02:18 | 显示全部楼层
lnskngdc 发表于 2010-4-3 16:56
用040很好啊,本身中断并不占用多少时间.
可以实现你说的那种竞争,因为CAN总线是自动仲裁的,总线忙的时候会 ...

请求lnskngdc 给个c8051f045的CAN完整程序,带ID过滤的。谢谢,加我QQ,916696187

出0入0汤圆

发表于 2013-3-28 01:05:06 | 显示全部楼层
fzuzwl 发表于 2010-12-17 16:19
回复【47楼】lnskngdc
-----------------------------------------------------------------------
再次感 ...

你好,能给一个你已经测试成功了的完整CAN程序吗?谢谢

出0入0汤圆

发表于 2013-5-8 00:41:40 | 显示全部楼层
lnskngdc 发表于 2010-12-16 16:05
回复【44楼】fzuzwl
回复【6楼】lnskngdc  
---------------------------------------------------------- ...

实在是悲剧,打个招呼都没权限!
如何设置c8051F040 CAN通信的固定ID和公用ID,可以给我一个CAN通信的程序吗?谢谢,加我QQ吧:911781291,非常感谢。

出0入0汤圆

发表于 2013-5-12 20:29:11 | 显示全部楼层
lnskngdc 发表于 2010-3-21 12:28
silabs的CAN是用博世的核做的,符合CAN2.0标准,但是,他们在嵌入到c8051F040的时候,不知道什么原因,也许是bug ...

帮帮忙吧,程序能正常发送,但是接收不到数据,进入中断后,中断标识为01.发送能够发送出去。我想接收总线上所以设备的数据。
#include "C8051F040.h"
#include "can.h"
#include "uart.h"
//CAN接收缓冲区
xdata unsigned char g_ucCanRecvBuff[16];        //CAN接收数据缓冲区
unsigned char g_ucCanSendBuff[16];        //CAN发送数据缓冲区
xdata unsigned char g_ucCanSendId[4];        //存对应发送CAN_ID
char status;
extern unsigned char canflag;

void clear_msg_objects (void)
{
        unsigned char i;
        SFRPAGE  = CAN0_PAGE;
        CAN0ADR  = IF1CMDMSK;    // Point to Command Mask Register 1
        CAN0DATL = 0xFF;         // Set direction to WRITE all IF registers to Msg Obj
        for(i=1;i<33;i++)
        {
                CAN0ADR = IF1CMDRQST; // Write blank (reset) IF registers to each msg obj
                CAN0DATL = i;
        }
        }

//Initialize Message Object for RX
void init_msg_object_RX (char MsgNum)
{
        SFRPAGE  = CAN0_PAGE;
        CAN0ADR  = IF1CMDMSK;  // Point to Command Mask 1
        CAN0DAT  = 0x00B8;     // Set to WRITE, and alter all Msg Obj except ID MASK
                             // and data bits
        CAN0ADR  = IF1MSK1;  // Point to IF1 Mask1 register
        CAN0DAT  = 0x0000;
        CAN0DAT  = 0xE000;

        CAN0ADR  = IF1ARB1;    // Point to arbitration1 register
        CAN0DAT  = 0x0001;     // Set arbitration1 ID to "1"
        CAN0DAT  = 0xC000;     // Arb2 high byte:Set MsgVal bit, no extended ID,                 扩展ID
                             // Dir = RECEIVE
        CAN0DAT  = 0x0488;     // Msg Cntrl: set RXIE, remote frame function disabled
        CAN0ADR  = IF1CMDRQST; // Point to Command Request reg.
        CAN0DATL = MsgNum;     // Select Msg Obj passed into function parameter list
                             // --initiates write to Msg Obj
        // 3-6 CAN clock cycles to move IF register contents to the Msg Obj in CAN RAM
}

//Initialize Message Object for TX
void init_msg_object_TX (char MsgNum)
{
  SFRPAGE = CAN0_PAGE;
  CAN0ADR = IF1CMDMSK;  // Point to Command Mask 1
  CAN0DAT = 0x00B2;     // Set to WRITE, & alter all Msg Obj except ID MASK bits
  CAN0ADR = IF1ARB1;    // Point to arbitration1 register
  CAN0DAT = 0x108A;     // Set arbitration1 ID to highest priority
  CAN0DAT = 0xE011;     // Autoincrement to Arb2 high byte:                    0xA002;                扩展ID
                        // Set MsgVal bit, no extended ID, Dir = WRITE
  CAN0DAT = 0x0088;     // Msg Cntrl: DLC = 1, remote frame function not enabled
  CAN0ADR = IF1CMDRQST; // Point to Command Request reg.
  CAN0DAT = MsgNum;     // Select Msg Obj passed into function parameter list
                        // --initiates write to Msg Obj
  // 3-6 CAN clock cycles to move IF reg contents to the Msg Obj in CAN RAM.
}
/***********************************************
** 函数名        :OpenCanInt
** 函数说明        :打开CAN中断
** 输入                :无
** 输出                :无
** 其它                :无
************************************************/
void OpenCanInt(void)                 //打开CAN中断
{
        EIE2 |= 0x20;                      //CPU开can中断
}

/***********************************************
** 函数名        :CloseCanInt
** 函数说明        :关闭CAN中断
** 输入                :无
** 输出                :无
** 其它                :无
************************************************/
void CloseCanInt(void)               //关闭CAN中断  
{
        EIE2 &= ~0x20;                    //CPU关can中断
}
/***********************************************
** 函数名        :Can_Init
** 函数说明        :初始化CAN
** 输入                :baudRate,CAN波特率
** 输出                :无
** 其它                :无
************************************************/
void Can_Init(unsigned int baudRate)
{

        SFRPAGE  = CAN0_PAGE;
        CAN0CN   = 0x41;       // Configuration Change Enable CCE and INIT
        CAN0ADR  = BITREG;     // Point to Bit Timing register
        CAN0DATH         = HIGH_WORD(baudRate);         //设置CAN波特率            
        CAN0DATL         = LOW_WORD(baudRate);        //设置CAN波特率  
        CAN0ADR  = IF1CMDMSK;  // Point to Command Mask 1
        CAN0DAT  = 0x0087;     // Config for TX : WRITE to CAN RAM, write data bytes,
                             // set TXrqst/NewDat, clr IntPnd
       
        // RX-IF2 operation may interrupt TX-IF1 operation
        CAN0ADR  = IF2CMDMSK;  // Point to Command Mask 2
        CAN0DATL = 0x1F;       // Config for RX : READ CAN RAM, read data bytes,
                             // clr NewDat and IntPnd
        CAN0CN  |= 0x06;       // Global Int. Enable IE and SIE
        CAN0CN  &= ~0x41;      // Clear CCE and INIT bits, starts CAN state machine
        EIE2                 |=0x20;                                 //开启CAN中断
}
void start_CAN (void)
{
        // Clear CAN RAM
        clear_msg_objects();
       
        // Initialize message object to transmit data
        init_msg_object_TX (0x02);
       
        // Initialize message object to receive data
        init_msg_object_RX (0x01);
       
        // Enable CAN interrupts in CIP-51
        EIE2 = 0x20;
       
        //Function call to start CAN
        Can_Init(CAN_RATE);
       
        //Global enable 8051 interrupts
        EA = 1;
}
void SendCanData (unsigned char MsgNum,unsigned char *sendcmdtocan)
{
        SFRPAGE  = CAN0_PAGE;  // IF1 already set up for TX
       
        CAN0ADR  = IF1CMDMSK;  // Point to Command Mask 1
        CAN0DAT  = 0x0087;     // Config to WRITE to CAN RAM, write data bytes,
                             // set TXrqst/NewDat, Clr IntPnd
        CAN0ADR  = IF1DATA1;   // Point to 1st byte of Data Field
        CAN0DATH = *(sendcmdtocan+1);
        CAN0DATL = *(sendcmdtocan);       // Ones signals to turn LED's light ON in data A1 field
        CAN0DATH = *(sendcmdtocan+3);
        CAN0DATL = *(sendcmdtocan+2);
        CAN0DATH = *(sendcmdtocan+5);
        CAN0DATL = *(sendcmdtocan+4);
        CAN0DATH = *(sendcmdtocan+7);
        CAN0DATL = *(sendcmdtocan+6);   
        CAN0ADR  = IF1CMDRQST; // Point to Command Request Reg.
        CAN0DATL = MsgNum;     // Move new data for TX to Msg Obj "MsgNum"
       
}

void receive_data (unsigned char MsgNum,unsigned char i)
{
       
        SFRPAGE  = CAN0_PAGE; // IF1 already set up for RX
        CloseCanInt();
        CAN0ADR  = IF2CMDRQST;// Point to Command Request Reg.
        CAN0DATL = MsgNum;    // Move new data for RX from Msg Obj "MsgNum"
                            // Move new data to a
        CAN0ADR  = IF2DATA1;  // Point to 1st byte of Data Field
       
        g_ucCanRecvBuff[i+1] = CAN0DATH;
        g_ucCanRecvBuff = CAN0DATL;
        g_ucCanRecvBuff[i+3] = CAN0DATH;
        g_ucCanRecvBuff[i+2] = CAN0DATL;
        g_ucCanRecvBuff[i+5] = CAN0DATH;
        g_ucCanRecvBuff[i+4] = CAN0DATL;
        g_ucCanRecvBuff[i+7] = CAN0DATH;
        g_ucCanRecvBuff[i+6] = CAN0DATL;
        OpenCanInt();
        canflag=1;
}
void ISRname (void) interrupt 19
{
        unsigned char temp;
        temp=SFRPAGE;
        SFRPAGE=CAN0_PAGE;
        status = CAN0STA;
        if ((status&0x10) != 0)
        {                            // RxOk is set, interrupt caused by reception
          CAN0STA = (CAN0STA&0xEF)|0x07;         // Reset RxOk, set LEC to NoChange
          /* read message number from CAN INTREG */
          receive_data (0x01,0);             // Up to now, we have only one RX message         注意,目前只接收八个数据
        }
        if ((status&0x08) != 0)
        {                            // TxOk is set, interrupt caused by transmision
          CAN0STA = (CAN0STA&0xF7)|0x07;        // Reset TxOk, set LEC to NoChange
        }
        if (((status&0x07) != 0)&&((status&0x07) != 7))
        {                           // Error interrupt, LEC changed
          /* error handling ? */
          CAN0STA = CAN0STA|0x07;              // Set LEC to NoChange
        }
        SFRPAGE=temp;
}
/***********************************************
** 函数名        :ComToCan
** 函数说明        :复制上位机命令,发送到角度传感器
** 输入                :n:发送数据的个数
** 输出                :无
** 其它                :无
************************************************/
void CopyComToCan(unsigned char n,unsigned char *comcmd)
{
        unsigned char i,j,k;
        for(i=0;i<4;i++)
        {
                g_ucCanSendId=*(comcmd+i);
                send_char_com(g_ucCanSendId);
        }

        if(n<=8)                                //如果n小于等于8,可以一次发送完
        {
                j=n;
                k=0;
        }
        else                                         //如果n大于8,要分多次发送
        {
                j=8;
                k=n-8;
        }

        delay(50);
        for(i=0;i<j;i++)                //数据拷备
        g_ucCanSendBuff=*(comcmd+(i+4));
//        k=g_ucCanSendBuff[0];
//        send_char_com(j);
//        send_char_com(k);
        SendCanData (0x02,g_ucCanSendBuff);                                           //第一次发送数据
        delay(500);
        for(i=0;i<16;i++)
        {
                g_ucCanSendBuff=0;   //清除CAN发送缓冲区       
        }
       
}

出0入0汤圆

发表于 2013-8-22 15:12:03 | 显示全部楼层
汲取经验来了,现在刚接以前同事的手来弄这个片子的can

出0入0汤圆

发表于 2013-9-13 16:20:45 | 显示全部楼层
lnskngdc 发表于 2010-4-4 15:08
不客气,呵呵
多字节传输一般的应用层协议好像都有描述,据我所知的是canopen用的比较多.也有用SDS的.
你可以 ...

问一下,如果是需要两路can接口呢?

出0入10汤圆

发表于 2016-10-11 11:52:11 | 显示全部楼层
这么多年的帖子,仔细看了下,好像还是没有说明ID验收滤波怎么搞,我也设置为全部ID接收,就是只能识别到指定的ID
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 21:25

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表