LIST P=16F877 #INCLUDE P16F877.INC AH EQU 30H AL EQU 31H ACCAHI EQU 32H ACCALO EQU 33H EXPA EQU 34H ACCBHI EQU 35H ACCBLO EQU 36H EXPB EQU 37H C1 EQU 38H C2 EQU 39H ACCDHI EQU 40H ACCDLO EQU 41H TEMP EQU 42H SIGN EQU 43H BB EQU 44H COUNT1 EQU 45H COUNT2 EQU 46H ACCEHI EQU 47H ACCELO EQU 48H EXPE EQU 49H ACCFHI EQU 50H ACCFLO EQU 51H EXPF EQU 52H BB1 EQU 53H PE EQU 54H STATUSS EQU 55H WS EQU 56H PE1 EQU 57H RXB1 EQU 58H RXB2 EQU 59H TMR1LS EQU 60H TMR1HS EQU 61H ACCCHI EQU 62H ACCCLO EQU 63H EXPC EQU 64H RXB3 EQU 65H R10 EQU 70H R11 EQU 71H R12 EQU 72H R13 EQU 73H R0 EQU 74H R1 EQU 75H ; ORG 0 MAIN BCF INTCON,GIE ;开总中断 BSF STATUS,RP0 MOVLW 87H ;设AE口为I/O口-- MOVWF ADCON1 MOVLW 0C1H MOVWF TRISC MOVLW 1H MOVWF TRISB BCF STATUS,RP0 CLRF PORTD MOVLW 70H MOVWF PORTB ;CAN_ALE=0,CAN_CS=1,CAN_RD_WR=1 CALL CANINT ;CAN初始化 MA BSF PORTC,1;内灯亮 BSF PORTC,2 CALL DELY BCF PORTC,2;外灯XING CALL CALL_F;发送子程序 ;MOVLW 2 ;MOVWF PE ;MA1 CALL CAN_R ; BTFSS PE1,0 ; GOTO MA1 CALL CALL_S;接收子程序???? BCF PORTC,1;内灯熄灭 CALL DELY GOTO MA
CALL_S MOVLW 2 MOVWF PE CALL CAN_R;读状态寄存器 BTFSS PE1,7;总线关闭 GOTO S1 MOVLW 3 MOVWF PE CALL CAN_R;读中断寄存器,清除中断位 MOVLW 0CH MOVWF PE1 CLRF PE CALL CAN_W;方式寄存器的复位位清零 BSF PORTC,2;外灯亮 CALL DELY BCF PORTC,2;若总线关闭,令外灯亮1秒后熄灭 RETLW 0 S1 MOVLW 2 MOVWF PE CALL CAN_R BTFSS PE1,1;数据溢出,RXFIFO没有空间存储 GOTO S2 MOVLW 1 MOVWF PE MOVLW 0CH MOVWF PE1 CALL CAN_W;清除数据溢出状态位,释放接收缓冲器 BSF PORTC,2;外灯亮 CALL DELY BCF PORTC,2;令外灯亮1秒后熄灭 CALL DELY BSF PORTC,2;外灯亮 CALL DELY BCF PORTC,2;令外灯亮1秒后熄灭,共亮两次 RETLW 0 S2 BTFSS PE1,0;接收到可用信息 GOTO S3;缓存无数据,退出接收? MOVLW 16 MOVWF PE CALL CAN_R;读接收缓存器首地址中的数据 BTFSS PE1,6;第六位为1,是远程帧无数据 GOTO S4;是数据帧 MOVLW 1 MOVWF PE MOVLW 4 MOVWF PE1 CALL CAN_W;写命令寄存器,释放接收缓冲器 BSF PORTC,2;外灯亮 CALL DELY BCF PORTC,2;令外灯亮1秒后熄灭 CALL DELY BSF PORTC,2;外灯亮 CALL DELY BCF PORTC,2;令外灯亮1秒后熄灭 BSF PORTC,2;外灯亮 CALL DELY BCF PORTC,2;令外灯亮1秒后熄灭,共亮三次 GOTO S3;退出接收 S4 MOVLW 16 MOVWF PE CALL CAN_R;读数据帧的第一个字节 MOVF PE1,0;第一个字节取到W ANDLW 0FH;取数据长度码到W ADDLW 2 MOVWF R10;长度码加2字节的标识符存R10 INCF PE,1 CALL CAN_R;读下一个字节,标识符的第一字节 MOVF PE1,0 MOVWF R11;第一字节存R11 INCF PE,1 CALL CAN_R MOVF PE1,0 MOVWF R12;第二字节存R12 INCF PE,1 CALL CAN_R MOVF PE1,0 MOVWF R13;第三字节存R13 MOVLW 1 MOVWF PE MOVLW 4 MOVWF PE1 CALL CAN_W;写命令寄存器,释放接收缓冲器 MOVLW 5 MOVWF R0 S6 BSF PORTC,2 CALL DELY BCF PORTC,2 CALL DELY DECFSZ R0,1 GOTO S6 S3 MOVLW 11;退出接收 MOVWF PE CALL CAN_R;读仲裁丢失捕捉寄存器,释放 INCF PE CALL CAN_R;读错误代码捕捉寄存器,释放 RETLW 0
CALL_F MOVLW 2;CAN发送数据子程序 MOVWF PE W3 CALL CAN_R;读SR状态寄存器 BTFSC PE1,4;SJA1000正在接收信息,则等待 GOTO W3 W4 CALL CAN_R BTFSS PE1,3;当前请求的发送未处理完,则等待 GOTO W4 W5 CALL CAN_R BTFSS PE1,2;发送缓存器锁定,则等待 GOTO W5 MOVLW 1;111GAI,命令寄存器,释放接收缓冲器,中止发送单次 MOVWF PE MOVLW 6 MOVWF PE1 CALL CAN_W;111 MOVLW 16;向发送缓存区写数据 MOVWF PE MOVLW 1 MOVWF PE1;标准帧格式,数据长度为1字节 CALL CAN_W CALL DELY1 INCF PE MOVLW 55H MOVWF PE1 CALL CAN_W CALL DELY1 INCF PE MOVLW 55H MOVWF PE1;GAI CALL CAN_W CALL DELY1 INCF PE MOVLW 55H MOVWF PE1;数据为55H,GAI CALL CAN_W CALL DELY1 MOVLW 1 MOVWF PE MOVLW 12H;GAI3???11 MOVWF PE1 CALL CAN_W;设置命令寄存器,开始自发送 BSF PORTC,2 CALL DELY CALL DELY CALL DELY CALL DELY BCF PORTC,2 BSF PORTC,3 RETLW 0
CAN_W BCF PORTB,6 ;CS=0_2008/向CAN寄存器写命令子程序 BSF PORTB,7 ;ALE=1 BSF STATUS,RP0 ; CLRF TRISD ;D口设为输出 BCF STATUS,RP0 MOVF PE,0 ;PE-->PORTD(PE中存CAN寄存器地址) MOVWF PORTD CALL DELY1;GAI BCF PORTB,7 ;ALE=0 CALL DELY1 CLRF PORTD ;清除地址 BCF PORTB,4 ;WR=0 CALL DELY1 MOVF PE1,0 ;PE1-->PORTD(PE1中存CAN寄存器命令信号) MOVWF PORTD CALL DELY1 BSF PORTB,4 ;WR=1 CALL DELY1 CLRF PORTD BSF PORTB,6 ;CS=1 RETLW 0
CAN_R BCF PORTB,6 ;CS=0_2008/读CAN寄存器子程序 BSF PORTB,7 ;ALE=1 BSF STATUS,RP0 ; CLRF TRISD ;D口设为输出 BCF STATUS,RP0 MOVF PE,0 ;访问寄存器地址PE-->PORTD MOVWF PORTD CALL DELY1 BCF PORTB,7 ;ALE=0 CALL DELY1 BSF STATUS,RP0 MOVLW 0FFH ;D口设为输入 MOVWF TRISD BCF STATUS,RP0 CALL DELY1 BCF PORTB,5 ;RD=0 CALL DELY1 MOVF PORTD,0 ;将寄存器内容读入PE1 MOVWF PE1 CALL DELY1 BSF PORTB,5 ;RD=1 BSF PORTB,6 ;CS=1 RETLW 0
CANINT CLRF PE;方式寄存器地址/2008,CAN初始化子程序 INT0 MOVLW 09H;GAI2 MOVWF PE1;要写入方式寄存器的数据存PE1 CALL CAN_W CALL DELY1 CALL CAN_R;111GAI2,没有复位则重写方式寄存器 BTFSS PE1,0 GOTO INT0;111 MOVLW 31 MOVWF PE;PE存CDR地址 MOVLW 0C8H;GAI MOVWF PE1;c8H-->CDR寄存器,选择PELICAN模式 CALL CAN_W MOVLW 4;写AMR寄存器 MOVWF R1; MOVLW 20 MOVWF PE W1 MOVLW 0FFH MOVWF PE1 CALL CAN_W INCF PE DECFSZ R1,1 GOTO W1 MOVLW 4;写ACR寄存器 MOVWF R1 MOVLW 16 MOVWF PE W2 MOVLW 55H MOVWF PE1 CALL CAN_W INCF PE DECFSZ R1,1 GOTO W2 MOVLW 6;BTR0地址/写BTR0寄存器 MOVWF PE MOVLW 0H;GAI3!!! MOVWF PE1;3H-->BTR0寄存器,选择500K波特率 CALL CAN_W MOVLW 7;BTR1地址/写BTR1寄存器 MOVWF PE MOVLW 1CH;GAI3!!! MOVWF PE1;0FFH-->BTR1寄存器,选择10K波特率 CALL CAN_W MOVLW 8;OCR地址/写OCR寄存器 MOVWF PE MOVLW 0FAH;GAI2!!!! MOVWF PE1;0AAH-->OCR寄存器 CALL CAN_W MOVLW 30;接收缓存起始地址寄存器/写寄存器 MOVWF PE MOVLW 0 MOVWF PE1;0-->接收缓存起始地址寄存器 CALL CAN_W MOVLW 15;TXERR地址/写TXERR寄存器 MOVWF PE CLRF PE1 CALL CAN_W MOVLW 12;读ECC清除寄存器内容 MOVWF PE CALL CAN_R CLRF PE;方式寄存器地址 MOVLW 0CH;INT1----- MOVWF PE1 CALL CAN_W CALL DELY1 ;CALL CAN_R;GAI2111 ;MOVLW 0CH ; SUBWF PE1,0;减 ; BTFSS STATUS,2;Z=1 ; GOTO INT1;111GAI3 RETLW 0
DELY CLRF COUNT2 ;延时子程序,系统时钟为16MHZ时,延时为1S-2008 CLRF COUNT1 MOVLW 14H MOVWF WS LOOP INCFSZ COUNT1 GOTO LOOP INCFSZ COUNT2 GOTO LOOP DECFSZ WS GOTO LOOP MOVLW 4CH MOVWF COUNT2 LOOP1 MOVLW 5 MOVWF COUNT1 LOOP2 INCFSZ COUNT1 GOTO LOOP2 DECFSZ COUNT2 GOTO LOOP1 RETLW 0
DELY1 MOVLW 30H ;延时子程序 MOVWF COUNT2 CLRF COUNT1 LOOP3 INCFSZ COUNT1 GOTO LOOP3 DECFSZ COUNT2 GOTO LOOP3 RETLW 0 END 我用的是C1C2口接的两个指示灯,显示程序的状态! 我总感觉是SJA1000初始化的问题,或是硬件的问题! 我在程序中用的是查询方式接收,即查询SJA1000状态寄存器的第0位为1时接收. CAN_W和CAN_R是模拟SJA1000的写和读子程序.CANINT子程序为初始化子程序,请各位重点帮助看一下! 硬件:PIC16F877和SJA1000都是低电平复位,接在一点用按钮复位,PIC和SJA1000都是16MHZ晶振,两个小灯分别接RC1和RC2,SJA1000的ALE、CS、RD、WR接单片机RB7至RB4,SJA1000的RX1接地,MODE接+5V,SJA1000的TX1悬空,SJA1000的TX0、RX0分别接82C250的TXD和RXD端。 现在已经调了好久了,能发送就是接收不到!真是急死人了!
|