标题:
基于树莓派的can总线MCP2515驱动源程序(波形很好)
[打印本页]
作者:
jhaa9793
时间:
2018-4-21 01:51
标题:
基于树莓派的can总线MCP2515驱动源程序(波形很好)
工作项目用到了can总线,是在树莓派的板子上运行的。用的can芯片是mcp2515。效果还不错,波形很好。
0.png
(44.94 KB, 下载次数: 88)
下载附件
2018-4-21 02:04 上传
单片机源程序如下:
#define CAN_10Kbps 0x31
#define CAN_25Kbps 0x13
#define CAN_50Kbps 0x09
#define CAN_100Kbps 0x04
#define CAN_125Kbps 0x03
#define CAN_250Kbps 0x01
#define CAN_500Kbps 0x00
#define SCK 14
#define SI 12
#define SO 13
#define CS 10 //CE0
#define INTIN 3
#define RST 4
#define TXREQ_M 0b11110111
#define CH 0
#include "MCP2515.h"
#include "bcm2835.h"
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//#include <wiringPiSPI.h>
//采用bcm2835spi
void MCP2515_WriteByte(unsigned char addr,unsigned char dat)
{
unsigned char buf = CAN_WRITE;
unsigned char spiDat[] = {CAN_WRITE,addr,dat};
digitalWrite(CS,LOW); //置MCP2515的CS为低电平
bcm2835_spi_transfern(spiDat,3);
digitalWrite(CS,HIGH); //置MCP2515的CS为高电平
}
unsigned char MCP2515_ReadByte(unsigned char addr)
{
unsigned char rByte = 0;
unsigned char spiDat[] = {CAN_READ,addr,0xff};
digitalWrite(CS,LOW); //置MCP2515的CS为低电平
bcm2835_spi_transfern(spiDat,3);
digitalWrite(CS,HIGH); //置MCP2515的CS为高电平
rByte = spiDat[2];
return rByte; //返回读到的一个字节数据
}
void MCP2515_Reset(void)
{
digitalWrite(RST,LOW);
delay(100);
digitalWrite(RST,HIGH);
delay(100);
}
//void IntHandle()
//{
// char temp=0;
// //中断处理函数,MCU清除中断FLAG,重新使能INTE,并且输出RXB
// //digitalWrite(28,HIGH);
// printf("into the interrupt mode\nINT-IN is: %d\n",digitalRead(INTIN));
//// temp = MCP2515_ReadByte(CANINTF);
// //MCP2515_WriteByte(CANINTF,0x00);
// printf("into the interrupt mode\nINT-IN is: %d\n",digitalRead(INTIN));
// printf("RXB0SIDH : %02x\n",MCP2515_ReadByte(RXB0SIDH));
// printf("RXB0SIDL : %02x\n",MCP2515_ReadByte(RXB0SIDL));
// printf("RXB0D0 : %02x\n",MCP2515_ReadByte(RXB0D0));
// printf("RXB0D1 : %02x\n",MCP2515_ReadByte(RXB0D1));
// printf("RXB0D2 : %02x\n",MCP2515_ReadByte(RXB0D2));
// printf("RXB0D3 : %02x\n",MCP2515_ReadByte(RXB0D3));
// printf("RXB0D4 : %02x\n",MCP2515_ReadByte(RXB0D4));
// printf("RXB0D5 : %02x\n",MCP2515_ReadByte(RXB0D5));
// printf("RXB0D6 : %02x\n",MCP2515_ReadByte(RXB0D6));
// printf("RXB0D7 : %02x\n",MCP2515_ReadByte(RXB0D7));
// printf("\n\n");
// exit(1);
//}
void MCP2515_Init(void)
{
unsigned char temp=1;
MCP2515_Reset(); //发送复位指令软件复位MCP2515
printf("Reset OK \n");
// delay(1); //Delay_Nms(1); //通过软件延时约nms(不准确)
//设置波特率为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(RXB0CTRL,0x20);//接收 过滤器信息
MCP2515_WriteByte(RXB0DLC,DLC_8);//设置接收数据的长度为8个字节
MCP2515_WriteByte(RXF0SIDH,0x12);//配置验收滤波寄存器n标准标识符高位
MCP2515_WriteByte(RXF0SIDL,0x11);//配置验收滤波寄存器n标准标识符低位
MCP2515_WriteByte(RXM0SIDH,0xFF);//配置验收屏蔽寄存器n标准标识符高位
MCP2515_WriteByte(RXM0SIDL,0xE0);//配置验收屏蔽寄存器n标准标识符低位
// MCP2515_WriteByte(RXB0SIDH,0x00);//清空接收缓冲器0的标准标识符高位
// MCP2515_WriteByte(RXB0SIDL,0x00);//清空接收缓冲器0的标准标识符低位
MCP2515_WriteByte(CANINTE,0x01);//配置CAN中断使能寄存器的接收缓冲器0满中断使能,其它位禁止中断
MCP2515_WriteByte(CANINTF,0x00);//清空CAN中断标志寄存器的所有位(必须由MCU清空)
MCP2515_WriteByte(CANCTRL,REQOP_LOOPBACK|CLKOUT_ENABLED);//将MCP2515设置为环回模式,退出配置模式
temp=MCP2515_ReadByte(CANSTAT);//读取CAN状态寄存器的值
while(OPMODE_LOOPBACK!=(temp & 0xE0))//判断MCP2515是否已经进入环回模式
{
//MCP2515_WriteByte(CANCTRL,REQOP_LOOPBACK|CLKOUT_ENABLED);//再次将MCP2515设置为环回模式,退出配置模式
temp=MCP2515_ReadByte(CANSTAT);
}
printf("MCP2515 loopback mode OK\n");
}
void LOOPTest()
{
printf("LoopTest begin\n");
MCP2515_WriteByte(TXB0DLC,DLC_8);//设置发送数据长度为8
MCP2515_WriteByte(TXB0SIDH,0x12);//发送缓冲器0标准标识符高位
MCP2515_WriteByte(TXB0SIDL,0x11);//发送缓冲器0标准标识符低位
MCP2515_WriteByte(TXB0CTRL,0x02); //高优先级
MCP2515_WriteByte(TXB0D0,0x83); //数据
MCP2515_WriteByte(TXB0D1,0x83);
MCP2515_WriteByte(TXB0D2,0x83);
MCP2515_WriteByte(TXB0D3,0x87);
MCP2515_WriteByte(TXB0D4,0x87);
MCP2515_WriteByte(TXB0D5,0x87);
MCP2515_WriteByte(TXB0D6,0x84);
MCP2515_WriteByte(TXB0D7,0x84);
printf("TXB0D0 : %02x\n",MCP2515_ReadByte(TXB0D0));
printf("TXB0D1 : %02x\n",MCP2515_ReadByte(TXB0D1));
printf("TXB0D2 : %02x\n",MCP2515_ReadByte(TXB0D2));
printf("TXB0D3 : %02x\n",MCP2515_ReadByte(TXB0D3));
printf("TXB0D4 : %02x\n",MCP2515_ReadByte(TXB0D4));
printf("TXB0D5 : %02x\n",MCP2515_ReadByte(TXB0D5));
printf("TXB0D6 : %02x\n",MCP2515_ReadByte(TXB0D6));
printf("TXB0D7 : %02x\n",MCP2515_ReadByte(TXB0D7));
printf("RXB0SIDH : %02x\n",MCP2515_ReadByte(RXB0SIDH));
printf("RXB0SIDL : %02x\n",MCP2515_ReadByte(RXB0SIDL));
printf("RXB0D0 : %02x\n",MCP2515_ReadByte(RXB0D0));
printf("RXB0D1 : %02x\n",MCP2515_ReadByte(RXB0D1));
printf("RXB0D2 : %02x\n",MCP2515_ReadByte(RXB0D2));
printf("RXB0D3 : %02x\n",MCP2515_ReadByte(RXB0D3));
printf("RXB0D4 : %02x\n",MCP2515_ReadByte(RXB0D4));
printf("RXB0D5 : %02x\n",MCP2515_ReadByte(RXB0D5));
printf("RXB0D6 : %02x\n",MCP2515_ReadByte(RXB0D6));
printf("RXB0D7 : %02x\n",MCP2515_ReadByte(RXB0D7));
printf("\n\n");
char temp = 0;
temp = MCP2515_ReadByte(TXB0CTRL);
MCP2515_WriteByte(TXB0CTRL,(temp| (~TXREQ_M ))); //请求发送
int cnt = 0;
while(MCP2515_ReadByte(TXB0CTRL)&(0b00001000) != 0x00)
{
cnt++;
if(cnt>=100000)
{
printf("trasmission failed\n");
exit(1);
}
}
delay(100);
printf("RXB0SIDH : %02x\n",MCP2515_ReadByte(RXB0SIDH));
printf("RXB0SIDL : %02x\n",MCP2515_ReadByte(RXB0SIDL));
printf("RXB0D0 : %02x\n",MCP2515_ReadByte(RXB0D0));
printf("RXB0D1 : %02x\n",MCP2515_ReadByte(RXB0D1));
printf("RXB0D2 : %02x\n",MCP2515_ReadByte(RXB0D2));
printf("RXB0D3 : %02x\n",MCP2515_ReadByte(RXB0D3));
printf("RXB0D4 : %02x\n",MCP2515_ReadByte(RXB0D4));
printf("RXB0D5 : %02x\n",MCP2515_ReadByte(RXB0D5));
printf("RXB0D6 : %02x\n",MCP2515_ReadByte(RXB0D6));
printf("RXB0D7 : %02x\n",MCP2515_ReadByte(RXB0D7));
printf("\n\n");
}
void bcm2835_SPISetup(void)
{
if (!bcm2835_init())
{
printf("bcm2835_init failed. Are you running as root??\n");
exit(1);
}
if (!bcm2835_spi_begin())
{
printf("bcm2835_spi_begin failed. Are you running as root??\n");
exit(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
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
MCP2515.rar
(25.34 KB, 下载次数: 116)
2018-4-21 01:50 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
kenchen
时间:
2018-4-24 22:50
感谢楼主热心分享
作者:
jiawei_zhong
时间:
2018-5-14 16:40
感谢楼主热心分享!!!
作者:
jiawei_zhong
时间:
2018-5-14 16:59
非常感谢楼主分享,我找了好多地方,都不是专门针对树莓派。自己写因为不熟悉又太花时间了
作者:
北纬30度
时间:
2018-7-30 13:00
挺好的 参考参考
作者:
lalalala256
时间:
2018-8-13 11:43
谢谢分享,
作者:
ZTG_5930
时间:
2018-9-17 16:30
楼主好,很感谢你的分享。但是我想问一下那个printf()串口打印是MCP2515和CAN收发器之间的CAN串口,还是单纯的MCU的串口。谢谢
作者:
ZTG_5930
时间:
2018-9-17 16:31
请回复一下,初学者2677957815
作者:
hongyeluzhu
时间:
2018-12-11 16:43
谢谢分享
作者:
askloser
时间:
2019-1-14 13:12
謝謝分享, 學習一下
作者:
xiguaxiao
时间:
2019-1-20 10:38
多谢楼主分享
作者:
snni00
时间:
2019-5-7 14:15
正好需要扩一路CAN,感谢分享
作者:
捍卫者
时间:
2019-11-18 13:57
感谢楼主热心分享
作者:
contactdeshine
时间:
2020-5-19 20:39
非常感谢,热心分享
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1