xzf962 发表于 2009-12-7 21:20:21

独立CAN芯片SJA1000的读写函数问题?

#define startadd 0x7F00 //SJA1000的首地址
unsigned char read_sja(unsigned char addr)   //读SJA1000状态寄存器子程序
{
    unsigned char *sja_address = (unsigned char *)startadd;
    sja_address = sja_address + addr;
    return (*(sja_address));
}

void write_sja(unsigned char addr,unsigned char val)   //写SJA1000控制寄存器子程序
{
    unsigned char *sja_address = (unsigned char *)startadd;
    sja_address = sja_address + addr;
    *(sja_address) = val;
}

读写程序如上,原理图如下。

xzf962 发表于 2009-12-7 21:28:39

http://cache.amobbs.com/bbs_upload782111/files_23/ourdev_511797.jpg
(原文件名:243543656.jpg)

我是用ATMEGA128硬件访问的,AD接PA。外部存储器使能是对的,就是在初始化SJA1000时,程序停在while()循环内。

xzf962 发表于 2009-12-8 14:16:09

请路过的高手帮忙回答一下,谢谢!!!!!!!!

erxun 发表于 2009-12-8 14:29:03

先这样定义好寄存器的地址
#define CAN_MOD   (*(volatile unsigned char *)0xfb00)      //模式寄存器
#define CAN_CMR   (*(volatile unsigned char *)0xfb01)      //命令寄存器 只写
#define CAN_SR      (*(volatile unsigned char *)0xfb02)      //状态寄存器 只读
#define CAN_IR      (*(volatile unsigned char *)0xfb03)      //中断寄存器 只读
#define CAN_IER   (*(volatile unsigned char *)0xfb04)      //中断使能寄存器
#define CAN_BTR0    (*(volatile unsigned char *)0xfb06)      //总线定时寄存器0
#define CAN_BTR1    (*(volatile unsigned char *)0xfb07)      //总线定时寄存器1

那么对它们的读写这样就可以了。
   CAN_MOD=0x01;         

   CAN_CDR=0xc8;    //配置时钟分频寄存器-Pelican,CBP=1,
                                 //关闭TX1中断与时钟输出
   CAN_AMR0=0xff;   //配置验收屏蔽AMR0=0FFH
   CAN_AMR1=0xff;   //配置验收屏蔽AMR1=000H
   CAN_AMR2=0xff;   //配置验收屏蔽AMR2=0FFH
   CAN_AMR3=0xff;   //配置验收屏蔽AMR3=000H
   CAN_ACR1=0x00;   //配置验收代码ACR1=0:广播
   CAN_ACR3=0x00;   //配置验收代码ACR3=地址 =0

yunqian09 发表于 2009-12-8 22:05:39

老大,你要写程序模拟intel时序吧,RD WR ALE你怎么没控制啊

好有楼上的方法是用51控制 的方法吧

yunqian09 发表于 2009-12-8 22:08:54

LZ仔细研究下,把程序发上来参考参考啊

xzf962 发表于 2009-12-8 23:01:08

/*******************************************************************************功能说明:   计算SJA1000在电路中的实际地址:基址+内部寄存器地址
其它说明:   以下的定义为SJA1000的内部寄存器的地址,不可修改
         各寄存器的具体功能清参阅sja1000的数据手册
*******************************************************************************/
#define startadd 0x7F00 //SJA1000的首地址
// 控制寄存器
#define         MODE      0x00       //内部控制寄存器
#define         CMR       0x01       //命令寄存器
#define         SR      0x02       //状态寄存器
#define         IR      0x03       //中断寄存器
#define         IER       0x04       //中断使能寄存器
#define         BTR0      0x06       //总线定时寄存器0
#define         BTR1      0x07       //总线定时寄存器1
#define         OCR       0x08       //输出控制寄存器
#define         TEST      0x09       //测试寄存器

#define         RESVER1   0x0A       //保留1
#define         ALC       0x0B       //仲裁丢失捕捉
#define         ECC       0x0C       //错误代码捕捉
#define         EWLR      0x0D       //错误报警限额

#define         RXERR   0x0E       //接收错误计数器
#define         TXERR   0x0F       //发送错误计数器

#define         ACR0      0x10       //验收代码寄存器
#define         ACR1      0x11       //验收代码寄存器
#define         ACR2      0x12       //验收代码寄存器
#define         ACR3      0x13       //验收代码寄存器
#define         AMR0      0x14       //验收屏蔽寄存器
#define         AMR1      0x15       //验收屏蔽寄存器
#define         AMR2      0x16       //验收屏蔽寄存器
#define         AMR3      0x17       //验收屏蔽寄存器


// 发送缓冲区寄存器
#define         TXD_FID       0x10       //发送缓冲区1
#define         TXD_ID1       0x11       //发送缓冲区2
#define         TXD_ID2       0x12       //发送缓冲区3
#define         TXD_ID3       0x13       //发送缓冲区4
#define         TXD_ID4       0x14       //发送缓冲区5
#define         TXBuffer1   0x15       //发送缓冲区6
#define         TXBuffer2   0x16       //发送缓冲区7
#define         TXBuffer3   0x17       //发送缓冲区8
#define         TXBuffer4   0x18       //发送缓冲区9
#define         TXBuffer5   0x19       //发送缓冲区10
#define         TXBuffer6   0x1A       //发送缓冲区11
#define         TXBuffer7   0x1B       //发送缓冲区12
#define         TXBuffer8   0x1C       //发送缓冲区13

// 接收缓冲区寄存器
#define         RXD_FID       0x10       //接收缓冲区1
#define         RXD_ID1       0x11       //接收缓冲区2
#define         RXD_ID2       0x12       //接收缓冲区3
#define         RXD_ID3       0x13       //接收缓冲区4
#define         RXD_ID4       0x14       //接收缓冲区5
#define         RXBuffer1   0x15       //接收缓冲区6
#define         RXBuffer2   0x16       //接收缓冲区7
#define         RXBuffer3   0x17       //接收缓冲区8
#define         RXBuffer4   0x18       //接收缓冲区9
#define         RXBuffer5   0x19       //接收缓冲区10
#define         RXBuffer6   0x1A       //接收缓冲区11
#define         RXBuffer7   0x1B       //接收缓冲区12
#define         RXBuffer8   0x1C       //接收缓冲区13

#define         RMC         0x1D       //RX报文计数器
#define         RBSA          0x1E       //接收缓冲区起始地址
#define         CDR         0x1F       //时钟分频寄存器

/*******************************************************************************
功能说明:   CAN控制器SJA1000通讯波特率.SJA1000的晶振为必须为16MHZ
其它说明:
*******************************************************************************/
#define         BTR0_Rate_20k      0x53          //20KBPS的预设值
#define         BTR1_Rate_20k      0x2F          //20KBPS的预设值
#define         BTR0_Rate_40k      0x87          //40KBPS的预设值
#define         BTR1_Rate_40k      0xFF          //40KBPS的预设值
#define         BTR0_Rate_50k      0x47          //50KBPS的预设值
#define         BTR1_Rate_50k      0x2F          //50KBPS的预设值
#define         BTR0_Rate_80k      0x83          //80KBPS的预设值
#define         BTR1_Rate_80k      0xFF          //80KBPS的预设值
#define         BTR0_Rate_100k   0x43          //100KBPS的预设值
#define         BTR1_Rate_100k   0x2f          //100KBPS的预设值
#define         BTR0_Rate_125k   0x03          //125KBPS的预设值
#define         BTR1_Rate_125k   0x1c          //125KBPS的预设值
#define         BTR0_Rate_200k   0x81          //200KBPS的预设值
#define         BTR1_Rate_200k   0xFA          //200KBPS的预设值
#define         BTR0_Rate_250k   0x01          //250KBPS的预设值
#define         BTR1_Rate_250k   0x1c          //250KBPS的预设值
#define         BTR0_Rate_400k   0x80          //400KBPS的预设值
#define         BTR1_Rate_400k   0xfa          //400KBPS的预设值
#define         BTR0_Rate_500k   0x00          //500KBPS的预设值
#define         BTR1_Rate_500k   0x1c          //500KBPS的预设值
#define         BTR0_Rate_666k   0x80          //666KBPS的预设值
#define         BTR1_Rate_666k   0xb6          //666KBPS的预设值
#define         BTR0_Rate_800k   0x00          //800KBPS的预设值
#define         BTR1_Rate_800k   0x16          //800KBPS的预设值
#define         BTR0_Rate_1000k    0x00          //1000KBPS的预设值
#define         BTR1_Rate_1000k    0x14          //1000KBPS的预设值

/*******************************************************************************
功能说明:   定义系统参数
其它说明:   无
*******************************************************************************/
// 本地的IP地址
#define    Local_IP1   1    // IP地址最高位
#define    Local_IP2   2
#define    Local_IP3   3
#define    Local_IP4   4    // IP地址最低位

// 本地的CAN标识
#define    REG_ACR1_FIDLocal_IP4   // 滤波器的标识符最高位
#define    REG_ACR2_FIDLocal_IP3
#define    REG_ACR3_FIDLocal_IP2
#define    REG_ACR4_FIDLocal_IP1   // 滤波器的标识符最低位
#define    REG_AMR1_FID0x00      // 滤波器的屏蔽符最高位
#define    REG_AMR2_FID0x00
#define    REG_AMR3_FID0x03
#define    REG_AMR4_FID0x07      // 滤波器的屏蔽符最低位

// 发往目标CAN标识
#define    SEND_ACR1_FID   Local_IP4   // 滤波器的最高位
#define    SEND_ACR2_FID   Local_IP3
#define    SEND_ACR3_FID   Local_IP2
#define    SEND_ACR4_FID   Local_IP1   // 滤波器的最低位

// 模式参数
#define    REG_MODE_DATA         0x0C    // 模式控制器:   单滤波器、自检测模式
#define    REG_TEST_DATA         0xAA    // 测试值
#define    REG_CDR_DATA          0x88    // 时分控制的值:    PeilCAN模式、CLOCK无效
#define    REG_INTENABLE_DATA    0x83    // 中断使能控制的值: 总线错误中断、发送中断、接收中断
#define    REG_OCR_DATA          0x1A    // 输出控制的值:

// 定义命令字
#define    TXD_ONE_CMD      0x03    // 产生一次报文发送,当错误时不再生发(单次发送)
#define    TXD_CMD          0x01    // 发送请求命令,当错误时可重发
#define    T_R_CMD          0x12    // 产生一次自接收性质的报文发送,发送错误时不会重发
#define    AT_CMD         0x02    // 中止发送命令
#define    RRB_CMD          0x04    // 释放接收缓冲区
#define    COS_CMD          0x08    // 数据溢出清除命令
unsigned char TransBuffer;
unsigned char RxBuffer[];
unsigned char *sja_address=(unsigned char *)startadd;

unsigned char read_sja(unsigned char addr)                                    //读SJA1000状态寄存器子程序
{
        sja_address=(unsigned char *)startadd;
        sja_address=sja_address+addr;
        return (*(sja_address));
}

void write_sja(unsigned char addr,unsigned char val)            //写SJA1000控制寄存器子程序
{
        sja_address=(unsigned char *)startadd;
        sja_address=sja_address+addr;
        *(sja_address)=val;
}


void SJA1000_init(void)            
{
    //CLI();
       
    write_sja(MODE,0x01);
        read_sja(IR);                                    //读取CAN的中断标识
        while(!(read_sja(MODE)&0x01))        //检测SJA1000是否达到复位工作模式
        {
           write_sja(MODE,0x01);                //进入复位工作模式
        }
        delay_us(5);                                   //延时约5us
        write_sja(CDR,0xC8);            //PeliCAN 模式,禁能CLOCKOUT引脚
        delay_us(5);                                   //延时约5us
        write_sja(BTR0,0x53);                 //设置时钟分频器,20k
        write_sja(BTR1,0x2F);                 
        write_sja(OCR,0x1a);                 //输出控制
        write_sja(RXERR,0x00);                       
        write_sja(TXERR,0x00);
        write_sja(ECC,0x00);
        write_sja(RBSA,0x00);                        //缓存器起始地址寄存器设置为0
       
        write_sja(ACR0,0x00);                 //acceptcode default ffffffff
        write_sja(ACR1,0x00);
        write_sja(ACR2,0x00);
        write_sja(ACR3,0x00);         //配置验收代码ACR3地址

        write_sja(AMR0,0xff);                        //acceptmask default ffffffff
        write_sja(AMR1,0xff);
        write_sja(AMR2,0xff);
        write_sja(AMR3,0xff);

        write_sja(IER,0x01);            //接收中断使能
        write_sja(CMR,0x0c);                          //清除数据溢出和释放接收缓冲器;
        do
        {
           write_sja(MODE,0x00);                 //设置SJA1000工作模式,双滤波接收工作模式
        }
        while((read_sja(MODE)&0x01));        //确认复位标志是否被删除                     
        //SEI();
}
void CanTransmit(void)
{
        unsigned char status;
        CLI();                                                        //关中断               
        TransBuffer=0x88;               
        TransBuffer=0x00;       
        TransBuffer=0x00;       
        TransBuffer=0x00;       
        TransBuffer=0x00;       
        TransBuffer=0x01;       
        TransBuffer=0x02;       
        TransBuffer=0x03;       
        TransBuffer=0x04;       
        TransBuffer=0x05;       
        TransBuffer=0x06;       
        TransBuffer=0x07;       
        TransBuffer=0xaa;                                          
        while(!(read_sja(SR)&0x04));   //wait until reg2^2==1 ,即判断发送缓冲器的状态
        write_sja(TXD_FID,TransBuffer);                   //扩展帧,数据长度为8个字节
        write_sja(TXD_ID1,TransBuffer);
        write_sja(TXD_ID2,TransBuffer);
        write_sja(TXD_ID3,TransBuffer);
        write_sja(TXD_ID4,TransBuffer);
        write_sja(TXBuffer1,TransBuffer);
        write_sja(TXBuffer2,TransBuffer);
        write_sja(TXBuffer3,TransBuffer);
        write_sja(TXBuffer4,TransBuffer);
        write_sja(TXBuffer5,TransBuffer);
        write_sja(TXBuffer6,TransBuffer);
        write_sja(TXBuffer7,TransBuffer);
        write_sja(TXBuffer8,TransBuffer);
        write_sja(CMR,0x01);                  //发送请求命令
        while(!(read_sja(SR) & 0x08));//检测SR.3位,判断发送是否完成
        SEI();                                                      //开中断
}
unsigned char Receive(void)
{
        unsigned char result=0;
        unsigned char status,number,sff,j;
        unsigned char mp=RXD_FID;
    status=read_sja(SR);
        if((status&0xc3)!=0)                  //读取总线脱离、错误状态、接收溢出、有数据等位
        {
                if((status&0x80)==0x80)
                {
                        write_sja(MODE,0x00);
                        return 0;
                }
                if((status&0x02)==0x02)
                {
                        write_sja(CMR,0x0c);
                        return 0;
                }
               
                if((status&0x01)==0x01)
                {
                        if((read_sja(RXD_FID)&0x40)==0x40)//如果RTR=1,为远程帧
                        {
                                write_sja(CMR,0x04);                  //则释放FXFIFO
                        }
                        else                                                          //为0,则是数据帧
                        {
                                sff=read_sja(RXD_FID)&0x80;          //取第一个字节的最高位
                                number=(read_sja(RXD_FID)&0x0f);//取第一个字节的低四位,即数据长度
                                if ((sff&0x80)==0x80)                  //判断是标准帧还是扩展帧
                                number=number+5;                          //扩展帧,则帧的总长度加5(13字节)
                                else
                                number=number+3;                          //标准帧,则帧的总长度加3(11字节)
                                for(j=0;j<number;j++)                  //读取数据
                                {
                                        RxBuffer=read_sja(RXD_FID);
                                        mp++;
                                }
                                result=1;                                    //读取到正确的数据则返回TRUE
                                write_sja(CMR,0x04);                  //最后释放FXFIFO
                        }
                }
        }
        return result;
}       
       
       
以上是“SJA1000.h”部分

xzf962 发表于 2009-12-8 23:10:06

基本上是修改这个帖子的程序。“http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=598348&bbs_page_no=1&search_mode=1&search_text=CAN调试成功,特上传资料与大家共享&bbs_id=1000”
下面是我整个的程序:
点击此处下载 ourdev_512166.rar(文件大小:42K) (原文件名:SJA1000.rar)

xzf962 发表于 2009-12-8 23:15:59

问题出现在SJA1000初始化子函数“void SJA1000_init(void) ”中的while查询语句:
while(!(read_sja(MODE)&0x01)) //检测SJA1000是否达到复位工作模式
{
   write_sja(MODE,0x01); //进入复位工作模式
}

这句话始终为真!请各位大侠帮忙看看哈,谢谢!!

xzf962 发表于 2009-12-9 16:44:28

大侠,知道的加我QQ:752791687

erxun 发表于 2009-12-9 17:17:55

不能进入复位模式,
1.检查SJA1000的时钟,CLKOUT 有脉冲输出不?有时候换换晶振就好了。
2.CPU与SJA1000的连接线是否正常,遇到过cpu的数据线因为焊接原因,导致数据一直不正常;
3.读写SJA1000的寄存器,参考3楼的写法就行,和51的一样,前提:开M128的总线;

yunqian09 发表于 2009-12-10 10:34:07

while(!(read_sja(MODE)&0x01)) //检测SJA1000是否达到复位工作模式

MODE的zui低位为1的时候,进入了复位模式。。((read_sja(MODE)&0x01))为1.

取反后为假,退出while语句,

正确啊,


还有问一下,你的自收发实验成功没?能否正确读出sja1000寄存器的值?

xzf962 发表于 2009-12-24 18:07:08

【回复】: erxun 老孟

老孟大侠,请您看一下我上面的原理图是否有错?缺少16M晶振,我已经加上了。现在,我怀疑我的硬件有误!请您指点……

yxlsdbz 发表于 2011-10-2 10:43:28

mark

sisia 发表于 2012-10-12 10:53:46

mark 好东西

yujian12365 发表于 2012-10-23 15:58:58

楼主的现在好了没有?

znxy141w1 发表于 2015-8-11 10:27:16

感谢楼主分享啊,对我这初学者用处很大
页: [1]
查看完整版本: 独立CAN芯片SJA1000的读写函数问题?