📄 main.c
字号:
#include "p30f2020.h"
/* Configuration Bit Settings */
_FOSCSEL(FRC_PLL)
_FOSC(CSW_FSCM_OFF & FRC_LO_RANGE & OSC2_CLKO)
_FPOR(PWRT_128)
_FGS(CODE_PROT_OFF)
#define READ 0x03 // 读MCP2510指令代码
#define WRITE 0x02 // 写MCP2510指令代码
#define RESET 0xC0 // 复位MCP2510指令代码
#define RTS 0x80 // MCP2510请求发送指令代码
#define STA2510 0xA0 // 读MCP2510状态指令代码
#define BITMOD 0x05 // MCP2510位修改指令代码
#define CANCTRL 0x0F //ZJH
#define CANSTAT 0x0E //ZJH
#define CNF3 0x28 //ZJH
#define RXM0SIDH 0x20 //ZJH
#define RXF0SIDH 0x00 //ZJH
#define CANINTE 0x2B //ZJH
#define TXB0D0 0x36 //ZJH
#define TXB0DLC 0x35 //ZJH
#define TXB0CTRL 0x30 //ZJH
#define CANINTF 0x2C //ZJH
#define RXB0SIDH 0x61 //ZJH
#define RXB0DLC 0x65 //ZJH
#define RXB0D0 0x66 //ZJH
int a[12]; // SPI发送或接收数据寄存器
int b[8]; // 发送或接收的数据
int c[8]; // 发送或接收的数据
int i; // 临时变量
int count; // 发送接收计数器
int count1=0; // for test
int RecID_H=0;
int RecID_L=0;
int DLC=8;
void SPIINT();
void SPIEXCHANGE(int count);
void WAIT_SPI();
void RESET2510();
int RD2510(int adress,int n);
void WR2510(int adress,int n);
void RTS2510(int RTSn);
int GETS2510();
void BM2510(int adress,int mask,int data);
void SETNORMAL();
void TXCOMPLETE(int adress);
void TXMSG(int DLC);
int RXMSG();
void INIT2510();
void INIT877();
void INITSPI();
void ACK();
void wait();
int main(void)
{
int l,detect=0;
//SSPIE=1;
//SPIEN=1; //ZJH
SPI1STATbits.SPIEN=1; //ZJH
//PEIE=1;
//SPI1IE=1; //ZJH
IEC0=0;IEC1=0;IEC2=0; //ZJH
IEC0bits.SPI1IE=1; //ZJH
//ei(); // 开中断 ZJH
INIT877(); // 初始化PIC16F877芯片
INITSPI(); // 初始化SPI接口
INIT2510(); // 初始化MCP2510芯片
while(1)
{
RXMSG();
TXMSG(8);
}
}
// ========中断服务程序=======
// SPI中断服务子程序
void SPIINT()
{
//SSPIF=0;
IFS0bits.SPI1IF=0; //ZJH
//a[i++]=SSPBUF; // 数据暂存a[]中
a[i++]=SPI1BUF; //ZJH
count-=1;
//if(count>0) SSPBUF=a[i]; // 未发送完,继续
if(count>0) SPI1BUF=a[i]; // ZJH
//else RE2=1; // 否则,片选信号置高电平
//else RD0=1; //ZJH
return;
}
//中断入口,保护现场,判中断类型
void __attribute__((__interrupt__)) _SPI1Interrupt(void) //ZJH Declaration method
{
//di(); //ZJH
IEC0bits.SPI1IE=0; //ZJH
if(IFS0bits.SPI1IF) SPIINT(); //ZJH
//ei(); //ZJH
IEC0bits.SPI1IE=1; //ZJH
}
// ========子程序=======
// 启动SPI传送
void SPIEXCHANGE(count)
int count;
{
if(count>0)
{ // 有数据可送?
i=0;
//RE2=0; // 片选位置低电平
// RD0=0; //ZJH
//SSPBUF=a[i]; // 送数
SPI1BUF=a[i]; //ZJH
}
else
; // 否则,空操作,并返回
return;
}
// 等待SPI传送完成
void WAIT_SPI()
{
do
{
;
}while(count>0); // 当count!=0时,等待 to add "CLRWDT"
return;
}
// 对MCP2510芯片进行复位
void RESET2510()
{
a[0]=RESET;
count=1;
SPIEXCHANGE(count); // 送复位指令
WAIT_SPI();
return;
}
// 读取从地址"adress"开始的寄存器中的数据,共n个,存放在数组b[n]中
int RD2510(adress,n)
int adress;
int n;
{
int j;
a[0]=READ;
a[1]=adress;
for(j=0;j<n;j++)
a[j+2]=0;
count=n+2; // 指令、地址和要得到的数据量n
SPIEXCHANGE(count);
WAIT_SPI();
for(j=0;j<n;j++)
b[j]=a[j+2]; // 数据存到数组b[]中
return;
}
// 向从地址"adress"开始的寄存器写入数据,共n个,数据存放数组b[n]中
void WR2510(adress,n)
int adress;
int n;
{
int j;
a[0]=WRITE;
a[1]=adress;
for(j=0;j<n;j++)
a[j+2]=b[j];
count=n+2; // 指令、地址和要写入的数据量n
SPIEXCHANGE(count);
WAIT_SPI();
return;
}
// MCP2510芯片请求发送程序
void RTS2510(RTSn)
int RTSn;
{
a[0]=RTS^RTSn;
count=1;
SPIEXCHANGE(count); // 发送MCP2510芯片,请求发送指令
WAIT_SPI();
return;
}
// 读取MCP2510芯片的状态
int GETS2510()
{
a[0]=STA2510;
a[1]=0;
count=2;
SPIEXCHANGE(count); // 读取MCP2510芯片状态
WAIT_SPI();
b[0]=a[1]; // 状态存到数组b[]中
return;
}
// 对MCP2510芯片进行位修改子程序
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芯片为正常操作模式
void SETNORMAL()
{
int k=1;
BM2510(CANCTRL,0xe0,0x00); // 设置为正常操作模式
//ZJH REQOP2 REQOP1 REQOP0 BIT7 BIT6 BIT5 OF CANCTRL
do
{
RD2510(CANSTAT,1); //ZJH OPMOD2 OPMOD1 OPMOD0,THE BIT7,6,5 OF CANSTAT
k=b[0]&0xe0;
}while(k); // 确认已进入正常操作模式
return;
}
// 对MCP2510进行初始化
void INIT2510()
{
RESET2510(); // 使芯片复位
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); // 确认是否已发送完毕 to add CLRWDT
return;
}
// 初始化PIC16F877芯片
void INIT877()
{
PORTA=0;
PORTB=0;
//PORTC=0; //ZJH
PORTD=0;
PORTE=0;
TRISA=0xff;
TRISB=0xfd;
//TRISC=0xd7; //ZJH // SCK, SDO:输出,SDI:输入
TRISD=0;
TRISE=0x03; // 片选CS信号输出
PORTA=0xff;
PORTB=0x03; // RST=1
//PORTC=0; //ZJH
PORTD=0xff;
PORTE=0x04;
return;
}
// 初始化SPI接口
void INITSPI()
{
//SSPCON=0x11;
SPI1CON=0; //ZJH The value should be confirmed???????????????????????????
//SSPEN=1; // SSP使能
SPI1STATbits.SPIEN=1; //ZJH
//SSPSTAT=0;
SPI1STAT=0; //ZJH
return;
}
// 发送数据子程序
void TXMSG(int DLC)
{
for(i=0;i<DLC;i++)
b[i]=c[i];
WR2510(TXB0D0,DLC);
b[0]=DLC;
WR2510(TXB0DLC,1);
b[0]=0x03;
b[1]=RecID_H;
b[2]=RecID_L;
WR2510(TXB0CTRL,3);
RTS2510(0x01); // 请求发送 //by TXB0 ZJH
TXCOMPLETE(TXB0CTRL); //等待发送完毕 //READ STATE OF TXB0CTRL.TXREQ ZJH
return;
}
// 接收数据子程序
int RXMSG()
{
int k;
RD2510(CANINTF,1); //READ STATE OF CANINTF.RX0IF ZJH
k=b[0]&0x01;
if(k==1) //IF THERE ARE RECEIVING DATA ZJH
{
BM2510(CANINTF,0x01,0x00);
RD2510(RXB0SIDH,2);
RecID_H=b[0];
RecID_L=b[1]&0xe0;
RD2510(RXB0DLC,1);
DLC=b[0]&0x0f;
RD2510(RXB0D0,DLC);
for(i=0;i<DLC;i++)
c[i]=b[i];
return 1;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -