📄 sja1000.asm
字号:
MODE EQU 0100H
CMR EQU 0101H
SR EQU 0102H
IR EQU 0103H
IER EQU 0104H
BTR0 EQU 0106H
BTR1 EQU 0107H
OCR EQU 0108H
ALC EQU 010BH
ECC EQU 010CH
EWLR EQU 010DH
RXERR EQU 010EH
TXERR EQU 010FH
TXB EQU 0110H
RXB EQU 0110H
RXCMD EQU 0115H
RTRDLC EQU 0110H
ACR EQU 0110H
AMR EQU 0114H
RMC EQU 011DH
RBSA EQU 011EH
CDR EQU 011FH
CBFRTP EQU 30H ;CPU接收或发送报文缓冲区首址
FRNUM EQU 40H ;接收报文数
RECOK BIT 00H ;接收报文标志,RECOK为1表示接收到一帧有效报文
RFRM BIT 01H ;回送报文标志,RFRM 为1表示该帧接收的报文应该返回
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN: MOV SP,#6FH ;SP初始化
MOV R0,#6FH
CLR A ;清零片内RAM,初始化变量和标志
CLAIR: MOV @R0,A
DJNZ R0,CLAIR
LCALL CANINI ;SJA1000初始化
MOV P1,#0FFH
MOV IE,#00H ;采用查询方式工作,关闭所有中断
;CAN控制器初始化子程序
CANINI:
MOV DPTR,#MODE ;方式寄存器
MOV A,#01H ;进入复位模式,对SJA1000进行初始化
MOVX @DPTR,A
MOV DPTR,#CDR ;时钟分频寄存器
MOV A,#88H ;选择PeliCAN模式,关闭时钟输出(CLKOUT)
MOVX @DPTR,A
MOV DPTR,#IER ;中断允许寄存器
MOV A,#0EH ;开放发送中断,溢出中断和错误警告中断
MOVX @DPTR,A
MOV DPTR,#AMR ;接收屏蔽寄存器
MOV R6,#4
MOV A,#0 ;接收屏蔽寄存器都参与
AMR1: MOVX @DPTR,A
INC DPTR
DJNZ R6,AMR1
ACR1: MOV DPTR,#ACR ;接收代码寄存器
MOV A,#0 ;ACR0和ACR1存储接收广播报文用的ID为0000H
MOVX @DPTR,A ;接收代码寄存器ACR0赋初值
INC DPTR
MOVX @DPTR,A ;接收代码寄存器ACR1赋初值
INC DPTR ;ACR2和ACR3存储接收数据报文用的ID,为节点自身的ID
MOVX @DPTR,A ;接收代码寄存器ACR2赋初值
INC DPTR
MOV A,R6
MOVX @DPTR,A ;接收代码寄存器ACR3赋初值
MOV DPTR,#BTR0 ;总线定时寄存器0
MOV A,#07H
MOVX @DPTR,A
MOV DPTR,#BTR1 ;总线定时寄存器1
MOV A,#0FFH ;设置波特率40kbps
MOVX @DPTR,A
MOV DPTR,#OCR ;输出控制寄存器
MOV A,#0AAH
MOVX @DPTR,A
MOV DPTR,#RBSA ;接收缓冲器起始地址寄存器
MOV A,#0 ;设置接收缓冲器FIFO起始地址为0
MOVX @DPTR,A
MOV DPTR,#TXERR ;发送错误计数寄存器
MOV A,#0 ;清除发送错误计数寄存器
MOVX @DPTR,A
MOV DPTR,#ECC ;错误代码捕捉寄存器
MOVX A,@DPTR ;清除错误代码捕捉寄存器
MOV DPTR,#MODE ;方式寄存器
MOV A,#00H ;设置双滤波接收方式,并返回工作状态
MOVX @DPTR,A
RET
;CAN控制器查询接收子程序
CANREC: MOV DPTR,#SR ;状态寄存器
MOVX A,@DPTR ;从SJA1000读入状态寄存器
ANL A,#0C3H ;读取总线关闭、错误状态、接收溢出、有数据等位状态
JNZ CX ;A≠0,即有上述状态,转CX
RET ;A=0,即无上述状态,结束
CX: JNB ACC.7,CXI ;SR.7=0,即总线开启,转CXI
BUSERR: MOV DPTR,#IR ;IR中断寄存器,出现总线关闭
MOVX A,@DPTR ;读中断寄存器,清除中断位
MOV DPTR,#MODE ;方式寄存器地址
MOV A,#08H
MOVX @DPTR,A ;将方式寄存器复位请求位清0
RET
NOP
CXI: MOV DPTR,#IR ;总线正常
MOVX A,@DPTR ;读中断寄存器,清除中断位
JNB ACC.3,OTHER ;IR.3=0,即数据没溢出,转OTHER
OVER: MOV DPTR,#CMR ;数据溢出,读命令寄存器地址
MOV A,#0CH
MOVX @DPTR,A ;在命令寄存器中清除数据溢出和释放接受缓冲区
RET
NOP
OTHER: JB ACC.0,RECE ;IR.0=1,接收缓冲区有数据
LJMP RECOUT ;IR.0=0,接收缓冲区无数据,退出接收
NOP
RECE: MOV DPTR,#RXB ;读取并保存接收缓冲区的数据
MOV R1,#CBFRTP ;CPU片内接收缓冲区首址
MOVX A,@DPTR ;读取数据帧格式字
MOV @R1,A ;保存
ANL A,#0FH ;截取低4位是数据场长度(0~8)
ADD A,#4 ;加4个字节的标识符(ID)
MOV R6,A
RDATA0: INC DPTR
INC R1
MOVX A,@DPTR
MOV @R1,A
DJNZ R6,RDATA0 ;循环读取与保存
MOV DPTR,#CMR
MOV A,#04H ;释放CAN接收缓冲区
MOVX @DPTR,A
RECOUT: MOV DPTR,#ALC ;释放促裁丢失捕捉寄存器和错误捕捉寄存器
MOVX A,@DPTR
MOV DPTR,#ECC
MOVX A,@DPTR
NOP
RET
;CAN控制器发送子程序
TDATA: MOV DPTR,#SR ;状态寄存器
MOVX A,@DPTR ;从SJA1000读入状态寄存器
JB ACC.4,TDATA ;判断是否正在接收,正在接收则等待,1:正在接收
TS20: MOVX A,@DPTR
JNB ACC.3,TS20 ;判断先前发送是否完成,未完成则等待发送完成,1:完成
TS21: MOVX A,@DPTR
JNB ACC.2,TS21 ;判断发送缓冲区是否锁定,锁定则等待,0:锁定
TS22: MOV DPTR,#TXB ;将CPU报文发送缓冲区数据送往CAN发送缓冲区
MOV R1,#CBFRTP ;CPU报文发送缓冲区首址
MOV A,@R1
MOVX @DPTR,A
ANL A,#0FH
ADD A,#4
MOV R6,A
MTBS: INC R1
INC DPTR
MOV A,@R1
MOVX @DPTR,A
DJNZ R6,MTBS
MOV DPTR,#CMR ;命令寄存器地址
MOV A,#01H
MOVX @DPTR,A ;启动SJA1000发送
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -