📄 mscan12.c
字号:
//[MSCAN12.c]串行通信------------------------------------------------------*
//本文件包含: *
// (1)CANInit:CAN通信初始化 *
// (2)GetSNDBUF:查找空闲发送缓冲区 *
// (3)CANSND1DFRM:CAN发送1帧数据帧(数据长度<=8字节) *
// (4)CANRCV1FRM:CAN接收1帧数据帧 *
//-------------------------------------------------------------------------*
//头文件
#include "MSCAN12.h" //CAN通信头文件
//CANInit:CAN通信初始化----------------------------------------------------*
//功 能:CAN初始化 *
//参 数:无 *
//返 回:无 *
//说 明:在9.83M 外部晶振频率下将总线速率设为200kbps,节点标识符为0 *
// 双滤波方式,工作在查询方式 *
//-------------------------------------------------------------------------*
void CANInit(void)
{
CAN0CTL1 |= (1 << CANE); //MSCAN12模块使能
//初始化模式请求,并判断初始化应答位,INITACK为1则CAN模块已进入初始化
CAN0CTL0 |= (1 << INITRQ); // INITRQ=1,初始化请求
//等待应答
while ((CAN0CTL1 & (1<<INITACK)) == 0)
{
}
CAN0CTL1 &= ~(1 << CLKSRC); //MSCAN12时钟源选择外部晶振fmscan=9.83M
CAN0CTL1 |= (1 << LOOPB); //回环自测模式
CAN0CTL1 &= ~(1 << LISTEN); //禁止只听模式
CAN0BTR0 = CAN0BTR0V; //同步跳转宽度为1,预分频因子为5
CAN0BTR1 = CAN0BTR1V; //将位速率设置成 197kbps
CAN0IDAC = CAN0IDACV; //两个32位验收过滤器
CAN0IDAR0 = CAN0IDAR0V; //给接收验证码寄存器0-1赋值
CAN0IDAR1 = CAN0IDAR1V;
CAN0IDMR0 = CAN0IDMR0V; //给接收验证屏蔽寄存器0-1赋值
CAN0IDMR1 = CAN0IDMR1V;
CAN0TIER = CAN0TIERV; //设置中断方式
CAN0TIER = CAN0TIERV;
CAN0CTL0 &= ~(1<<INITRQ); //INITRQ=0,退出初始化模式
//等待应答
while ((CAN0CTL1 | (1<<INITACK)) == 1)
{
}
}
//CANSND1DFRM:CAN发送1帧数据-----------------------------------------------*
//功 能:CAN发送1帧数据(数据长度<=8) *
//参 数:ID---报文标识符 *
// DataBUF---报文数据区首址 *
// LEN---报文数据长度 *
//返 回:INT8U CANsnd1DFrm --- 发送成功与否标志, *
// =0,没有空闲发送缓冲区,发送不成功;=1,发送成功 *
//说明:在发送数据之前,先查询是否有空闲发送缓冲区,若无则不能发送,返回0 *
//-------------------------------------------------------------------------*
INT8U CANSND1DFRM(INT16U ID,INT8U * DataBUF, INT8U LEN)
{
INT8U i;
INT8U * addr; //发送缓冲区
INT8U BufNum = 0xFF; //空闲的发送缓冲区号
BufNum = GetSNDBUF(); //查找空闲的发送缓冲区
if (BufNum == 0xFF) //若返回0xff,则没有空闲的发送缓冲区
return 0; //没有空闲的发送缓冲区,发送不成功,返回0
switch(BufNum)
{
case 0:
CAN0TBSEL |= (1<<TXS0); //选中发送缓冲区0
break;
case 1:
CAN0TBSEL |= (1<<TXS1); //选中发送缓冲区1
break;
case 2:
CAN0TBSEL |= (1<<TXS2); //选中发送缓冲区2
break;
default:
break;
}
addr=(INT8U *)(&CAN0TXFG); //获得发送前台缓冲区首地址
//---------------------------------------------------------------------
//将报文按CAN格式进行封装并存入空闲发送缓冲区等待发送
addr[0] = (INT8U)(ID >> 8); //11位报文标识符高8位
addr[1] = ((INT8U)(ID)); //低3位
addr[1] &= ~(1 << RTR); //RTR=0,数据帧
addr[1] &= ~(1 << IDE); //IDE位=0
for(i = 0; i < LEN; i++)
addr[i+4] = DataBUF[i]; //数据赋值
addr[12] = LEN; //数据长度
//---------------------------------------------------------------------
//发送缓冲区相应TXE位写1清除该位来通知MSCAN12发送数据
switch(BufNum)
{
case 0:
CAN0TFLG |= (1<<TXF0); //发送缓冲区0准备就绪
break;
case 1:
CAN0TFLG |= (1<<TXF1); //发送缓冲区1准备就绪
break;
case 2:
CAN0TFLG |= (1<<TXF2); //发送缓冲区2准备就绪
break;
default:
break;
}
return (1); //数据成功写入空闲缓冲区,返回1
}
//GetSNDBUF:查找空闲发送缓冲区---------------------------------------------*
//功能:查找空闲发送缓冲区 *
//入口:无 *
//出口:空闲区号或0xFF *
//-------------------------------------------------------------------------*
INT8U GetSNDBUF(void)
{
INT8U bufbit = 0xFF; //空闲区号
//查找空闲的发送缓冲区
if ((CAN0TFLG & (1 << TXE0)) != 0)
{ //发送缓冲区0空
bufbit = 0;
}
else if ((CAN0TFLG & (1 << TXE1)) != 0)
{ //发送缓冲区1空
bufbit = 1;
}
else if ((CAN0TFLG & (1 << TXE2)) != 0)
{ //发送缓冲区2空
bufbit = 2;
}
return bufbit;//返回空闲区号
}
//CANRCV1FRM:CAN接收1帧数据------------------------------------------------*
//功 能:CAN接收1帧子程序 *
//参 数:无 *
//返 回:INT8U CANRCV1FRM---函数名,表示接收帧的情况, *
// =0xFF,未收到帧;=1,收到数据帧;=2,收到远程帧 *
// CANRCVBUF--若收到报文,为16字节报文缓冲区的首地址 *
//说 明:无 *
//-------------------------------------------------------------------------*
INT8U CANRCV1FRM(INT8U * CANRCVBUF)
{
INT8U i;
INT8U IDEFlag; //IDE标志
INT8U RTRFlag; //RTR标志
INT8U FrameFlag; //帧标志
INT8U * addr; //接收帧首地址
if ((CAN0RFLG &(1 << RXF)) == 0)
return 0xFF; //未收到数据,返回0xFF
//RXF=1,表示收到数据,取数据处理
addr = (INT8U *)(&CAN0RXFG);
for(i = 0; i < 16; i++)
CANRCVBUF[i] = addr[i]; //将CAN接收缓冲区中的数据取到临时缓冲区
CAN0RFLG = 0xFF; //清所有接收标志
//------判断是标准帧还是扩展帧-----------------------------------------
IDEFlag = (CANRCVBUF[1] & (1 << IDE)); //取标识符中IDE标志
if (IDEFlag == 0) //标准帧
{
RTRFlag = (CANRCVBUF[1] & (1 << RTR)); //取标识符中RTR标志
//判断是数据帧还是远程帧
FrameFlag = ((RTRFlag == 0)?DataFrm:RemoteFrm);
}
else //扩展帧
{
RTRFlag = (CANRCVBUF[3] & (1 << ERTR)); //取标识符中RTR标志
//判断是数据帧还是远程帧
FrameFlag = ((RTRFlag == 0)?DataFrm:RemoteFrm);
}
return FrameFlag; //返回数据帧标志(1)或远程帧(2)标志
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -