一 程序目的
1 用CAN来监控主、从站间的通信数据,并传到电脑上。其中CAN,SCI的波特率,SCI的数据格式可调,并通过数码管显示;
2 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总线上的电平可以直接通过将发送接收信号直接相与的方式。如下图:
而我的板子利用下图电路发送时,由于经过了与门,所以我在发送的同时也在接收自己发送的数据。波形如下图:
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(内部复位)会一直处于低电平。
多加一些电容稳住内核电压即正常。
六 其余笔记