⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 PIC16F877与MCP2510的通讯源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	for(j=0;j<n;j++) 
	a[j+2]=b[j];                 		//要写的数据从后面第3个开始,第1个是WRITE,第2个adress
	count=n+2;					//指令、地址和要写入的数据量n ,一共要写入的数据为n+2个
	SPIEXCHANGE(count);       	//执行SPI传送,写入的数据从a[0]开始一直到a[n+2]
	WAIT_SPI();             	//SPI延时
	return;
}
/*****************************************************************************************
MCP2510芯片请求发送程序 ,这个函数主要实现了MCP2510请求发送指令的操作,主要通过调用SPIEXCHANGE()函数来实现。具体的流程见图5.11-4。
*****************************************************************************************/
void RTS2510(RTSn)
 int RTSn;
{
	a[0]=RTS^RTSn;                            	//请求发送指令RTS=0x80
	count=1;
	SPIEXCHANGE(count);			         		//发送MCP2510芯片,请求发送指令
	WAIT_SPI();
	return;
}
/*****************************************************************************************
读取MCP2510芯片的状态,这个函数主要实现了读取MCP2510指令的操作,主要通过调用SPIEXCHANGE()函数来实现。具体的流程见图5.11-6。
Status 		7   	6    	5    	4    	3    	2  	1	0
		|	|	|	|	|	|	|	|									
		|	|	|	|	|	|	|	|___CANINTF.RX0IF
		|	|	|	|	|	|	|_______CANINTF.RX1IF
		|	|	|	|	|	|___________TXB0CTRL.TXREQ
		|	|	|	|	|_______________CANINTF.TX0IF
		|	|	|	|___________________TXB1CTRL.TXREQ
		|	|	|_______________________CANINTF.TX1IF
		|	|___________________________TXB2CTRL.TXREQ
		|_______________________________CANINTF.TX2IF
*****************************************************************************************/
int GETS2510()
{
	a[0]=STA2510;                        			//读MCP2510状态指令STA2510=0xA0	
	a[1]=0;
	count=2;
	SPIEXCHANGE(count);			   		 //读取MCP2510芯片状态 
	WAIT_SPI();                            			//SPI延时
	b[0]=a[1];					       	//状态存到数组b[]中 
	return;
}
/*****************************************************************************************
对MCP2510芯片进行位修改子程序,参数有:address:目标地址;data:目标数值;mask:屏蔽位。操作方法是依次调用SPI传送函数将为修改指令、位修改寄存器地址、位修改屏蔽位、位修改数据写入到MCP2510控制器中。这个函数主要实现了MCP2510位修改指令的操作,具体的流程见图5.11-5。
*****************************************************************************************/
 void BM2510(adress,mask,data)
 int  adress;
 int  mask;
 int  data;
{
	a[0]=BITMOD;							//位修改指令 
	a[1]=adress;							//位修改寄存器地址 
	a[2]=mask;					    		//位修改屏蔽位 
	a[3]=data;					    		//位修改数据 
	count=4;
	SPIEXCHANGE(count);
	WAIT_SPI();
	return;
}
/*****************************************************************************************
设置MCP2510芯片为正常操作模式,操作步骤,通过位修改指令函数,修改寄存器CANCTRL<7:5>位,修改完毕之后,通过一个读取CANSTAT寄存器的相应位,通过检验,确认是否已经进入正常模式。
*****************************************************************************************/
void  SETNORMAL()
{
	int  k=1;
	BM2510(CANCTRL,0xe0,0x00);	           			//调用位操作函数设置为正常操作模式 
	do	
{
	     RD2510(CANSTAT,1);               				//读CAN总线的状态将读出的状态值放入到B[]中
	     k=b[0]&0xe0;
	      }
while(k);					      			//确认已进入正常操作模式 
	return;
}
/*******************************************************************************************
对MCP2510进行初始化。复位主要的步骤为:首先执行SPI复位指令、设置CAN总线的速率;然后通过设置RXM0SIDH寄存器设置接收报文中标准标识码进行屏蔽;接下来禁止CAN中断;最后设置CAN为正常操作模式。
*******************************************************************************************/
void INIT2510()
{
	RESET2510();					    		//使MCP2510软复位 
	b[0]=0x02;
	b[1]=0x90;
	b[2]=0x07;
	WR2510(CNF3,3);				     			//波特率为 125 kbps 
	b[0]=0x00;
	b[1]=0x00;
	WR2510(RXM0SIDH,2);
	b[0]=0x00;
	b[1]=0x00;
	WR2510(RXF0SIDH,2);			    			// RX0接收,屏蔽位为0,过滤器为0 
	b[0]=0x00;
	WR2510(CANINTE,1);			     			// CAN中断不使能 
	SETNORMAL();							//设置为正常操作模式 
	return;
}
/**************************************************************************************
MCP2510芯片发送完成与否判断,邮箱号为adress。
**************************************************************************************/
void TXCOMPLETE(adress)
int adress;
{
	int k=1;
	do	
{
	     RD2510(adress,1);
	     k=b[0]&0x08;
	   }while(k);							//确认是否已发送完毕 
	return;
}
/**************************************************************************************
初始化PIC16F877微处理器。关于PIC16F877微处理器的初始化过程的配置,用户可以参考PIC16F877处理器芯片手册。
**************************************************************************************/
void INIT877()
{
	PORTA=0;
	PORTB=0;
	PORTC=0;
	PORTD=0;
	PORTE=0;
	TRISA=0xff;
	TRISB=0xfd;
	TRISC=0xd7;						//SCK, SDO:输出,SDI:输入  
	TRISD=0;
	TRISE=0x03;						//片选CS信号输出
	PORTA=0xff;
	PORTB=0x03;						//RST=1 
	PORTC=0;
	PORTD=0xff;
	PORTE=0x04;
	return;
}
/*****************************************************************************************
初始化SPI接口,因为PIC16F87X系列的处理器,SSP接口由两种配置方式,一是SPI模式,一是IIC模式,因此,必须对处理器的SSSP接口进行配置,配置为SPI接口模式。配置主要包括的寄存器为:SSPSTAT、SSPCON、SSPCON2。寄存器的具体功能描述读者可以参阅相关文献。
*****************************************************************************************/
 void INITSPI()
{
	SSPCON=0x11;               			//SSP在SPI模式下,clock = FOSC/16,空闲状态下时钟为高电平
	SSPEN=1;					// SSP使能SPI模式,同时配置SDI、SDO、SCK
	SSPSTAT=0;              			//SSP在SPI模式下,数据在SCK的下降沿传输
	return;
}
/*******************************************************************************************
发送数据子程序。具体操作流程为:函数定义数据的长度DLC参数;首先将将c[]中的数据依次放入到b[]数组中;然后调用WR2510()函数将DLC长度的数据放到TXB0D0缓冲区中;发送数据长度位;定义最高报文优先级;调用函数RTS2510()请求发送;最后等待发送完毕。
*******************************************************************************************/
void  TXMSG(int DLC)
{
	for(i=0;i<DLC;i++) 
b[i]=c[i];                                  		//将c[]中的数据依次放入到b[]中
	WR2510(TXB0D0,DLC);	                  	//将DLC长度的数据放到TXB0D0缓冲区中
	b[0]=DLC;
	WR2510(TXB0DLC,1);                      	//发送的长度位DLC
	b[0]=0x03;
	b[1]=RecID_H;
	b[2]=RecID_L;
	WR2510(TXB0CTRL,3);                     	//定义最高报文优先级
	RTS2510(0x01);					         	//请求发送 
	TXCOMPLETE(TXB0CTRL);	 			//等待发送完毕 
	return;
}
/****************************************************************************************
接收数据子程序。接收数据子程序的流程为:首先读CANINTF寄存器,比较CANINTF寄存器的最后一位,判断缓冲器区是否已满,若为1,说明缓冲器区已满,等待中断处理;中断处理过程为:通过调用位修改指令置位,清除中断;从RXB0SIDH寄存器中连续读两位,判断;然后从RXB0DLC寄存器中读1位,判断,确定长度;最后将对出的数据依次放入c[i]中。
*****************************************************************************************/
 int RXMSG()
{
	int k;
	RD2510(CANINTF,1);             					//读CANINTF寄存器
	k=b[0]&0x01;                     				//比较CANINTF寄存器的最后一位,判断接收缓冲区是否已满
	if(k==1)	                      				//若最后一位为1表示:接收缓冲区已满,有等待处理的中断
{ 
	BM2510(CANINTF,0x01,0x00);                 			//采用位修改指令置位,清除中断
		RD2510(RXB0SIDH,2);                       		//从RXB0SIDH寄存器中连续读两位
		RecID_H=b[0];
	RecID_L=b[1]&0xe0;
	RD2510(RXB0DLC,1);                       			//从RXB0DLC寄存器中读1位
	DLC=b[0]&0x0f;                            			//判断
	RD2510(RXB0D0,DLC);                     			//读的数据长度
		for(i=0;i<DLC;i++)
 c[i]=b[i];                                 				//将读出的数据b[]依次放入到c[i]中
		return 1;                                       	//返回
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -