CCS-1: 基于28035的CAN监控模块

时间:2024-04-13 15:26:02

一 程序目的

1 用CAN来监控主、从站间的通信数据,并传到电脑上。其中CAN,SCI的波特率,SCI的数据格式可调,并通过数码管显示;

2 CAN作为主站发送数据,实现与从站的通信。

二 程序构成

CCS-1: 基于28035的CAN监控模块

三 具体程序

1 main.c

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

// Prototype statements for functions found within this file.
void mailbox_check(int32 T1, int32 T2, int32 T3);
void mailbox_read(void);
interrupt void ecan_rev_isr(void);
interrupt void sciaTxFifoIsr(void);
void delay(Uint32 n);

// Global variable for this example
Uint32  ErrorCount=0;
Uint32  PassCount=0;
Uint32  MessageReceivedCount=0;

Uint32  TestMbox1 = 0;
Uint32  TestMbox2 = 0;
Uint32  TestMbox3 = 0;
Uint32  TestMbox4 = 0;
Uint32  TestMbox5 = 0;
Uint32  TestMbox6 = 0;

int16 ComCanVar1 = 0;
int16 SciTxdNum = 0;
Uint32 m=0,j=0;
int16 sdataA[10]={0,0,0,0,0,0,0,0,0,0};
int16 *SciPoint;
int16 *SciPoint2;

const Uint16 CANBrtTAB[]=
{
 //BRPREG  TSEG2   TSEG1
   199,    2,    10,    // 0-10K
   99,        2,    10,    // 1-20K
   39,        2,    10,    // 2-50K
   19,        2,    10,    // 3-100K
   15,        2,    10,    // 4-125K
   11,        1,    6    ,    // 5-250K
   5,        1,    6    ,    // 6-500K
   2,        1,    6    ,    // 7-1M
};

const Uint16 SCIBrtTAB[]=
{              //    波特率
    0x061A,    // 0  4800   bps
    0x030C,    // 1  9600   bps
    0x0186,    // 2  19200  bps
    0x00C2,    // 3  38400  bps
    0x0081,    // 4  57600  bps
    0x0040,    // 5  115200 bps
    0x004A,    // 6  100000 bps
    0x0020,    // 7  230400 bps
    0x000F,    // 8  460800 bps
    0x000B,    // 9  614400 bps
    0x0007,    // 10 921600 bps
    0x0005,    // 11 1228800bps
};


const Uint16 ModPtlTAB[]=
{
               //                                               停止位   0奇/1偶 禁止校验  0  |空闲线 长度
    0x0086,    // 0, 7N2(ASCII)  7 位数据位,无校验,2位停止位       1        0      0      0  |   0  110
    0x0066,    // 1, 7E1(ASCII)  7 位数据位,偶校验,1位停止位       0        1      1      0  |   0  110
    0x0026,    // 2, 7O1(ASCII)  7 位数据位,无校验,1位停止位       0        0      1      0  |   0  110
    0x0087,    // 3, 8N2(ASCII)  8 位数据位,无校验,2位停止位       1        0      0      0  |   0  111
    0x0067,    // 4, 8E1(ASCII)  8 位数据位,无校验,1位停止位       0        1      1      0  |   0  111
    0x0027,    // 5, 8O1(ASCII)  8 位数据位,无校验,1位停止位       0        0      1      0  |   0  111
    0x0087,    // 6, 8N2(RTU)    8 位数据位,无校验,2位停止位       0        0      0      0  |   0  111
    0x0067,    // 7, 8E1(RTU)    8 位数据位,偶校验,1位停止位       0        1      1      0  |   0  111
    0x0027,    // 8, 8O1(RTU)    8 位数据位,奇校验,1位停止位       0        0      1      0  |   0  111
    0x0007,    // 9, 8N1(RTU)    8 位数据位,无校验,1位停止位       0        0      0      0  |   0  111
};

Uint16 display[]=
{
                       0x033F,//第3个数码管显示0
                       0x0306,//第3个数码管显示1
                       0x035B,//第3个数码管显示2
                       0x034F,//第3个数码管显示3
                       0x0366,//第3个数码管显示4
                       0x036D,//第3个数码管显示5
                       0x037D,//第3个数码管显示6
                       0x0307,//第3个数码管显示7
                       0x037F,//第3个数码管显示8
                       0x036F,//第3个数码管显示9
                       0x00FF,//第3个数码管显示10
                       0x0106,//后2个数码管显示11
};


 

void main(void)
{

    InitSysCtrl();
    DINT;          //关CPU中断
    InitPieCtrl();
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();
    InitECan();         // Initialize eCAN-A module
    InitSci();
    InitOthers();

    EALLOW;
    ECanaShadow.CANMIM.all = 0x00000009;   //开邮箱0,3的中断;CANMIM:Mailbox interrupt mask
    ECanaRegs.CANMIM.all = ECanaShadow.CANMIM.all;

    ECanaShadow.CANMIL.all  = 0x00000008 ; // 邮箱0的中断 分配在 eCAN1INT,邮箱3的中断 分配在 eCAN1INT
    ECanaRegs.CANMIL.all = ECanaShadow.CANMIL.all;

    ECanaShadow.CANGIM.all = 0;
    ECanaShadow.CANGIM.all = 0x00000003;   //开 eCAN0INT, eCAN1INT的中断使能
    ECanaRegs.CANGIM.all = ECanaShadow.CANGIM.all;

    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.STM = 0;         // Configure CAN for 正常 mode
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

//    PieVectTable.ECAN10NTA = &ecan_trans_isr;
    PieVectTable.ECAN1INTA = &ecan_rev_isr;
    PieVectTable.SCITXINTA = &sciaTxFifoIsr;

    PieCtrlRegs.PIECTRL.bit.ENPIE = 1;  // Enable vector fetching from PIE block
//    PieCtrlRegs.PIEIER9.bit.INTx5 = 1;  // Enable INTx.5 of INT9 (eCAN5INT)
    PieCtrlRegs.PIEIER9.bit.INTx6 = 1;  // Enable INTx.6 of INT9 (eCAN1INT)
//    PieCtrlRegs.PIEIER9.bit.INTx2 = 1;  // 使能SCI发送中断
    IER |= 0x0100;                    // Enable INT9 of CPU
    EDIS;

    while(1)
    {
        ReceiveData = readata165(sdata);
        if (ReceiveData == 0xF7FF)     //无任何按键按下
        {                              //保持原来的显示
            display595(sdata);
        }
        else if (ReceiveData == 0xF3FF) //K3按下,设置波特率
        {
            display595(0x007C);
            sdata = 0x007C;
            brt_flaga=1;
            delay(500000);
            while(brt_flaga)          //显示bbb
            {
                ReceiveData = readata165(sdata);//读取按键状态
                delay(1);
                if (ReceiveData == 0xF7FF)     //无任何按键按下                             //保持原来的显示
                    display595(sdata);
                else if (ReceiveData == 0xF3FF)//K3再次按下
                {
                    display595(0x006D);        //显示sss
                    sdata = 0x006D;
                    delay(500000);
                    brt_flagd=1;
                }

                else if ((ReceiveData == 0xF6FF)&&(brt_flagd==0))      //K1按下
                {
                    display595(display[Can_Brt]);              //显示7
                    sdata = display[Can_Brt];
                    delay(500000);
                    brt_flagb=1;
                    while(brt_flagb)
                    {
                        ReceiveData = readata165(sdata);//读取按键状态
                        if (ReceiveData == 0xF7FF)      //无任何按键按下                             //保持原来的显示
                        {
                            display595(sdata);

                        }
                        else if(ReceiveData == 0xF5FF)  //K2按下一次,波特率调整1次
                                {
                                    Can_Brt--;
                                    display595(display[Can_Brt]); //显示Can_Brt
                                    sdata=display[Can_Brt];
                                    delay(500000);      //这组延时必须加,否则会显示错误
                                                        //应该是调用了数组,所以需要的时间增加
                                }
                        else if(ReceiveData == 0xF6FF)  //K1按下
                        {
                            brt_flagb=0;
                            brt_flaga=0;
                            display595(0x007C);
                            sdata=0x007C;
                            delay(500000);

                        }
                    }
                }
                else if ((ReceiveData == 0xF6FF)&&(brt_flagd==1))
                {
                    display595(display[Sci_Brt]);              //显示1
                    sdata = display[Sci_Brt];
                    delay(500000);
                    brt_flagd=1;
                    while(brt_flagd)
                    {
                        ReceiveData = readata165(sdata);//读取按键状态
                        if (ReceiveData == 0xF7FF)      //无任何按键按下                             //保持原来的显示
                        {
                            display595(sdata);

                        }
                        else if(ReceiveData == 0xF5FF)  //K2按下一次,波特率调整1次
                                {
                                    Sci_Brt++;
                                    display595(display[Sci_Brt]); //显示Sci_Brt
                                    sdata=display[Sci_Brt];
                                    delay(500000);      //这组延时必须加,否则会显示错误
                                                                  //应该是调用了数组,所以需要的时间增加
                                }
                        else if(ReceiveData == 0xF6FF)  //K1按下
                        {
                            brt_flagd=0;
                            brt_flaga=0;
                            display595(0x006D);  //显示sss
                            sdata=0x006D;
                            delay(500000);

                        }
                    }
                }

            }
        }

        else if(ReceiveData == 0xF5FF) //K2按下,设置SCI数据格式
        {                              //显示ccc
             display595(0x0058);
             sdata = 0x0058;
              delay(500000);
             brt_flage=1;
             while(brt_flage)
             {
                 ReceiveData = readata165(sdata);//读取按键状态
                                 delay(1);
                                 if (ReceiveData == 0xF7FF)     //无任何按键按下                             //保持原来的显示
                                     display595(sdata);

                                 else if(ReceiveData == 0xF5FF) //K2再次按下
                                 {

                                         display595(0x0078);        //显示ttt
                                         sdata = 0x0078;
                                         delay(500000);
                                         brt_flagf=1;
                                 }
                                 else if ((ReceiveData == 0xF6FF)&&(brt_flagf==0))      //K1按下
                                 {
                                     display595(display[Mod_dat_Ptl]);              //第三个数码管显示9
                                     sdata = display[Mod_dat_Ptl];
                                     delay(500000);
                                     brt_flagb=1;
                                     while(brt_flagb)
                                     {
                                         ReceiveData = readata165(sdata);//读取按键状态
                                         if (ReceiveData == 0xF7FF)      //无任何按键按下                             //保持原来的显示
                                             {
                                             display595(sdata);
                                             }
                                         else if(ReceiveData == 0xF5FF)  //K2按下一次,波特率调整1次
                                             {
                                                 Mod_dat_Ptl--;
                                                 display595(display[Mod_dat_Ptl]); //显示Mod_dat_Ptl
                                                 sdata=display[Mod_dat_Ptl];
                                                 delay(500000);      //这组延时必须加,否则会显示错误
                                                                     //应该是调用了数组,所以需要的时间增加
                                              }
                                         else if(ReceiveData == 0xF6FF)  //K1按下
                                             {
                                                 brt_flagb=0;
                                                 brt_flaga=0;
                                                 display595(0x0058);
                                                 sdata=0x0058;
                                                 delay(500000);
                                             }
                                    }
                                 }
                                 else if ((ReceiveData == 0xF6FF)&&(brt_flagf==1))      //K2 再次按下,开启CAN 邮箱0 发送601模式
                                 {
                                     while(1)
                                     {
                                      display595(0x007C); //显示666
                                      sdata=0x007C;
                                     ECanaRegs.CANRMP.all=0xFFFFFFFF; //清接收标志位
                                     ECanaRegs.CANTRS.all = 0x00000001;  // Set TRS for all transmit mailboxes
                                     while(ECanaRegs.CANTA.all != 0x00000001 ) {}  // Wait for all TAn bits to be set..
                                     ECanaRegs.CANTA.all = 0x00000001;   // Clear all TAn
 //                                      while(ECanaRegs.CANRMP.all != 0x00000008){}
                                     delay(100000);
                                     }
                                 }

             }
        }

        else if(ReceiveData == 0xF6FF) // K1按下,
        {                              //显示ddd
            display595(0x005E);
            sdata = 0x005E;
            d++;
            delay(500000);
            while(d==3)
            {
                ECan_BrtChange();
                Sci_BrtChange();
                Sci_DataFormatChange();
                e=1;
                while(e)
                {
                EINT;  //开CPU中断
                }
            }
        }
    }

}


   
     

interrupt void ecan_rev_isr(void)            //邮箱3接收到数据中断处理
{
    Uint32 CANID;
    int16  s16Dat;

   // DINT;             //关CPU中断

    ECanaRegs.CANRMP.all = 0x00000008; //清接收标志
    PieCtrlRegs.PIEACK.all|=0x100;      // Issue PIE ACK


    TestMbox1=ECanaMboxes.MBOX3.MDL.all;      //低32位
    TestMbox2=ECanaMboxes.MBOX3.MDH.all;     //高32位
    CANID=ECanaMboxes.MBOX3.MSGID.all;        //COD-ID  11位的标准标识符,存储在bit18~bit28
    SciTxdNum=ECanaMboxes.MBOX3.MSGCTRL.bit.DLC;//数据长度,除了标识符以外的邮箱接收到的数据字节长度
    SciTxdNum+=2;                                                   //数据长度+两个字节的标识符(COB-ID),即为传送给PC机的数据字节数

    s16Dat = (CANID>>18)&0x7ff;                            //将邮箱中的数据和标识符存入SCI发送缓冲区
    sdataA[0] = (s16Dat>>8) & 0x00ff;
    sdataA[1] = s16Dat & 0x00ff;

    s16Dat = TestMbox1 & 0x0ffff;
    sdataA[2] = s16Dat & 0x00ff;
    sdataA[3] = (s16Dat>>8) & 0x00ff;
    s16Dat = TestMbox1>>16;
    sdataA[4] = s16Dat & 0x00ff;
    sdataA[5] = (s16Dat>>8) & 0x00ff;

    s16Dat = TestMbox2 & 0x0ffff;
    sdataA[6] = s16Dat & 0x00ff;
    sdataA[7] = (s16Dat>>8) & 0x00ff;
    s16Dat = TestMbox2>>16;
    sdataA[8] = s16Dat & 0x00ff;
    sdataA[9] = (s16Dat>>8) & 0x00ff;
    SciPoint=&sdataA[0];


    m++;


           for(;SciTxdNum>0;SciTxdNum--)
           {
               SciaRegs.SCITXBUF = *SciPoint++;
               while(SciaRegs.SCIFFTX.bit.TXFFST !=1) { } // wait for RRDY/RXFFST =1 for 1
           }

 

}

 

 

/*===========================================================*/
/*SCI中断函数*/
/*===========================================================*/
interrupt void sciaTxFifoIsr(void)        //需要通过SCI多次传输数据时,用到了SCI中断
{
    SciTxdNum--;
    SciaRegs.SCITXBUF=*SciPoint++;        //写入SCI发送缓冲区
    SciaRegs.SCIFFTX.bit.TXFFIENA=0;//禁止中断
    SciaRegs.SCIFFTX.bit.TXFFINTCLR=1;  // Clear SCI Interrupt flag
    PieCtrlRegs.PIEACK.all|=0x100;      // Issue PIE ACK

}

void delay(Uint32 n)
{
    while(n)
    n--;
}

 

void InitOthers(void)
{
    InitSpiGpio();    //SPI配置
    spi_fifo_init();      // Initialize the Spi FIFO
    spi_init();          // init SPI
}

void spi_fifo_init()
{
// Initialize SPI FIFO registers
    SpiaRegs.SPIFFTX.all=0xE004;//使能FIFO
    SpiaRegs.SPIFFRX.all=0x2044;
    //SpiaRegs.SPIFFRX.all=0x0004;
    SpiaRegs.SPIFFCT.all=0x0;    //FIFO transmit delay bits.
}                                //These bits define the delay between every transfer from FIFO transmit buffer
                                 //to transmit shift register

void spi_init()
{
    SpiaRegs.SPICCR.all =0x004F; // Reset on, rising edge, 16-bit char bits;CPOL=1
    SpiaRegs.SPICTL.all =0x000E; // Enable master mode, normal phase;CPHA=1
                                 // enable talk, and SPI int disabled.
    SpiaRegs.SPIBRR =0x0005;     //127,故SPI的波特率=60M/128=468750
    SpiaRegs.SPICCR.all =0x008F; // Relinquish SPI from Reset,Set the SPI SW RESET bit to 1 to release the SPI from the reset state.
    //SpiaRegs.SPIPRI.bit.FREE = 0;// Set so breakpoints don't disturb xmission
    //SciaRegs.SCICTL1.all =0x0023;     // Relinquish SCI from Reset
}

void spi_xmit(Uint16 a)
{
    SpiaRegs.SPITXBUF=a;
}

void display595(Uint16 DisplayData)
{
    GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
    spi_xmit(DisplayData);
    delay(1);
    GpioDataRegs.GPASET.bit.GPIO19 = 1;
}

Uint16 readata165(Uint16 SendData)  //SendData:为读取165提供脉冲而必须发送的无效数据
{                                   //ReadData:从165读到的数据,反应了按键情况
    GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
    delay(1);
    GpioDataRegs.GPASET.bit.GPIO19 = 1;
    spi_xmit(SendData);
    delay(10);
    return SpiaRegs.SPIDAT;
    //delay(1);
}

void ECan_BrtChange()
{


    ECanaShadow.CANBTC.bit.BRPREG   = CANBrtTAB[Can_Brt*3];
    ECanaShadow.CANBTC.bit.TSEG2REG = CANBrtTAB[Can_Brt*3+1];
    ECanaShadow.CANBTC.bit.TSEG1REG = CANBrtTAB[Can_Brt*3+2];
    ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;

}


void Sci_DataFormatChange()
{
    SciaRegs.SCICCR.all=ModPtlTAB[Mod_dat_Ptl];
}


void Sci_BrtChange()
{
    SciaRegs.SCIHBAUD=SCIBrtTAB[Sci_Brt]>>8;     //波特率;SCI时钟60M;
    SciaRegs.SCILBAUD=SCIBrtTAB[Sci_Brt]&0x00ff;
}

 

2 DSP2803x_ECan.c

//###########################################################################
//
// FILE:    DSP2803x_ECan.c
//
// TITLE:   DSP2803x Enhanced CAN Initialization & Support Functions.
//
//###########################################################################
// $TI Release: F2803x C/C++ Header Files and Peripheral Examples V130 $
// $Release Date: May  8, 2015 $
// $Copyright: Copyright (C) 2009-2015 Texas Instruments Incorporated -
//             http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################

#include "DSP2803x_Device.h"     // DSP28 Headerfile Include File
#include "DSP2803x_Examples.h"   // DSP28 Examples Include File

//---------------------------------------------------------------------------
// InitECan:
//---------------------------------------------------------------------------
// This function initializes the eCAN module to a known state.
//
void InitECan(void)
{
    InitECanGpio();
    InitECana();
}

void InitECana(void)        // Initialize eCAN-A module
{

/* 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. */

struct ECAN_REGS ECanaShadow;

    EALLOW;     // EALLOW enables access to protected bits

 

    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;

 

    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.SCB = 0;                                //工作在SCC模式 :0~15号邮箱可用
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

 

    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;
    ECanaRegs.CANOPC.all = 0xFFFFFFFF;   //不允许新的数据覆盖老的数据
 

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

    // Wait until the CPU has been granted permission to change the configuration registers
    do
    {
      ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 1 );       // Wait for CCE bit to be set..

    ECanaShadow.CANBTC.all = 0;
    /* The following block is only for 60 MHz SYSCLKOUT. (30 MHz CAN module clock Bit rate = 1 Mbps
       See Note at end of file. */

    ECanaShadow.CANBTC.bit.BRPREG = 2;           //配置CAN波特率:由于SYSCLK=60MHz,所以CANCLK=30MHz
    ECanaShadow.CANBTC.bit.TSEG2REG = 1;       //CAN波特率=30MHz/(6+1+3)*3=1MHz
    ECanaShadow.CANBTC.bit.TSEG1REG = 6;

    ECanaShadow.CANBTC.bit.SAM = 1;                  //采样3次
    ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;

    ECanaShadow.CANGAM.all = ECanaRegs.CANGAM.all;
    ECanaShadow.CANGAM.bit.AMI = 1;                  //AMI=1,可接收标准/扩展帧
    ECanaRegs.CANGAM.all = ECanaShadow.CANGAM.all;

    ECanaLAMRegs.LAM3.all = 0x9ffc0000;             //用于邮箱3 ,屏蔽邮箱的低11位ID码的比较

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

    // Wait until the CPU no longer has permission to change the configuration registers
    do
    {
      ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 0 );       // Wait for CCE bit to be  cleared..


    ECanaShadow.CANMC.bit.PDR=0;
    ECanaShadow.CANMC.bit.DBO = 1;                      //Set DBO = 1,先接收或发送低字节
    ECanaShadow.CANMC.bit.ABO = 1;                      //bus-off状态检测到128*11位隐性位后自动进入bus-on
    ECanaShadow.CANMC.bit.WUBA= 0;
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
    ECanaRegs.CANME.all = 0;        // Required before writing the MSGIDs

    ECanaMboxes.MBOX0.MSGID.all = (int32)0x00000601<<18;   //邮箱0用作发送邮箱,标识符为601
    ECanaMboxes.MBOX3.MSGID.all = 0x5fffffff;                             //标识符全部屏蔽,都设置成1


    ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8;       //数据长度为8位
    ECanaMboxes.MBOX3.MSGCTRL.bit.DLC = 8;       //数据长度为8位

    ECanaMboxes.MBOX0.MDL.all = 0x00dfd740;         // MBOX0作为发送邮箱时的发送数据
    ECanaMboxes.MBOX0.MDH.all = 0;
    ECanaMboxes.MBOX1.MDL.all=0;                            //清邮箱的数据区
    ECanaMboxes.MBOX1.MDH.all=0;
    ECanaMboxes.MBOX2.MDL.all=0;                            //清邮箱的数据区
    ECanaMboxes.MBOX2.MDH.all=0;
    ECanaMboxes.MBOX3.MDL.all=0;                            //清邮箱的数据区
    ECanaMboxes.MBOX3.MDH.all=0;
    ECanaMboxes.MBOX4.MDL.all=0;                            //清邮箱的数据区
    ECanaMboxes.MBOX4.MDH.all=0;
    ECanaMboxes.MBOX5.MDL.all=0;                            //清邮箱的数据区
    ECanaMboxes.MBOX5.MDH.all=0;
    ECanaMboxes.MBOX6.MDL.all=0;                             //清邮箱的数据区
    ECanaMboxes.MBOX6.MDH.all=0;
    ECanaMboxes.MBOX7.MDL.all=0;                             //清邮箱的数据区
    ECanaMboxes.MBOX7.MDH.all=0;


    ECanaRegs.CANMD.all = 0xFFFFFFFE;      //方向寄存器,1:接收;0:发送
                                                                           //邮箱0:发送;其余邮箱接收
    ECanaRegs.CANME.all = 0x0000009;          //开0,3号邮箱

    EDIS;
}

//---------------------------------------------------------------------------
// Example: InitECanGpio:
//---------------------------------------------------------------------------
// This function initializes GPIO pins to function as eCAN pins
//
// Each GPIO pin can be configured as a GPIO pin or up to 3 different
// peripheral functional pins. By default all pins come up as GPIO
// inputs after reset.
//
// Caution:
// Only one GPIO pin should be enabled for CANTXA operation.
// Only one GPIO pin shoudl be enabled for CANRXA operation.
// Comment out other unwanted lines.

void InitECanGpio(void)
{
   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.GPIO31 = 0;     // Enable pull-up for GPIO31 (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)

/* 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 operation
    GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1;    // Configure GPIO31 for CANTXA operation

    EDIS;
}

3 DSP2803x_Sci.c

#include "DSP2803x_Device.h"     // DSP2803x Headerfile Include File
#include "DSP2803x_Examples.h"   // DSP2803x Examples Include File

//---------------------------------------------------------------------------
// InitSci:
//---------------------------------------------------------------------------
// This function initializes the SCI(s) to a known state.
//
void InitSci(void)
{
    // Initialize SCI-A:
    InitSciGpio();

    SciaRegs.SCICCR.all=0x07;           //1 bit停止位;无极性,异步,8数据位
    SciaRegs.SCICTL1.all=0x03;          //使能TX RX
    SciaRegs.SCICTL2.bit.TXINTENA =1;
    SciaRegs.SCIHBAUD=0x06;          //波特率:4800;SCI时钟60M;
    SciaRegs.SCILBAUD=0x1A;

    //SciaRegs.SCIHBAUD=0x03;        //波特率:9600;SCI时钟60M;
    //SciaRegs.SCILBAUD=0x0C;

    SciaRegs.SCIFFRX.all=0x0004;     //bit5=1:Transmit FIFO interrrupt enable,并设置FIFO中断等级为4
    SciaRegs.SCIFFTX.all=0xE004;     //设置FIFO中断等级为4
    SciaRegs.SCIFFCT.all=0x00;
    SciaRegs.SCICTL1.all =0x0023;     // Relinquish SCI from Rese

}

//---------------------------------------------------------------------------
// Example: InitSciGpio:
//---------------------------------------------------------------------------
// This function initializes GPIO pins to function as SCI pins
//
// Each GPIO pin can be configured as a GPIO pin or up to 3 different
// peripheral functional pins. By default all pins come up as GPIO
// inputs after reset.
//
// Caution:
// Only one GPIO pin should be enabled for SCITXDA/B operation.
// Only one GPIO pin shoudl be enabled for SCIRXDA/B operation.
// Comment out other unwanted lines.

void InitSciGpio()
{
   InitSciaGpio();
}

void InitSciaGpio()
{
    EALLOW;


    GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0;    // Enable pull-up for GPIO28 (SCIRXDA)
//    GpioCtrlRegs.GPAPUD.bit.GPIO7 = 0;     // Enable pull-up for GPIO7  (SCIRXDA)

    GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0;       // Enable pull-up for GPIO29 (SCITXDA)
//    GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0;       // Enable pull-up for GPIO12 (SCITXDA)

    // 将SCIRXDA的输入限制类型设为异步(Asynchronous)
    GpioCtrlRegs.GPAQSEL2.bit.GPIO28 = 3;  // Asynch input GPIO28 (SCIRXDA)
//    GpioCtrlRegs.GPAQSEL1.bit.GPIO7 = 3;   // Asynch input GPIO7 (SCIRXDA)

    // 配置复用寄存器,使SCIRXDA、SCITXDA对应的GPIO设置为正确的外设用途
    GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1;    // Configure GPIO28 for SCIRXDA operation
//    GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 2;    // Configure GPIO7  for SCIRXDA operation

    GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1;     // Configure GPIO29 for SCITXDA operation
//    GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 2;   // Configure GPIO12 for SCITXDA operation

    // 配置485读写控制信号
    GpioCtrlRegs.GPAMUX1.bit.GPIO9   = 0;   // 将GPIO30配置成普通IO口
    GpioCtrlRegs.GPAPUD.bit.GPIO9      = 0;    // 0->使能内部上拉 1->屏蔽内部上拉
    GpioDataRegs.GPASET.bit.GPIO9     = 1;   // 作为485控制信号,GPIO30低电平时为读,高电平为写
    GpioCtrlRegs.GPADIR.bit.GPIO9        = 1;     // 配置GPIO为输出

    EDIS;
}

//===========================================================================
// End of file.
//===========================================================================

4 DSP2803x_MemCopy.c

#include "DSP2803x_Device.h"

void MemCopy(Uint16 *SourceAddr, Uint16* SourceEndAddr, Uint16* DestAddr)
{
    while(SourceAddr < SourceEndAddr)
    { 
       *DestAddr++ = *SourceAddr++;
    }
    return;
}

5  F2808.cmd

MEMORY
{
PAGE 0:    /* Program Memory */
           /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE1 for data allocation */
   RAML0       : origin = 0x008000, length = 0x000800     /* on-chip RAM block L0 */
   RAML1       : origin = 0x008800, length = 0x000400     /* on-chip RAM block L1 */
   OTP         : origin = 0x3D7800, length = 0x000400     /* on-chip OTP */
   FLASHH      : origin = 0x3E8000, length = 0x002000     /* on-chip FLASH */
   FLASHG      : origin = 0x3EA000, length = 0x002000     /* on-chip FLASH */
   FLASHF      : origin = 0x3EC000, length = 0x002000     /* on-chip FLASH */
   FLASHE      : origin = 0x3EE000, length = 0x002000     /* on-chip FLASH */
   FLASHD      : origin = 0x3F0000, length = 0x002000     /* on-chip FLASH */
   FLASHC      : origin = 0x3F2000, length = 0x002000     /* on-chip FLASH */
   FLASHA      : origin = 0x3F6000, length = 0x001F80     /* on-chip FLASH */
   CSM_RSVD    : origin = 0x3F7F80, length = 0x000076     /* Part of FLASHA.  Program with all 0x0000 when CSM is in use. */
   BEGIN       : origin = 0x3F7FF6, length = 0x000002     /* Part of FLASHA.  Used for "boot to Flash" bootloader mode. */
   CSM_PWL_P0  : origin = 0x3F7FF8, length = 0x000008     /* Part of FLASHA.  CSM password locations in FLASHA */

   IQTABLES    : origin = 0x3FE000, length = 0x000B50     /* IQ Math Tables in Boot ROM */
   IQTABLES2   : origin = 0x3FEB50, length = 0x00008C     /* IQ Math Tables in Boot ROM */
   IQTABLES3   : origin = 0x3FEBDC, length = 0x0000AA      /* IQ Math Tables in Boot ROM */

   ROM         : origin = 0x3FF27C, length = 0x000D44     /* Boot ROM */
   RESET       : origin = 0x3FFFC0, length = 0x000002     /* part of boot ROM  */
   VECTORS     : origin = 0x3FFFC2, length = 0x00003E     /* part of boot ROM  */

PAGE 1 :   /* Data Memory */
           /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE0 for program allocation */
           /* Registers remain on PAGE1                                                  */
   BOOT_RSVD   : origin = 0x000000, length = 0x000050     /* Part of M0, BOOT rom will use this for stack */
   RAMM0       : origin = 0x000050, length = 0x0003B0     /* on-chip RAM block M0 */
   RAMM1       : origin = 0x000400, length = 0x000400     /* on-chip RAM block M1 */
   RAML2       : origin = 0x008C00, length = 0x000400     /* on-chip RAM block L2 */
   RAML3       : origin = 0x009000, length = 0x001000     /* on-chip RAM block L3 */
   FLASHB      : origin = 0x3F4000, length = 0x002000     /* on-chip FLASH */

}

/* Allocate sections to memory blocks.
   Note:
         codestart user defined section in DSP28_CodeStartBranch.asm used to redirect code
                   execution when booting to flash
         ramfuncs  user defined section to store functions that will be copied from Flash into RAM
*/

SECTIONS
{

   /* Allocate program areas: */
   .cinit              : > FLASHA      PAGE = 0
   .pinit              : > FLASHA,     PAGE = 0
   .text               : > FLASHA      PAGE = 0
   codestart           : > BEGIN       PAGE = 0
   ramfuncs            : LOAD = FLASHD,
                         RUN = RAML0,
                         LOAD_START(_RamfuncsLoadStart),
                         LOAD_SIZE(_RamfuncsLoadSize),
                         RUN_START(_RamfuncsRunStart),
                         PAGE = 0

   csmpasswds          : > CSM_PWL_P0  PAGE = 0
   csm_rsvd            : > CSM_RSVD    PAGE = 0

   /* Allocate uninitalized data sections: */
   .stack              : > RAMM0       PAGE = 1
   .ebss               : > RAML2       PAGE = 1
   .esysmem            : > RAML2       PAGE = 1

   /* Initalized sections go in Flash */
   /* For SDFlash to program these, they must be allocated to page 0 */
   .econst             : > FLASHA      PAGE = 0
   .switch             : > FLASHA      PAGE = 0

   /* Allocate IQ math areas: */
   IQmath              : > FLASHA      PAGE = 0            /* Math Code */
   IQmathTables        : > IQTABLES,   PAGE = 0, TYPE = NOLOAD

  /* Uncomment the section below if calling the IQNexp() or IQexp()
      functions from the IQMath.lib library in order to utilize the
      relevant IQ Math table in Boot ROM (This saves space and Boot ROM
      is 1 wait-state). If this section is not uncommented, IQmathTables2
      will be loaded into other memory (SARAM, Flash, etc.) and will take
      up space, but 0 wait-state is possible.
   */
   /*
   IQmathTables2    : > IQTABLES2, PAGE = 0, TYPE = NOLOAD
   {

              IQmath.lib<IQNexpTable.obj> (IQmathTablesRam)

   }
   */
    /* Uncomment the section below if calling the IQNasin() or IQasin()
       functions from the IQMath.lib library in order to utilize the
       relevant IQ Math table in Boot ROM (This saves space and Boot ROM
       is 1 wait-state). If this section is not uncommented, IQmathTables2
       will be loaded into other memory (SARAM, Flash, etc.) and will take
       up space, but 0 wait-state is possible.
    */
    /*
    IQmathTables3    : > IQTABLES3, PAGE = 0, TYPE = NOLOAD
    {

               IQmath.lib<IQNasinTable.obj> (IQmathTablesRam)

    }
    */

   /* .reset is a standard section used by the compiler.  It contains the */
   /* the address of the start of _c_int00 for C Code.   /*
   /* When using the boot ROM this section and the CPU vector */
   /* table is not needed.  Thus the default type is set here to  */
   /* DSECT  */
   .reset              : > RESET,      PAGE = 0, TYPE = DSECT
   vectors             : > VECTORS     PAGE = 0, TYPE = DSECT

}

/*
//===========================================================================
// End of file.
//===========================================================================
*/

四 总结:

1  这份程序还有很多不完善的地方,如:

A 进入发送模式、监控模式之后就进入永久循环,若要退出此模式必须通过断电的方式;

B 三个数码管无法分别显示不同内容;

C 某些地方程序相应有些慢

2 测量CAN端子处发现,对于主站来说,发送时其接收端电平为高(从站也是如此),固想要检测CAN总线上的电平可以直接通过将发送接收信号直接相与的方式。如下图:

 

而我的板子利用下图电路发送时,由于经过了与门,所以我在发送的同时也在接收自己发送的数据。波形如下图:

 

 

CCS-1: 基于28035的CAN监控模块

 

3 串口转USB电路:注意中间的发送接收不要接反

 

 

 

 

 

五 出现的问题:

1为什么ECanaRegs.CANRMP.all = = 0x00000008; 这句清不掉RMP3?

因为我用的 ==,应该用=

2 为什么MCU通过SPI发送的数据总是偏了一位?我发送0x00BC,低8位本来应该收到00111101,但数码管显示出来的是01111010。即少给了595一个脉冲。

分析发现,是SPI的CPOL CPHA设置有问题:我设置的是CPOL=0, CPHA=0(之前调STM32控制数码管时就是这样设置的);

修改为CPOL=1, CPHA=1 后问题解决。

为什么跟STM32的设置有区别呢?这里还没想明白。

3 为什么我按一下按键会减两个数?按我的想法应该是按一次,减一个数。

因为我在读取按键值时读的是SPIRXBUF中的内容,这个缓冲区的内容好像总是之后于SPIDAT和SPIRXEMU寄存器中的内容。最后更改为读取SPIDAT中的内容即可。

但是为什么SPIRXBUF中的内容与SPIDAT和SPIRXEMU中的内容不同步?这里还没想明白。

看TI 的SPI参考手册Page10 Figure 2. Serial Peripheral Interface Module Block Diagram,接收到的数据是先到SPIDAT,然后再到SPIRXBUF,但SPIRXEMU是SPIRXBUF的镜像,按道理数据应该是和SPIRXBUF一致的,但实际SPIRXEMU中的数据却是和SPIDAT中的数据保持一致。

4 28035的BOR POR的检测电压范围是多少?当内核电压1.8V波动很大时,如下图,XRS(内部复位)会一直处于低电平。

多加一些电容稳住内核电压即正常。

CCS-1: 基于28035的CAN监控模块

 

六 其余笔记

CCS-1: 基于28035的CAN监控模块

CCS-1: 基于28035的CAN监控模块

CCS-1: 基于28035的CAN监控模块

CCS-1: 基于28035的CAN监控模块

CCS-1: 基于28035的CAN监控模块

CCS-1: 基于28035的CAN监控模块

CCS-1: 基于28035的CAN监控模块