分享

我的 CAN总线 SJA1000调试经历

 弓道自然_改名 2012-04-09
我的 CAN总线 SJA1000调试经历

    前几天学校实验室赶活,调试了SJA1000的CAN总线驱动,我所做的平台是在Intel PXA270的ARM处理器上面进行控制的,通过读写总线的方式进行控制的,期间对着SJA1000的databook查找了很多,期间调试时也走了不少的弯路,现在把调试心得一些经验在这里讲讲。

    由于以前对CAN的驱动接触比较少,只是了解过它的物理特性和用途,所以下手点就是从databook这块着手的,于是先调试CAN的初始化配置,首先是通过CPU能够读写SJA1000的寄存器了,然后我从网上下了一个基于Linux内核的CAN驱动代码,往里一直添加,但最后发现这套代码写得太复杂了,可能本身自己对SJA1000的寄存器设置也不是很了解,没办法,看了大半天的databook,终于有些头绪想清楚该是怎样去控制了,从ZLG网站中下了一个BASIC模式下的参考例程,我看了一下,然后SJA的寄存器详细看了看(由于开始的时候比较忙,所以直到这个时候才算是仔细看了看SJA的内部,至于CAN的基础协议我是根本没有看,这给我后面带来了极大的麻烦)。然后就参考ZLG的程序开始写SJA的测试程序,那个程序写的很大,也比较完整,因为我想快点把CAN打通,于是弄了一个一千多行的程序,以前我的调试程序一般都很小的。写好程序之后就开始测试,首先测试的是测试寄存器,然后一步步测试下去,在BASIC模式下所有的寄存器都正常,但是在发送的时候是总是不正常,启动发送之后就一直在发送,状态寄存器的标志位一直处在发送的状态下,然后就是报总线错误,不知道是怎么会事情,很郁闷,上网上的BBS看了一下。其他人告诉我单个CAN节点发送是成功不了的,如果没有收到接受CAN节点的应答,发送节点就会一直发送,直到超出错误计数器的允许值使得总线关闭。这下我终于明白是怎么回事了,同时在精华区发现在peli模式下有ECC(错误寄存器),可以跟踪错误,于是开始改成用Peli CAN模式操作过程。这个东西比较麻烦。
接下来我第一步的目标是自发送,改成在Peli模式下有自发送这种模式,而在Basic模式下面是没有这种自发送的模式的,Peli模式中在有匹配电阻的情况下可以进行单个节点的接收和发送。再仔细阅读了一次Peli模式下的操作指南,发现在自发送的时候发送的命令应该是0x10或者是0x12(即CMR寄存器里面有一个专门的控制位是用来控制自发送的,和普通的发送命令位是不同的)。在发现了这个问题之后,自发送一切顺利的通过了。
再接下来就是两个节点的互调了,我首先用自发送程序把两个节点都调试了一下,保证单个节点发送硬件没有任何问题。然后就用双绞线通过接线端子把两个板子连接到了一起。调试CAN的波特率的时候可以通过观察ECC寄存器的变化做出判断。
最后,总结几个经验:
    1、一定要详细的阅读sja1000的databook和CAN的相关知识;
    2、SJA的复位是低电平
    3、在自发送的模式下,需要匹配电阻,而且自发送的启动命令和普通发送的启动命令不相同;
    4、BRT0和BRT1的选择,一定要精心选择,建议SJA的外部晶体选择16M的,这样有利于参考ZLG的标准数值
    5、以下是在Peli模式下的初始化流程
    a)检测硬件连接是否正确       
    b)进入复位状态       
    c)设置时钟分频寄存器        
    d)设置输出控制寄存器    
    e)设置通讯波特率                   
    f)设置代码验收寄存器           
    g)设置代码屏蔽寄存器           
    h)退出复位状态                    
    i)设置工作模式                        
    j)设置中断使能寄存器

以下是我实现的部分代码:

//***************************************************************************
// 头文件声明
//***************************************************************************

#include "../../ucos-ii/ucos_ii.h"
#include "../../inc/sysconfig.h"

#define __REG(x) (*(volatile INT32U*)(x))

//--------------------------------------------------------------------
// x为基地址,y为对基地址的偏移量。
//--------------------------------------------------------------------
#define __REG2(x,y)     (*(volatile INT32U *)((INT32U)&__REG(x) + (y)))

#define CANSJA1000_readb(a)   (*(volatile unsigned char *)(a))
#define CANSJA1000_readw(a)   (*(volatile unsigned short *)(a))
#define CANSJA1000_readl(a)   (*(volatile unsigned int   *)(a))

#define CANSJA1000_writeb(v,a) (*(volatile unsigned char *)(a) = (v))
#define CANSJA1000_writew(v,a) (*(volatile unsigned short *)(a) = (v))
#define CANSJA1000_writel(v,a) (*(volatile unsigned int   *)(a) = (v))

#define CANSJA1000_PHY_START   PXA_CS5_PHYS // nCS<5>: pxa270 platform edited by quentin
#define CANSJA1000_BASE     CANSJA1000_PHY_START

#define addr_base (1<<2) //操作的偏移地址
#define data_base (1<<3) //操作的偏移地址

//CAN总线的波特率定义
typedef enum{
BandRate_125kbps=125000,
BandRate_250kbps=250000,
BandRate_500kbps=500000,
BandRate_1Mbps=1000000
}CanBandRate;

#define CAN_MSG_LENGTH 8 //定义消息发送的长度

//CAN总线应用结构体

typedef struct {
INT32U id;        //CAN总线ID
INT8U data[CAN_MSG_LENGTH];    //CAN总线数据
INT8U dlc;        //数据长度
INT8U flags;
}CanData, *PCanData;

#define UPCAN_FLAG_EXCAN     (1<<31) //extern can flag
#define UPCAN_FLAG_RTR      (1<<30) //remote frame

/*********************************************************************\
CAN设备设置接收过滤器结构体
参数: IdMask,Mask
     IdFilter,Filter
是否接收数据按照如下规律:
Mask Filter RevID Receive
0    x     x    yes
1    0     0    yes
1    0     1    no
1    1     0    no
1    1     1    yes
\*********************************************************************/
typedef struct{
INT32U Mask;//unsigned int Mask;
INT32U Filter;//unsigned int Filter;
INT32U flags;//unsigned int flags; //是否是扩展ID
}CanFilter,*PCanFilter;

#define CAN_BUFFER_SIZE   512
#define CHIP_MAX_IRQLOOP 100
#define MAX_RETRY_COUNT   10

/* poll sja1000 status: 1 second in case of losting interrupt*/
#define CAN_POLL_TIMER (jiffies+(HZ))
//#undef CAN_POLL_TIMER

typedef struct{
CanData buffer[CAN_BUFFER_SIZE];
//wait_queue_head_t wq;
INT8U head;
INT8U tail;
}CANmsg_Buffer;

#define CAN_DEV_NAMESIZE 64

typedef struct
{
INT32U     index;   /*device index*/
INT32U     RecID;
INT32S    RecBuf[CAN_DEV_NAMESIZE]; /*device RecBuf*/
INT8U    sja1000RecPrintfFlag; /*whether Printf the sja1000Rec Buf Flag*/
INT8U     addr_addr; /* device ALE(address) address*/
INT8U     data_addr; /* device data address */
INT32U     irq;    /* device IRQ number */
INT8U     SJA1000RecFlag;
CanBandRate   bandrate;
INT32U     clock;
CanFilter    filter;
CANmsg_Buffer receive;
CANmsg_Buffer send;
INT32U tx_retry_cnt;
}can_device,*pcan_device;

//2.定义CAN信息帧的数据类型。
typedef struct _VCI_CAN_OBJ{
INT32U ID;
INT32U TimeStamp;
INT8U TimeFlag;
INT8U SendType;
INT8U RemoteFlag;//是否是远程帧
INT8U ExternFlag;//是否是扩展帧
INT8U DataLen;
INT8U Data[8];
INT8U Reserved[3];
}VCI_CAN_OBJ,*PVCI_CAN_OBJ;

#define CYCLE_INC(d) ((d+1)&(CAN_BUFFER_SIZE-1))
#define IS_CYCLE_BUFFER_FULL(buffer) (CYCLE_INC((buffer).head) == ((buffer).tail))
#define IS_CYCLE_BUFFER_EMPTY(buffer) ((buffer).head == (buffer).tail)


