打印
[CAN-bus/DeviceNet]

sja1000遇到的不解问题,请高手进来帮帮!

[复制链接]
2287|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
danfeidie|  楼主 | 2008-6-11 12:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
SJA1000初始化成功!当想发送数据的时候,先检测了状态寄存器,REG_STATUS寄存器 = 0x44,第四位为0,表示正在发送,可我还没发送呢?所以在下面标记 1 的循环里跳不出来,原因是出在标记 2 的地方。
既然SJA1000初始化成功,那还出现这个问题,真是想了几天都没想不通。只能麻烦一下高手们了。下面附了小弟的程序,挺长,真是麻烦大家了。
#include    <reg51.h>
#include    "SJA_BCANCONF.H"
#include    <string.h>
void delay(unsigned int t);
bit Sja_1000_Init(void);
sbit LED = P1^0;
unsigned char data send_data[10] = {0xaa,0x08,2,3,4,5,6,7,8,9};

main()
{
    while(Sja_1000_Init());
    while(1)
    {
        while(BCAN_DATA_WRITE(send_data));/*老是跳不出来*/
        while(BCAN_CMD_PRG(0x01));
        delay(1000);
        LED = ~LED;
    }
}

/************************************************************************
* delay()
* 延时函数
*************************************************************************/
void delay(unsigned int t)
{
    unsigned char i;
    while(t--)
    {
        for(i=0;i<125;i++);
    }
}

/************************************************************************
* Sja_1000_Init()
* SJA1000初始化
*************************************************************************/
bit Sja_1000_Init(void)
{
    if(BCAN_CREATE_COMMUNATION())    //通信测试;
        return 1;
    if(BCAN_ENTER_RETMODEL())        //申请进入复位模式
        return 1;
    if(BCAN_SET_BANDRATE())             //设置波特率为50K
        return 1;
    if(BCAN_SET_OBJECT(0xaa,0xFF))   //设置ACK、AMR
        return 1;
    if(BCAN_SET_OUTCLK(0xaa,0x48))   //设置输出方式禁止clkout
        return 1;
    if(BCAN_QUIT_RETMODEL())            //退出复位状态
        return 1;
    SJA_BCANAdr = REG_CONTROL;        //送控制寄存器地址
    *SJA_BCANAdr |= 0x0A;             //开放错误中断和接收中断
    return 0;
}

/************************************************************************
*函数原型:  bit   BCAN_CREATE_COMMUNATION(void)                        * 
*参数说明:  无                                                         *
*返回值:                                                               *
*           0 ; 表示SJA1000接口正常                                    *
*           1 ; 表示SJA1000与处理器接口不正常                          *
*                                                                      * 
*说明:该函数用于检测CAN控制器的接口是否正常                            *
************************************************************************/
bit   BCAN_CREATE_COMMUNATION(void)
{  
    SJA_BCANAdr=REG_TEST;                     //访问测试寄存器            
    
    *SJA_BCANAdr   =0xaa;                     //写入测试值
    if(*SJA_BCANAdr == 0xaa)
    {
        return    0;                          //读测试正确
    }
    else
    {    
       return    1;
    } 
}       

/************************************************************************
*函数原型:      bit   BCAN_ENTER_RETMODEL(void)                        *
*参数说明:  无                                                         *
*返回值:                                                               *
*           0 ; 表示成功进入复位工作模式                               *
*           1 ; 表示不能进入复位工作模式                               *
*                                                                      * 
*说明:      CAN控制器进入复位工作模式                                  *
************************************************************************/ 
bit   BCAN_ENTER_RETMODEL(void)
{
    unsigned   char   TempData;
    SJA_BCANAdr  = REG_CONTROL;                   //访问地址指向控制寄存器 
    TempData=  *SJA_BCANAdr;                      //保存原始值
    *SJA_BCANAdr=(TempData|0x01);                 //置位复位请求
    if((*SJA_BCANAdr&0x01) == 1)
    {
       return   0;
    }
    else
    {
       return   1;
    }
    
}

/************************************************************************
*函数原型:      bit   BCAN_QUIT_RETMODEL(void)                         *
*参数说明:  无                                                         *
*返回值:                                                               *
*           0 ; 表示成功退出复位工作模式                               *
*           1 ; 表示不能退出复位工作模式                               *
*                                                                      * 
*说明:      CAN控制器退出复位工作模式                                  *
************************************************************************/ 
bit   BCAN_QUIT_RETMODEL(void)
{
    unsigned   char   TempData;
    SJA_BCANAdr = REG_CONTROL;                   //访问地址指向控制寄存器 
    TempData    = *SJA_BCANAdr;                  //保存原始值
    *SJA_BCANAdr=(TempData&0xfe);                //清除复位请求
    if((*SJA_BCANAdr&0x01) == 0)
    {
       return   0;                               //
    }
    else
    {
       return   1;                              //退出成功
    }

}

/************************************************************************
;*函数原型:   bit   BCAN_SET_BANDRATE(unsigned char CAN_ByteRate)       *
;*参数说明:  R7            波特率(Kbit/s) BTR0     BTR1               *
;*                         50Kbit/s         0xC9     0xA7               *
;*返回值:                                                               *
;*           0 ;波特率设置成功                                          *
;*           1 ;波特率设置失败                                          *
;*                                                                      * 
;*说明:设置CAN控制器SJA1000通讯波特率.SJA1000的晶振为必须为12MHZ,       *
;*     其它晶体的频率的值的波特率,需自己计算 。该子程序只能用于        *
;*     复位模式                                                         *  
;************************************************************************/


bit   BCAN_SET_BANDRATE(void)
{
  unsigned  char  BTR0_num,BTR1_num;
  BTR0_num = 0xC9;
  BTR1_num = 0xA7;
  //将波特率的的预设值装入sja1000的总线定时器
  SJA_BCANAdr=REG_BTR0;                  //访问地址指向总线定时寄存器0
  *SJA_BCANAdr=BTR0_num;                  //写入参数
  if(*SJA_BCANAdr != BTR0_num)            //校验写入值
  {
    return  1; 
  }
  SJA_BCANAdr=REG_BTR1;                 //访问地址指向总线定时寄存器0
  *SJA_BCANAdr=BTR1_num;                  //写入参数
  if(*SJA_BCANAdr != BTR1_num)            //校验写入值
  {
    return  1; 
  }

  return    0;
}  


/************************************************************************
;*函数原型:    BCAN_SET_OBJECT                                          *
*参数说明:                                                              *
*    BCAN_ACR:存放验收代码寄存器(ACR)的参数设置                      *
*    BCAN_AMR:存放接收屏蔽寄存器(AMR)的参数设置                      *
;*返回值:                                                               *
;*           0 ;通信对象设置成功                                        *
;*           1 ;通信对象设置失败                                        *
;*                                                                      * 
;*说明:设置CAN节点的通讯对象,允许接收的报文ID号的高8位(D10--D3) 。     *
;*     允许接收的报文,是由AMR和ACR共同决定的.                           *  
;*    满足以下条件的ID号的报文才可以被接收                              *
;*[(ID.10-ID.3)≡(AC.7-AC.0)]||(AM.7-AM.0)≡11111111              *
;*    该子程序只能用于复位模式                                          *                                                                                                                     *             
;************************************************************************/
bit    BCAN_SET_OBJECT(unsigned char  BCAN_ACR,unsigned char  BCAN_AMR)
{
   SJA_BCANAdr=REG_ACR;                  //访问地址指向验收代码寄存器(ACR)
  *SJA_BCANAdr=BCAN_ACR;                //写入参数
  if(*SJA_BCANAdr != BCAN_ACR)          //校验写入值
  {
    return  1; 
  }
  SJA_BCANAdr=REG_AMR;                  //访问地址指向验收屏蔽寄存器(AMR)
  *SJA_BCANAdr=BCAN_AMR;                //写入参数
  if(*SJA_BCANAdr != BCAN_AMR)          //校验写入值
  {
    return  1; 
  }

  return    0;
}

/************************************************************************
;*函数原型: bit  BCAN_SET_OUTCLK (unsigned char Out_Control,             *
                                  unsigned char  Clock_Out);            *
;*参数说明:                                                                  *
*    Out_Control:存放输出控制寄存器 (OC)  的参数设置                   *
*    Clock_Out:存放时钟分频寄存器 (CDR) 的参数设置                     *
*                                                                      *   
;*返回值:                                                               *
;*           0 ;设置成功                                                *
;*           1 ;设置失败                                                *
;*                                                                      * 
;*说明:设置SJA1000的输出模式和时钟分频 。该子程序只能用于复位模式       *                                                                                                                     *             
;************************************************************************/
bit  BCAN_SET_OUTCLK (unsigned char Out_Control,    
                     unsigned char  Clock_Out)
{
  SJA_BCANAdr=REG_OCR ;                  //访问地址指向输出控制寄存器
  *SJA_BCANAdr=Out_Control;              //写入参数
  if(*SJA_BCANAdr != Out_Control)        //校验写入值
  {
    return  1; 
  } 
  SJA_BCANAdr=REG_CDR;                  //访问地址指向输出控制寄存器
  *SJA_BCANAdr=Clock_Out;                //写入参数
  return    0;
}

