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

📄 mcp2515.c

📁 430配合数字电位器使用
💻 C
字号:
#include "msp430x14x.h"
#include "mcp2515.h"
//u8_t temp;
u8_t TxFrameID[2];              //发送帧ID
u8_t TxFrameDLC;
u8_t TxFrameData[8];

extern void delay(u32_t delaytime);
/* MCP2515 复位 */
void MCP2515_Reset(void)
{
  P3OUT &= 0xfe;                        // P3.0 CS 拉低,片选mcp2515
  TXBUF0=CMD_RESET;                   // 复位指令,TXBUF0即为U0TXBUF,是430的USART0的发送缓冲寄存器
  while(!(U0TCTL & TXEPT));           //  U0TCTL为USART0的发送控制寄存器。TXEPT=0,表示UTXBUF有数据或正在传;
                                      // TXEPT=1,UTXBUF空或SWRST=1,TXEPT=1,继续下一句
  P3OUT|=0x01;                        // P3.0 CS 拉高
  delay(100);
}

/* MCP2515 读寄存器 */
u8_t MCP2515_ReadReg(u8_t addr)
{
  P3OUT &= 0xfe;                       // P3.0 CS 拉低
  TXBUF0 = CMD_READ;
  while(!(U0TCTL & TXEPT));            
  TXBUF0 = addr;                       // 发送地址
  while(!(U0TCTL & TXEPT));            
  TXBUF0 = 0x00;                       // 据读指令,此字节为任意状态,这里定义为0x00
  while(!(U0TCTL & TXEPT));
  P3OUT |= 0x01;                       // P3.0 CS 拉高
  return RXBUF0;                       // RXBUF0即为U0RXBUF,是430的USART0的接收缓冲寄存器
}

/* MCP2515 写寄存器 */
void MCP2515_WriteReg(u8_t addr, u8_t data)
{
  P3OUT &= 0xfe;                       // P3.0 CS 拉低
  TXBUF0 = CMD_WRITE;                  
  while(!(U0TCTL & TXEPT));
  TXBUF0 = addr;
  while(!(U0TCTL & TXEPT));
  TXBUF0 = data;
  while(!(U0TCTL & TXEPT));
  P3OUT |= 0x01;                       // P3.0 CS 拉高
  
}


/* 顺序读寄存器 */
void MCP2515_ReadSeqReg(u8_t addr, u8_t *data, u8_t num)
{
  P3OUT &= 0xfe;                       // P3.0 CS 拉低
  TXBUF0 = CMD_READ;
  while(!(U0TCTL & TXEPT));
  TXBUF0 = addr;
  while(!(U0TCTL & TXEPT));
  for(u8_t i = 0; i < num; i++)
  {
    TXBUF0 = 0x00;
    while(!(U0TCTL & TXEPT));
    *data++ = RXBUF0;                  //此语句即为以下两个语句   *data = RXBUF0;
                                       //                          data = data+1;
  }
  P3OUT |= 0x01;                       // P3.0 CS 拉高
}
/* 顺序写寄存器 */
void MCP2515_WriteSeqReg(u8_t addr, u8_t *data, u8_t num)
{
  P3OUT &= 0xfe;                       // P3.0 CS 拉低
  TXBUF0 = CMD_WRITE;                  
  while(!(U0TCTL & TXEPT));
  TXBUF0 = addr;
  while(!(U0TCTL & TXEPT));
  for(u8_t i = 0; i < num; i++)
  {
    TXBUF0 = *data++;                 //此语句即为以下两个语句   TXBUF0 = *data;
                                      //                          data = data+1;
    while(!(U0TCTL & TXEPT));
  }
  P3OUT |= 0x01;                       // P3.0 CS 拉高
}


/* MCP2515 请求发送TX中内容 (cmd=0x81,请求发TXB0;cmd=0x82,请求发TXB1;cmd=0x84,请求发TXB2) */
void MCP2515_SndRequest(u8_t cmd)
{
  //u8_t temp;
  P3OUT &= 0xfe;                       // P3.0 CS 拉低
  TXBUF0 = cmd;                        
  while(!(U0TCTL & TXEPT));
  //temp = MCP2515_ReadReg(CANINTF);   // 读CAN状态寄存器内容
  P3OUT |= 0x01;                       // P3.0 CS 拉高
}
/* 修改后的发送标准帧函数 */
void sendStandardFrame(u8_t bufn, u8_t btPri, u8_t btFrameType, u8_t btModuleId, u8_t btChnId,u8_t btCommandType, u8_t btDlc, u8_t *data)
{
   u8_t size = btDlc & 0x0f;   
   TxFrameID[0] = (btPri | (btFrameType << 1) | btModuleId );
   TxFrameID[1] = ((btChnId <<5 )& 0xf7);
   TxFrameDLC = btDlc;
   TxFrameData[0] = btCommandType;
   for(u8_t i=1;i<size;i++)
   {
     TxFrameData[i]=data[i-1];
   }
   
   switch(bufn){
    case 0:
      MCP2515_WriteSeqReg(TXB0SIDH, TxFrameID, 2);     // 发送id,2字节,分别写入TXB0SIDH,TXB0SIDL
      MCP2515_WriteReg(TXB0DLC, TxFrameDLC);           // 发送数据长度,1字节,写入TXB0DLC
      MCP2515_WriteSeqReg(TXB0D0, TxFrameData, size);  // Can数据发送
      MCP2515_SndRequest(CMD_REQUEST0);                // 开始发送
      break;
    case 1:
      MCP2515_WriteSeqReg(TXB1SIDH, TxFrameID, 2);
      MCP2515_WriteReg(TXB1DLC, TxFrameDLC);
      MCP2515_WriteSeqReg(TXB1D0, TxFrameData, size);
      MCP2515_SndRequest(CMD_REQUEST1);
      break;
    case 2:
      MCP2515_WriteSeqReg(TXB2SIDH, TxFrameID, 2);
      MCP2515_WriteReg(TXB2DLC, TxFrameDLC);
      MCP2515_WriteSeqReg(TXB2D0, TxFrameData, size); 
      MCP2515_SndRequest(CMD_REQUEST2);
  }
}

/* MCP2515 位修改 0 屏蔽*/
void MCP2515_BitModify(u8_t addr, u8_t mask, u8_t data)
{
  P3OUT &= 0xfe;
  TXBUF0 = CMD_BITMODIFY;              // 位修改指令
  while(!(U0TCTL & TXEPT));
  TXBUF0 = addr;                       // 地址字节
  while(!(U0TCTL & TXEPT));
  TXBUF0 = mask;                       // 屏蔽字节
  while(!(U0TCTL & TXEPT));
  TXBUF0 = data;                       // 修改位
  while(!(U0TCTL & TXEPT));
  P3OUT |= 0x01;
}

/* MCP2515初始化 */
void MCP2515_Init(void)                    //只有在配置模式下,才能对器件进行初始化
{
   u8_t temp1,temp2;
    do{
       MCP2515_Reset();                    // 复位(在上电或复位时,器件会自动进入配置模式)
       temp1 = MCP2515_ReadReg(CANSTAT);   // 读CAN状态寄存器内容
       temp1 = temp1 >> 5;
       }while(temp1 != 0x04);              // 是否进入配置模式(若没有进入配置模式,一直进行复位)
    
    MCP2515_WriteReg(RXB0CTRL, 0x64);      // 接收所有帧,允许滚存(RXB0CTRL为接收缓冲器0控制寄存器)
    MCP2515_WriteReg(RXB1CTRL, 0x60);      // 接收所有帧          (RXB1CTRL为接收缓冲器1控制寄存器)
    MCP2515_WriteReg(RXM0SIDH, 0x00);     // 全通,不滤波         (RXM0SIDL验收屏蔽滤波器0标准标识符高位)
    MCP2515_WriteReg(RXM0SIDL, 0x00);     //                      (RXM0SIDL验收屏蔽滤波器0标准标识符低位)
    MCP2515_WriteReg(RXM1SIDH, 0x00);     //                      (RXM1SIDL验收屏蔽滤波器1标准标识符高位)
    MCP2515_WriteReg(RXM1SIDL, 0x00);     //                      (RXM1SIDL验收屏蔽滤波器1标准标识符低位)
    
    MCP2515_WriteReg(BFPCTRL, 0x0f);     // 缓冲器满引脚使能      (BFPCTRL为RXnBF引脚控制寄存器和状态寄存器)
    
    /* 125Kbps 8TQ*/
    /*
    MCP2515_WriteReg(CNF1, 0x07);        // BRP = 7  ,8TQ
    MCP2515_WriteReg(CNF2, 0x90);        // 采样1次, PS1 = 2TQ, 传播段 = 2TQ
    MCP2515_WriteReg(CNF3, 0x82);        // CLKOUT 为SOF, PS2 = 2TQ    
    */
    /* 250Kbps 16TQ*/  
    
    MCP2515_WriteReg(CNF1, 0x01);        // BRP = 1  ,16TQ    (4TQ)
    MCP2515_WriteReg(CNF2, 0xb1);        // 采样1次, PS1 = 7TQ, 传播段 = 2TQ
    MCP2515_WriteReg(CNF3, 0x85);        // CLKOUT 为SOF, PS2 = 6TQ 
    
    /* 500Kbps 8TQ*/
    /*
    MCP2515_WriteReg(CNF1, 0x01);        // BRP = 1 , 8TQ
    MCP2515_WriteReg(CNF2, 0x90);        // 采样1次, PS1 = 3TQ, 传播段 = 1TQ
    MCP2515_WriteReg(CNF3, 0x82);        // CLKOUT 为SOF, PS2 = 3TQ 
    */
    /* 500Kbps 16TQ*/
    /*
    MCP2515_WriteReg(CNF1, 0x00);        // BRP = 0 ,16TQ 
    MCP2515_WriteReg(CNF2, 0xb1);        // 采样1次, PS1 = 7TQ, 传播段 = 2TQ
    MCP2515_WriteReg(CNF3, 0x85);        // CLKOUT 为SOF, PS2 = 6TQ    
    */
     MCP2515_WriteReg(TXRTSCTRL, 0x00);   // 禁掉发送请求引脚(TXRTSCTRL为TXnRTS引脚控制和状态寄存器)
    _NOP();
    
    do{
        //MCP2515_WriteReg(CANCTRL,0x40); //for test
        MCP2515_WriteReg(CANCTRL, 0x00);  //正常工作模式(CANCTRL为CAN控制寄存器)
        temp2 = MCP2515_ReadReg(CANSTAT);
        temp2 = temp2 >> 5;
      }while(temp2 != 0x00);               // 是否进入正常模式
    _NOP();
    MCP2515_BitModify(TXB0CTRL, 0x03, 0x03);  // 最高优先级(TXB0CTRL为发送缓冲器0控制寄存器)
    //temp3 = MCP2515_ReadReg(TXB0CTRL);     // TXB0CTRL=0x03
    _NOP(); 
    MCP2515_WriteReg(CANINTF, 0x00);     // 清所有中断标志(CANINTF为中断标志寄存器)
    MCP2515_WriteReg(EFLG, 0x00);         //(EFLG为错误标志寄存器)
    MCP2515_WriteReg(CANINTE, 0x03);     // 中断使能 10100011 //enable rxe0 rxe1(CANINTE为中断使能寄存)
    _NOP();
}    

 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -