⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can好文[转载](梦醒了).htm

📁 现场总线can的详细资料
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0036)http://www.daxia.com/list_1476.shtml -->
<HTML><HEAD><TITLE>大虾电子-CAN好文[转载](梦醒了)</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312"><LINK 
href="CAN好文[转载](梦醒了).files/style.css" rel=stylesheet>
<META content="MSHTML 6.00.2800.1528" name=GENERATOR></HEAD>
<BODY>
<DIV align=center>
<CENTER>
<SCRIPT type=text/javascript><!--
google_ad_client = "pub-1260019700816245";
google_alternate_ad_url = "http://www.daxia.com/product/dx58";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_color_bg = "efefef";
google_ad_type = "text";
google_ad_channel ="";
//--></SCRIPT>

<SCRIPT src="CAN好文[转载](梦醒了).files/show_ads.js" type=text/javascript>
</SCRIPT>
</CENTER></DIV>
<DIV align=center>
<CENTER>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width="97%" 
borderColorLight=#000000 border=1>
  <TBODY>
  <TR>
    <TD width="100%" bgColor=#d0d0d0>
      <P align=center>文章编号:1476----加入日期:2004-5-18 </P></TD></TR>
  <TR>
    <TD width="100%">
      <P align=right><A href="javascript:self.close()">『关闭窗口』</A></P></TD></TR>
  <TR>
    <TD width="100%">
      <P align=center><B>CAN好文[转载](梦醒了)</B></P></TD></TR>
  <TR>
    <TD width="100%">
      <BLOCKQUOTE><BR>我在学习CAN应用设计中的一点心得体会,也算是走了一些弯路,现在把它写出来和大家共<BR>同交流。<BR>  
        不知道各位注意到没有,大多数情况下,SJA1000是与8250+51系列单片机的方式来做<BR>CAN的控制应用。如果是1M/s的通讯速度的话,实际上的流量只有大概500多K的样子,此点<BR>希望大家在以后的应用设计中需要考虑周到。<BR>  上诉问题产生的原因是SJA1000的发送缓冲区只有1个,应用程序在判断发送完一幀<BR>数据后,需要计算下一幀需要装载的数据长度,然后根据长度再装载相应的数据到缓冲区<BR>,这个过程要消耗掉了一定的时间(特别是标准51内核的单片机),因此CAN总线上的数据<BR>流实际上是发送一幀就有一个比较长的空闲区(单片机装载数据的时间),这样一来就浪费<BR>了总线资源。微芯的MCP2510有3个发送缓冲区,在5V的电源下以5Mb/s的SPI端口读写数据,可<BR>以较好的解决这个问题,但是多数的51单片机都无SPI,这样也给单片机的选择上带来了一<BR>定的麻烦。具体选择怎样的方案,只能看各自的应用情况来定了!<BR>  <BR>sja1000调试经验    <BR>  去年年底的时候,一个公司给我打电话,问我最近有没有空,说要请我帮忙做一个基于<BR>CAN总线通讯的东西,我去看了看,是一个数据采集系统,下面是一系列数据采集的智能板<BR>卡,上位机是基于WINBOND的一块486的工业嵌入式控制板,操作系统使用的是WINCE。智能<BR>板卡通过工业底板和数据线两种方式和上位机通讯,通信协议选择的是CAN,其中底板上的<BR>通信选用高速波特率(1Mbps),数据线选用低速(100kbps)。<BR>  去公司的时候,公司给了我一个参考的东西,采用SST单片机+SJA1000的方案构成的智<BR>能板卡,同时告诉我可以自己设计方案。考虑到SST的东西没有用过,P8X591是PLCC封装<BR>的,烧写起来不方便,于是我设计了如下的方案:<BR>  1、智能板卡上的通讯采用AT89S51+两块SJA1000的方式进行;<BR>  2、上位机通过PC104总线和一块CAN控制板卡连接,CAN控制板卡上同样采用AT89S51+两<BR>块SJA1000的方案。AT89S51和上位机通过PC104总线共享内存(使用IDT的双口RAM);<BR>  3、采用西门子的组态软件进行WINCE下的板卡驱动开发;<BR>   
        由于以前没有做过CAN的东西,于是决定了先调试CAN通信,然后设计板卡的方案。<BR>方案确定之后,首先是上www.zlgmcu.com上下载了全部的SJA1000和PCA82C250的资料。然后<BR>始设计电路板。采用了SJA1000应用指南中推荐的方案,采用SJA1000的时钟输出为AT89S51<BR>的时钟,没有采用光电隔离芯片,把TX1接地,TX0和RX0分别连接到PCA82C250的TXD和RXD引<BR>脚上,RX1连接到PCA82C250的VR上;加上了5欧姆的限流电阻和120欧姆的匹配电阻(用110欧<BR>姆替代),另外加上了一个调试用的串口。没有注意而且要命的是把SJA1000的复位引脚和单<BR>片机的复位引脚连接到了一起。<BR>  第一次的板子用的加急,用了三天,结果那次的板子做的极差——连铜皮都翻起来了;<BR>我马上让那个电路板厂重新做了三块。在做板的过程中我发现了复位引脚的错误,SJA1000的<BR>文档上提供的是一个复位电路,但是没有给出电路的详细组成,于是我就误以为和单片机的<BR>复位电路是一样的了。在设计这块电路板的时候,最担心的事情就是SJA1000的输出时钟能<BR>不能够驱动AT89S51,如果不能够驱动,那么一切就OVER了,可惜的是我的担心成为了现<BR>实,板子焊好之后系统不工作,在SJA1000的时钟输入引脚上有信号输入,而且输出时钟也<BR>正常,但是单片机就是不工作。于是我先把SJA1000的复位引脚连线割断,连接到了AT89S51<BR>的IO引脚上,再把S51的XTAL的两个引脚连接到SJA晶体的上,可惜系统还是不工作,这次电<BR>路板设计失败了。<BR>  在总结了第一次失败的经验后,参看了21IC上的一个设计,决定把AT89S51和SJA的晶体<BR>分开。并且用单片机的一个IO引脚来控制对SJA的复位。<BR> &nbsp;&nbsp;第二次的电路板比较成功,焊接好了之后首先测试单片机的串口和LED指示灯,一切<BR>OK。然后就开始测试SJA。ZLG提供了一个BASIC模式下的参考例程,我看了一下,然后又找<BR>了本《现场总线CAN的原理和测试》把SJA的寄存器详细看了看(由于开始的时候比较忙,所<BR>以直到这个时候才算是仔细看了看SJA的内部,至于CAN的基础协议我是根本没有看,这给我<BR>后面带来了极大的麻烦)。然后就参考ZLG的程序开始写SJA的测试程序,那个程序写的很<BR>大,也很全,因为我想快点把东西给做出来,于是弄了一个1000多行的程序,以前我的调试<BR>程序一般都很小的。写好程序之后就开始测试,首先测试的是测试寄存器,然后一步步测试<BR>下去,在BASIC模式下所有的寄存器都正常,但是在发送的时候是总是不正常,启动发送之<BR>后就一直在发送,状态寄存器的标志位一直处在发送的状态下,然后就是报总线错误,不知<BR>道是怎么会事情,很郁闷,上bbs看了一下。bullfrog告诉我单个CAN节点发送是成功不了<BR>的,如果没有收到接受CAN节点的应答,发送节点就会一直发送,直到超出错误计数器的允<BR>许值使得总线关闭。同时在精华区发现在peli模式下有ECC(错误寄存器),可以跟踪错误,<BR>于是开始看peli模式操作过程。这个东西比较麻烦,zlg没有提供公开的c代码,我找了一个<BR>汇编的作为参考。<BR>  
        我第一步的目标是自发送,在peli模式下有自发送这种模式,在有匹配电阻的情况下可<BR>以进行单个节点的接收和发送。第一次调试的时候没有成功,给北京zlg打电话,北京分公<BR>司说让我给广州打电话,给广州打电话,几个问题都得到了很好的解答(在此谢谢zlg的工<BR>程师了):<BR>     
        1、自发送的时候必须加上匹配电阻;<BR>     2、5欧的限流电阻可以不需要;<BR>     3、每次发送完成之后<BR>     
        4、建议使用中止发送来进行单步发送;<BR>     另外他告诉我可以在zlg的论坛上找到很多很有用的东西。<BR>     
        听了他的建议,我第一件事情就是检查我的电路板,检查的结果让我大吃一惊—<BR>—我的ch和cl竟然是短路的,万用表的狂叫不止。一步步检查,发现那个110欧的匹配电阻<BR>有问题,万用表碰上去就叫,于是把那个电阻剪下来,量量还是短路。于是我怀疑把5欧的<BR>限流电阻当成了110欧的电阻,于是把匹配电阻都去掉了。没有想到的是当我把新的110欧电<BR>阻拿来的时候,万用表还是叫,这时候才发现这块万用表在300欧姆以下都要叫,可怜我又<BR>打理了n长时间的电路板......再仔细阅读了一次peli模式下的操作指南,又仔细阅读了zlg<BR>提供的初始化规范,发现在子发送的时候发送的命令应该是0x10或者是0x12(即CMR寄存器里<BR>面有一个专门的控制位是用来控制自发送的,和普通的发送命令位是不同的)。在发现了这<BR>个问题之后,自发送一切顺利的通过了。<BR>  接下来就是两个节点的互调了,我首先用自发送程序把两个节点都调试了一下,保证单<BR>个节点发送硬件没有任何问题。然后就用双绞线通过接线端子把两个系统连接到了一起。第<BR>一次调试采用的是1M的波特率(由于ZLG只给出了16M晶体下的BTR0和BTR1的初始值,我在ZLG<BR>的论坛上找到了一个网友自己计算的数值,后来证明这个东西有些问题),没有成功。发送节<BR>点通过串口利用串口调试助手来控制发送,接收节点通过仿真器观察数据。虽然没有发送成<BR>功,但是通过串口的反馈数据和仿真器的观察窗,可以看到ECC寄存器都发生了变化,证明<BR>数据线上有数据过去(由于我没有示波器,只有采用这种办法)。于是我改变了两次波特率,<BR>最低到了5k,都没有成功,最后我从21IC上的一篇应用文章上找到了两个参数,这次就成功<BR>了,通讯速率20k。现在一切稳定,在写这篇文章的时候哪几个LED正欢快的闪烁着。<BR>     
        最后,总结几个经验:<BR>     1、一定要详细的阅读sja的手册和CAN的相关知识;<BR>     
        2、SJA的复位是低电平,而且不是用一个非们把单片机的RST反相就可以的,有两<BR>种解决方式:第一种是使用单片机的IO引脚来控制SJA的复位引脚,好处是单片机完全控制<BR>SJA的复位过程;第二种是采用适当的复位芯片,ZLG给我推荐的是CAT1161,我没有用过,<BR>其好处是同步复位。<BR>     
        3、在自发送的模式下,需要匹配电阻,而且自发送的启动命令和普通发送的启动<BR>命令不相同;<BR>     
        4、BRT0和BRT1的选择,和串口通信中只要两个的误差一样就可以了不同,一定要<BR>精心选择,建议SJA的外部晶体选择16M的,这样有利于参考ZLG的标准数值<BR>     
        5、SJA和其他外部器件连接的时候,数据线在373前后都可以;<BR>     6、最好有一个示波器;<BR>     
        7、不要太大意的相信万用表的蜂鸣器;<BR>     8、这是从ZLG网站上转载过来的peli模式下的初始化流程<BR>     
        a)检测硬件连接是否正确 <BR>     b)进入复位状态 <BR>     c)设置时钟分频寄存器 <BR>     d)设置输出控制寄存器 
        <BR>     e)设置通讯波特率 <BR>     f)设置代码验收寄存器 <BR>     g)设置代码屏蔽寄存器 <BR>     
        h)退出复位状态 <BR>     i)设置工作模式 <BR>     j)设置中断使能寄存器 
        <BR>    <BR>    这是一个自发收程序,采用at89s51+sja1000,分离晶体,at89s51晶体11.0592<BR>    sja1000外部晶体为12M,通过串口进行监控<BR>    ******************************************************<BR>    <BR>    以下为头文件定义<BR>    copyright 
        by 
        alloy<BR>    <BR>    ******************************************************<BR>    <BR>    #define 
        SJA_REG_BaseADD 0x7800<BR>    <BR>    #define REG_MODE 
        XBYTE[SJA_REG_BaseADD + 0x00]<BR>    #define REG_CMD 
        XBYTE[SJA_REG_BaseADD + 0x01]<BR>    #define REG_SR 
        XBYTE[SJA_REG_BaseADD + 0x02]<BR>    #define REG_IR 
        XBYTE[SJA_REG_BaseADD + 0x03]<BR>    #define REG_IR_ABLE 
        XBYTE[SJA_REG_BaseADD + 0x04]<BR>    #define REG_BTR0 
        XBYTE[SJA_REG_BaseADD + 0x06] //05保留<BR>    #define REG_BTR1 
        XBYTE[SJA_REG_BaseADD + 0x07]<BR>    #define REG_OCR 
        XBYTE[SJA_REG_BaseADD + 0x08]<BR>    #define REG_TEST 
        XBYTE[SJA_REG_BaseADD + 0x09]<BR>    #define REG_ALC 
        XBYTE[SJA_REG_BaseADD + 0x0b] //0a保留<BR>    #define REG_ECC 
        XBYTE[SJA_REG_BaseADD + 0x0c]<BR>    #define REG_EMLR 
        XBYTE[SJA_REG_BaseADD + 0x0d]<BR>    #define REG_RXERR 
        XBYTE[SJA_REG_BaseADD + 0x0e]<BR>    #define REG_TXERR 
        XBYTE[SJA_REG_BaseADD + 0x0f]<BR>    <BR>    #define REG_ACR0 
        XBYTE[SJA_REG_BaseADD + 0x10]<BR>    #define REG_ACR1 
        XBYTE[SJA_REG_BaseADD + 0x11]<BR>    #define REG_ACR2 
        XBYTE[SJA_REG_BaseADD + 0x12]<BR>    #define REG_ACR3 
        XBYTE[SJA_REG_BaseADD + 0x13]<BR>    #define REG_AMR0 
        XBYTE[SJA_REG_BaseADD + 0x14]<BR>    #define REG_AMR1 
        XBYTE[SJA_REG_BaseADD + 0x15]<BR>    #define REG_AMR2 
        XBYTE[SJA_REG_BaseADD + 0x16]<BR>    #define REG_AMR3 
        XBYTE[SJA_REG_BaseADD + 0x17]<BR>    <BR>    #define REG_RxBuffer0 
        XBYTE[SJA_REG_BaseADD + 0x10]<BR>    #define REG_RxBuffer1 
        XBYTE[SJA_REG_BaseADD + 0x11]<BR>    #define REG_RxBuffer2 
        XBYTE[SJA_REG_BaseADD + 0x12]<BR>    #define REG_RxBuffer3 
        XBYTE[SJA_REG_BaseADD + 0x13]<BR>    #define REG_RxBuffer4 
        XBYTE[SJA_REG_BaseADD + 0x14]<BR>    <BR>    #define REG_TxBuffer0 
        XBYTE[SJA_REG_BaseADD + 0x10]<BR>    #define REG_TxBuffer1 
        XBYTE[SJA_REG_BaseADD + 0x11]<BR>    #define REG_TxBuffer2 
        XBYTE[SJA_REG_BaseADD + 0x12]<BR>    #define REG_TxBuffer3 
        XBYTE[SJA_REG_BaseADD + 0x13]<BR>    #define REG_TxBuffer4 
        XBYTE[SJA_REG_BaseADD + 0x14]<BR>    <BR>    #define REG_DataBuffer1 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -