打印
[ZLG-MCU]

SJA1000不能置工作模式

[复制链接]
4486|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
haiougege|  楼主 | 2011-7-26 10:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我想做一个基于单片机的can总线,用的是51单片机+sja1000+pca82c250,现在sja1000的片选接的是单片机的P2^7,sja的初始地址是0x7f00,对吗?现在初始化时sja不能进入工作模式,哪位前辈做过类似东西可否指点一下啊?在下新手,还望前辈们指点,如果有调试成功的初始化程序可否发给小弟参考一下,在下邮箱790562728@qq.com,也可qq交流,不胜感激。

相关帖子

沙发
加班加点| | 2011-7-26 12:22 | 只看该作者
sja1000是用啥接口和51接的,没有进入工作模式,是你没有选通根本就,好好看看sja1000的手册吧

使用特权

评论回复
板凳
haiougege|  楼主 | 2011-7-26 14:21 | 只看该作者
单片机的P0和sja1000的AD0—AD7连接,肯定是选通了的啊,可是不知道为啥就是不行……

使用特权

评论回复
地板
haiougege|  楼主 | 2011-7-27 17:00 | 只看该作者
各位大虾们给点意见啊,小弟跪求了……

使用特权

评论回复
5
柠檬恋上雨| | 2011-8-2 10:36 | 只看该作者
你是单个节点Plican自检测还是多个节点通讯
无论哪个我想你必须注意一下几点:
1.确保sja1000初始化成功,你可以通过串口显示直接观看
2.如果你采用中断方式收发数据,一定要确保中断是否能成功进入,你可以在中断管脚加一个1K的上拉电阻效果很好
3.另外你要确保你的芯片没问题,我做的过程中就遇到这个问题,因为我们买的好多十多块钱的便宜芯片其实都不是正版的,正版的40多块钱
4.你的sja复位才用的是什么方式,上电自动复位还是IO口复位,我推荐后者,因为前者很容易与MCU的复位发生错乱而导致初始化失败
5.在多个节点通讯前,你最好利用Plican自检测模式检测一下节点的情况,看自接收是否正确。
这是我给你的一点我调试的经验,如果还有什么问题你可以跟帖或留言给我,我qq466213743加我的时候说清你是谁,要不我怕找不到你!呵呵,最后祝你成功……

使用特权

评论回复
6
柠檬恋上雨| | 2011-8-2 10:39 | 只看该作者
这是我调试成功的自检测程序Pelican模式下的  硬件和你的差不多cs接P2.7  Rst接P2.0希望对你有用
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//描述:                                                                                                                                                   &
//      CAN自收发程序                                                          &                                                         
//      CAN主要参数:       PeliCAN模式,扩展帧EFF模式                          &
//      29位标示码结构:                                                       &
//      发送数据结构:计数结果,0x02,0x03,0x04,0x05,0x06,0x07,0x08              &
//      接收数据结构: 待显示数据+其它7个字节的数据                             &
//      本节点的地址: 0x11,0x22,0x33,0x00;可以接收全部节点的数据               &
//      目的节点地址:0x01,0x02,0x03,0x00;可以被能接收全部节点数据的节点接收   &
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//对管脚分配进行了定义
//对子函数进行了声明

# define uchar unsigned char
# define uint  unsigned int

#define        N_can        13        //N_can代表一帧字节数


bit        TXD_flag = 0;        //若TXD_flag=1,要求发送处理
bit        RXD_flag = 0;   //RXD_flag=0说明无数据可以接收,RXD_flag=1说明有数据可以接收

unsigned    char    xdata   CAN_SJA_BaseAdr;                            //定义SJA1000的片选基址
unsigned    char    xdata   *SJA_CS_Point;

unsigned    char        xdata        CAN_SJA_BaseAdr        _at_ 0x7E00;                            //定义SJA1000的片选基址
unsigned           char    xdata   *SJA_CS_Point ;                                                         //指针指向空

/*P1 口分配*/

/*P2 口分配*/
sbit    SJA_RST = P2^0;//SJA1000复位管脚

/*CAN总线SJA1000寄存器地址定义(用的是PeliCAN模式,扩展帧EFF模式)*/

uchar   xdata    MODR     _at_   0x7E00;                // 模式寄存器
uchar   xdata    CMR          _at_   0x7E01;                // 命令寄存器
uchar   xdata    SR              _at_   0x7E02;                // 状态寄存器
uchar   xdata    IR              _at_   0x7E03;                // 中断寄存器
uchar   xdata    IER          _at_   0x7E04;                // 中断使能寄存器
uchar   xdata    BTR0          _at_   0x7E06;                // 总线定时寄存器0 ;总线波特率的选择
uchar   xdata    BTR1          _at_   0x7E07;                // 总线定时寄存器1 ;总线波特率的选择
uchar   xdata    OCR          _at_   0x7E08;                // 输出控制寄存器
uchar   xdata    ACR          _at_   0x7E10;//16;
uchar   xdata    ACR1          _at_   0x7E11;//17;
uchar   xdata    ACR2          _at_   0x7E12;//18;
uchar   xdata    ACR3          _at_   0x7E13;//19;                // 接收代码(0x16_0x19);接收过滤位的选择*******复位模式
uchar   xdata    AMR          _at_   0x7E14;//20;
uchar   xdata    AMR1          _at_   0x7E15;//21;
uchar   xdata    AMR2          _at_   0x7E16;//22;
uchar   xdata    AMR3          _at_   0x7E17;//23;                // 掩码(0x20_0x23); 接收过滤位的选择*******复位模式
uchar   xdata    CDR          _at_   0x7E1F;//31;                // 时钟分频器
uchar   xdata    ALC          _at_   0x7E0B;//11;                // 仲裁丢失捕捉寄存器
uchar   xdata    ECC          _at_   0x7E0C;//12;                // 误码捕捉寄存器
uchar   xdata    TXERR          _at_   0x7E0F;//15;                //发送错误计数器

uchar   xdata    TBSR0          _at_   0x7E10;//16;
uchar   xdata    TBSR1          _at_   0x7E11;//17;
uchar   xdata    TBSR2          _at_   0x7E12;//18;
uchar   xdata    TBSR3          _at_   0x7E13;//19;
uchar   xdata    TBSR4          _at_   0x7E14;//20;
uchar   xdata    TBSR5          _at_   0x7E15;//21;
uchar   xdata    TBSR6          _at_   0x7E16;//22;
uchar   xdata    TBSR7          _at_   0x7E17;//23;
uchar   xdata    TBSR8          _at_   0x7E18;//24;
uchar   xdata    TBSR9          _at_   0x7E19;//25;
uchar   xdata    TBSR10          _at_   0x7E1A;//26;
uchar   xdata    TBSR11          _at_   0x7E1B;//27;
uchar   xdata    TBSR12          _at_   0x7E1C;//28;        // 发送缓冲器首地址(0x16_0x28)

uchar   xdata    RBSR0          _at_   0x7E10;//16;
uchar   xdata    RBSR1          _at_   0x7E11;//17;
uchar   xdata    RBSR2          _at_   0x7E12;//18;
uchar   xdata    RBSR3          _at_   0x7E13;//19;
uchar   xdata    RBSR4          _at_   0x7E14;//20;
uchar   xdata    RBSR5          _at_   0x7E15;//21;
uchar   xdata    RBSR6          _at_   0x7E16;//22;
uchar   xdata    RBSR7          _at_   0x7E17;//23;
uchar   xdata    RBSR8          _at_   0x7E18;//24;
uchar   xdata    RBSR9          _at_   0x7E19;//25;
uchar   xdata    RBSR10          _at_   0x7E1A;//26;
uchar   xdata    RBSR11          _at_   0x7E1B;//27;
uchar   xdata    RBSR12          _at_   0x7E1C;//28;// 接收缓冲器首地址(0x16_0x28)

