这是我第一次设计调试的总线程序和硬件,其间犯了些小错误,但还好,最终还是成功了,已应用到实际项目中。在此将所设计的程序与硬件接口与大家共享,希望能为与我同样初作总线的朋友多一份参考,当然还请总线设计方面的大侠多提建议啦。 我有的是PIC18F4580控制芯片,晶振是12MHz。设计要求是,利用总线接收指令信号,同时发送当前系统状态信息。总线采用接收中断方式,为低优先级中断。 一、软件的设计 基于PIC18F4580总线的波特率的计算,如波特率为250Kbit/s,则每位的时间是T bit=4us,如果晶振为12MHz,Fosc=12MHz,由于为保证正常工作,Tbit>=8TQ。因此取TQ=0.5us,则TQ=[2×(BRP+1)]/Fosc=0.5us则2×(BRP+1)=0.5×12=6。可求得,BRP=2,即BRP54321 =0 1 ; 取T bit=8 TQ。同时要求:Prog_Seg+ Phase_Seg1≥Phase_Seg2;Phase_Seg2≥SJW。因此取 SJW1 =0 ,则Sync_Seg=1 TQ; 因此SJW1 BRP54321 =BRGCON1=0x02; SEG2PHTS=1,SAM=0, phasic time one=SEG1:21 =01 =3TQ, transmission time=PRSEG:21 =0 =1TQ 则1001 0000=BRGCON2=0x90; SEG2:21 =01 ,则Phase_Seg2=3TQ。 因此BRGCON3=0x02; 注意,T bit可编程的数值是4-25 TQ,但是为了正常工作Tbit>=8TQ。 设计的总线初始化函数如下: void CANinitial(void) { TRISB=(TRISB|0x08)&0xFB; //定义 CANRX/RB3输入口, CANTX/RB2为输出口CANCON=0x80; //申请进入总线配置模式,并选报接收缓冲器0 while(CANSTAT&0x80==0){;} //等待进入总线配置模式 BRGCON1=0x02; BRGCON2=0x90; BRGCON3=0x02; TXB0CON=0x03; /*set the priority*/ //the ID is 0x582,101 1000 0010, 1011 0000 010 TXB0SIDH=0xb0; /*the standard frame id id3-10,the frame ID is 0x582= 101 1000 0010,id10-id3=1011 0000*/ TXB0SIDL=0x40; /*the standard frame id (id0-2:bit5-0)=0100 0000,and define standard frame(bit3=EXIDE=0) or extend frame*/ TXB0DLC=0x08; /*the register defines remote frame request or no,and defines the length of the date*/ TXB0D0=0x00; TXB0D1=0x00; TXB0D2=0x00; TXB0D3=0x00; TXB0D4=0x00; TXB0D5=0x00; TXB0D6=0x00; TXB0D7=0x00; RXB0CON=0x20; /*receive buffer 0 control register ,0010 1000,define receive standard frame(0010) and remote frame*/ /*and select acceptance filter 0(RXF0)*/ //the fiter id is 0x10a=001 0000 1010 RXF0SIDH=0x21; /*define the filter register 11-3bits 0010 0001 */ RXF0SIDL=0x40; /*define the filter register 2-0bits 010*/ RXM0SIDH=0xff; RXM0SIDL=0xe0; RXB0SIDH=0x21; /*the standard frame id id3-10,the frame ID is 0x10A= 001 0000 1010, id10-id3=0010 0001*/ RXB0SIDL=0x40; RXB0DLC=0x08; /*define the lengh of the received data bytes*/ RXB0D0=0x00; RXB0D1=0x00; RXB0D2=0x00; RXB0D3=0x00; RXB0D4=0x00; RXB0D5=0x00; RXB0D6=0x00; RXB0D7=0x00;
CIOCON=0x20; CANCON=0x00; while(CANSTAT&0xe0!=0){;} PIR3=0x00; /*external interupt mark register,clear all interupt marks*/ PIE3=0x01; /*external interupt enable register,1000 0001,enable receive interupt,enable receive buffer 0 interupt*/ IPR3=0x00; //为低优先级 } #pragma interrupt can_isr #pragma code low_ISR=0x18 void low_ISR() { _asm goto can_isr _endasm } #pragma code int CAN_FLAG; void can_isr(void) //void interrupt HI_ISR(void) { if(PIR3bits.RXB0IF==1) //jude if the receive buffer 0 has received a new data { CAN_FLAG=1; CANData=RXB0D6; PIR3bits.RXB0IF=0; //crear the reveive mark RXB0CONbits.RXFUL=0; switch (CANData&0xff) { case 0x40: { _asm RESET _endasm } break; case 0x9c: { _asm RESET _endasm } default: break; } } } 说明:CANData为全局变量,当有总线接收中断发生时,取CANData=RXB0D6。在主程序中即调用CANFunction()函数,此函数中对CANData 值进行判断,当为一定值时即执行相关子程序,详细程序与此贴无关,略。同时在执行任何程序过程中,当总线中断发生时,如果总线数据为RXB0D6=0x40或0x9c均会使系统复位。 二、CAN接口硬件设计 CAN接口电路图 CAN接口硬件电路如上图所示,在此CAN总线接口电路中,应用高速光耦ADUM1201对总线收发器82C250与主控制器PIC18F4580进行隔离。因为当总线速率高于62.5kbps以上均为高速模式,斜率电阻不应大于1.8k,因此本设计选用的斜率电阻R1为1k。应用隔离电源U3为IB0505LS进行隔离供电。82C250 的CANH 和CANL 引脚各自通过一个5Ω 的电阻与CAN 总线相连,电阻可起到一定的限流作用,保护82C250 免受过流的冲击。CANH 和CANL 与地之间并联了两个30P 的小电容,可以起到滤除总线上的高频干扰和一定的防电磁辐射的能力,另外在两根CAN 总线接入端与地之间分别反接了一个保护二极管,当CAN 总线有较高的负电压时,通过二极管的短路可起到一定的过压保护作用。其中82C250T 是CAN 控制器与物理总线之间的接口,它最初是为汽车高速通信(1Mbps)应用而设计的,可以提供对总线的差动发送和接收功能,支持多达110 个节点,并能以1Mbps 的速率工作于恶劣电气环境下。
|