历史上的今天
今天是: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 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 *
上一篇:PIC18F45K80 将RA0等配置为数字输入I/O
下一篇:PIC知识点汇总
史海拾趣
|
导师说要我自己去找。 要求是关于FPGA的,或者DS18b20的文章也可以! 然而我以前收藏的资料中,都觉得不太适合。 因为这论文篇幅不能太长,最好能控制在5页上下。 具有一定可读性,不要全是公式什么的,呵呵! 所以我来求助了!!! 望有 ...… 查看全部问答> |
|
【求助】怎么将AMR2410自带的TFT液晶屏换成单片机上的圆形点阵液晶屏? 因为开发板上的液晶屏长宽比列不合用,因此想把液晶屏换成单片机上用的那种圆形点阵液晶屏。我的目的是想让液晶屏显示我在开发板上移植的QT程序,开发板上是有操作系统的,哪位高手能指点下呢?… 查看全部问答> |
|
以前公司进了几块天津索思的WT-900型表。现在表有点不准,听别人说900型有工厂模式,可以通过工厂模式来调。 请问各位,有谁知道怎么进入工厂模式?谢谢 … 查看全部问答> |
|
FPGA 中文意思现场可编程门阵列,以逻辑资源多,D触发器多,可以完成各种同步与异步时序电路设计.DSP,ARM 数据总线与FPGA进行数据交换,涉及到两个不同时钟的逻辑时序电路.对于两个异步时钟时序电路设计,常用的设计方法就是RAM 或FIFO 进行数据存 ...… 查看全部问答> |
|
各位朋友我看了几天的资料,我终于下定决心弄一弄我的小lm3s811开发板了,但是遇到了一些问题, 1.我的keil建立工程为什么不显示工程名字呢,我起的工程名为lm3s811可是显示的是这样的 2.即使我不自己建立工程,我把从网上网友分享的文件打开, ...… 查看全部问答> |
|
DDR3 内存条、IC颗粒 台湾工厂级内存测试维修系统 DDR3 内存测试维修系统 一、价格:18000元。 二、包装附件:两个测试系统硬盘,一个服务器启动卡,一个终端测试卡,两个网卡,两颗终端网卡启动芯片。 三、客户自备服务器 ...… 查看全部问答> |
|
现在做一个项目,ISE调用microblaze已经实现。现在需要把microblaze的一些数据输出到超级终端上,如果只是在EDK里,只需要建立一个串口IP,然后用xil_printf就能输出。现在需要用ise调用microblaze,在ISE里把microblaze 的串口线引出来,没法输出 ...… 查看全部问答> |




