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

📄 main.c

📁 PIC16F877与MCP2510的通讯源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	<pic16f87x.h>           		//定义PIC16F877相关寄存器的地址
#include	<mcp2510.h>				// MCP2510寄存器定义,主要定义寄存器的地址 
// =========常数和变量定义=========  
#define	READ  	0x03				// 读MCP2510指令代码 
#define	WRITE	0x02				// 写MCP2510指令代码 
#define	RESET	0xC0				// 复位MCP2510指令代码 
#define	RTS	0x80			        // MCP2510请求发送指令代码 
#define	STA2510	0xA0				// 读MCP2510状态指令代码 
#define	BITMOD	0x05				// MCP2510位修改指令代码 
int	a[12];						// SPI发送或接收数据寄存器
int	b[8];					     	//发送或接收的数据
int	c[8];					     	//发送或接收的数据
int	i;						// 临时变量
int	count;						// 发送接收计数器
int	count1=0;				     	// 用于测试
int	RecID_H=0;
int	RecID_L=0;
int	DLC=8;
void SPIINT();                       		//定义SPI中断函数
void TMR1INT();                     		//定义定时器中断函数
void CCP1INT();                     		//定义CCP中断函数
void SPIEXCHANGE(int count);         		//执行SPI传送
void WAIT_SPI();                     		//SPI访问延时函数
void RESET2510();                    		//复位MCP2510函数
int  RD2510(int adress,int n);           	// MCP2510读函数
void WR2510(int adress,int n);           	//MCP2510写函数
void RTS2510(int RTSn);                		//MCP2510复位函数
int  GETS2510();                      		//读取MCP2510芯片状态
void BM2510(int adress,int mask,int data);  	//位修改操作函数
void SETNORMAL();                		//设置MCP2510为正常模式函数
void TXCOMPLETE(int adress);         		//判断是否发送完毕
void TXMSG(int DLC);                		//发送报文函数
int  RXMSG();                      		//接收报文函数
void INIT2510();                     		//初始化MCP2510函数
void INIT877();                      		//初始化PIC16F877函数
void INITSPI();                     		//初始化SPI函数
void ACK();                        		//应答函数
void wait();                         		//等待延时延时
// =========================主程序======= ======================================
/*主要的操作流程为:使能相关的中断、SPI、定时器,打开中断;初始化PIC16F877微处理器;初始化SPI接口;初始化MCP2510 CAN控制器;执行接收发送报文循环。*/
main(void)
{
	int l,detect=0;
	SSPIE=1;                         		//使能SSP中断
	TMR1IE=1;                       		//使能定时器中断
	CCP1IE=1;                       		//使能CCP1中断
	CCP2IE=1;                       		//使能CCP2中断
	PEIE=1;                          		//使能所有未屏蔽的外围器件
	ei();					         //开中断 
	INIT877();				         //初始化PIC16F877微处理器
	INITSPI();					//初始化SPI接口 
	INIT2510();					//初始化MCP2510 CAN控制器 
	flag1=0;
	flag2=0;
	CCP1CON=0x05;      				//CCP捕捉模式,每个上升沿
	CCP2CON=0x04;      				//CCP捕捉模式,每个下降沿
	while(1)	{
		RXMSG();            	 		//接收报文
		TXMSG(8);            			//发送报文
	}
}
// =====================中断服务程序==========================================
// SPI中断服务子程序:首先设定SSPIF=0;将SSPBUF寄存器的值暂存在a[]中,
void SPIINT()
{
	SSPIF=0;                            		//SSP中断标志位
	a[i++]=SSPBUF;			             	//SSP是MCU的SPI数据寄存器,数据暂存a[]中 
	count-=1;
	if(count>0)  SSPBUF=a[i];             		//未发送完,继续 
	else   RE2=1;				       	//否则,片选信号置高电平 
	return;
}
//定时器TMR1中断服务子程序 
void TMR1INT()
{
	TMR1IF=0; 
	T1CON=0;
	if(!flag1){
		TMR1H=0xfe;					// 512 μs 脉冲宽度
		TMR1L=0x00;
		T1CON=0x01;
		PORTD=0xff;					// 输出所有通道
		flag1=1;
	}
	else	{
		flag1=0;
		PORTD=0;
		T1CON=0;
	}
	return;
}
// CCP1中断服务子程序 
void CCP1INT()
{
	CCP1IF=0;
	T1CON=0x01;                         		//使能定时器1
	return;
}
// CCP2中断服务子程序 
 void CCP2INT()
{
	CCP2IF=0;
	T2CON=0x01;                     		//使能定时器2
	return;
}
//中断入口,保护现场,判中断类型 
void interrupt INTS()
{
	di();
	if(TMR1IF)  TMR1INT();				// 定时器TMR1中断 
	else if(CCP1IF)  CCP1INT();			// 电压过零捕捉中断1 
	else if(CCP2IF)  CCP2INT();			// 电压过零捕捉中断2 
	else if(SSPIF)  SPIINT();			// SPI接口中断 
	ei();
}
// ================================子程序分析======= =============================
/*****************************************************************************************
启动SPI传送,判断count是否大于0,若大于0说明有数据传送;然后将变量a[]中的数据依次放入到SSPBUFF寄存器中。若count等于0,则直接返回。
*****************************************************************************************/
void SPIEXCHANGE(count)
 int count;
{
	if(count>0)
 {			           				//有数据可送? 
	  i=0;
	  RE2=0;				  		//片选位置低电平,启动MCP2510 
	  SSPBUF=a[i];	            				//送数,将a[i]中的数值放入SSPBUF寄存器中
       count-=count;             				//count递减
	    }
	else
	  ;					        	//否则,空操作,并返回 
	return;
}
/*****************************************************************************************
等待SPI传送完成,判断count是否为0,若为0,则延时完成。
*****************************************************************************************/
 void WAIT_SPI()
{
	do{
	  ;
	}while(count>0);					// 当count!=0时,等待 to add "CLRWDT" 
	return;
}
/*****************************************************************************************
对MCP2510芯片进行复位 ,复位操作就是通过SPI的传送函数,将RESET指令写入到MCP2510中。这个函数主要实现了MCP2510复位指令的操作,主要通过调用SPIEXCHANGE()函数来实现。具体的流程见图5.11-7。
*****************************************************************************************/
void RESET2510()
{
	a[0]=RESET;                     	//将复位指令放入到a[0]中,RESET=0xC0
	count=1;                         	//count=1,说明SPIEXCHANGE函数仅仅发送一个字节
	SPIEXCHANGE(count);			// 送复位指令 ,传送0xC0
	WAIT_SPI();                     	//等待
	return;
}
/*****************************************************************************************
读取从地址"adress"开始的寄存器中的数据,共n个,存放在数组b[n]中。操作的过程,首先通过SPI传送函数将READ=0x03指令传送到MCP2510,然后传送要读取的数据的地址,最后从SO引脚读取相应的 数据。参数address为读取的源地址,n是取出数据的数据,b[j]读取数据后放的目的地址。这个函数主要实现了MCP2510读指令的操作,主要通过调用SPIEXCHANGE()函数来实现。具体的流程见图5.11-2。
*****************************************************************************************/
 int RD2510(adress,n) 
 int 	adress;
 int	n;
{
	int j;
	a[0]=READ;                           		//读指令READ=0x03
	a[1]=adress;                            	//读操作的目的地址
	for(j=0;j<n;j++)                         	//循环语句
		a[j+2]=0;
	count=n+2;					 //指令、地址和要得到的数据量n 
	SPIEXCHANGE(count);                		//执行SPI传送函数
	WAIT_SPI();                         		//SPI延时函数
	for(j=0;j<n;j++)
b[j]=a[j+2];                        			//读出的数据存到数组b[]中 
	return;
}
/*****************************************************************************************
向从地址"adress"开始的寄存器写入数据,共n个,数据存放数组b[n]中。操作过程为首先通过SPI的传送函数将WRITE=0x02写入MCP2510;然后写入要写的地址;最后就是要写入的数据。参数:adress:写入的目的地址;n要写入的数目。这个函数主要实现了MCP2510写指令的操作,主要通过调用SPIEXCHANGE()函数来实现。具体的流程见图5.11-3。
****************************************************************************************/
 void WR2510(adress,n)
 int	adress;
 int	n;
{
	int j;
	a[0]=WRITE;            			//读指令WRITE=0x02
	a[1]=adress;              		//要写入的目的地址

⌨️ 快捷键说明

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