📄 12.2.c
字号:
/**************************************************************
**功能描述: 2812ECAN通信程序程序,用于两块实验开发板间的相互控制**
**************************************************************/
#include "DSP28_Device.h"
Uint32 TestMbox1 = 0;
Uint32 TestMbox2 = 0;
Uint32 TestMbox3 = 0;
void CAN_INIT()
{
struct ECAN_REGS ECanaShadow;
EALLOW;
GpioMuxRegs.GPFMUX.bit.CANTXA_GPIOF6 = 1; // 设置GPIOF6为CANTX
GpioMuxRegs.GPFMUX.bit.CANRXA_GPIOF7 = 1; // 设置GPIOF7为CANRX
EDIS;
/*eCAN 控制寄存器需要32位访问。如果想向一个单独位进行写操作,编译器可能会使其进入16位访问。这儿引用了一种解决方法,就是用影子寄存器迫使进行32位访问。 把整个寄存器读入一个影子寄存器。 这个访问将是32位的。用32位写操作改变需要改的位,然后把该值拷贝回eCAN寄存器*/
EALLOW;
ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all; // 把CANTIOC读入影子寄存器
ECanaShadow.CANTIOC.bit.TXFUNC = 1; // 外部引脚I/O使能标志位。
// TXFUNC=1 CANTX引脚被用于CAN发送功能。
// TXFUNC=0 CANTX引脚被作为通用I/O引脚被使用
ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all; // 把配置好的寄存器值回写
ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all; // 把CANRIOC读入影子寄存器
ECanaShadow.CANRIOC.bit.RXFUNC = 1; // 外部引脚I/O使能标志位。
// RXFUNC=1 CANRX引脚被用于CAN接收功能。
// RXFUNC=0 CANRX引脚被作为通用I/O引脚被使用。
ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all; // 把配置好的寄存器值回写
EDIS;
// 在配置邮箱ID值之前,CANME对应的位必须复位,
// 如果CANME寄存器中对应的位被置位,则ID写入操作无效。
ECanaRegs.CANME.all = 0; // 复位所有的邮箱
ECanaMboxes.MBOX0.MID.all = 0x15100000; // 配置发送邮箱0的ID:标识符11位
ECanaMboxes.MBOX1.MID.all = 0x15100000; // 配置发送邮箱1的ID:标识符11位
ECanaMboxes.MBOX16.MID.all = 0x15200000; // 确定接收邮箱16的ID
// 把邮箱0~15 配置为发送邮箱 , 把邮箱16~31 配置为接收邮箱
ECanaRegs.CANMD.all = 0xFFFF0000;
ECanaRegs.CANME.all = 0xFFFFFFFF; // CAN模块使能对应的邮箱,
ECanaMboxes.MBOX0.MCF.bit.DLC = 8;
ECanaMboxes.MBOX1.MCF.bit.DLC = 8; // 把发送,接收数据的长度定义为8位
ECanaMboxes.MBOX0.MCF.bit.RTR = 0; // 无远程帧请求
// 因为RTR位在复位后状态不定,因此在程序进行初始化的时候必须对该位赋值。
ECanaMboxes.MBOX1.MCF.bit.RTR = 0;
// 把待发送的数据写入发送邮箱
ECanaMboxes.MBOX0.MDRL.all = 0x55555555;
ECanaMboxes.MBOX0.MDRH.all = 0x55555501;
ECanaMboxes.MBOX1.MDRL.all = 0x55555555;
ECanaMboxes.MBOX1.MDRH.all = 0x55555502;
EALLOW;
// 邮箱中断屏蔽寄存器。上电后所有的中断屏蔽位都清零且中断被停止使能。
// 这些位允许独立屏蔽任何邮箱中断。
ECanaRegs.CANMIM.all = 0xFFFFFFFF;
// CANMIM .BIT.X=1 邮箱中断被使能(X=1~31)
// CANMIM .BIT.X=0 邮箱中断被禁止(X=1~31)
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all; // 把CANMC读入影子寄存器
ECanaShadow.CANMC.bit.CCR = 1; // 改变配置请求位
ECanaShadow.CANMC.bit.SCM = 1; // eCAN模式,所有邮箱使能
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all; // 把配置好的寄存器值回写
EDIS;
/*CPU要求对配置寄存器CANBTC和SCC的接收屏蔽寄存器(CANGAM,LAM[0]和LAM[3])进行写操作。对该位置位后,CPU必须等待,直到CANES寄存器的CCE标志位在送入CANBTC寄存器之前为1 */
do
{
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
} while(ECanaShadow.CANES.bit.CCE != 1 ); // 当CCE=1时可以对CANBTC进行操作。
// 配置波特率
EALLOW;
ECanaShadow.CANBTC.all = ECanaRegs.CANBTC.all; // 把CANBTC读入影子寄存器
ECanaShadow.CANBTC.bit.BRP = 149; // (BRP+1)=150, 最小时间单位TQ=1us
ECanaShadow.CANBTC.bit.TSEG2 = 2; // 位定时bit-time=(TSEG1+1)+(TSEG1+1)+1
ECanaShadow.CANBTC.bit.TSEG1 = 3; // bit-time=8us, 所以波特率为125Kpbs
ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all; // 把配置好的寄存器值回写
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all; // 把CANMC读入影子寄存器
ECanaShadow.CANMC.bit.CCR = 0 ; // 设置CCR=0,请求正常模式
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all; // 把配置好的寄存器值回写
EDIS;
do
{
ECanaShadow.CANES.all = ECanaRegs.CANES.all;
} while(ECanaShadow.CANES.bit.CCE != 0 ); // 等待 CCE 位被清零
EALLOW;
ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
ECanaShadow.CANMC.bit.STM = 0; // 配置CAN 为正常模式
// CANMC.bit.STM=0,正常模式
// CANMC.bit.STM=1,自测试模式
ECanaShadow.CANMC.bit.SCM = 1; // 选择HECC模式
ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
EDIS;
}
// 该函数读出邮箱序号(MBXnbr)指示的邮箱内容.
void mailbox_read(int16 MBXnbr)
{
volatile struct MBOX *Mailbox;
Mailbox = &ECanaMboxes.MBOX0 + MBXnbr;
TestMbox1 = Mailbox->MDRL.all; // 读出当前邮箱数据低4字节
TestMbox2 = Mailbox->MDRH.all; // 读出当前邮箱数据高4字节
TestMbox3 = Mailbox->MID.all; // 读出当前邮箱ID
}
void IOinit(void)
{
EALLOW;
// 将GPIOE0~GPIOE2配置为一般I/O端口输出,作138译码
GpioMuxRegs.GPEMUX.all = GpioMuxRegs.GPEMUX.all&0xfff8;
GpioMuxRegs.GPEDIR.all = GpioMuxRegs.GPEDIR.all|0x0007;
// 将GPIOB8~GPIOB15配置为一般I/O端口,D0~D7
GpioMuxRegs.GPBMUX.all = GpioMuxRegs.GPBMUX.all&0x00ff;
EDIS;
}
int KeyIn(void)
{
unsigned long int i = 0;
EALLOW;
// 将GPIOB8~GPIOB15配置为输入,D0~D7
GpioMuxRegs.GPBDIR.all = GpioMuxRegs.GPBDIR.all&0x00ff;
EDIS;
GpioDataRegs.GPEDAT.all = 0xfff8; // 选通键盘低8位
for (i=0; i<100; i++){} // 延时
// 判S1是否按下
if ((GpioDataRegs.GPBDAT.all|0x00ff)==0xfeff)
{
for (i=0; i<100000; i++){} // 延时消抖动
if ((GpioDataRegs.GPBDAT.all|0x00ff)==0xfeff)
{
while ((GpioDataRegs.GPBDAT.all|0x00ff)==0xfeff) // 判S1是否断开
{
GpioDataRegs.GPDDAT.bit.GPIOD1 = !GpioDataRegs.GPDDAT.bit.GPIOD1;
for (i=0; i<1000; i++){}
}
return (1);
}
}
// 判S2是否按下
if ((GpioDataRegs.GPBDAT.all|0x00ff)==0xfdff)
{
for (i=0; i<100000; i++){} // 延时消抖动
if ((GpioDataRegs.GPBDAT.all|0x00ff)==0xfdff)
{
while ((GpioDataRegs.GPBDAT.all|0x00ff)==0xfdff) // 判S2是否断开
{
GpioDataRegs.GPDDAT.bit.GPIOD1 = !GpioDataRegs.GPDDAT.bit.GPIOD1;
for (i=0; i<1000; i++){}
}
return (2);
}
}
return (0);
}
void LedOut(Uint16 led)
{
unsigned long int i = 0;
EALLOW;
// 将GPIOB8~GPIOB15配置为输出,D0~D7
GpioMuxRegs.GPBDIR.all = GpioMuxRegs.GPBDIR.all|0xff00;
EDIS;
GpioDataRegs.GPEDAT.all = 0xfffb; // LEDB清零
GpioDataRegs.GPBDAT.all =-led;
for (i=0; i<100; i++){} // 延时
GpioDataRegs.GPEDAT.all = 0xffff; // 锁存高8位
GpioDataRegs.GPEDAT.all = 0xfffa; // LEDA清零
GpioDataRegs.GPBDAT.all =-(led<<8);
for (i=0; i<100; i++){}
GpioDataRegs.GPEDAT.all = 0xffff; // 锁存低8位
}
void main(void)
{
Uint16 dis = 0x0000;
InitSysCtrl(); // 系统初始化程序,该子程序在DSP28_sysctrl.c中
DINT; // 关闭总中断
IER = 0x0000; // 关闭外设中断
IFR = 0x0000; // 请中断标志
CAN_INIT();
IOinit();
LedOut(dis);
while(1)
{
if (KeyIn() = = 1)
{
ECanaRegs.CANTRS.all = 0x00000001;
// while(ECanaRegs.CANTA.all != 0x00000001) {};
ECanaRegs.CANTA.all = 0x0000FFFF;
}
if (KeyIn() = = 2)
{
ECanaRegs.CANTRS.all = 0x00000002;
// while(ECanaRegs.CANTA.all != 0x00000002) {};
ECanaRegs.CANTA.all = 0x0000FFFF;
}
if(ECanaRegs.CANRMP.all = = 0x00010000)
{
ECanaRegs.CANRMP.all = 0xFFFF0000;
mailbox_read(16);
if (TestMbox2 = = 0x55555501)
{
dis = dis+1;
LedOut(dis);
}
if (TestMbox2 = = 0x55555502)
{
dis = dis-1;
LedOut(dis);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -