TMS320F28335 eCAN Module
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을 쓰면 이 비트는 초기화 된다.
결과
TR28335 개발 KIT CPU Timer 인터럽트 사용 (0) | 2017.06.23 |
---|---|
TR28335 개발 KIT GPIO LED 제어 (0) | 2017.06.23 |
TR28335 개발 KIT SCI 통신 (0) | 2017.06.22 |
F2833X General Purpose I/O (GPIO) 사용법 (0) | 2017.06.19 |
TR28335 Spec (0) | 2017.06.14 |