我的 CAN总线 SJA1000调试经历 sja1000
由于以前对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;
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;
}
更多阅读
我的华为面试经历,想入职华为的可以来看看 华为实习生面试经历
华为是一家业内的大公司,待遇、前景都不错,所以想要加入华为的人也有很多。最近参加了华为的面试,有很多感触,于是把面试的过程以及要点都写出来给大家参考参考,希望对大家有所帮助。我的华为面试经历,想入职华为的可以来看看——步骤/方
我的第一次刷机经历 我的第一次作文400字
我的第一次刷机经历手机和电脑是我们现在必不可少的日常工具,对于电脑来说,人们已经习惯电脑系统的升级换代,比如从以前的Windows95升级到WindowsXP,再到现在的 Windows7。但是对于手机来说,人们还不太关注其内置操作系统的升级换代。
我的羊水穿刺经历 羊水穿刺经历
怀孕后第一次产检,在b超时发现了nt值异常,2.6,微微高于临界值2.5,医生让我们考虑是否作羊水穿刺。回家后我们上网查相关资料,发现咨询的多,介绍过程或者经历的很少。当时我们内心的忐忑不安,可能只有经历的筒子们才能体会得到。都说怀孕是
我的渣打银行实习经历内含四大求职面经
导语:俗话说不打无准备之仗,那些有志于在金融行业闯出一番天地的同学们,来看看在渣打银行实习过的前辈怎么说,还附赠四大求职的经验之谈哦。序曲这样一年的旅程一定要从去年的这个时候讲起。记忆里的2011年春天充满阳光的味道。那个
转载 我的当兵被捆绑经历 转载当兵裸检经历
原文地址:我的当兵被捆绑经历作者:蜘足常乐我是九十年代初当得兵,当的是海军,被分到了一个小岛上,到了秋季穿的是那种全蓝的大翻领水兵服。这一年我经历了三次让我难以忘怀的捆绑经历。我虽然是北方人,但人长的挺秀气的,记得那时十月中刚过