系统can地址为550,用于can系统测试,应用T0定时器每隔1s向can总线发送一组数据:数据长度为8个字节, 首字节为05H,第二个字节为累加变量,每秒钟数值增加1, ********************************************************************************************************* CONTROLLER_BASE EQU 7E00H ;SJA1000的片选地址
RCV_GOOD BIT 0FH ;成功的接收一帧标志 SEC_FLAG BIT 010H ;一秒到标志 ERR_FLAG BIT 011H ;监测到错误标志
SAVE_INT_INFO DATA 032H ;保存SJA1000中断寄存器的内容
SEND_DATA_BUF1 DATA 040H ;发送缓冲区 SEND_DATA_BUF2 DATA 041H SEND_DATA_BUF3 DATA 042H SEND_DATA_BUF4 DATA 043H SEND_DATA_BUF5 DATA 044H SEND_DATA_BUF6 DATA 045H SEND_DATA_BUF7 DATA 046H SEND_DATA_BUF8 DATA 047H SEND_DATA_BUF9 DATA 048H SEND_DATA_BUF10 DATA 049H
RCV_DATA_BUF1 DATA 050H ;接收缓冲区 RCV_DATA_BUF2 DATA 051H RCV_DATA_BUF3 DATA 052H RCV_DATA_BUF4 DATA 053H RCV_DATA_BUF5 DATA 054H RCV_DATA_BUF6 DATA 055H RCV_DATA_BUF7 DATA 056H RCV_DATA_BUF8 DATA 057H RCV_DATA_BUF9 DATA 058H RCV_DATA_BUF10 DATA 059H
ERROR_STATUS DATA 07CH ;错误状态表示 TEST_DATA DATA 07FH ;测试发送数据 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;程序开始 ORG 0000H LJMP MAIN ;运行主程序
ORG 0003H LJMP BCAN_INT0 ;中断方式访问SJA1000程序
ORG 000BH LJMP T0_INTERRUPT ;定时器0中断
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG 0100H ;程序开始 MAIN: MOV R0,#07fH CLR A MOV @R0,A DJNZ R0,$-1 MOV @R0,A MOV SP,#60H ;设置SP CLR P2.0 ;SJA1000退出硬件复位模式 LCALL SJA1000_INT0 ;初始化SJA1000 LCALL T0_INIT CLR P3.4 ;点亮指示灯 SETB PX0 SETB IT0 SETB EX0 SETB ET0 SETB TR0 SETB EA
LOOPER: JNB RCV_GOOD,LOOPER2 ;sja1000成功接收一帧,通知CPU处理 CLR RCV_GOOD LCALL RCVDATA_PRG LOOPER2: JNB SEC_FLAG,LOOPER3 ;一秒时间到,每秒发送一次 CLR SEC_FLAG CLR P3.5 ;点亮指示灯 LCALL SENDDATA_PRG LOOPER3: JNB ERR_FLAG,LOOPER4 ;错误标志,错误处理 CLR ERR_FLAG LCALL ERR_PRG LOOPER4: AJMP LOOPER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;初始化SJA1000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SJA1000_INT0: LCALL BCAN_CREATE_COMMUNATION ;调用SJA1000接口测试函数 MOV R7, #04 LCALL BCAN_SET_BANDRATE ;设置波特率为100k MOV R7, #0A8H ;设置接收报文ID MOV R6, #0FFH LCALL BCAN_SET_OBJECT MOV R7, #0AAH ;设置输出控制、时钟分频;正常输出模式 MOV R6, #048H ;使能内部比较器、禁止CLKOUT LCALL BCAN_SET_OUTCLK ; LCALL BCAN_QUIT_RETMODEL ;退出复位状态 MOV DPTR,#REG_CONTROL ;开放SJA1000内部功能中断 MOV A,#01EH ;中断开放 MOVX @DPTR,A CLR F0 RET
;;;;;;;;;;;;;;;;;;;;;;错误信息处理;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ERR_PRG: LCALL BCAN_ENTER_RETMODEL ;进入复位模式 LCALL SJA1000_INT0 ; MOV ERROR_STATUS,#0FCH RET
;;;;;;;;;;;;;;;;;;;;;;;接收数据处理部分;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RCVDATA_PRG: MOV R0,# RCV_DATA_BUF1 ;微处理器接收首地址 LCALL BCAN_DATA_RECEIVE ;调用接收数据子程序 MOV R7,#04H ;释放接收缓冲区 LCALL BCAN_CMD_PRG ; RET ;;;;;;;;;;;;;;;;;;控制SJA1000向CAN总线发送数据处理部分;;;;;;;;;;;;;;; SENDDATA_PRG: MOV R0, #SEND_DATA_BUF1 MOV @R0, #02H INC R0 MOV @R0, #08H INC R0 MOV @R0, #05H MOV A, TEST_DATA INC R0 MOV @R0, A MOV R0, #SEND_DATA_BUF1 LCALL BCAN_DATA_WRITE ;将要发送的数据送入发送缓冲区 MOV R7, #01 LCALL BCAN_CMD_PRG RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;定时器0初始化;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; T0_INIT: MOV A,TMOD ANL A,#0F0H ORL A,#01H MOV TMOD,A;T0工作在方式1 MOV TH0,#0FCH ;定时周期1MS MOV TL0,#066H MOV 3AH,#00H RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;外部中断0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BCAN_INT0: push DPH PUSH DPL PUSH PSW ;PSW,ACC入栈 PUSH ACC USING 3 ;应用寄存器第3组 MOV DPTR,#REG_INTERRUPT ;读中断寄存器 MOVX A,@DPTR ; MOV SAVE_INT_INFO,A ;保存中断寄存器的内容 JNB ACC.0,BCAN_INT1 ;接收中断 SETB RCV_GOOD ;置位接收标志
BCAN_INT1: MOV A,SAVE_INT_INFO JNB ACC.2,BCAN_INT2 ;错误中断 SETB ERR_FLAG ;置位错误标志 BCAN_INT2: POP ACC POP PSW POP DPL POP DPH RETI ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;定时器0中断;;;;;;;;;;;;;;;; T0_INTERRUPT: push DPH PUSH DPL PUSH PSW ;PSW、ACC入栈 PUSH ACC USING 2 MOV TH0,#80H ;设置定时周期0.3S MOV TL0,#26H INC 3AH MOV A,3AH CJNE A,#23H,T0_QUIT ;判断1秒时间是否到 MOV 3AH,#00H INC TEST_DATA ;测试发送的数据,每1秒加1 SETB SEC_FLAG ;置位1秒到标志 T0_QUIT: POP ACC POP PSW POP DPL POP DPH RETI
BCAN_ENTER_RETMODEL: MOV DPTR, #REG_CONTROL ;控制寄存器访问 MOVX A, @DPTR ; ORL A, #01H ;置位复位请求 MOVX @DPTR, A ; CLR F0 MOVX A, @DPTR ;验证复位是否写入 JB ACC.0, BCAN_ER_QUIT SETB F0 ;复位不成功 BCAN_ER_QUIT: RET
BCAN_QUIT_RETMODEL: MOV DPTR, #REG_CONTROL ; 控制寄存器访问 MOVX A, @DPTR ; ANL A, #0FEH ;清零复位请求,进入工作状态 MOVX @DPTR, A CLR F0 MOVX A, @DPTR JNB ACC.0, BCAN_QR_QUIT ;验证是否退出复位状态 SETB F0 BCAN_QR_QUIT: RET
BCAN_DATA_WRITE: MOV DPTR, #REG_STATUS ;读取状态寄存器 MOVX A, @DPTR ;判断上次发送是否完成 SETB F0 JNB ACC.3, BCAN_DW_QUIT ;正在发送退出 CLR F0 MOVX A, @DPTR ;判断发送缓冲区是否锁定, SETB F0 JNB ACC.2, BCAN_DW_QUIT ;锁定则跳出 CLR F0 INC R0 ; MOV A, @R0 ;ID号的低3位 RTR位 数据长度DLC DEC R0 ;恢复指针指向发送数据的首地址 MOV DPTR, #REG_TxBuffer1;发送缓冲区首地址
JB ACC.4, BCAN_WYB ;远程帧 ;数据帧 ANL A, #0FH ;计算发送数据的长度 ADD A, #02H MOV R7, A AJMP BCAN_WRTXBUF ;
BCAN_WYB: MOV R7, #02 ;写入发送缓冲区数据长度为2
BCAN_WRTXBUF: MOV A, @R0 ;开始写入 MOVX @DPTR, A SETB F0 MOVX A, @DPTR ;校验写入的是否正确 XRL A, @R0 JNZ BCAN_DW_QUIT ;写入错误退出 CLR F0 ;正确写入继续 INC R0 INC DPTR DJNZ R7, BCAN_WRTXBUF ;没有写完继续 BCAN_DW_QUIT: RET
BCAN_DATA_RECEIVE: MOV DPTR, #REG_STATUS MOVX A, @DPTR SETB F0 JNB ACC.0, BCAN_DR_QUIT ;判断报文是否有效 CLR F0
MOV DPTR, #REG_RxBuffer2 ;接收报文的ID号的低3位 RTR位 数据长度DLC MOVX A, @DPTR MOV DPTR, #REG_RxBuffer1 ;接收缓冲区的首地址 JB ACC.4, BCAN_RCVYB ;接收到的是远程帧 ;数据帧 ANL A, #0FH ;计算接收到的数据长度 ADD A, #02H ;计算报文的长度 MOV R6, A AJMP BCAN_RCVDATA
BCAN_RCVYB: MOV R6, #02 ;远程帧
BCAN_RCVDATA: ;开始读取数据 MOVX A, @DPTR MOV @R0, A INC DPTR INC R0 DJNZ R6, BCAN_RCVDATA
BCAN_DR_QUIT: RET
BCAN_SET_BANDRATE: MOV A, R7 ;判断波特率的值是否存在 CLR CY SUBB A, #13 ; SETB F0 JNC BCAN_SETBR_QUIT ;输入的值大于12则不正确 CLR F0 MOV A, R7 RL A MOV DPTR, #BCAN_SETBR ;查表找出相应的预设第一个值 MOVC A, @A+DPTR MOV R5, A ;将数据保存 MOV A, R7 ;找出第二个值 RL A INC A MOVC A, @A+DPTR MOV R6, A ;保存值
MOV DPTR, #REG_BTR0 ;装入波特率预设值,同步跳转宽度 ;位宽度 MOV A, R5 MOVX @DPTR, A SETB F0 MOVX A, @DPTR XRL A, R5 ;判断写入是否正确 JNZ BCAN_SETBR_QUIT ;不正确 CLR F0 INC DPTR MOV A, R6 MOVX @DPTR, A SETB F0 MOVX A, @DPTR XRL A, R6 ;判断写入是否正确 JNZ BCAN_SETBR_QUIT CLR F0 BCAN_SETBR_QUIT: RET
BCAN_SETBR: DB 053H, 02FH ;20KBPS的预设值 DB 087H, 0FFH ;40KBPS的预设值 DB 047H, 02FH ;50KBPS的预设值 DB 083H, 0FFH ;80KBPS的预设值 DB 043H, 02fH ;100KBPS的预设值 DB 03H, 01cH ;125KBPS的预设值 DB 081H, 0faH ;200KBPS的预设值 DB 01H, 01cH ;250KBPS的预设值 DB 080H, 0faH ;400KBPS的预设值 DB 00H, 01cH ;500KBPS的预设值 DB 080H, 0b6H ;666KBPS的预设值 DB 00H, 016H ;800KBPS的预设值 DB 00H, 014H ;1000KBPS的预设值
BCAN_SET_OBJECT: MOV DPTR, #REG_ACR ;写ACR寄存器 MOV A, R7 MOVX @DPTR, A MOVX A, @DPTR SETB F0 XRL A, R7 ;检验写入是否正确 JNZ BCAN_SETO_QUIT CLR F0 INC DPTR ;写AMR寄存器 MOV A, R6 MOVX @DPTR, A MOVX A, @DPTR SETB F0 XRL A, R6 ;检验写入是否正确 JNZ BCAN_SETO_QUIT CLR F0 BCAN_SETO_QUIT: RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BCAN_CMD_PRG: MOV A, R7 CJNE A, #01, BCAN_CMD1 ;发送请求命令 MOV DPTR, #REG_COMMAND; 地址指向命令寄存器 MOVX @DPTR, A ;写入命令字 CLR F0 RET
BCAN_CMD1: CJNE A, #02, BCAN_CMD2 ;;//夭折发送命令 MOV DPTR, #REG_STATUS ;地址指向状态寄存器 MOVX A, @DPTR ;判断是否有正在发送的状态 SETB F0 JB ACC.5, BCAN_CMD_QUIT CLR F0 BCAN_CMD_QUIT: RET
CAN开发板使用说明
1、 实验板分为主节点和从节点;CAN通讯波特率设置为800K;最高可设置为1M,用户根据自己的需要进行设置. 2、 从节点每隔2.25秒钟向主节点发送一组8个字节的数据,数据格式为:05H i 00H 00H 00H 00H 00H 00H ;其中变量I的范围是00H~FFH,他随着每发送一次数据而累加递增1;从节点指示灯1表示实验板工作正常,指示灯2以0.44Hz的频率闪烁,表示发送数据正常. 3、 主节点的ID为550,每当收到从节点发送的数据后,主节点便以9.6K波特率把收到的数据通过232串口发送给计算机,计算机上安装的用户界面(串口调试助手),可以实时显示接收到的数据,此数据用户可以存储于计算机上;主节点指示灯1表示实验板工作正常,指示灯2以1Hz的频率闪烁(如果是调用c语言程序,则以0.44Hz频率闪烁),表示接收和串口发送数据正常. 4、 单片机为AT89c51,适用于实验板(电源没有隔离); 主控单片机为ADuC812,适用于工程应用(电源隔离):ADuC812通过自带的12位精度的A/D采集传感器信号后,将采集结果通过can总线传输到“主控节点”,主控节点将数据通过串口传输给计算机;指示灯显示状态;可以通过串口给主控节点发送指令,来完成对某一节点的控制;通过串口下载程序到单片机ADuC812(详见ADuC812用户手册),可以不用编程器; 5、 串口调试助手的页面设置详见下图所示:
用户严格按照上图所示进行设置; 6、使用CAN开发板的用户请务必注意以下事项: A、开发板的供电电压为12V,插头处有+12V和GND标志; B、SJA1000的地址为0X7E00; C、注意P2_0=0;以便使SJA1000退出复位状态; D、主节点的地址为550,通讯波特率为800K; E、RS232串口三根线说明:白色线为地线;红色线为发送线;黑色线为接收线; 感谢您选用CAN开发板!真诚的希望您在短时间内掌握CAN的基本知识,如有任何问题请发至nnyt@tom.com,我将尽快给您答复;
本人同时提供can实验开发板给初学者 1 CAN控制器为SJA1000,驱动器为TJA1050,电源隔离; 2 提供详尽的源程序,可根据用户需求编写程序 联系我:13671387011(短信联系,QQ详谈) QQ: 531706356 |