树莓派3b(ubuntu16.04)使用MCP2515

1、首先在系统上添加spi驱动(请参考以前的教程)
2、安装bcm2835 C library
树莓派3b的引脚图:
树莓派3b(ubuntu16.04)使用MCP2515_第1张图片
这里选用11脚作为CS信号。
3、下载bcm2835-1.50.tar.gz文件
解压后在examples\spi文件夹里有spi的使用历程
4、编写MCP2515.c
/*********************************************************************
* 函数名 : SPI_ReadByte
* 描述 : 通过SPI读取一个字节数据
* 输入 : 无
* 输出 : 无
* 返回值 : rByte(读取到的一个字节数据)
* 说明 : 无
*********************************************************************/
unsigned char SPI_ReadByte(void)
{
return bcm2835_spi_transfer(0xFF);
}

/*********************************************************************
* 函数名 : SPI_SendByte
* 描述 : SPI发送一个字节数据
* 输入 : dt:待发送的数据
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*********************************************************************/
void SPI_SendByte(unsigned char dt)
{
bcm2835_spi_transfer(dt);
}

/*********************************************************************
* 函数名 : MCP2515_WriteByte
* 描述 : 通过SPI向MCP2515指定地址寄存器写1个字节数据
* 输入 : addr:MCP2515寄存器地址,dat:待写入的数据
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*********************************************************************/
void MCP2515_WriteByte(unsigned char addr,unsigned char dat)
{
bcm2835_gpio_write(MCP2515_CS,LOW);//置MCP2515的CS为低电平
SPI_SendByte(CAN_WRITE); //发送写命令
SPI_SendByte(addr); //发送地址
SPI_SendByte(dat); //写入数据
bcm2835_gpio_write(MCP2515_CS,HIGH);//置MCP2515的CS为高电平
}

/*********************************************************************
* 函数名 : MCP2515_ReadByte
* 描述 : 通过SPI从MCP2515指定地址寄器读1个字节数据
* 输入 : addr:MCP2515寄存器地址
* 输出 : 无
* 返回值 : rByte:读取到寄存器的1个字节数据
* 说明 : 无
*********************************************************************/
unsigned char MCP2515_ReadByte(unsigned char addr)
{
unsigned char rByte;

bcm2835_gpio_write(MCP2515_CS,LOW);             //置MCP2515的CS为低电平
SPI_SendByte(CAN_READ);     //发送读命令
SPI_SendByte(addr);         //发送地址
rByte=SPI_ReadByte();       //读取数据
bcm2835_gpio_write(MCP2515_CS,HIGH);                //置MCP2515的CS为高电平
return rByte;               //返回读到的一个字节数据

}

/*********************************************************************
* 函数名 : MCP2515_Reset
* 描述 : 发送复位指令软件复位MCP2515
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 将内部寄存器复位为缺省状态,并将器件设定为配置模式
*********************************************************************/
void MCP2515_Reset(void)
{
bcm2835_gpio_write(MCP2515_CS,LOW); //置MCP2515的CS为低电平
SPI_SendByte(CAN_RESET); //发送寄存器复位命令
bcm2835_gpio_write(MCP2515_CS,HIGH); //置MCP2515的CS为高电平
}

/*********************************************************************
* 函数名 : MCP2515_Init
* 描述 : MCP2515初始化配置
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 初始化包括:软件复位、工作波特率设置、标识符相关配置等。
*********************************************************************/
int MCP2515_Init(void)
{
unsigned char temp=0;

if (!bcm2835_init())
{
  printf("bcm2835_init failed. Are you running as root??\n");
  return 1;
}

if (!bcm2835_spi_begin())
{
  printf("bcm2835_spi_begin failedg. Are you running as root??\n");
  return 1;
}
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);      // The default
bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);                   // The default 上跳沿或下跳沿的选择
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default  时钟速率
bcm2835_spi_chipSelect(BCM2835_SPI_CS0);                      // The default  片选信号
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);      // the default

bcm2835_gpio_fsel(MCP2515_CS, BCM2835_GPIO_FSEL_OUTP);

MCP2515_Reset();    //发送复位指令软件复位MCP2515
bcm2835_delay(5);

//设置波特率为125Kbps
//set CNF1,SJW=00,长度为1TQ,BRP=49,TQ=[2*(BRP+1)]/Fsoc=2*50/8M=12.5us
MCP2515_WriteByte(CNF1,CAN_125Kbps);
//set CNF2,SAM=0,在采样点对总线进行一次采样,PHSEG1=(2+1)TQ=3TQ,PRSEG=(0+1)TQ=1TQ
MCP2515_WriteByte(CNF2,0x80|PHSEG1_3TQ|PRSEG_1TQ);
//set CNF3,PHSEG2=(2+1)TQ=3TQ,同时当CANCTRL.CLKEN=1时设定CLKOUT引脚为时间输出使能位
MCP2515_WriteByte(CNF3,PHSEG2_3TQ);

MCP2515_WriteByte(TXB0SIDH,0xFF);//发送缓冲器0标准标识符高位
MCP2515_WriteByte(TXB0SIDL,0xE0);//发送缓冲器0标准标识符低位

MCP2515_WriteByte(RXB0SIDH,0x00);//清空接收缓冲器0的标准标识符高位
MCP2515_WriteByte(RXB0SIDL,0x00);//清空接收缓冲器0的标准标识符低位
MCP2515_WriteByte(RXB0CTRL,0x20);//仅仅接收标准标识符的有效信息
MCP2515_WriteByte(RXB0DLC,DLC_8);//设置接收数据的长度为8个字节

MCP2515_WriteByte(RXF0SIDH,0xFF);//配置验收滤波寄存器n标准标识符高位
MCP2515_WriteByte(RXF0SIDL,0xE0);//配置验收滤波寄存器n标准标识符低位
MCP2515_WriteByte(RXM0SIDH,0xFF);//配置验收屏蔽寄存器n标准标识符高位
MCP2515_WriteByte(RXM0SIDL,0xE0);//配置验收屏蔽寄存器n标准标识符低位

MCP2515_WriteByte(CANINTF,0x00);//清空CAN中断标志寄存器的所有位(必须由MCU清空)
MCP2515_WriteByte(CANINTE,0x01);//配置CAN中断使能寄存器的接收缓冲器0满中断使能,其它位禁止中断

MCP2515_WriteByte(CANCTRL,REQOP_LOOPBACK|CLKOUT_ENABLED);//将MCP2515设置为环回模式,退出配置模式

temp=MCP2515_ReadByte(CANSTAT);//读取CAN状态寄存器的值
if(OPMODE_NORMAL!=(temp&&0xE0))//判断MCP2515是否已经进入环回模式
{
    MCP2515_WriteByte(CANCTRL,REQOP_LOOPBACK|CLKOUT_ENABLED);//再次将MCP2515设置为环回模式,退出配置模式
}
return 0;

}

void MCP2515_End(void)
{
bcm2835_spi_end();
bcm2835_close();
}
/*********************************************************************
* 函数名 : CAN_Send_Buffer
* 描述 : CAN发送指定长度的数据
* 输入 : *CAN_TX_Buf(待发送数据缓冲区指针),len(待发送数据长度)
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*********************************************************************/
void CAN_Send_Buffer(unsigned char *CAN_TX_Buf,unsigned char len)
{
unsigned char j,dly,count;

count=0;
while(count=len) break;
    }
    MCP2515_WriteByte(TXB0DLC,j);//将本帧待发送的数据长度写入发送缓冲器0的发送长度寄存器
    bcm2835_gpio_write(MCP2515_CS,LOW);
    MCP2515_WriteByte(TXB0CTRL,0x08);//请求发送报文
    bcm2835_gpio_write(MCP2515_CS,HIGH);
}

}

/*********************************************************************
* 函数名 : CAN_Receive_Buffer
* 描述 : CAN接收一帧数据
* 输入 : *CAN_TX_Buf(待接收数据缓冲区指针)
* 输出 : 无
* 返回值 : len(接收到数据的长度,0~8字节)
* 说明 : 无
*********************************************************************/
unsigned char CAN_Receive_Buffer(unsigned char *CAN_RX_Buf)
{
unsigned char i=0,len=0,temp=0;

temp = MCP2515_ReadByte(CANINTF);
if(temp & 0x01)
{
    len=MCP2515_ReadByte(RXB0DLC);//读取接收缓冲器0接收到的数据长度(0~8个字节)
    while(i

}

5、测试程序test.c
int main(int argc, char const *argv[])
{
unsigned char bufTx[8] = “87654321”;
unsigned char len = 8;
unsigned char bufRx[8] ;
if(1 == MCP2515_Init()){
return 1;
}

CAN_Send_Buffer(bufTx,len);

len = CAN_Receive_Buffer(bufRx);

printf("len = %d  bufRx=%s\n",len,bufRx);

return 0;

}

6、编写makefile
OBJECTS = test.o MCP2515.o
LIBS = bcm2835

all : (OBJECTS)gccotest (OBJECTS) -l$(LIBS)

clean :
rm *.o
7、make all 编译生产test可执行文件
8、sudo ./test
这里写图片描述
这里使用的是mcp2515的回环模式
其他模式可以参考手册进行设置。

你可能感兴趣的:(树莓派,ROS,mcp2515)