TMS320F28335开发之--CAN通信

CAN配置共分为以下步骤进行:

  1. GPIO配置为CAN功能的Tx、Rx引脚
  2. 配置CAN寄存器参数
  3. 编写发送API函数、接收中断处理函数

1.GPIO配置为CAN功能的Tx、Rx引脚

其实主要是配置寄存器Mux,可以直接调用DSP2833x_ECan.c中官方提供的函数 InitECanaGpio(void); 此处贴出该函数。

InitECanaGpio(void)
{
    EALLOW;

    //
    // Enable internal pull-up for the selected CAN pins
    // Pull-ups can be enabled or disabled by the user.
    // This will enable the pullups for the specified pins.
    // Comment out other unwanted lines.
    //
    //GpioCtrlRegs.GPAPUD.bit.GPIO30 = 0;	  // Enable pull-up for GPIO30 (CANRXA)
    GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0; // Enable pull-up for GPIO18 (CANRXA)

    //GpioCtrlRegs.GPAPUD.bit.GPIO31 = 0;	 //Enable pull-up for GPIO31 (CANTXA)
    GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0;  //Enable pull-up for GPIO19 (CANTXA)

    //
    // Set qualification for selected CAN pins to asynch only
    // Inputs are synchronized to SYSCLKOUT by default.
    // This will select asynch (no qualification) for the selected pins.
    //
    //GpioCtrlRegs.GPAQSEL2.bit.GPIO30 = 3;   // Asynch qual for GPIO30 (CANRXA)
    GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3;  // Asynch qual for GPIO18 (CANRXA)

    //
    // Configure eCAN-A pins using GPIO regs
    // This specifies which of the possible GPIO pins will be eCAN functional 
    // pins.
    //
    //GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1;	// Configure GPIO30 for CANRXA
    GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 3;	// Configure GPIO18 for CANRXA
    //GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1;	// Configure GPIO31 for CANTXA
    GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 3;	// Configure GPIO19 for CANTXA

    EDIS;
}

2.配置CAN寄存器参数

2.1 通用配置

此处配置内容为所有CAN通用的配置,也就是使用CAN外设都会进行的配置,官方提供了相应的函数 InitECana(void); 可以直接调用。下面贴出官方给的函数。注意代码中有一部分是进行发送频率配置的,我这里设置的是150Mhz主频下使用500k发送,读者可根据自己情况进行自行配置(具体应该配置为多少可查阅官方芯片数据手册)。

//
// InitECana - Initialize eCAN-A module
//
void 
InitECana(void)
{
    //
    // Create a shadow register structure for the CAN control registers. This 
    // is needed, since only 32-bit access is allowed to these registers. 
    // 16-bit access to these registers could potentially corrupt the register
    // contents or return false data. This is especially true while writing 
    // to/reading from a bit (or group of bits) among bits 16 - 31
    //
    struct ECAN_REGS ECanaShadow;

    EALLOW;		// EALLOW enables access to protected bits

    //
    // Configure eCAN RX and TX pins for CAN operation using eCAN regs
    //
    ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all;
    ECanaShadow.CANTIOC.bit.TXFUNC = 1;
    ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all;

    ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all;
    ECanaShadow.CANRIOC.bit.RXFUNC = 1;
    ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all;

    //
    // Configure eCAN for HECC mode - (reqd to access mailboxes 16 thru 31)
    // HECC mode also enables time-stamping feature
    //
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.SCB = 1;//使其工作于SCB模式
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

    //
    // Initialize all bits of 'Master Control Field' to zero
    // Some bits of MSGCTRL register come up in an unknown state. For proper 
    // operation, all bits (including reserved bits) of MSGCTRL must be 
    // initialized to zero
    //
    ECanaMboxes.MBOX0.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX1.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX2.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX3.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX4.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX5.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX6.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX7.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX8.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX9.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX10.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX11.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX12.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX13.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX14.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX15.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX16.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX17.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX18.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX19.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX20.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX21.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX22.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX23.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX24.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX25.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX26.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX27.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX28.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX29.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX30.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX31.MSGCTRL.all = 0x00000000;

    //
    // TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
    // as a matter of precaution.
    //
    ECanaRegs.CANTA.all	= 0xFFFFFFFF;       // Clear all TAn bits

    ECanaRegs.CANRMP.all = 0xFFFFFFFF;      // Clear all RMPn bits

    ECanaRegs.CANGIF0.all = 0xFFFFFFFF;     // Clear all interrupt flag bits
    ECanaRegs.CANGIF1.all = 0xFFFFFFFF;

    //
    // Configure bit timing parameters for eCANA
    //
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.CCR = 1 ;            // Set CCR = 1
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

    ECanaShadow.CANES.all = ECanaRegs.CANES.all;

    do
    {
        ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 1 );  	// Wait for CCE bit to be set

    ECanaShadow.CANBTC.all = 0;

    //
    // CPU_FRQ_150MHz is defined in DSP2833x_Examples.h
    //
    #if (CPU_FRQ_150MHZ)
    //
    // The following block for all 150 MHz SYSCLKOUT 
    // (75 MHz CAN clock) - default. Bit rate = 1 Mbps See Note at End of File
    //此处修改了波特率为500k
    ECanaShadow.CANBTC.bit.BRPREG = 9;
    ECanaShadow.CANBTC.bit.TSEG2REG = 2;
    ECanaShadow.CANBTC.bit.TSEG1REG = 10;
    #endif
    
    //
    // CPU_FRQ_100MHz is defined in DSP2833x_Examples.h
    //
    #if (CPU_FRQ_100MHZ)
    //
    // The following block is only for 100 MHz SYSCLKOUT (50 MHz CAN clock). 
    // Bit rate = 1 Mbps See Note at End of File
    //
    ECanaShadow.CANBTC.bit.BRPREG = 4;
    ECanaShadow.CANBTC.bit.TSEG2REG = 1;
    ECanaShadow.CANBTC.bit.TSEG1REG = 6;
    #endif

    ECanaShadow.CANBTC.bit.SAM = 1;
    ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;

    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.CCR = 0 ;            // Set CCR = 0
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

    ECanaShadow.CANES.all = ECanaRegs.CANES.all;

    do
    {
        ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 0 );// Wait for CCE bit to be  cleared

    //
    // Disable all Mailboxes
    //
    ECanaRegs.CANME.all = 0;		// Required before writing the MSGIDs

    EDIS;
}

2.2 用户邮箱配置

CAN外设除了要配置公共寄存器,告诉他应该工作在哪个频率、开启引脚Tx、Rx、设置SCB工作模式这些通用配置(已在2.1中进行)外,还需设置邮箱。

F28335芯片共提供了32个邮箱供用户使用,每个邮箱都可以单独设置为发送/接收模式,当然我们用不到这么多,所以此处我们只使用邮箱1用于发送、邮箱2用于消息接收。

发送邮箱可设置发送数据长度(单次最大为8Byte即8个字节),发送ID等。接收邮箱可设置接收ID和接收掩码(设置要匹配ID的哪一位)。

下面是进行配置的c代码(由用户自己进行编写):

void CAN_MailBox_Config(void)//邮箱配置函数
{
	struct ECAN_REGS ECanaShadow;//因为无法对CAN寄存器进行直接按位修改,此处借助一个影子寄存器来进行修改。
	
    ECanaShadow.CANME.all = ECanaRegs.CANME.all;//保存旧有的寄存器值
    ECanaShadow.CANME.bit.ME1 = 0;//修改系统寄存器前需关闭要配置的邮箱,此处不使能邮箱1
    ECanaShadow.CANME.bit.ME2 = 0;//不使能邮箱2
    ECanaRegs.CANME.all = ECanaShadow.CANME.all;//将修改完毕的值写入系统寄存器内
    
    /*----------------------	对发送邮箱MailBox1进行配置	---------------------*/
    ECanaMboxes.MBOX1.MSGCTRL.bit.DLC = 8;//配置数据长度为8;
    ECanaMboxes.MBOX1.MSGID.bit.STDMSGID = 0x21;//设置发送消息的ID;
    ECanaMboxes.MBOX1.MSGID.bit.AME =0;//因为是发送邮箱所以屏蔽使能位,如果需要使用屏蔽,必须将该位置1
    ECanaMboxes.MBOX1.MSGID.bit.IDE = 0;//不使用扩展ID,使用11bit的标志ID(数据手册Page829)

    /*----------------------	对接收邮箱MailBox2进行配置	---------------------*/
    ECanaMboxes.MBOX2.MSGCTRL.bit.DLC = 8;//配置数据长度;
    ECanaMboxes.MBOX2.MSGID.bit.STDMSGID = 0x21;//设置接收消息的有效ID
    ECanaMboxes.MBOX2.MSGID.bit.AME =1;//接收消息ID过滤器使能
    ECanaMboxes.MBOX2.MSGID.bit.IDE = 0;//不使用扩展ID,使用11bit的标志ID(数据手册Page829)

	//ECanaLAMRegs.LAM2.bit.LAMI = 0;//当为0时只接受标准帧
	ECanaLAMRegs.LAM2.all = 0x00;//设置只接收标准帧的ID=0x21消息

	ECanaRegs.CANRMP.all      = 0xFFFFFFFF;

    ECanaShadow.CANMD.all     = ECanaRegs.CANMD.all;
    ECanaShadow.CANMD.bit.MD1 = 0;//配置邮箱1用于发送
    ECanaShadow.CANMD.bit.MD2 = 1;//邮箱2用于接收
    ECanaRegs.CANMD.all       = ECanaShadow.CANMD.all;
    
    ECanaShadow.CANME.all       = ECanaRegs.CANME.all;//配置完毕使能邮箱1、2
    ECanaShadow.CANME.bit.ME1   = 1;//使能邮箱1
    ECanaShadow.CANME.bit.ME2  = 1;//使能邮箱2
    ECanaRegs.CANME.all         = ECanaShadow.CANME.all;
	/*----------------------	对接收中断进行配置	---------------------*/
	EALLOW;
    ECanaRegs.CANMIM.bit.MIM2 = 1;//使能中断邮箱2的中断;
    ECanaRegs.CANMIL.bit.MIL2 = 1;//将中断1连接至中断INT9.6;
    ECanaRegs.CANGIM.bit.I1EN = 1;//使能中断1;
    EDIS;
	
	//下列两行最好写在main函数中,和其他中断一起使能。
	IER|=M_INT9;//开启系统中断线
    PieCtrlRegs.PIEIER9.bit.INTx6=1;使能CAN线
}

3.编写发送API函数即接收中断响应函数

3.1 编写发送API

首先编写头文件,定义用于发送的数据结构。
F2833x_can.h定义如下

/*
 * F2833x_can.h
 *
 *  Created on: 2023年11月9日
 *      Author: jarvis
 */

#ifndef USER_F2833X_CAN_H_
#define USER_F2833X_CAN_H_


#include "DSP28x_Project.h"

/**********************   存储将要发送的数据8Byte  ****************************/
typedef struct _CAN_MSG_byte
{
    unsigned char data[8];
} CAN_MSG_byte;
typedef struct _CAN_MSG_BYTE
{
    unsigned char byte0;
    unsigned char byte1;
    unsigned char byte2;
    unsigned char byte3;
    unsigned char byte4;
    unsigned char byte5;
    unsigned char byte6;
    unsigned char byte7;
} CAN_MSG_BYTE;
typedef union _CAN_MSG_DATA
{
    CAN_MSG_byte msg_byte;
    CAN_MSG_BYTE msg_Byte;
} CAN_MSG_DATA;

/**************************    将要发送的数据信息     **************************************/

typedef struct _CanTxMsg
{
    union
    {
        unsigned short int all;
        struct
        {
            unsigned short int StdId :11;
            unsigned short int resved :5;
        } bit;
    } StdId; //标准帧ID
    unsigned char DLC;  //数据长度,可为0到8;
    CAN_MSG_DATA CAN_Tx_msg_data; /*!< 帧消息内容,共8字节 */
} CanTxMsg;

/**************************    将要接收的数据信息     **************************************/

typedef struct _CanRxMsg
{
    union
    {
        unsigned short int all;
        struct
        {
            unsigned short int StdId :11;
            unsigned short int resved :5;
        } bit;
    } StdId; //标准帧ID,值为0x000到0x7FFF;
    unsigned char DLC;  //数据长度,可为0到8;
    CAN_MSG_DATA CAN_Rx_msg_data; /*!< 帧消息内容,共8字节 */
    UPDATE_State rx_update;
} CanRxMsg;

//声明发送API函数
void CAN_Send_Msg(CanTxMsg *can_tx_msg);//发送一帧数据;

#endif /* USER_F2833X_CAN_H_ */

源文件用于实现头文件中的函数。

F2833x_can.c定义如下

void CAN_Send_Msg(CanTxMsg *can_tx_msg)//发送一帧数据
{
    Uint16 time_cnt=0;
    Uint32 mbox_enable_temp = 0x0000;
    Uint32 mbox_dir_temp = 0x0000;

   struct ECAN_REGS ECanaShadow;
   volatile struct MBOX *Mailbox = &ECanaMboxes.MBOX1;

   Mailbox->MSGID.bit.STDMSGID = can_tx_msg->StdId.bit.StdId;//发送标准帧ID

   Mailbox->MSGCTRL.bit.DLC = can_tx_msg->DLC;//数据长度

   Mailbox->MDL.byte.BYTE0 = can_tx_msg->CAN_Tx_msg_data.msg_Byte.byte0;
   Mailbox->MDL.byte.BYTE1 = can_tx_msg->CAN_Tx_msg_data.msg_Byte.byte1;
   Mailbox->MDL.byte.BYTE2 = can_tx_msg->CAN_Tx_msg_data.msg_Byte.byte2;
   Mailbox->MDL.byte.BYTE3 = can_tx_msg->CAN_Tx_msg_data.msg_Byte.byte3;
   Mailbox->MDH.byte.BYTE4 = can_tx_msg->CAN_Tx_msg_data.msg_Byte.byte4;
   Mailbox->MDH.byte.BYTE5 = can_tx_msg->CAN_Tx_msg_data.msg_Byte.byte5;
   Mailbox->MDH.byte.BYTE6 = can_tx_msg->CAN_Tx_msg_data.msg_Byte.byte6;
   Mailbox->MDH.byte.BYTE7 = can_tx_msg->CAN_Tx_msg_data.msg_Byte.byte7;

   ECanaShadow.CANTRS.all = 0;
   ECanaShadow.CANTRS.bit.TRS1 = 1;
   ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;
    do
    {
    ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;
    time_cnt++;
    } while(((ECanaShadow.CANTA.bit.TA1) == 0 )&&(time_cnt<100));

   ECanaShadow.CANTA.all = 0;
   ECanaShadow.CANTA.bit.TA1 = 1;
   ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;

}

3.2 中断响应函数

注意在进行中断向量表重映射时需要映射到中断1中如下:

    EALLOW;
    PieVectTable.ECAN1INTA = &CANA_ISR;
    EDIS;
//接收中断处理函数:
__interrupt void CANA_ISR(void)
{
    if((ECanaRegs.CANGIF1.bit.GMIF1 == 1)&&(ECanaRegs.CANRMP.bit.RMP2 == 1))
    {
       can_rx_msg.DLC = ECanaMboxes.MBOX2.MSGCTRL.bit.DLC;

       can_rx_msg.StdId.bit.StdId = ECanaMboxes.MBOX2.MSGID.bit.STDMSGID;

       can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte0 = ECanaMboxes.MBOX2.MDL.byte.BYTE0;
       can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte1 = ECanaMboxes.MBOX2.MDL.byte.BYTE1;
       can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte2 = ECanaMboxes.MBOX2.MDL.byte.BYTE2;
       can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte3 = ECanaMboxes.MBOX2.MDL.byte.BYTE3;
       can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte4 = ECanaMboxes.MBOX2.MDH.byte.BYTE4;
       can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte5 = ECanaMboxes.MBOX2.MDH.byte.BYTE5;
       can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte6 = ECanaMboxes.MBOX2.MDH.byte.BYTE6;
       can_rx_msg.CAN_Rx_msg_data.msg_Byte.byte7 = ECanaMboxes.MBOX2.MDH.byte.BYTE7;

       ECanaRegs.CANRMP.bit.RMP2 = 1;
     }
    PieCtrlRegs.PIEACK.bit.ACK9 = 1;
}

本文章引用自,对扩展帧等内容进行了删减
https://blog.csdn.net/ad596142041/article/details/84980655

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值