📄 can485.asm
字号:
;程序功能:用于CAN总线与RS485总线之间的通讯转换
;修改日期:2004/04/08
;============================================================================
;定义伪指令
INDICATOR BIT P3.3 ;测试信号输出位(用于工作指示)
RT BIT P3.4 ;RS485允许接收/允许发送控制位
ID EQU 30H ;本机识别码寄存器
COMMAND EQU ID+1 ;命令寄存器
SENT BIT 00H ;CAN总线发送标志位
ORG 0000H
SJMP START ;主程序入口
ORG 0003H
LJMP INT_0 ;外部中断0入口
ORG 000BH
LJMP INT_T0 ;定时器0中断入口
; ORG 0023H
; LJMP INT_S ;串口中断入口
START:
;============================================================================
;程序初始化
MOV SP,#60H
SETB indicator ;灭工作指示灯
SETB RT
CLR A
MOV ID,A
MOV COMMAND,A
CLR SENT
;初始化串行口,定时器
MOV TMOD,#21H ;T1工作于方式2,用作波特率发生器; T0工作于方式1
MOV TH1,#0FDH ;波特率设置为9600 bps
MOV TL1,#0FDH
MOV TH0,#00H ;定时器T0装入初值,定时时间为 65535us
MOV TL0,#00H
MOV PCON,#00H ;SMOD=0
SETB TR1 ;启动T1
SETB TR0 ;启动T0
MOV SCON,#50H ;串口工作方式1, SM2=0,REN=1允许接收
SETB ET0 ;允许T0中断
SETB ES ;允许串口中断
SETB EA ;CPU开中断
LCALL SJAINI ;初始化SJA1000
SJMP $
;============================================================================
;外部中断0服务程序
INT_0:
CLR EX0 ;关外部中断0
PUSH ACC ;保护现场
PUSH DPL
PUSH DPH
PUSH PSW
MOV A,R0
PUSH ACC
MOV A,R2
PUSH ACC
MOV DPTR,#0FF03H ;指向中断寄存器
MOVX A,@DPTR ;读中断寄存器
ANL A,#04H ;检查接收错误 (00000100B)
JNZ ENDI ;ACC.2=1,错误中断
MOV DPTR,#0FF02H ;指向状态寄存器
MOVX A,@DPTR ;读状态寄存器
JNB ACC.0,ENDI ;ACC.0=0,无可用信息;ACC.0=1,RXFIFO中有可用信息
MOV DPTR,#0FF14H ;
MOVX A,@DPTR ;读取ID
XRL A,ID ;
JNZ ENDI ;不是本节点ID,退出
MOV DPTR,#0FF15H
MOVX A,@DPTR ;读取数据长度
MOV R2,A ;数据长度暂存于R2
MOV R0,#31H ;指向RAM存储单元首地址
DATALOP: INC DPTR
MOVX A,@DPTR ;接收数据
MOV @R0,A
INC R0
DJNZ R2,DATALOP
MOV DPTR,#0FF01H ;指向命令寄存器
MOV A,#04H ;将04H写入命令寄存器
MOVX @DPTR,A ;ACC.2=1,接收缓冲器中存放信息的内存空间被释放
MOV A,#7dH ;
XRL A,COMMAND ;
JNZ ENDI ;
SETB SENT ;
ENDI:
MOV DPTR,#0FF00H ;指向控制寄存器
MOV A,#62H ;将62H (01100010B)写入控制寄存器
MOVX @DPTR,A
POP ACC
MOV R2,A
POP ACC
MOV R0,A
POP PSW
POP DPH
POP DPL
POP ACC
SETB EX0 ;INT0开中断
RETI ;中断返回
;============================================================================
;初始化SJA1000子程序
SJAINI:
MOV A,#0FFH ;从P1口读入拨码状态
MOV P1,A
MOV A,P1
ANL A,#0FFH
MOV P1,#0FFH
ADD A,#10H ;当前节点ID 为拨码状态+10H 即: 16(0#),17(1#)...
MOV ID,A ;将拨码对应的节点号存入ID寄存器
SETB PX0 ;设置INT0为最高优先级
CLR IT0 ;
CLR EX0 ;关INT0中断
LOOP0: MOV DPTR,#0FF00H ;指向控制寄存器
MOV A,#61H ;将61H (01100001B)写入控制寄存器
MOVX @DPTR,A ;SJA1000检测到复位请求后,中止当前接收/发送的信息进入复位模式
CLR A
MOVX A,@DPTR ;读控制寄存器
NOP
NOP
ANL A,#01H ;取出控制寄存器的最低位
JZ LOOP0 ;ACC.0=0,重新复位
MOV DPTR,#0FF1FH ;指向内部时钟分频器
MOV A, #40H
MOVX @DPTR,A
MOV DPTR,#0FF06H ;指向总线定时寄存器0 Clkout=fosc/2
MOV A,#53H ;波特率为20Kbps,最大传输距离为3.3千米
MOVX @DPTR,A
MOV DPTR,#0FF07H ;指向总线定时寄存器1
MOV A,#2FH ;波特率为20Kbps
MOVX @DPTR,A
MOV DPTR,#0FF08H ;指向输出控制寄存器
MOV A,#1AH
MOVX @DPTR,A
MOV A,ID ;A<==ID
MOV DPTR,#0FF04H ;指向验收代码寄存器
MOVX @DPTR,A ;ID写入验收代码寄存器
MOV DPTR,#0FF05H ;指向验收屏蔽寄存器
MOV A,#0C0H
MOVX @DPTR,A
LOOP1: MOV DPTR,#0FF00H ;指向控制寄存器
MOV A,#6AH ;使SJA1000进入工作模式
MOVX @DPTR,A
CLR A
MOVX A,@DPTR
NOP
NOP
ANL A,#01H
JNZ LOOP1 ;写入不正确,重写
SETB EA ;CPU开中断
SETB EX0 ;开外部中断0
RET
;============================================================================
;T0中断服务程序
INT_T0: PUSH ACC
PUSH PSW
MOV TH0,#00H
MOV TL0,#00H
CPL indicator
QUIT: POP PSW
POP ACC
RETI
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -