历史上的今天

今天是:2024年08月27日(星期二)

正在发生

2020年08月27日 | PIC16F887 SPI CAN 传输,操作MCP2515

发布者:GHR2596 来源: eefocus关键字:PIC16F887  SPI  CAN  传输  操作MCP2515 手机看文章 扫描二维码
随时随地手机看文章

主函数:


#include

#include

#include

 

#define uchar unsigned char

#define uint  unsigned int

#define nop() asm("nop")

#define CS    RD1 //标签为CANCSRH4

#define RESET  RD0  //标签为RESETCAN

 

__CONFIG (CP_OFF &WDTE_OFF& BOREN_OFF&PWRTE_OFF &FOSC_HS&WRT_OFF&LVP_OFF&CPD_OFF);

 

void Init_Int(void);//初始化中断

void Init_Can(void);//初始化CAN通讯

void interrupt ISR(void);//中断处理函数

void delay(unsigned int n);//毫秒延时函数

void CAN_Set_Var(uchar address,uchar mask,uchar dat);//修改寄存器的值,mask为掩码

void Init_Spi(void);//初始化SPI

void SPISendByte(unsigned char dat);//SPI 发送一个字节数据

char SPIRecvByte(void);//SPI 读取一个字节数据

void CAN_Write_SS(uchar address ,uchar Value);//往MCP2515写一个字节数

char CAN_Read_SS(uchar address);//从MCP2515读一个字节数

//void CAN_Send_End(void);//CAN发送程序 

void CAN_Send(unsigned char *CAN_TX_Buf);//发送数据

void SPIReset(void);//SPI复位

void CAN_writetxb0id(unsigned int txb0id);

 

unsigned char dummy;

unsigned char cansentbuf[8];

unsigned char canrecbuf[8];

 

void main()

{

 

Init_Int();//初始化中断

 

//SPI init

Init_Spi();//初始化SPI

 

//can init

RESET=0;

delay(100);

RESET=1;

delay(100);

 

 

 

Init_Can();//初始化CAN通讯

 

CAN_writetxb0id(0x0025);

cansentbuf[0]=1;

cansentbuf[1]=0;

cansentbuf[2]=0x29;

cansentbuf[3]=0;

cansentbuf[4]=0;

cansentbuf[5]=0;

cansentbuf[6]=0;

cansentbuf[7]=0;

// for(bats2chloop=3;bats2chloop<8;bats2chloop++)

// {

// cansentbuf[bats2chloop]=0;

// }

// cansentbuf[5]=batleft;

// cansentbuf[6]=batright;

 

 

/*发一帧数据*/

CAN_Send(cansentbuf);

 

 

while(1)

{

//发送数据

CAN_writetxb0id(0x0025);//帧ID

// cansentbuf[0]=1;

// cansentbuf[1]=0;

// cansentbuf[2]=0x29;

// cansentbuf[3]=0;

// cansentbuf[4]=0;

// cansentbuf[5]=0;

// cansentbuf[6]=0;

// cansentbuf[7]=0;

CAN_Send(cansentbuf);

// CAN_Send(cansentbuf);

// delay(100);

 

// SPISendByte(0XAA);

// SPISendByte(0X00);

// SPISendByte(0X00);

delay(100);

}

 

 

}

 

 

//初始化中断

void Init_Int(void)

{

OPTION_REG = 0b00000000;//B口弱上拉,RB0为下降沿触发中断

TRISB      = 0b00000001;//设定RB0为输入,其余为输出

INTCON     = 0b10010000;//允许RB0/INT中断

}

 

//初始化SPI

void Init_Spi(void)

{

TRISC=0b00010000;//RC5/SDO为输出,RD4/SDI为输入,RC3/SCK为输出

 

//SSPSTAT_SMP=0;//在数据输出时间的中间采样输入数据

//CKE:SPI 时钟边沿选择位   CKP = 0: STAT_CKE=1 在SCK 引脚的上升沿发送数据

//SSPSTAT=0X80;//在数据输出时间的末尾采样输入数据

SSPSTAT=0X40;//在数据输出时间的中间采样输入数据  bit 7,SMP=0,采样位

 

//SSPEN=1;//SPI串口使能

//CKP=0;//空闲时钟为低电平

//SSPCON+=0b0001;//SPI主控模式,时钟为Fosc/16

/*SSPEN=1;使能串行端口;CKP=2,时钟空闲状态为高电平

SSPM<3:0>=0001,主控模式,时钟=Fosc/16

*/

//SSPCON=0x31;

SSPCON=0x21;//bit 4,CKP:时钟极性选择位,0 = 时钟空闲状态为低电平

 

TRISD=0b00000000;//RD1输出;RD0输出;

}

 

 

 

//中断服务程序

void interrupt ISR(void)

{

// if(INTF==1)//如果是INT中断才执行以下程序

// {

//

// INTF==1;//清中断标志位

// }

 

uchar Sta_Int,i;

Sta_Int=CAN_Read_SS(0X2C);//读中断标志寄存器

CAN_Write_SS(0X2C,0x00);//清除所有中断标志位

/*如果为接收缓冲器0中断*/

if(Sta_Int & 0x01)

{

for(i=0;i<12;i++)

{

//Put_Char(CAN_Read_SS(0x60+i)); 

}

//com_fs=com_fs+12

}

}

 

//延时(n)ms

void delay(unsigned int n)

{

unsigned int j;

char k;

for(j=0;j for(k=246;k>0;k--)

nop();

}

 

 

 

 

 

 

 

 

//SPI 读取一个字节数据

char SPIRecvByte(void)

{

//从MISO线上读取一个数据字节

char BUF;

// SPISendByte(0x01);

// SPISendByte(0x80|0x00);

// nop();//延时

// SPISendByte(0);//给SSPBUF一个0,才能开始读取SSPBUF的数据

SSPBUF=0x00;

delay(2);

BUF=SSPBUF;

delay(20);

return BUF;

}

 

//SPI 发送一个字节数据

void SPISendByte(unsigned char dat)

{

SSPBUF=dat;//往缓冲里面写入dat

// while(!SSPIF)//等待写入成功

// SSPIF=0;//SSPIF清零

delay(20);

}

 

//往MCP2515指定地址addr写一个字节数据value

void CAN_Write_SS(uchar address ,uchar Value)

{

CS=0;

SPISendByte(0x02);//写命令

SPISendByte(address);//写地址

SPISendByte(Value);//写数据

CS=1;

}

 

 

//从MCP2515指定地址addr读取一个字节数据value

char CAN_Read_SS(uchar address)

{

char BUF;

CS=0;

// delay(5);

SPISendByte(0x03);//读命令

SPISendByte(address);//读地址

BUF=SPIRecvByte();//读一个字节数据

CS=1;

return BUF;

}

 

//SPI复位

void SPIReset(void)

{

// CS=LOW;

// WriteSPI(CAN_RESET);

// CS=HIGH;

CS=0;

SSPBUF=0XC0;//CAN_RESET=0XC0

// RESET=1;

// RESET=0;

delay(20);

// RESET=1;

CS=1;

}

 

/**修改寄存器的值**/

//mask为掩码

void CAN_Set_Var(uchar address,uchar mask,uchar dat)

{

// CS=1;//片选

// delay(10);

CS=0;

delay(10);

SPISendByte(0x05);//位修改命令 CAN_BIT_MODIFY

//CANCTRL——CAN 控制寄存器(地址:XFh)

SPISendByte(address);//地址为0fH

SPISendByte(mask);//掩码为E0H,修改CANCTRL的高三位

SPISendByte(dat);

CS=1;//片选

}

 

 

//初始化CAN通讯

void Init_Can(void)

{

/**复位MCP2515**/

SPIReset();

delay(20);

 

/**设置为配置模式**/

//CAN_Set_Var(0x0F,0XE0,0X80);

 

CAN_Write_SS(RXM0SIDH, 0x00);

CAN_Write_SS(RXM0SIDL,0x00);

CAN_Write_SS(RXF0SIDH,0x00);

CAN_Write_SS(RXF0SIDL,0x00);

 

/**设置通讯速率 晶振16M 速率125K**/

//CAN_Write_SS(0x2A,0X03);

//CAN_Write_SS(0x29,0XB9);

//CAN_Write_SS(0x28,0X04);

 

//设置波特率为125Kbps

//set CNF1,SJW=00,长度为1TQ,BRP=49,TQ=[2*(BRP+1)]/Fsoc=2*50/8M=12.5us,16M

CAN_Write_SS(CNF1,CAN_125Kbps);//CNF1=0X03

//set CNF2,SAM=0,在采样点对总线进行一次采样,PHSEG1=(2+1)TQ=3TQ,PRSEG=(0+1)TQ=1TQ

CAN_Write_SS(CNF2,0x80|PHSEG1_3TQ|PRSEG_1TQ);//3,1;6,2

//set CNF3,PHSEG2=(2+1)TQ=3TQ,同时当CANCTRL.CLKEN=1时设定CLKOUT引脚为时间输出使能位

CAN_Write_SS(CNF3,PHSEG2_3TQ);//3;7

 

//set TXB0,设置发送缓冲器0的标识符和发送的数据,以及发送的数据长度

CAN_Write_SS(TXB0SIDH,0x06);//设置发送缓冲器0的标准标识符,待修改***

CAN_Write_SS(TXB0SIDL,0x00);//用到标准标识符

CAN_Write_SS(TXB0DLC,DLC_8);//设置发送数据的长度为8个字节,DLC_1

//CAN_Write_SS(TXB0D0,0x1E);//有待修改及确定是否使用

//CAN_Write_SS(TXB0D1,0x10);//有待修改及确定是否使用

/*set TXB1

CAN_Write_SS(TXB1SIDH,0x50);    //Set TXB0 SIDH

  CAN_Write_SS(TXB1SIDL,0x00);    //Set TXB0 SIDL

  CAN_Write_SS(TXB1DLC,0x40 | DLC_8);    //Set DLC = 3 bytes and RTR bit*/

 

 

  //设置接收缓冲器0的标识符和初始化数据

  CAN_Write_SS(RXB0SIDH,0x00);//设置接收缓冲器0的标准标识符,待修改***

  CAN_Write_SS(RXB0SIDL,0x60);//用到标准标识符

  CAN_Write_SS(RXB0CTRL,0x60);//仅仅接收标准标识符的有效信息,FIILHIT0=0表示RXB0 ,采用FILHIT0

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

 

  CAN_Write_SS(RXF0SIDH,0xFF);//初始化接收滤波器0,待修改***

  CAN_Write_SS(RXF0SIDL,0xE0);

  CAN_Write_SS(RXM0SIDH,0xFF);//初始化接收屏蔽器0,待修改***

  CAN_Write_SS(RXM0SIDL,0xE0);

 

  //设置接收缓冲器0中断

  CAN_Write_SS(CANINTF,0x00);//清空中断标志位

  CAN_Write_SS(CANINTE,0x01);//接收缓冲器0满中断使能位

 

CAN_Write_SS(CANCTRL,REQOP_NORMAL | CLKOUT_ENABLED);//设置正常模式

 

  delay(10);

  dummy=CAN_Read_SS(CANSTAT);

if (OPMODE_NORMAL != (dummy && 0xE0))

  CAN_Write_SS(CANCTRL,REQOP_NORMAL | CLKOUT_ENABLED);//判断进入正常工作模式

  //CAN_Write_SS(CANCTRL,0x00);//选定正常工作模式

 

 

 

0x00 仅接收标准或扩展标识符

0x60 关闭接收所有数据

//CAN_Write_SS(0x60,0X60);

//

滤波

//CAN_Write_SS(0x00,0);

//CAN_Write_SS(0x01,0);

//CAN_Write_SS(0x02,0);

//CAN_Write_SS(0x03,0);

//

屏蔽

//CAN_Write_SS(0x20,0);

//CAN_Write_SS(0x21,0);

//CAN_Write_SS(0x22,0);

//

接收数据产生中断

//CAN_Write_SS(0x2B,0X01);

//

环回模式

CAN_Set_Var(0x0F,0XE0,0X40);

工作模式

//CAN_Set_Var(0x0F,0XE0,0);

}

 

 

void CAN_writetxb0id(unsigned int txb0id)

{

CAN_Write_SS(TXB0SIDH,(txb0id>>3));//设置发送缓冲器0的标准标识符,待修改***

CAN_Write_SS(TXB0SIDL,(0x00FF&(txb0id<<5)));//用到标准标识符

}

 

 

 

 

//CAN发送数据程序 

void CAN_Send(unsigned char *CAN_TX_Buf)

{

unsigned char tempdata;

tempdata=CAN_Read_SS(CAN_RD_STATUS);

CAN_Write_SS(TXB0D0,CAN_TX_Buf[0]);

CAN_Write_SS(TXB0D1,CAN_TX_Buf[1]);

CAN_Write_SS(TXB0D2,CAN_TX_Buf[2]);

CAN_Write_SS(TXB0D3,CAN_TX_Buf[3]);

CAN_Write_SS(TXB0D4,CAN_TX_Buf[4]);

CAN_Write_SS(TXB0D5,CAN_TX_Buf[5]);

CAN_Write_SS(TXB0D6,CAN_TX_Buf[6]);

CAN_Write_SS(TXB0D7,CAN_TX_Buf[7]);

if(tempdata&0x04)//判断TXREQ标志位

{

delay(5);

CAN_Write_SS(TXB0CTRL,0);//清除TXREQ标志位

while(CAN_Read_SS(CAN_RD_STATUS)&0x04);//等待TXREQ清零

}

CS=0;

SPISendByte(CAN_RTS_TXB0);//发送缓冲器0请求发送

CS=1;

}

头文件1:

#ifndef __CAN_H__

#define __CAN_H__

// write your header here

 

#include

 

#define CAN_10Kbps 0x31

#define CAN_25Kbps 0x13

#define CAN_50Kbps 0x09

#define CAN_100Kbps 0x04

#define CAN_125Kbps 0x07

#define CAN_250Kbps 0x01

#define CAN_500Kbps 0x00

#endif


头文件2:

#ifndef __2515_h__

#define __2515_h__

// write your header here

//#pragma nolist

/*********************************************************************

 *   CAN MCP2510 C definitions file                                  *

 *********************************************************************

 *   Filename:       2515REGS.h                                      *

 *   Date:           06/17/03                                        *

 *   File Version:   1.00 (Beta)                                     *

 *********************************************************************

 *   Functions:                                                      *

 *               Header file                                         *

 *********************************************************************

 *   Revision History:                                               *

 *    06/17/03 Updated from MCP2510.inc which was for the 756 board  *

 *********************************************************************/

 

 

/*******************************************************************

 *                   Register Definitions                          *

[1] [2] [3]
关键字:PIC16F887  SPI  CAN  传输  操作MCP2515 引用地址:PIC16F887 SPI CAN 传输,操作MCP2515

上一篇:PIC18F45K80 将RA0等配置为数字输入I/O
下一篇:PIC知识点汇总

推荐阅读

在电动和混合动力汽车中,需要一种方法将高压电池与车辆的其他部分断开连接。专门设计的大电流继电器(接触器)历来一直是执行此功能的首选方案。此继电器的设计必须支持在负载下断开连接,而不受损坏。这是通过使用带有真空封装触点的继电器来实现的。这些接触器通常充满惰性气体,包围触点以消除空气。通常,在高压电池系统中,需要三个接触器:一个用于两...
随着美国市场进入5G时代,市场领导者苹果和三星可能会拉开与LG、摩托罗拉、中兴和谷歌等其追逐者的差距。 由于苹果和三星在高端市场占主导地位,其它品牌的换机竞争将在零售价600美元以下的手机中展开。实际上,Strategy Analytics认为消费者根本不会接受800美元或1000美元的零售价格点。 即使是3年的EIP(设备分期付款),除了两个品牌领导者之外,Strat...
由Summit Wireless Technologies(纳斯达克股票代码:WiSA)发起创立的无线扬声器和音频协会(WiSA® LLC)宣布,协会成员、中国最大的电视制造商创维(SKYWORTH)集团有限公司(港股代码:00751),推出了配有无线连接技术的美兹雕塑 1(Metz Skulptur 1)电视和扬声器。作为美兹黑标品牌的一部分,此次推出的产品是拥有百年历史的奢华电视制造商美...
后摩尔时代,先进封装是必然选择。得益于对更高集成度的广泛需求,摩尔定律逐渐放缓,在异构集成和5G、AI、HPC、IoT等大趋势推动下,先进封装成为后摩尔时代的主战场之一。Yole数据显示,2020年全球封测市场达594亿美元,同比增长5.3%。预计到2025年达到420亿美元,等同于传统封装的营收,到2026年则将彻底实现反超。于是乎,作为曾经是OSAT、IDM厂商的主...

史海拾趣

问答坊 | AI 解惑

IAR 简明使用指南!!!

IAR 简明使用指南!!!…

查看全部问答∨

PARALIGHT有源光缆组件

PARALIGHT有源光缆组件,该产品为1.2.1或更高版本的InfiniBand兼容光缆组件,采用带有安装在连接器外壳内的光电组件的光纤,具有标准InfiniBand电气连接器接口。PARALIGHT有源光缆组件集其它光缆组件的所有优点于一身,具有速度高、传输距离长、体 ...…

查看全部问答∨

ARM开发板

市场上有三星,TI,飞思卡尔等,但是那一款比较事可做消费电子,三星产品最大的缺点就是外部接口太少不亦可乎外来的升级换代也不宜与客户未来的功能扩展,TI价格成本太过所需要的人力资源也太多。所以我觉得还是飞思卡尔的产品不较好,说道飞思卡尔 ...…

查看全部问答∨

单片机教程

不错的教程 大家看看。。。…

查看全部问答∨

ICC中宏定义位的问题

如果PA口的4,5,6,7引脚分别控制我的4位数码管的各个位,我应该如何宏定义呢? 谢谢…

查看全部问答∨

深圳地区找一块单片机学习板.

一些小要求:串口是必须的,USB通讯(如果有最好),ROM要大的(准备跑UCOSSII操作系统),仿真器,烧录器是要有的.            阵列键盘.数码管,LED灯.这些都是基本的咯 大家能帮我找到这样的学习板吗??? 二 ...…

查看全部问答∨

导师要求做个小型嵌入式防火墙,大伙有啥好建议?

天哪,导师要求做个小型嵌入式防火墙。 要能跑UCOS系统。 我想请教各位,能否使用仿真或者什么方法比较快的做出来呢? 急死我了。希望高手赐教指点迷津 本人愿意散分。。。。 救命啊!…

查看全部问答∨

关于保护模式和实模式的一些问题

请各位大虾解释一下为什么一定要从16位代码段才能从保护模式返回实模式,而32位不能?…

查看全部问答∨

C8051F020发送32位数据的问题?

请问各位大虾,谁有通过C8051F020发送32位数据的程序。 给小弟指点一二阿。急 说说思路也行。…

查看全部问答∨

在基本共射放大电路中,为什么发射结电阻上流过的是基极电流而不是发射极电流?

模电初学者,第一次发帖,不知道问题是否合适,还望各位多关照…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved