历史上的今天
返回首页

历史上的今天

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

正在发生

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

2020-08-27 来源:eefocus

主函数:


#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                          *

推荐阅读

史海拾趣

Graseby Infrared公司的发展小趣事
穿戴好绝缘手套和鞋子,避免直接接触带电部分。
思瑞浦微电子科技(3PEAK INCORPORATED)公司的发展小趣事
如果以上检查均正常,可能是电动机本身故障,如绕组断路、轴承卡死等。可以尝试手动转动电动机轴,检查是否有阻力或异常声音。
ET Enterprises Ltd公司的发展小趣事

进入1940年代后期,ET Enterprises Ltd公司将业务重心转向光电倍增管的开发和制造。通过不断的技术创新和市场拓展,公司逐渐在光电倍增管领域建立起领先地位,成为国际知名的光电倍增管供应商。

Ho Chien Electronics Group Inc公司的发展小趣事

在竞争激烈的电子行业中,ET Enterprises Ltd公司始终保持对技术创新的重视。公司不断投入研发资源,推动光电倍增管技术的不断进步。同时,公司也注重人才培养和团队建设,为公司的持续发展提供了有力保障。

HARTING公司的发展小趣事

ET Enterprises Ltd公司的历史可以追溯到1930年代,当时它作为EMI公司的一部分,开始涉足光检测技术领域。在这个早期阶段,公司致力于研究光信号的特性及其检测方法,为后续的光电倍增管技术奠定基础。

BITECH公司的发展小趣事

ET Enterprises Ltd公司的历史可以追溯到1930年代,当时它作为EMI公司的一部分,开始涉足光检测技术领域。在这个早期阶段,公司致力于研究光信号的特性及其检测方法,为后续的光电倍增管技术奠定基础。

问答坊 | AI 解惑

医疗电子设备的接地系统

接地对任何设备都至关重要,咱们一起来看看医疗设备的接地系统。 …

查看全部问答>

本科毕业设计要求论文翻译,求一篇适合翻译的英文论文

导师说要我自己去找。 要求是关于FPGA的,或者DS18b20的文章也可以! 然而我以前收藏的资料中,都觉得不太适合。 因为这论文篇幅不能太长,最好能控制在5页上下。 具有一定可读性,不要全是公式什么的,呵呵! 所以我来求助了!!! 望有 ...…

查看全部问答>

【求助】怎么将AMR2410自带的TFT液晶屏换成单片机上的圆形点阵液晶屏?

  因为开发板上的液晶屏长宽比列不合用,因此想把液晶屏换成单片机上用的那种圆形点阵液晶屏。我的目的是想让液晶屏显示我在开发板上移植的QT程序,开发板上是有操作系统的,哪位高手能指点下呢?…

查看全部问答>

关于天津索思的WT-900型表

以前公司进了几块天津索思的WT-900型表。现在表有点不准,听别人说900型有工厂模式,可以通过工厂模式来调。 请问各位,有谁知道怎么进入工厂模式?谢谢 …

查看全部问答>

求助!信号问题

怎么样用单片机采集正弦信号的幅值和频率!小弟做一个多参数测试仪,要求给一个正弦信号,采集它的幅值和频率。…

查看全部问答>

图象处理算法

用摄相头拍出一件物品的照片,如何用计算机程序计算出它是否为一个标准的矩形…

查看全部问答>

FPGA 与DSP,ARM总线数据交换需要注意的关键点!

 FPGA 中文意思现场可编程门阵列,以逻辑资源多,D触发器多,可以完成各种同步与异步时序电路设计.DSP,ARM 数据总线与FPGA进行数据交换,涉及到两个不同时钟的逻辑时序电路.对于两个异步时钟时序电路设计,常用的设计方法就是RAM 或FIFO 进行数据存 ...…

查看全部问答>

LM3S811学习进行中问题不断

各位朋友我看了几天的资料,我终于下定决心弄一弄我的小lm3s811开发板了,但是遇到了一些问题, 1.我的keil建立工程为什么不显示工程名字呢,我起的工程名为lm3s811可是显示的是这样的 2.即使我不自己建立工程,我把从网上网友分享的文件打开, ...…

查看全部问答>

台湾高级版DDR3内存测试软件

DDR3 内存条、IC颗粒 台湾工厂级内存测试维修系统     DDR3 内存测试维修系统 一、价格:18000元。 二、包装附件:两个测试系统硬盘,一个服务器启动卡,一个终端测试卡,两个网卡,两颗终端网卡启动芯片。 三、客户自备服务器 ...…

查看全部问答>

ISE调用microblaze输出数据到超级终端上

现在做一个项目,ISE调用microblaze已经实现。现在需要把microblaze的一些数据输出到超级终端上,如果只是在EDK里,只需要建立一个串口IP,然后用xil_printf就能输出。现在需要用ise调用microblaze,在ISE里把microblaze 的串口线引出来,没法输出 ...…

查看全部问答>