/************************************************************************
*函数原型:  bit   BCAN_DATA_WRITE(unsigned char *SendDataBuf)*
*参数说明:  特定帧各式的数据?                                         *
*返回值:                                                               *
*           0    ; 表示将数据成功的送至发送缓冲区                      *
*           1      ; 表示上一次的数据正在发送,                          *
*                ; 表示发送缓冲区被锁定,不能写入数据                  *
*                ; 表示写入数据错误                                    * 
*说明: 将待发送特定帧各式的数据,送入SJA1000发送缓存区中,然后启动     *
*        SJA1000发送。                                                 *
*   特定帧格式为:开始的两个字节存放 '描述符' ,以后的为数据             *
*   描述符包括11位长的ID(标志符)\1位RTR\4位描述数据长度的DLC共16位    *
*                                                                      *
*注:本函数的返回值仅指示,将数据正确写入SJA1000发送缓存区中与否。     *
*    不指示SJA1000将该数据正确发送到CAN总线上完毕与否                  *
************************************************************************/ 
bit  BCAN_DATA_WRITE(unsigned char *SendDataBuf)
{
   unsigned  char  TempCount;
   SJA_BCANAdr = REG_STATUS;            //访问地址指向状态寄存器
   if((*SJA_BCANAdr&0x08) == 0)         //判断上次发送是否完成
   {
    return    1;  //????????     总是进来,此时的STATUS = 0x44       ??????????
   }

   if((*SJA_BCANAdr&0x04)==0)          //判断发送缓冲区是否锁定
   {
     return    1;
   }  

   SJA_BCANAdr = REG_TxBuffer1;        //访问地址指向发送缓冲区1
   if((SendDataBuf[1]&0x10)==0)        //判断RTR,从而得出是数据帧还是远程帧
   { 
     TempCount =(SendDataBuf[1]&0x0f)+2; //输入数据帧
   }

   else
   {
     TempCount =2;                     //远程帧
   }

  memcpy(SJA_BCANAdr,SendDataBuf,TempCount);
   return 0;
}

/************************************************************************
*函数原型:  bit  BCAN_CMD_PRG(unsigned char cmd)             *
*参数说明:  cmd:sja1000运行的命令字                                    *
*             01:发送请求                                              *
*             02:中止发送                                             *
*             04:释放接收缓冲区                                       *
*             08:清除超载状态                                         *
*             0x10:进入睡眠状态                                        *
*                                                                      *
*返回值:                                                               *
*           0 ; 表示命令执行成功                                       *
*           1 ; 表示命令执行失败                                       *
*                                                                      * 
*说明:      执行sja1000命令                                            * 
************************************************************************/ 
bit  BCAN_CMD_PRG(unsigned char cmd)
{
   SJA_BCANAdr=REG_COMMAND;            //访问地址指向命令寄存器
   *SJA_BCANAdr=cmd;                   //启动命令字
   switch(cmd)
   {
     case  TR_CMD:                     //发送请求命令
           return    0;
           break;
     case  AT_CMD:                     //夭折发送命令 
           SJA_BCANAdr = REG_STATUS;   //访问地址指向状态寄存器   
           if((*SJA_BCANAdr & 0x20)==0)//判断是否正在发送
           {
              return  0;
           }
           else
           {
              return  1;
           }   
           break; 
     case  RRB_CMD:                    //释放接收缓冲区 
           SJA_BCANAdr = REG_STATUS;   //访问地址指向状态寄存器   
           if((*SJA_BCANAdr & 0x01)==1)//判断是否释放成功
           {
             return  1;
           }
           else
           {
              return  0;
           }   
           break; 
  
     case  COS_CMD:                    //清除超载状态
           SJA_BCANAdr = REG_STATUS;   //访问地址指向状态寄存器   
           if((*SJA_BCANAdr & 0x02)==0)//判断清除超载是否成功
           {
             return  0;
           }
           else
           {
              return  1;
           }   
           break; 
     
     case  GTS_CMD:                    //进入睡眠状态命令 
           return    0;
           break; 
     default:
             return  1;
             break; 
   }

}



相关帖子

沙发
danfeidie|  楼主 | 2008-6-13 09:11 | 只看该作者

凡事要靠自己啊!

没人帮俺,自助者天助。原来俺把收发器的管脚接错了。都怪周立功,提供的原理图都错了,也怪俺,太相信周立功。现在一切正常了。哈哈哈哈哈哈哈哈哈……

使用特权

评论回复
板凳
yuhison| | 2008-6-23 19:41 | 只看该作者

学习了

我也是参照周立功做的,我也一直没挑出来,我看看是不是我的管脚也反了。

还有你用的收发器是什么??是周立功的CTM系列的吗?

使用特权

评论回复
地板
xuxiaozhao| | 2008-7-7 23:50 | 只看该作者

SJA1000

这个程序我做过.我的博客有我调式通过的程序:
xuxiaozhao163.blog.163.com

使用特权

评论回复
5
donkevin| | 2008-8-17 22:44 | 只看该作者

建议到pudn上下载其他人的程序借鉴一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

109

帖子

0

粉丝