我的 CAN总线 SJA1000调试经历 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,%dn", (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,%dn", (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,%dn", (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,%dn", (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;

我的 CAN总线 SJA1000调试经历 sja1000
INT8U tmp;

DPRINTK("!INTn");

//首先读取中断寄存器值,判断中断类型

//tmp = can_read_reg(pchip, SJAIR); DPRINTK("the SJAInterrupt RegValue is 0x%xn",tmp);

//tmp = can_read_reg(pchip, SJAECC); DPRINTK("the CAN SJAECC Interrupt 0x%xn", 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 Errorn"); 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 Errorn"); 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 Errorn"); return;}

//设置验收代码寄存器ACR,验收屏蔽寄存器AMR //配置验收屏蔽寄存器,是任何数据都可以通过

can_write_reg(pchip,0x00, SJAACR0); if(can_read_reg(pchip, SJAACR0) != 0x00) {DPRINTK("sja1000 SJAACR0 Errorn"); return;}

can_write_reg(pchip,0x00, SJAACR1); if(can_read_reg(pchip, SJAACR1) != 0x00) {DPRINTK("sja1000 SJAACR1 Errorn"); return;}

can_write_reg(pchip,0x00, SJAACR2); if(can_read_reg(pchip, SJAACR2) != 0x00) {DPRINTK("sja1000 SJAACR2 Errorn"); return;}

can_write_reg(pchip,0x00, SJAACR3); if(can_read_reg(pchip, SJAACR3) != 0x00) {DPRINTK("sja1000 SJAACR3 Errorn"); return;}

can_write_reg(pchip,0xff, SJAAMR0); if(can_read_reg(pchip, SJAAMR0) != 0xff) {DPRINTK("sja1000 SJAAMR0 Errorn"); return;}

can_write_reg(pchip,0xff, SJAAMR1); if(can_read_reg(pchip, SJAAMR1) != 0xff) {DPRINTK("sja1000 SJAAMR1 Errorn"); return;}

can_write_reg(pchip,0xff, SJAAMR2); if(can_read_reg(pchip, SJAAMR2) != 0xff) {DPRINTK("sja1000 SJAAMR2 Errorn"); return;}

can_write_reg(pchip,0xff, SJAAMR3); if(can_read_reg(pchip, SJAAMR3) != 0xff) {DPRINTK("sja1000 SJAAMR3 Errorn"); return;}

//配置总线定时寄存器

if (sja1000_baud_rate(pchip,0,75,0)) { DPRINTK("The CAN device baud_rate errorn"); return; }

//can_write_reg(pchip,0x00, SJABTR0); if(can_read_reg(pchip, SJABTR0) != 0x00) {DPRINTK("sja1000 SJABTR0 Errorn"); return;}

//can_write_reg(pchip,0x1c, SJABTR1); if(can_read_reg(pchip, SJABTR1) != 0x1c) {DPRINTK("sja1000 SJABTR1 Errorn"); 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 Errorn"); 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 initializedn");

}

//***************************************************************************************

// 函数名: __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;

}

  

爱华网本文地址 » http://www.413yy.cn/a/25101011/52533.html

更多阅读

我的第一次刷机经历 我的第一次作文400字

我的第一次刷机经历手机和电脑是我们现在必不可少的日常工具,对于电脑来说,人们已经习惯电脑系统的升级换代,比如从以前的Windows95升级到WindowsXP,再到现在的 Windows7。但是对于手机来说,人们还不太关注其内置操作系统的升级换代。

我的羊水穿刺经历 羊水穿刺经历

怀孕后第一次产检,在b超时发现了nt值异常,2.6,微微高于临界值2.5,医生让我们考虑是否作羊水穿刺。回家后我们上网查相关资料,发现咨询的多,介绍过程或者经历的很少。当时我们内心的忐忑不安,可能只有经历的筒子们才能体会得到。都说怀孕是

我的渣打银行实习经历内含四大求职面经

导语:俗话说不打无准备之仗,那些有志于在金融行业闯出一番天地的同学们,来看看在渣打银行实习过的前辈怎么说,还附赠四大求职的经验之谈哦。序曲这样一年的旅程一定要从去年的这个时候讲起。记忆里的2011年春天充满阳光的味道。那个

转载 我的当兵被捆绑经历 转载当兵裸检经历

原文地址:我的当兵被捆绑经历作者:蜘足常乐我是九十年代初当得兵,当的是海军,被分到了一个小岛上,到了秋季穿的是那种全蓝的大翻领水兵服。这一年我经历了三次让我难以忘怀的捆绑经历。我虽然是北方人,但人长的挺秀气的,记得那时十月中刚过

声明:《我的 CAN总线 SJA1000调试经历 sja1000》为网友禁语分享!如侵犯到您的合法权益请联系我们删除