⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mscan12.c

📁 《嵌入式系统-使用HCS12微控制器的设计与应用》在CodeWarrior开发环境下的源程序。
💻 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 + -