extern void CAN_init(void);
extern  void CAN_Tx_data(void);




#include <ADUC812.H>
#include <stdio.h>
#include <intrins.h>
#include <can_selfdef.h>

unsigned char  Send_CAN_Info_ID[5]={0x88,0x00,0x00,0x2a,0x00};//扩展帧,8个字节数据,发送数据到ID为00000540的节点               
unsigned char  Send_CAN_Data[8]={0x23,0x02,0x03,0x04,0x05,0x06,0x07,0x08};

unsigned char  RX_buffer[13]; //接收的13个字节数据、
//unsigned char  TX_buffer[13]={0x88,0x11,0x22,0x33,0x44,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88} ; //接收的13个字节数据
//unsigned char data  rcv_data[8];
unsigned char j=0;

bit flag_sec,rcv_flag,err_flag;                             //发送,接收,错误中断标志

extern void CAN_Rx_display(void);
extern void CAN_Rx_data( void );
/******************************************************************************/
/*       serial_init: initialize serial interface                             */
/******************************************************************************/
void Serial_Init (void)
{
     SCON =  0x50 ; //SCON: serail mode 1, 8-bit UART, enable ucvr
         PCON |= 0x00 ;//SMOD=1

         TMOD &= 0x0F; /*清TMOD高4位 */
         TMOD |= 0x20 ; //方式控制:GATE=0;C/T=0;M1M0=10; timer 1, mode 2, 8-bit reload
       
         TH1 = 0xfd ; //Baud: fosc=11.0592MHz ,9600
         TL1 = 0xfd ;
         
         TR1 = 1 ; // 启动timer 1 run
         TI = 1;
         //EA=1;
         //ES  = 1;         
}

char _getkey ()
{
  char c;

  while (!RI)
  c = SBUF;
  RI = 0;
  return (c);
}

//putchar (basic version): expands '\n' into CR LF */
char putchar (char c)  
{
  if (c == '\n')  
  {
    while (!TI);
    TI = 0;
    SBUF = 0x0d;                          
  }
  while (!TI);
  TI = 0;
  return (SBUF = c);
}

///////////////////////////////////////////////
//函数:ex0_int
//说明:中断服务程序
//入口:无
//返回:无
///////////////////////////////////////////////
//***********************************************************
void ex0_int(void) interrupt 0 using 1
{
        if(IR&0x01)                                                //产生了接收中断
         {
      rcv_flag=1;
      CAN_Rx_data();
     }               
    if(IR&0x04)                                                //产生了错误中断
         { err_flag=1; }
                   
}
///////////////////////////////////////////////
//函数:main
//说明:主函数
//入口:无
//返回:无
///////////////////////////////////////////////
void main(void)
{
    //CPU初始化
    SJA_RST = 0;//CAN总线复位管脚,复位有效

        Serial_Init();
        PX0=1;                                          //外部中断0高优先级
        IT0=1;                                          //设置INT0为下降沿中断
        EX0=1;                                          //使能INT0中断
        EA=1;

        SJA_CS_Point=&CAN_SJA_BaseAdr;                                    //设置SJA1000的片选地址
        printf( "SJA1000 Init Start!\n");
    CAN_init(  ); //SJA1000初始化,对 SJA1000寄存器的读写是采用外部寄存器寻址方式,所以不需要程序单独控制片选有效无效

        CAN_Tx_data();
        printf(" \n \n");
        CAN_Rx_display();
    while(1);
}
//*********************CAN子函数***********************

void CAN_init( void )
{
        uchar i;
    uchar bdata Judge;
    uchar ACRR[4];
    uchar AMRR[4];

    ACRR[0] = 0x11;
    ACRR[1] = 0x22;
    ACRR[2] = 0x33;
    ACRR[3] = 0x44;//接收代码寄存器,节点1

    AMRR[0] = 0xff;
    AMRR[1] = 0xff;
    AMRR[2] = 0xff;
    AMRR[3] = 0xff;//接收屏蔽寄存器。 只接收主机发送的信息
    do
    {//  .0=1---reset MODRe,进入复位模式,以便设置相应的寄存器
     //防止未进入复位模式,重复写入
        MODR   = 0x09;
            Judge = MODR ;
                printf( " Judge=  %x \n",Judge);
    }
    while( !(Judge & 0x01) );//等待进入复位模式
    CDR  = 0x88;// CDR.3=1--时钟关闭, .7=0---basic CAN, .7=1---Peli CAN

    BTR0 = 0x00;
    BTR1 = 0x14;//总线波特率设定  1000Kbps
        printf( " BTR0 =  %x \n",BTR0);
        printf( " BTR1 =  %x \n",BTR1);

    IER  = 0x01;      // .0=1--接收中断使能;  .1=0--关闭发送中断使能
    OCR  = 0xaa;     // 配置输出控制寄存器
        printf( " OCR =  %x \n",OCR);
    CMR  = 0x04;      //释放接收缓冲器
        printf( " CMR =  %x \n",CMR);

    ACR  = ACRR[0];
    ACR1 = ACRR[1];
    ACR2 = ACRR[2];
    ACR3 = ACRR[3];//初始化标示码
        for(i=0;i<4;i++)
        {
                printf( " ACR = %x \n" ,ACRR[i]);
        }
    AMR  = AMRR[0];
    AMR1 = AMRR[1];
    AMR2 = AMRR[2];
    AMR3 = AMRR[3];//初始化掩码
    for(i=0;i<4;i++)
        {
                printf( " AMR = %x \n" ,AMRR[i]);
        }
    do
    {//确保进入自接收模式
          MODR   = 0x04;
          Judge  = MODR;
          printf( " MODR=  %x \n",MODR);
     }
    while( !(Judge & 0x04) );
        printf( "SJA1000 Init finish !\n");
        printf( "SJA1000 OK !\n");

}
///////////////////////////////////////////////
//函数:CAN_Tx_display
//说明:发送数据串口显示
//入口:无
//返回:无
///////////////////////////////////////////////
void CAN_Tx_display(void)
{
        printf( " TBSR5 = %x \n", TBSR5);
        printf( " TBSR6 = %x \n", TBSR6);
        printf( " TBSR7 = %x \n", TBSR7);
        printf( " TBSR8 = %x \n", TBSR8);
        printf( " TBSR9 = %x \n", TBSR9);
        printf( " TBSR10 = %x \n", TBSR10);
        printf( " TBSR11 = %x \n", TBSR11);
        printf( " TBSR12 = %x \n", TBSR12);
}
///////////////////////////////////////////////
//函数:can_txd
//说明:发送扩展数据帧
//入口:无
//返回:无
///////////////////////////////////////////////
void CAN_Tx_data(void)
{
    uchar state;
    uchar TX_buffer[ N_can ] ;        //N_can=13,TX_buffer数组为待传送的数据帧

        //初始化标示码头信息
    TX_buffer[0] = 0x88;        //.7=0--扩展帧;.6=0--数据帧; .0-.3=100--数据长度为8字节
    TX_buffer[1] = 0x11;        //本节点地址
    TX_buffer[2] = 0x22;
    TX_buffer[3] = 0x33;
    TX_buffer[4] = 0x44;

        //初始化发送数据单元
    TX_buffer[5]  = 0x11;        //1
    TX_buffer[6]  = 0x22;        //2
    TX_buffer[7]  = 0x33;        //3
    TX_buffer[8]  = 0x44;        //4
    TX_buffer[9]  = 0x55;        //5
    TX_buffer[10] = 0x66;        //6
    TX_buffer[11] = 0x77;        //7
    TX_buffer[12] = 0x88;        //8
       
        //初始化数据信息
    EA = 0; //关中断

        //查询SJA1000是否处于接收状态,当SJA1000不处于接收状态时才可继续执行
    do
    {
        state = SR;                //SR为SJA1000的状态寄存器
                        printf( "NO.1!\n");
    }
    while( state & 0x10 );  //SR.4=1 正在接收,等待
   
        //查询SJA1000是否处于发送完毕状态
   do
    {
        state = SR;       
                        printf( "NO.2!\n");       
    }
    while(!(state & 0x08)); //SR.3=0,发送请求未处理完,等待直到SR.3=1

        //查询发送缓冲器状态
    do
    {
        state = SR;       
                        printf( "NO.3!\n");       
    }
    while(!(state & 0x04)); //SR.2=0,发送缓冲器被锁。等待直到SR.2=1
          
        //将待发送的一帧数据信息存入SJA1000的相应寄存器中
    TBSR0  = TX_buffer[0];
    TBSR1  = TX_buffer[1];
    TBSR2  = TX_buffer[2];
    TBSR3  = TX_buffer[3];
    TBSR4  = TX_buffer[4];
    TBSR5  = TX_buffer[5];
    TBSR6  = TX_buffer[6];
    TBSR7  = TX_buffer[7];
    TBSR8  = TX_buffer[8];
    TBSR9  = TX_buffer[9];
    TBSR10 = TX_buffer[10];
    TBSR11 = TX_buffer[11];
    TBSR12  = TX_buffer[12];
        CAN_Tx_display();

    CMR = 0x10;        //置位自发送接收请求
    EA  = 1;         //重新开启中断
}
///////////////////////////////////////////////
//函数:CAN_Rx_display
//说明:接收数据串口显示
//入口:无
//返回:无
///////////////////////////////////////////////
void CAN_Rx_display(void)
{
                printf( " RBSR5 = %x \n", RBSR5);
                printf( " RBSR6 = %x \n", RBSR6);
                printf( " RBSR7 = %x \n", RBSR7);
                printf( " RBSR8 = %x \n", RBSR8);
                printf( " RBSR9 = %x \n", RBSR9);
                printf( " RBSR10 = %x \n", RBSR10);
                printf( " RBSR11 = %x \n", RBSR11);
                printf( " RBSR12 = %x \n", RBSR12);
}       
///////////////////////////////////////////////
//函数:CAN_Rx_data
//说明:接收数据函数,在中断服务程序中调用
//入口:无
//返回:无
///////////////////////////////////////////////
void CAN_Rx_data( void )
{
         uchar state;

         if(rcv_flag)
    {        //接收数据帧
        RX_buffer[0] =  RBSR0;
        RX_buffer[1] =  RBSR1;
        RX_buffer[2] =  RBSR2;
        RX_buffer[3] =  RBSR3;
        RX_buffer[4] =  RBSR4;
        RX_buffer[5] =  RBSR5;
        RX_buffer[6] =  RBSR6;
        RX_buffer[7] =  RBSR7;
        RX_buffer[8] =  RBSR8;
        RX_buffer[9] =  RBSR9;
        RX_buffer[10] =  RBSR10;
        RX_buffer[11] =  RBSR11;
        RX_buffer[12] =  RBSR12;

        rcv_flag = 0;        //接收标志置位,以便进入接收处理程序
        CMR = 0X04;                //CMR.2=1--接收完毕,释放接收缓冲器
        state = ALC;        //释放仲裁随时捕捉寄存器(读该寄存器即可)
        state = ECC;        //释放错误代码捕捉寄存器(读该寄存器即可)
    }

    IER = 0x01;                // IER.0=1--接收中断使能
    EA = 1;                        //重新开启CPU中断
}

使用特权

评论回复
7
yulri| | 2012-10-9 21:51 | 只看该作者
楼主,P0口是个很特殊的口,有的单片机P0口是不能输出高电平的!!

使用特权

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

本版积分规则

0

主题

5

帖子

1

粉丝