Microprocessor/DSP (TMS320F28x) TR28335 개발 KIT CAN 통신
  • 728x90
    반응형

     

     

    CAN (Controller Area Network) ?

    • Bosch사에서 자동차 전장용으로 개발한 비동기식 직렬 통신의 한 방식
    • 2가닥(CAN H, CAN L)의 CAN BUS에 접속된 다수의 주변 장치들 간에 Half-Duplex 통신이 가능함
    • 멀티 마스터 구조를 가지며 N : N 통신이 가능함
    • Differential 신호 방식을 사용해 전기적인 노이즈에 매우 강하고, 하드웨어적인 오류 검출 및 처리 기능이 있기 때문에 높은 신뢰성을 가지     고있음. 주로 자동차에서 사용되지만 항공기, 각종 산업용 제어기, 빌딩 관리 등 사용 분야가 확대되는 추세임

     

     

    TMS320F28335 eCAN Module 

     

    • CAN protocol version 2.0B
    • 지원 데이터 속도 최대 1Mbps
    • 32개의 사서함
      • 수신 또는 전송 구성 가능
      • 0 또는 8byte 데이터 구성
    • 저전력 모드 지원
    • Self-test 모드 지원

     

    CAN Data Frame

     

    32-bit Access 컨트롤 레지스터 및 Status 레지스터 사용법 

     

    위 그림과 같이 ECanaRegs 레지스터에 값을 넣기 위해서 ECanaShadow 레지스터를 생성하여 원하는 레지스터 값을 세팅 후 대입하여 값을 쓴다.

     

     

    SOURCE TR28335_Can.h

    /*===============================================
     *
     * FILE  : TR28335_Can.h .2017
     * TITLE : TR28335 CAN (Controller Area Network)
     *
     *===============================================*/ 
    #ifndef __TR28335_CAN_H__
    #define __TR28335_CAN_H__
    #ifdef _cplusplus
    extern "C" {
    #endif
    #include <main.h>
    
    #define SELF_TEST_MODE_DN   0
    #define SELF_TEST_MODE_EN   1
    
    void Initcan(void);
    void CanLpb(void);
    void SetCanStm(Uint16 mode);
    
    #ifdef _cplusplus
    }
    #endif  /* extern "C"        */
    #endif  /* __TR28335_CAN_H__ */
     

     

     

    SOURCE TR28335_Can.c

    /*===============================================
     *
     * FILE  : TR28335_Can.c .2017
     * TITLE : TR28335 CAN (Controller Area Network)
     *
     *===============================================*/ 
    #include <TR28335_Can.h>
    
    struct ECAN_REGS ECanaShadow;
    
    static Uint16 gCanTxBuff[8];
    static Uint16 gCanRxBuff[8];
    static Uint16 gCanErrorCount;
    static Uint16 gXint1Count;
    
    static interrupt void can_rx_isr(void);
    static void CanWData(Uint16 *data);
    
    /*=======================================
    *
    * Name        : Initcan
    * Type        : Fucntion
    * Description : CAN Initialization
    *
    =========================================*/
    void Initcan(void)
    {
        Uint32 i;
        
        /* Vector Remapping */
        EALLOW;
        PieVectTable.ECAN0INTA = &can_rx_isr;
        EDIS;
    
        /* CAN setting */
        InitECanaGpio();                                /* Peripheral Bootload Pins Init */
        InitECana();
    
        /* 0번 MailBox 설정 */
        ECanaMboxes.MBOX0.MSGID.bit.IDE = 0;            /* ID 확장 여부 설정 : 11Bit ID 사용                            */
        ECanaMboxes.MBOX0.MSGID.bit.AAM = 0;            /* 응답모드 설정 (송신 메일박스만 유효함) : Nomal transmit mode */
        ECanaMboxes.MBOX0.MSGID.bit.STDMSGID = 0x555;   /* Mailbox ID 설정 : CAN2.0A 기준 11Bit ID                      */
        ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8;          /* Mailbox Data-Lenth 설정 (최대 8byte 설정 가능) : 8 Byte      */
        ECanaMboxes.MBOX0.MDL.all = 0x00000000;         /* Mailbox 데이터 초기화                                        */
        ECanaMboxes.MBOX0.MDH.all = 0x00000000;         /* Mailbox 데이터 초기화                                        */
    
        /* 1번 MailBox 설정 */
        ECanaMboxes.MBOX1.MSGID.bit.IDE = 0;            /* ID 확장 여부 설정 : 11Bit ID 사용                            */
        ECanaMboxes.MBOX1.MSGID.bit.AME = 0;            /* Acceptance Mask 설정 : 사용안함                              */
        ECanaMboxes.MBOX1.MSGID.bit.STDMSGID = 0x555;   /* Mailbox ID 설정 : CAN2.0A 기준 11Bit ID                      */
        ECanaMboxes.MBOX1.MSGCTRL.bit.DLC = 8;          /* Mailbox Data-Lenth 설정 (최대 8byte 설정 가능) : 8 Byte      */
        ECanaMboxes.MBOX1.MDL.all = 0x00000000;         /* Mailbox 데이터 초기화                                        */
        ECanaMboxes.MBOX1.MDH.all = 0x00000000;         /* Mailbox 데이터 초기화                                        */
    
        /* 메일박스 송수신 설정 */
        ECanaShadow.CANMD.all = ECanaRegs.CANMD.all;
        ECanaShadow.CANMD.bit.MD0 = 0;                  /* Mailbox 0번 : 송신 */
        ECanaShadow.CANMD.bit.MD1 = 1;                  /* Mailbox 1번 : 수신 */
        ECanaRegs.CANMD.all = ECanaShadow.CANMD.all;
    
        /* 메일박스 Enable/Disable 설정 */
        ECanaShadow.CANME.all = ECanaRegs.CANME.all;
        ECanaShadow.CANME.bit.ME0 = 1;                  /* Mailbox 0번 : Enable */
        ECanaShadow.CANME.bit.ME1 = 1;                  /* Mailbox 1번 : Enable */
        ECanaRegs.CANME.all = ECanaShadow.CANME.all;    
    
        SetCanStm(SELF_TEST_MODE_EN);
    
        EALLOW;
        /* 메일박스 인터럽트 마스크 설정 */
        ECanaShadow.CANMIM.all = ECanaRegs.CANMIM.all;
        ECanaShadow.CANMIM.bit.MIM1 = 1;                /* Mailbox 1번 인터럽트 : Enable */
        ECanaRegs.CANMIM.all = ECanaShadow.CANMIM.all;
    
        /* 메일박스 인터럽트 라인 설정 */
        ECanaShadow.CANMIL.all = ECanaRegs.CANMIL.all;
        ECanaShadow.CANMIL.bit.MIL1 = 0;                /* Mailbox 1번 : 0번 인터럽트 라인 */
        ECanaRegs.CANMIL.all = ECanaShadow.CANMIL.all;
    
        /* 인터럽트 라인 Enable/Disable 설정 */
        ECanaShadow.CANGIM.all = ECanaRegs.CANGIM.all;
        ECanaShadow.CANGIM.bit.I0EN = 1;                /* 0번 인터럽트 라인 : Enable */
        ECanaRegs.CANGIM.all = ECanaShadow.CANGIM.all;
        EDIS;
    
        PieCtrlRegs.PIEIER9.bit.INTx5 = 1;              /* PIE 인터럽트 (ECAN0INTA) Enable */
        IER |= M_INT9;                                  /* CPU 인터럽트 (INT9) Enable      */
        
        for (i = 0; i < 8; i++)
            gCanTxBuff[i] = i;        
        for (i = 0; i < 8; i++)
            gCanRxBuff[i] = 0;
    
        gCanErrorCount = 0;
        gXint1Count = 0;    
    }
    
    /*====================================================
    *
    * Name        : can_rx_isr
    * Type        : Interrupt
    * Description : CAN Receive Interrupt Service Routine 
    *
    ======================================================*/
    static interrupt void can_rx_isr(void)
    {
        /* 메일박스에 수신된 데이터를 메모리에 저장 */
        gCanRxBuff[0] = ECanaMboxes.MBOX1.MDL.byte.BYTE0;
        gCanRxBuff[1] = ECanaMboxes.MBOX1.MDL.byte.BYTE1;
        gCanRxBuff[2] = ECanaMboxes.MBOX1.MDL.byte.BYTE2;
        gCanRxBuff[3] = ECanaMboxes.MBOX1.MDL.byte.BYTE3;
        gCanRxBuff[4] = ECanaMboxes.MBOX1.MDH.byte.BYTE4;
        gCanRxBuff[5] = ECanaMboxes.MBOX1.MDH.byte.BYTE5;
        gCanRxBuff[6] = ECanaMboxes.MBOX1.MDH.byte.BYTE6;
        gCanRxBuff[7] = ECanaMboxes.MBOX1.MDH.byte.BYTE7;        
    
        /* CAN 메일박스에 데이터가 수신되면 해당 CANRMP 레지스터 비트를 클리어 */
        ECanaShadow.CANRMP.all = 0;
        ECanaShadow.CANRMP.bit.RMP1 = 1;
        ECanaRegs.CANRMP.all = ECanaShadow.CANRMP.all;
    
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;         /* Acknowledge interrupt to PIE */    
    }
    
    /*=======================================
    *
    * Name        : CanWData
    * Type        : Fucntion
    * Description : CAN Write Data
    *
    =========================================*/
    static void CanWData(Uint16 *data)
    {
        /* CAN으로 송신할 데이터를 메일박스에 저장 */
        ECanaMboxes.MBOX0.MDL.byte.BYTE0 = data[0];
        ECanaMboxes.MBOX0.MDL.byte.BYTE1 = data[1];
        ECanaMboxes.MBOX0.MDL.byte.BYTE2 = data[2]; 
        ECanaMboxes.MBOX0.MDL.byte.BYTE3 = data[3]; 
        ECanaMboxes.MBOX0.MDH.byte.BYTE4 = data[4];
        ECanaMboxes.MBOX0.MDH.byte.BYTE5 = data[5];
        ECanaMboxes.MBOX0.MDH.byte.BYTE6 = data[6]; 
        ECanaMboxes.MBOX0.MDH.byte.BYTE7 = data[7];     
        
        /* 메일박스 데이터 전송 요청 */
        ECanaShadow.CANTRS.all = 0;
        ECanaShadow.CANTRS.bit.TRS0 = 1;
        ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;
    
        /* 메일박스 데이터 송신 완료 플래그 대기 */
        do {
            ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;
        } while (!ECanaShadow.CANTA.bit.TA0);
    
        /* 메일박스 데이터 송신 완료 플래그 초기화 */
        ECanaShadow.CANTA.all = 0;
        ECanaShadow.CANTA.bit.TA0 = 1;
        ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;    
    }
    
    /*=======================================
    *
    * Name        : CanLpb
    * Type        : Fucntion
    * Description : CAN Loop-Back Test
    *
    =========================================*/
    void CanLpb(void)
    {
        Uint32 i;
        
        CanWData(gCanTxBuff);
        for (i = 0 ; i < 20000000; i++);
    
        for (i = 0; i < 8; i++) {
            if (gCanTxBuff[i] != gCanRxBuff[i])
                gCanErrorCount++;    
        }
    
        for (i = 0; i < 8; i++) {
            gCanTxBuff[i] += 1;
            gCanTxBuff[i] &= 0xFF;
        }
    }
    
    /*=========================================
    *
    * Name        : SetCanStm
    * Type        : Fucntion
    * Description : CAN Self Test Mode Setting
    *
    ===========================================*/
    void SetCanStm(Uint16 mode)
    {
        /* 자체 LoopBack 테스트를 위한 설정 */
        EALLOW;
        ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
        if (mode == SELF_TEST_MODE_EN)
            ECanaShadow.CANMC.bit.STM = 1;                 /* CAN Self-test Mode 설정 */
        else
            ECanaShadow.CANMC.bit.STM = 0;
        ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
        EDIS;       
    }
     

     

     

    코드분석 

    Step .1 ECAN0INTA : PIE Vector Table 에 Interrupt Service Routine 을 등록 한다.

     

     

     

    Step .2 MSGID - IDE : ID 확장 여부 설정 비트이다. AMI 비트에 따라 상태가 바뀌며, 현재 코드에서는 Standard 모드로 설정한다.

     

     

     

    Step .3 MSGID - AAM : 자동 응답 모드 비트이다. 1을 넣으면 자동응답 모드이고, 0을 넣으면 일반 모드를 전송 합니다. 이 모드는 송신 메일박스에만 유효하다.

     

    Step .4 MSGID - STDMSGID : 이 비트는 CAN2.0A 기준 이라 데이터 시트에 나와 있지 않으나, 메일박스의 ID를 설정하는 비트이다.

     

     

     

    Step .5 MSGCTRL - DLC : 데이터의 길이를 결정하는 비트이다. 송/수신 바이트 길이를 결정한다. 유효한 값 범위는 0byte 에서 8byte 이다.

     

     

     

    Step .6 MDL, MDH : 메일박스 데이터 레지스트 이다.

     

     

     

    Step .7 CANMD[31:-] : 32개의 메일박스의 송/수신 모드를 결정하는 비트이다. 1을 넣으면 수신, 0을 넣으면 송신으로 설정 된다.

     

     

     

    Step .8 CANME[31:0] : 32개의 메일박스 활성/비활성 제어 비트이다. 사용하지 않는 메일박스는 추가 메모리로 사용할 수 있다. 1을 쓰면 메일박스가 활성화 된다. 0을 쓰면 메일박스가 비활성화 되며 추가 메모리로 사용 가능하다.

     

     

     

    Step .9 CANMC - STM : 자체 테스트 모드이다. 이 비트는 EALLOW로 보호 받고 있다. 1을 넣으면 자체 테스트 모드이고, 0을 넣으면 비활성화 된다.

     

     

     

    Step .10 CANMIM - MIM0~31 : 메일박스 인터럽트 마스크 비트이다. 1을 넣으면 메일박스 인터럽트가 활성화 되고, 0을 넣으면 비활성화 된다.

     

     

     

    Step .11 CANMIL - MIL0~31 : 메일박스 인터럽트 라인을 설정한다. 1을 넣으면 1번 인터럽트 라인, 0을 넣으면 0번 인터럽트 라인이 설정된다. 

     

     

     

    Step .12 CANGIM - I0EN : 0번 인터럽트 라인 활성/비활성을 설정한다. 1을 넣으면 0번 인터럽트 라인이 활성화 되고, 0을 넣으면 0번 인터럽트 라인이 비활성화 된다.

     

     

     

    Step .13 CANRMP - RMP31~0 : 데이터가 수신되면 pendig 시키는 비트이다. 1을 쓰면 클리어 된다.

     

     

     

    Step .14 CANTRS - TRS31~0 : 전송 요청 설정 비트이다. 해당 메일박스에 1을 쓰면 메시지가 전송된다.

     

     

     

    Step .15 CANTA = TA31~0 : 해당 메일박스에 전송요청이 완료되었는지 알려주는 비트이다. 성공적으로 전송이 완료되면 1이 읽힌다. 1을 쓰면 이 비트는 초기화 된다.

     

     

     

    결과 

     

     

     

     

    728x90
    반응형
상단으로