2020-10-13_CAN模块介绍

1、CAN通信协议基础知识

(1)两线制:CAN_H、CAN_L,两根信号线以差分电压的形式来传输0、1信息,抗干扰能力强。

(2)CAN虽然没有单独的时钟信号,但为了实现位同步、网络节点中多个设备间的仲裁,须保持主从机使用相同的波特率。

(3)数据传输格式:以“帧”为单位,“帧”中包含ID(标识符)、DATA、帧格式、有效数据长度、标识符类型等信息。网络中不同的节点通过ID来识别和过滤信息。  每帧最多包含8个字节的有效DATA。 “帧”的另一种描述为“报文”。具体组成如下:

IDR0-IDR3(4个字节的ID标识)、DSR0-DSR7(8个字节的数据)、DLR(1个字节的有效数据长度,指明前面8个字节寄存器中有几个数据是有效的)

(4)标识符ID:分为标准标识符(11bit)和扩展标识符(29bit)。

(5)波特率设置:须遵循CAN标准的时段设置(SEG2和SEG1有特定的组合约束),否则即使最终的波特率一致,也不能正常通信。

(6)ID滤波和ID屏蔽设置:为了接收网络中特定的“帧”,CAN控制器使用一套ID过滤机制来判断是否接收数据。包括IDAR(8个标识符接收寄存器)、IDMR(8个标识符掩码寄存器)。IDAR和IDMR分别分为两页,IDAR0-IDAR3、IDAR4-IDAR7、IDMR0-IDMR3、IDMR4-IDMR7。若使用标准ID标识符,则只用到IDAR0和IDAR1,以及对应的IDMR0和IDMR1;扩展标识符则用到整页的IDAR和IDMR。


(标准标识符中IDAR各位含义)


(扩展标识符中IDAR各位含义)

举例说明,如果上位机(电脑端)通过CAN向单片机发送一帧数据,其中ID为0x08,若单片机要接收此ID对应的数据,则需要设置IDAR0为0x01,IDAR1为0x00。因为0x08的ID用11bit表示为 0000 0001 000,映射到IDAR寄存器IDAR0和IDAR1,就拆分为0x01,0x00(RTR和IDE设置为0,标准标识符,数据帧;IDAR1中的最低3位不参与过滤识别)。     不必参考网上其它作者繁琐的转换和说明,直接将需要接收的ID对应到IDAR各位,填空,再分割,就得到IDAR应该设置的值了。

IDMR的设置,按照文档说明,对应位为0,则表示接收到的IDR对应位需要通过滤波器过滤识别,为1,则表示不需要过滤(任意数据都不影响接收)。 以上述例子,对应的IDMR0设置为0x00,IDMR1设置为0x07(最低3位无关,可屏蔽)。


2、MC9S12XEP100的CAN模块初始化步骤

(1)CANCTL0的INITRQ位置1,请求进入初始化状态。

(2)查询CANCTL1的INITAK是否为1,为1表示已进入初始化状态,为0表示为正常运行状态。

(3)设置CANCTL1,使能CAN、时钟选择。

(4)设置CANBTR0,CAN的时钟分频系数、同步跳转位宽等参数。

(5)设置CANBTR1,CAN的时段1、时段2等参数。(注意时段1、时段2和同步跳转位宽须满足特定的组合,参考对照表,否则即使波特率正确,也不能正常通信)

(6)设置CANIDAC,CAN的滤波器选择、标识符种类等参数。

(7)设置IDAR、IDMR,须满足主从机的ID对应关系。

(8)CANCTL0的INITRQ位置0,请求退出初始化状态。

(9)查询CANCTL1的INITAK,为0标识已退出初始化,进入正常运行状态。

(10)查询CANCTL0的SYNCH位,为1表示CAN已同步。

(11)使能CAN 的接收或发送中断,CANRIER的RXFIE为接收中断控制位。(这一步不能放在初始化状态中,否则不能开启中断!)


3、初始化程序

; 板卡号设置

BOARD_ID  EQU  1



CAN_init:

          PSHA

          PSHB

          PSHY

          PSHX


          BSET  CAN0CTL0,mCAN0CTL0_INITRQ

          BRCLR CAN0CTL1,mCAN0CTL1_INITAK,*      ; 检测是否进入初始化模式

          MOVB  #$80,CAN0CTL1                    ; CANE=1,  CLKSRC=0(外部晶振) 

          MOVB  #$07,CAN0BTR0                    ; SJW=0,  BRP=7(预分频8)

          MOVB  #$3A,CAN0BTR1                    ; TSEG2=3, TSEG1=10,  波特率=125KHz


          MOVB  #$10,CAN0IDAC                    ; IDAM=1, IDHIT=0, 4个16bit滤波器,标准标识符


          JSR  IDAR_init

          JSR  IDMR_init


          BCLR  CAN0CTL0,mCAN0CTL0_INITRQ

          BRSET CAN0CTL1,mCAN0CTL1_INITAK,*      ; 退出初始化模式 

          BRCLR CAN0CTL0,mCAN0CTL0_SYNCH,*      ; 等待同步


          MOVB  #$01,CAN0RIER                    ; RXFIE=1, 开接收中断, 必须在退出初始化模式后使能!


          PULX

          PULY

          PULB

          PULA

          RTC


      IDAR_init:

                CLRA

                LDAB  #BOARD_ID

                DECB

                LSLD

                LSLD                                    ; 查询表里,每个IDAR占4个字节,所以这里乘以4

                LDX  #Chanel1IDTable

                LEAY  D,X

                LDX  #CAN0IDAR0

                MOVW  0,Y,0,X


                RTS       

      IDMR_init:

                MOVB  #$00,CAN0IDMR0

                MOVB  #$07,CAN0IDMR1

                ;MOVB  #$00,CAN0IDMR2

                ;MOVB  #$07,CAN0IDMR3

                ;MOVB  #$00,CAN0IDMR4

                ;MOVB  #$07,CAN0IDMR5

                ;MOVB  #$00,CAN0IDMR6

                ;MOVB  #$07,CAN0IDMR7

                RTS


4、接收中断程序

       XDEF CAN0RX_ISR

        XREF    can0rx_buff

CAN0RX_ISR:

  ; Write your interrupt code here ...


        MOVB  #$00,CAN0RIER        ; 关中断

        LDY  #CAN0RXDSR0

        LDX  #can0rx_buff

        LDAB  CAN0RXDLR            ; 接收数据长度

        STAB  1,X+

        CMPB  #0

        BHI  rec_data              ; 数据长度 >0

        RTI


        rec_data:

                MOVB  1,Y+,1,X+

                DBNE  B,rec_data

        MOVB  #$01,CAN0RIER        ; 开中断

        MOVB  #$01,CAN0RFLG        ; 清RXF标志

        RTI

你可能感兴趣的:(2020-10-13_CAN模块介绍)