📄 main.c
字号:
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 + -