/*********************************************************************\
Define the CAN controller Register
\*********************************************************************/
/* PeliCAN mode */
enum SJA1000_PeliCAN_regs {
SJAMOD = 0x00,
/// Command register
SJACMR = 0x01,
/// Status register
SJASR = 0x02,
/// Interrupt register
SJAIR = 0x03,
/// Interrupt Enable
SJAIER = 0x04,
/// Bus Timing register 0
SJABTR0 = 0x06,
/// Bus Timing register 1
SJABTR1 = 0x07,
/// Output Control register
SJAOCR = 0x08,
/// Arbitration Lost Capture
SJAALC = 0x0b,
/// Error Code Capture
SJAECC = 0x0c,
/// Error Warning Limit
SJAEWLR = 0x0d,
/// RX Error Counter
SJARXERR = 0x0e,
/// TX Error Counter
SJATXERR0 = 0x0e,
SJATXERR1 = 0x0f,
/// Rx Message Counter (number of msgs. in RX FIFO
SJARMC = 0x1d,
/// Rx Buffer Start Addr. (address of current MSG)
SJARBSA = 0x1e,
/// Transmit Buffer (write) Receive Buffer (read) Frame Information
SJAFRM = 0x10,
/// ID bytes (11 bits in 0 and 1 or 16 bits in 0,1 and 13 bits in 2,3 (extended))
SJAID0 = 0x11, SJAID1 = 0x12,
/// ID cont. for extended frames
SJAID2 = 0x13, SJAID3 = 0x14,
/// Data start standard frame
SJADATS = 0x13,
/// Data start extended frame
SJADATE = 0x15,
/// Acceptance Code (4 bytes) in RESET mode
//SJAACR0 = 0x10,
/// Acceptance Mask (4 bytes) in RESET mode
//SJAAMR0 = 0x14,
/// 4 bytes
SJA_PeliCAN_AC_LEN = 4,
/// Clock Divider
SJACDR = 0x1f,
/// test node
SJATEST =0x09,
/// Internal RAM address 0(FIFO)
SJAInternalRecFIFO = 0x20,
/// Acceptance Code (4 bytes) in RESET mode
SJAACR0 = 0x10,
SJAACR1 = 0x11,
SJAACR2 = 0x12,
SJAACR3 = 0x13,
/// Acceptance Mask (4 bytes) in RESET mode
SJAAMR0 = 0x14,
SJAAMR1 = 0x15,
SJAAMR2 = 0x16,
SJAAMR3 = 0x17,
/// Transmit Buffer (write) Receive Buffer (read) Frame Information
SJARxBuffer0 = 0x10,
SJARxBuffer1 = 0x11,
SJARxBuffer2 = 0x12,
SJARxBuffer3 = 0x13,
SJARxBuffer4 = 0x14,

    SJATxBuffer0 = 0x10,
    SJATxBuffer1 = 0x11,
SJATxBuffer2 = 0x12,
SJATxBuffer3 = 0x13,
SJATxBuffer4 = 0x14,
/// Data start standard frame
SJAStandardDataBuffer1 = 0x13,
SJAStandardDataBuffer2 = 0x14,
SJAStandardDataBuffer3 = 0x15,
SJAStandardDataBuffer4 = 0x16,
SJAStandardDataBuffer5 = 0x17,
SJAStandardDataBuffer6 = 0x18,
SJAStandardDataBuffer7 = 0x19,
SJAStandardDataBuffer8 = 0x1a,
/// Data start extended frame
SJAExtendDataBuffer1 = 0x15,
SJAExtendDataBuffer2 = 0x16,
SJAExtendDataBuffer3 = 0x17,
SJAExtendDataBuffer4 = 0x18,
SJAExtendDataBuffer5 = 0x19,
SJAExtendDataBuffer6 = 0x1a,
SJAExtendDataBuffer7 = 0x1b,
SJAExtendDataBuffer8 = 0x1c
};

/** Mode Register 0x00 */
enum sja1000_PeliCAN_MOD {
sjaMOD_SM = 1<<4, // Sleep Mode (writable only in OPERATING mode)
sjaMOD_AFM= 1<<3, // Acceptance Filter Mode (writable only in RESET)
sjaMOD_STM= 1<<2, // Self Test Mode (writable only in RESET)
sjaMOD_LOM= 1<<1, // Listen Only Mode (writable only in RESET)
sjaMOD_RM = 1    // Reset Mode
};

/** Command Register 0x01 */
enum sja1000_PeliCAN_CMR {
sjaCMR_SRR= 1<<4, // Self Reception Request (GoToSleep in BASIC mode)
sjaCMR_CDO= 1<<3, // Clear Data Overrun
sjaCMR_RRB= 1<<2, // Release Receive Buffer
sjaCMR_AT = 1<<1, // Abort Transmission
sjaCMR_TR = 1 };   // Transmission Request

/** Status Register 0x02 */
enum sja1000_SR {
sjaSR_BS = 1<<7, // Bus Status
sjaSR_ES = 1<<6, // Error Status
sjaSR_TS = 1<<5, // Transmit Status
sjaSR_RS = 1<<4, // Receive Status
sjaSR_TCS = 1<<3, // Transmission Complete Status
sjaSR_TBS = 1<<2, // Transmit Buffer Status
sjaSR_DOS = 1<<1, // Data Overrun Status
sjaSR_RBS = 1 };   // Receive Buffer Status

/** Interrupt Enable Register 0x04 */
enum sja1000_PeliCAN_IER {
//sjaIER_BEIE= 1<<7, // Bus Error Interrupt Enable
//sjaIER_ALIE= 1<<6, // Arbitration Lost Interrupt Enable
//sjaIER_EPIE= 1<<5, // Error Passive Interrupt Enable
//sjaIER_WUIE= 1<<4, // Wake-Up Interrupt Enable
sjaIER_DOIE= 1<<3, // Data Overrun Interrupt Enable
sjaIER_EIE = 1<<2, // Error Warning Interrupt Enable
sjaIER_TIE = 1<<1, // Transmit Interrupt Enable
sjaIER_RIE = 1,    // Receive Interrupt Enable
sjaENABLE_INTERRUPTS = sjaIER_DOIE|sjaIER_EIE|sjaIER_TIE|sjaIER_RIE, //ENABLE_ALL_INTERRUPTS
sjaDISABLE_INTERRUPTS = 0 //DISABLE_ALL_INTERRUPTS
// WARNING: the chip automatically enters RESET (bus off) mode when
// error counter > 255
};

/** Arbitration Lost Capture Register 0x0b.
* Counting starts from 0 (bit1 of ID). Bits 5-7 reserved*/
enum sja1000_PeliCAN_ALC {
sjaALC_SRTR = 0x0b,// Arbitration lost in bit SRTR
sjaALC_IDE = 0x1c, // Arbitration lost in bit IDE
sjaALC_RTR = 0x1f, // Arbitration lost in RTR
};

/** Error Code Capture Register 0x0c*/
enum sja1000_PeliCAN_ECC {
sjaECC_ERCC1 = 1<<7,
sjaECC_ERCC0 = 1<<6,
sjaECC_BIT   = 0,
sjaECC_FORM = sjaECC_ERCC0,
sjaECC_STUFF = sjaECC_ERCC1,
sjaECC_OTHER = sjaECC_ERCC0 | sjaECC_ERCC1,
sjaECC_DIR   = 1<<5, // 1 == RX, 0 == TX
sjaECC_SEG_M = (1<<5) -1 // Segment mask, see page 37 of SJA1000 Data Sheet
};

/** Frame format information 0x10 */
enum sja1000_PeliCAN_FRM {
sjaFRM_FF = 1<<7, // Frame Format 1 == extended, 0 == standard
sjaFRM_RTR = 1<<6, // Remote request
sjaFRM_DLC_M = (1<<4)-1 // Length Mask
};


/** Interrupt (status) Register 0x03 */
enum sja1000_PeliCAN_IR {
//sjaIR_BEI = 1<<7, // Bus Error Interrupt
//sjaIR_ALI = 1<<6, // Arbitration Lost Interrupt
//sjaIR_EPI = 1<<5, // Error Passive Interrupt (entered error passive state or error active state)
sjaIR_WUI = 1<<4, // Wake-Up Interrupt
sjaIR_DOI = 1<<3, // Data Overrun Interrupt
sjaIR_EI = 1<<2, // Error Interrupt
sjaIR_TI = 1<<1, // Transmit Interrupt
sjaIR_RI = 1      // Receive Interrupt
};

/** Bus Timing 1 Register 0x07 */
enum sja1000_BTR1 {
sjaMAX_TSEG1 = 15, //Select the time segment 0-3
sjaMAX_TSEG2 = 7   //Select the time segment 0-2
};

/** Output Control Register 0x08 */
enum sja1000_OCR {
sjaOCR_MODE_BIPHASE = 0,
sjaOCR_MODE_TEST = 1, //output control mode0
sjaOCR_MODE_NORMAL = 2, //output control mode1
sjaOCR_MODE_CLOCK = 3, //output control polarity 0
/// TX0 push-pull not inverted
sjaOCR_TX0_LH = 0x18, //output control transister P0 and transister N0
/// TX1 floating (off)
sjaOCR_TX1_ZZ = 0
};

/** Clock Divider register 0x1f */
enum sja1000_CDR {
sjaCDR_PELICAN = 1<<7,
/// bypass input comparator
sjaCDR_CBP     = 1<<6,
/// switch TX1 to generate RX INT
sjaCDR_RXINPEN = 1<<5,
sjaCDR_CLK_OFF = 1<<3,
/// f_out = f_osc/(2*(CDR[2:0]+1)) or f_osc if CDR[2:0]==7
sjaCDR_CLKOUT_DIV1 = 7,
sjaCDR_CLKOUT_DIV2 = 0,
sjaCDR_CLKOUT_DIV4 = 1,
sjaCDR_CLKOUT_DIV6 = 2,
sjaCDR_CLKOUT_DIV8 = 3,
sjaCDR_CLKOUT_DIV10 = 4,
sjaCDR_CLKOUT_DIV12 = 5,
sjaCDR_CLKOUT_DIV14 = 6,
sjaCDR_CLKOUT_MASK = 7
};

/** flags for sja1000_baud_rate */
#define BTR1_SAM (1<<1)

//实现的部分C代码

can_device CanDevice; //基本CAN结构体的声明
pcan_device pchip = &CanDevice;

#define DUMP_CANDATA(d) DPRINTK("id=%x, data=%d,%d,%d,%d,%d,%d,%d,%d\n", (d)->id, (d)->data[0], (d)->data[1], (d)->data[2], (d)->data[3], (d)->data[4], (d)->data[5], (d)->data[6], (d)->data[7]);

#define DUMP_CANDATA1(d) DPRINTK("Inf1=0x%x, id=%d, data=%d,%d,%d,%d,%d,%d,%d,%d\n", (d)->RecBuf[1], (d)->RecBuf[2], (d)->RecBuf[3], (d)->RecBuf[4], (d)->RecBuf[5], (d)->RecBuf[6], (d)->RecBuf[7], (d)->RecBuf[8], (d)->RecBuf[9], (d)->RecBuf[10]);
#define DUMP_CANDATA2(d) DPRINTK("Inf2=0x%x, id=%d, data=%d,%d,%d,%d,%d,%d,%d,%d\n", (d)->RecBuf[11], (d)->RecBuf[12], (d)->RecBuf[13], (d)->RecBuf[14], (d)->RecBuf[15], (d)->RecBuf[16], (d)->RecBuf[17], (d)->RecBuf[18], (d)->RecBuf[19], (d)->RecBuf[20]);
#define DUMP_CANDATA3(d) DPRINTK("Inf3=0x%x, id=%d, data=%d,%d,%d,%d,%d,%d,%d,%d\n", (d)->RecBuf[21], (d)->RecBuf[22], (d)->RecBuf[23], (d)->RecBuf[24], (d)->RecBuf[25], (d)->RecBuf[26], (d)->RecBuf[27], (d)->RecBuf[28], (d)->RecBuf[29], (d)->RecBuf[30]);


//struct can_device *chip; //基本CAN结构体的声明

#define EIO   5 /* I/O error */
#define ENODEV   19 /* No such device */
#define EINVAL   20 /* invalid argument */

//***************************************************************************************
// 函数名: void CANIntHandle(void);
// 功能:    用于CAN中断处理函数
// 入口参数:
// 返回值: 无
//***************************************************************************************
void CANIntHandle(void)
{
INT8U irq_register, status, error_code;
INT16S loop_cnt = CHIP_MAX_IRQLOOP;
INT8U tmp;
DPRINTK("!INT\n");

//首先读取中断寄存器值,判断中断类型
//tmp = can_read_reg(pchip, SJAIR); DPRINTK("the SJAInterrupt RegValue is 0x%x\n",tmp);
//tmp = can_read_reg(pchip, SJAECC); DPRINTK("the CAN SJAECC Interrupt 0x%x\n", tmp);

BCAN_DATA_RECEIVE();

//接收缓冲器状态为满时,即RXFIFO有可用消息时,开启缓冲队列来存放
while(can_read_reg(pchip, SJASR) & sjaSR_RBS) { sja1000_irq_read_handler(pchip); }

return;
}

//***************************************************************************************
// 函数名: void sja1000_init(void)
// 功能:    CAN Bus初始化函数
// 入口参数:无    
// 返回值: 无
//***************************************************************************************
void sja1000_init(void)
{
INT16U tmp=0;
//can_device CanDevice; //基本CAN结构体的声明
//pcan_device chip;
//chip = &CanDevice;
//set CAN BUS(CS5 timing)
rMSC2 = (rMSC2&0x0000ffff)|(0x3ddc0000);
rGPDR1 = (rGPDR1 | 0x00000002); //set CS5 direction
rGAFR1_L = ((rGAFR1_L & 0xfffffff3)|0x00000008); //set CS5 function
set_gpios_IRQ(50, GPIO_EINT50, EXT_FALLING_EDGE); //set GPIO50 state

init_can_chip(pchip);    //init the CAN set
sja1000_enable_configuration(pchip); //进入复位模式

//建立连接
can_write_reg(pchip,0xaa, SJATEST); if(can_read_reg(pchip, SJATEST) != 0xaa) {DPRINTK("sja1000 test Error\n"); return;}

can_write_reg(pchip,sjaCDR_PELICAN|sjaCDR_CLK_OFF|sjaCDR_CBP, SJACDR); if(can_read_reg(pchip, SJACDR) != (sjaCDR_PELICAN|sjaCDR_CLK_OFF|sjaCDR_CBP)) {DPRINTK("sja1000 SJACDR Error\n"); return;}//配置时钟分频器
for(tmp=0;tmp<10000;tmp++);
/* Ensure, that interrupts are disabled even on the chip level now */
can_write_reg(pchip, sjaDISABLE_INTERRUPTS, SJAIER);
//set Rx Buffer start Addr
can_write_reg(pchip,0x00, SJARBSA); if(can_read_reg(pchip, SJARBSA) != 0) {DPRINTK("sja1000 SJARBSA Error\n"); return;}
//设置验收代码寄存器ACR,验收屏蔽寄存器AMR //配置验收屏蔽寄存器,是任何数据都可以通过
can_write_reg(pchip,0x00, SJAACR0); if(can_read_reg(pchip, SJAACR0) != 0x00) {DPRINTK("sja1000 SJAACR0 Error\n"); return;}
can_write_reg(pchip,0x00, SJAACR1); if(can_read_reg(pchip, SJAACR1) != 0x00) {DPRINTK("sja1000 SJAACR1 Error\n"); return;}
can_write_reg(pchip,0x00, SJAACR2); if(can_read_reg(pchip, SJAACR2) != 0x00) {DPRINTK("sja1000 SJAACR2 Error\n"); return;}
can_write_reg(pchip,0x00, SJAACR3); if(can_read_reg(pchip, SJAACR3) != 0x00) {DPRINTK("sja1000 SJAACR3 Error\n"); return;}
can_write_reg(pchip,0xff, SJAAMR0); if(can_read_reg(pchip, SJAAMR0) != 0xff) {DPRINTK("sja1000 SJAAMR0 Error\n"); return;}
can_write_reg(pchip,0xff, SJAAMR1); if(can_read_reg(pchip, SJAAMR1) != 0xff) {DPRINTK("sja1000 SJAAMR1 Error\n"); return;}
can_write_reg(pchip,0xff, SJAAMR2); if(can_read_reg(pchip, SJAAMR2) != 0xff) {DPRINTK("sja1000 SJAAMR2 Error\n"); return;}
can_write_reg(pchip,0xff, SJAAMR3); if(can_read_reg(pchip, SJAAMR3) != 0xff) {DPRINTK("sja1000 SJAAMR3 Error\n"); return;}
//配置总线定时寄存器
if (sja1000_baud_rate(pchip,0,75,0)) { DPRINTK("The CAN device baud_rate error\n"); return; }
//can_write_reg(pchip,0x00, SJABTR0); if(can_read_reg(pchip, SJABTR0) != 0x00) {DPRINTK("sja1000 SJABTR0 Error\n"); return;}
//can_write_reg(pchip,0x1c, SJABTR1); if(can_read_reg(pchip, SJABTR1) != 0x1c) {DPRINTK("sja1000 SJABTR1 Error\n"); return;}

can_write_reg(pchip,sjaOCR_MODE_NORMAL|sjaOCR_TX0_LH|sjaOCR_TX1_ZZ, SJAOCR);if(can_read_reg(pchip, SJAOCR) != (sjaOCR_MODE_NORMAL|sjaOCR_TX0_LH|sjaOCR_TX1_ZZ)) {DPRINTK("sja1000 SJAOCR Error\n"); return;} //配置输出控制寄存器

/* Enable hardware interrupts *///设置中断
can_write_reg(pchip, sjaIER_DOIE|sjaIER_EIE|sjaIER_RIE, SJAIER);

//配置为自接收模式
//can_write_reg(pchip, sjaMOD_AFM|sjaMOD_STM, SJAMOD);

sja1000_disable_configuration(pchip); //配置完毕,进入工作模式
for(tmp=0;tmp<10000;tmp++);
for(tmp=0;tmp<10000;tmp++);
UtPrintf("CAN SJA1000 initialized\n");
}

//***************************************************************************************
// 函数名: __inline PCanData GetFreeBuffer(CANmsg_Buffer *pbuffer)
// 功能:    获取存储缓冲区
// 入口参数:无    
// 返回值: 无
//***************************************************************************************
__inline PCanData GetFreeBuffer(CANmsg_Buffer *pbuffer)
{
PCanData pdata;
if(IS_CYCLE_BUFFER_FULL(*pbuffer)) return NULL;
pdata = pbuffer->buffer + pbuffer->head;
pbuffer->head = CYCLE_INC(pbuffer->head);
return pdata;
}
//***************************************************************************************
// 函数名: __inline void can_write_reg(const struct can_device *chip, INT8U data, INT8U address)
// 功能:    对CAN总线的地址进行写操作
// 入口参数:无    
// 返回值: 无
//***************************************************************************************
__inline void can_write_reg(pcan_device chip, INT8U data, INT8U address)
{
INT16U tmp=0;
CANSJA1000_writeb(address, (CANSJA1000_BASE + addr_base)); //地址输入
//for(tmp=0;tmp<10000;tmp++);
CANSJA1000_writeb(data,    (CANSJA1000_BASE + data_base)); //数据输入
}

//***************************************************************************************
// 函数名: __inline INT8U can_read_reg(const struct can_device *chip, INT8U address)
// 功能:    对CAN总线的地址进行读操作
// 入口参数:无    
// 返回值: 从SJA1000读回来的寄存器数值
//***************************************************************************************
__inline INT16S can_read_reg(pcan_device chip, INT8U address)
{
INT16U tmp=0;
CANSJA1000_writeb(address, (CANSJA1000_BASE + addr_base)); //地址输入
//for(tmp=0;tmp<10000;tmp++);
return CANSJA1000_readb(CANSJA1000_BASE + data_base);   //数据输入
}


//***************************************************************************************
// 函数名: static void init_can_chip(struct can_device *chip)
// 功能:    初始化CAN的参数结构体的说明
// 入口参数:无    
// 返回值: 无
//***************************************************************************************
//static void init_can_chip(struct can_device *chip)
static void init_can_chip(pcan_device chip)
{
//set default value
memset(chip, 0, sizeof(chip));
chip->clock = 16000000;
chip->bandrate = BandRate_500kbps;//BandRate_1Mbps; //工控板上面所用到的波特率
chip->receive.head = chip->receive.tail = 0;
chip->send.head = chip->send.tail = 0;
chip->tx_retry_cnt = 0;
chip->irq = 10; //the Interrupt chip PID
chip->addr_addr = addr_base;
chip->data_addr = data_base;
chip->SJA1000RecFlag = 0;
chip->RecID = 0;
chip->sja1000RecPrintfFlag = 0;
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多