树莓派通过spi发送数据c语言,树莓派利用MCP2515实现SPI转CAN通信(C语言)

#include

#include

#include

#include "mcp2515_new.h"

#include "MCP2515.h"

#define MCP2515_CS 8

unsigned char SPI_ReadByte(void)

{

return bcm2835_spi_transfer(0xFF);

}

void SPI_SendByte(unsigned char dt)

{

bcm2835_spi_transfer(dt);

}

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为高电平

}

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; //返回读到的一个字节数据

}

void MCP2515_Reset(void)

{

bcm2835_gpio_write(MCP2515_CS,LOW); //置MCP2515的CS为低电平

SPI_SendByte(CAN_RESET); //发送寄存器复位命令

bcm2835_gpio_write(MCP2515_CS,HIGH); //置MCP2515的CS为高电平

}

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_500Kbps);

//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,0x09);//发送缓冲器0标准标识符高位

// MCP2515_WriteByte(TXB0SIDL,0x20);//发送缓冲器0标准标识符低位

MCP2515_WriteByte(RXB0SIDH,0x00);//清空接收缓冲器0的标准标识符高位

MCP2515_WriteByte(RXB0SIDL,0x00);//清空接收缓冲器0的标准标识符低位

MCP2515_WriteByte(RXB0CTRL,0x20);//仅仅接收标准标识符的有效信息

MCP2515_WriteByte(RXB0DLC,DLC_8);//设置接收数据的长度为8个字节

MCP2515_WriteByte(RXF0SIDH,0x00);//配置验收滤波寄存器n标准标识符高位

MCP2515_WriteByte(RXF0SIDL,0x00);//配置验收滤波寄存器n标准标识符低位

MCP2515_WriteByte(RXM0SIDH,0x00);//配置验收屏蔽寄存器n标准标识符高位

MCP2515_WriteByte(RXM0SIDL,0x00);//配置验收屏蔽寄存器n标准标识符低位

MCP2515_WriteByte(CANINTF,0x00);//清空CAN中断标志寄存器的所有位(必须由MCU清空)

MCP2515_WriteByte(CANINTE,0x01);//配置CAN中断使能寄存器的接收缓冲器0满中断使能,其它位禁止中断

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

temp=MCP2515_ReadByte(CANSTAT);//读取CAN状态寄存器的值

if(OPMODE_NORMAL!=(temp&&0xE0))//判断MCP2515是否已经进入环回模式

{

MCP2515_WriteByte(CANCTRL,REQOP_NORMAL|CLKOUT_ENABLED);//再次将MCP2515设置为正常模式,退出配置模式

}

return 0;

}

void MCP2515_End(void)

{

bcm2835_spi_end();

bcm2835_close();

}

void CAN_Send_Buffer(unsigned char *CAN_TX_Buf,unsigned char len, unsigned char msgID)

{

unsigned char j,dly,count;

count=0;

MCP2515_WriteByte(TXB0SIDH, (msgID>>3)&0x1F);

MCP2515_WriteByte(TXB0SIDL, (msgID<<5)&0xE0);

while(count

{

dly=0;

while((MCP2515_ReadByte(TXB0CTRL)&0x08) && (dly<50))//快速读某些状态指令,等待TXREQ标志清零

{

bcm2835_delay(1);//通过软件延时约nms(不准确)

dly++;

}

for(j=0;j<8;)

{

MCP2515_WriteByte(TXB0D0+j,CAN_TX_Buf[count++]);//将待发送的数据写入发送缓冲寄存器

j++;

if(count>=len) break;

}

MCP2515_WriteByte(TXB0DLC,j);//将本帧待发送的数据长度写入发送缓冲器0的发送长度寄存器

bcm2835_gpio_write(MCP2515_CS,LOW);

MCP2515_WriteByte(TXB0CTRL,0x08);//请求发送报文

bcm2835_gpio_write(MCP2515_CS,HIGH);

}

}

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

{

CAN_RX_Buf[i]=MCP2515_ReadByte(RXB0D0+i);//把CAN接收到的数据放入指定缓冲区

i++;

}

CAN_RX_Buf[i]=(((MCP2515_ReadByte(RXB0SIDH))<<3) | ((MCP2515_ReadByte(RXB0SIDL))>>5));

}

MCP2515_WriteByte(CANINTF,0);//清除中断标志位(中断标志寄存器必须由MCU清零)

return len;

}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值