📄 canzj.c
字号:
#include <P18F258.H>
#include "MCP2510.H"
#include <delays.h>
void MCP2510Rec(void);
//------------------------------------
struct JFSC //计时时长、
{
unsigned char hour;
unsigned char min;
unsigned char sec;
unsigned char msec;
};
typedef union {
unsigned char word;
struct {
unsigned TMSEC_BIT:1; //100ms事件
unsigned TSEC_BIT:1; //1s事件
unsigned TMIN_BIT:1; //1min事件
unsigned THOUR_BIT:1; //1hour事件
unsigned CANRV_BIT:1;//CAN接收标志
unsigned CAN2510RV_BIT:1;//CAN2510接收标志
unsigned INT0_BIT:1;
unsigned RSV1_BIT:1;
}Bits;
}uProceSate;
struct CanRevType
{
unsigned char FrameID[4];
unsigned char FrameData[8];
};
typedef union {
unsigned char word;
struct {
unsigned RX0IF:1; //接收缓冲器0 满中断标志
unsigned RX1IF:1; //接收缓冲器1 满中断标志
unsigned TX0IF:1; //发送缓冲器0 空中断标志
unsigned TX1IF:1; //发送缓冲器1 空中断标志
unsigned TX2IF:1; //发送缓冲器2空中断标志
unsigned ERRIF:1; //出错中断标志
unsigned WAKIF:1; //唤醒中断标志
unsigned MERRF:1; //报文出错中断标志
}Bits;
}CAN2510IntStatus;
//------------变量--------------------
volatile struct JFSC CLOCK;
volatile uProceSate StateTemp;
struct CanRevType CanTxData;
struct CanRevType Can2510TxData;
volatile struct CanRevType CanRevData;
volatile struct CanRevType Can2510RevData;
unsigned char DebugErrorCode;//错误代码
unsigned char TestTryTime;
volatile CAN2510IntStatus MCP2510IntStatus;
unsigned char Thread;
//--------------------------------------
#define NO_THREAD 0x00
#define THREAD_IDLE 0x01
//#define Debug
//----------- 初始化程序---------------
void init_cpu(void)
{
//---------------------
INTCON = 0x00; //禁止所有中断
INTCON2 = 0x00;//int0 下降沿中断
INTCON3 = 0x00;
ADCON1 = 0x87; //设置所有与模拟输入共用的管腿为I/O方式
//---初始化管腿------------
TRISA = 0xfc;//RA0 RA1为输出
TRISB = 0xfb;//配置CAN
TRISC = 0xd0;//配置SPI SDO为输出 SDI为输入 SCK为输出
//---初始化timer0------------
T0CON = 0x8F;//16位定时器,不使用分频器
TMR0H = 0xD8;
TMR0L = 0xEF;//定时10ms
//------初始化CAN控制器--------
CANCON = 0x80;//进入配置方式
//while((CANSTAT&0x80)==0x00);//等待进入配置模式
DebugErrorCode=0x00;
TestTryTime=100;
while(TestTryTime--) //等待进入配置模式
{
if((CANSTAT&0x80)==0x80) break;
}
if(TestTryTime==0x00) DebugErrorCode=CAN_ENTCONFG_ERR;
//设置CAN的波特率为5K,在Fosc=4M时,Tbit=200us,假设BRP=39, 则
//TQ=[2*(1+BRP)]/Fosc=2*(1+39)/4=20us。
//NOMINAL BIT RATE=10TQ,SJW=1,Sync_Seg=1TQ,Prog _Seg=1TQ,Phase_Seg1=4TQ,Phase_Seg2=4TQ
BRGCON1 = 0x27; //设置SJW和BRP,SJW=1TQ,BRP=39H
BRGCON2 = 0x98; //设置Phase_Seg1=4TQ和Prog _Seg=1TQ
BRGCON3 = 0x43; //设置Phase_Seg2=4TQ
CIOCON = 0x00;//设置CAN输入输出控制寄存器
TXB0CON = 0x03;//设为最高优先级
TXERRCNT= 0x00;//清除发送错误计数器
RXB0CON = 0x00;//接收所有有效信息
RXB0DLC = 0x08;//接收数据长度为8
RXERRCNT= 0x00;//清除接收错误计数器
//初始化接收滤波器
RXF0SIDH= 0xff;
RXF0SIDL= 0xeb;
RXF0EIDH= 0xff;
RXF0EIDL= 0xff;
RXM0SIDH= 0x00;
RXM0SIDL= 0x00;
RXM0EIDH= 0x00;
RXM0EIDL= 0x00;
CANCON = 0x00;//进入正常工作模式
//while((CANSTAT&0xE0)!=0x00);//等待进入正常模式
TestTryTime=100;
while(TestTryTime--) //等待进入正常模式
{
if((CANSTAT&0xE0)==0x00) break;
}
if(TestTryTime==0x00) DebugErrorCode=CAN_QUITCONFG_ERR;
PIR3 = 0x00; //清除所有中断标志
//PIE3 = 0x01; //使能接收0的中断
//PIE3 = 0xe1; //使能接收0的中断
PIE3 = 0x61; //使能接收0的中断
IPR3 = 0x01; //接收0的中断为最高优先级
//------初始化SPI------------------
PIE1bits.SSPIE=0; //禁止中断
SSPCON1 = 0x30; //SSPEN=1;CKP=1;主控方式Fosc/4(1M波特率)
SSPSTAT = 0xc0;
PIR1bits.SSPIF=0;//清除SSPIF标志
//------设置中断优先级--------------
INTCON2bits.TMR0IP=0;//timer0 高优先机
RCONbits.IPEN=1;//使能中断优先级
//------初始化管腿----------------
PORTAbits.RA0=0;
PORTAbits.RA1=0;
CAN2510Disable();
MCP2510REST=1;
Thread=NO_THREAD;
StateTemp.word=0x00;//清标志位
}
//------timer0中断程序------------------
void timer0int(void);
#pragma code Low_Vector=0x18
void InterruptVectorLow (void)
{
_asm
goto timer0int
_endasm
}
#pragma code
#pragma interrupt timer0int
void timer0int(void)
{
unsigned char temp;
if(INTCONbits.T0IF)//timer0中断
{
TMR0H = 0xD9;
TMR0L = 0x7a;//定时10ms
INTCONbits.T0IF=0; //清中断标志
if((CLOCK.msec%10)==0) StateTemp.Bits.TMSEC_BIT=1; //100ms事件
if(++CLOCK.msec>=100)
{
CLOCK.msec=0;
StateTemp.Bits.TSEC_BIT=1;//秒事件
++CLOCK.sec;
temp=CLOCK.sec;
if((temp&0x0f)>9) CLOCK.sec=(temp&0xf0)+0x10;
if(CLOCK.sec>=0x60)
{
CLOCK.sec=0;
StateTemp.Bits.TMIN_BIT=1; //分事件
++CLOCK.min;
temp=CLOCK.min;
if((temp&0x0f)>9) CLOCK.min=(temp/16)*16+0x10;//(temp&0xf0)+0x10;
if(CLOCK.min>=0x60)
{
StateTemp.Bits.THOUR_BIT=1;//小时事件
CLOCK.min=0;
CLOCK.hour++;
temp=CLOCK.hour;
if((temp&0x0f)>9) CLOCK.hour=CLOCK.hour&0xf0+0x10;
if(CLOCK.hour==0x24) CLOCK.hour=0;
}
}
}
}
}
//------------------CAN程序-----------------------------
void send_data(unsigned char FrameType, unsigned char IDbuff[4],unsigned char DataBuff[8])
{
unsigned char temp;
unsigned char temp1;
unsigned char Flag;
Flag=0x00;
temp1=IDbuff[1]>>5;
temp=IDbuff[0]<<3;
TXB0SIDH=temp+temp1;
temp1=(IDbuff[1]&0x1f)<<3;//取后5位
temp=IDbuff[1]&0x03;//取后2位
temp1=temp1+temp;
if(FrameType==1) temp1=temp1|0x08;
if(FrameType==0) temp1=temp1&0xf7;
TXB0SIDL= temp1;
TXB0EIDH= IDbuff[2];
TXB0EIDL= IDbuff[3];
TXB0DLC = 0x08;//设置发送数据长度为8
TXB0D0 = DataBuff[0];
TXB0D1 = DataBuff[1];
TXB0D2 = DataBuff[2];
TXB0D3 = DataBuff[3];
TXB0D4 = DataBuff[4];
TXB0D5 = DataBuff[5];
TXB0D6 = DataBuff[6];
TXB0D7 = DataBuff[7];
TXB0CONbits.TXREQ=1;//请求发送
while(PIR3bits.TXB0IF!=1) //ClrWdt(); //等待
{
ClrWdt(); //等待
if(TXB0CONbits.TXLARB)//丢失仲裁,(断路)
{
TXB0CONbits.TXABT=1;//中止发送
TXB0CONbits.TXREQ=0;
TXERRCNT= 0x00;//清除发送错误计数器
DebugErrorCode=CAN_SEND1_ERR;
Flag=0x01;
break;
}
if(TXB0CONbits.TXERR)//总线错误(短路)
{
TXB0CONbits.TXABT=1;//中止发送
TXB0CONbits.TXREQ=0;
TXERRCNT= 0x00;//清除发送错误计数器(可能不起作用)
DebugErrorCode=CAN_SEND2_ERR;
Flag=0x02;
break;
}
if(COMSTATbits.TXBO)//发送错误计数大于255,总线关闭
{
TXB0CONbits.TXABT=1;//中止发送
TXB0CONbits.TXREQ=0;
TXERRCNT= 0x00;//清除发送错误计数器(可能不起作用)
DebugErrorCode=CAN_SEND3_ERR;
Flag=0x03;
break;
}
}
if(Flag==0x00) DebugErrorCode=CAN_SENDOK;
}
void CanRecvInt(void);
#pragma code High_Vector=0x08
void InterruptVectorHigh (void)
{
_asm
goto CanRecvInt
_endasm
}
#pragma code
#pragma interrupt CanRecvInt
void CanRecvInt(void)
{
unsigned char temp,temp1,temp2;
//INTCONbits.GIE=0;//关总中断
PORTAbits.RA1=0;
//----------PIC18F258 CAN中断程序-------------
if(PIR3bits.RXB0IF==1) //接收缓冲区0接收中断
{
temp=RXB0SIDH;
temp1=RXB0SIDL;
CanRevData.FrameID[0]=temp>>3;
temp2=temp1&0x03;//取后2位
temp2=temp2+((temp1&0xe0)>>3);
temp2=((temp&0x07)<<5)+temp2;
CanRevData.FrameID[1]=temp2;
CanRevData.FrameID[2]=RXB0EIDH;
CanRevData.FrameID[3]=RXB0EIDL;
CanRevData.FrameData[0]=RXB0D0;
CanRevData.FrameData[1]=RXB0D1;
CanRevData.FrameData[2]=RXB0D2;
CanRevData.FrameData[3]=RXB0D3;
CanRevData.FrameData[4]=RXB0D4;
CanRevData.FrameData[5]=RXB0D5;
CanRevData.FrameData[6]=RXB0D6;
CanRevData.FrameData[7]=RXB0D7;
StateTemp.Bits.CANRV_BIT=1; //置接收标志
RXB0CONbits.RXFUL=0;//清除接收缓冲区
PIR3bits.RXB0IF=0; //清除接收中断
}
if(PIR3bits.IRXIF==1) //错误收信息中断,与监听模式联合使用确定波特率
{
PIR3bits.IRXIF=0;
}
if(PIR3bits.WAKIF==1) //总线唤醒中断,休眠模式下,退出休眠
{
PIR3bits.WAKIF=0;
}
if(PIR3bits.ERRIF==1) //总线错误中断
{
PORTAbits.RA1=0;
if(COMSTATbits.RXB0OVFL)//接收缓冲区0溢出
{
COMSTATbits.RXB0OVFL=0;//清除溢出
DebugErrorCode=CAN_REVBUFF0_ERR;
}
if(COMSTATbits.RXWARN)//接收器警告位
{
RXERRCNT= 0x00;//清除接收错误计数器
DebugErrorCode=CAN_REVWAR_ERR;
}
if(COMSTATbits.TXBO)//发送错误计数大于255,总线关闭
{
TXB0CONbits.TXABT=1;//中止发送
TXB0CONbits.TXREQ=0;
TXERRCNT= 0x00;//清除发送错误计数器(可能不起作用)
DebugErrorCode=CAN_SEND3_ERR;
CANCON = 0x00;//进入正常工作模式
TestTryTime=20;
while(TestTryTime--) //等待进入正常模式
{
ClrWdt();
if((CANSTAT&0xE0)==0x00) break;
}
}
PIR3bits.ERRIF=0;
}
//---------MCP2510 Can中断程序-------------------
if(INTCONbits.INT0F) //外部中断,用于接收mcp2510
{
INTCONbits.INT0F=0;//清除中断
//MCP2510Rec();
StateTemp.Bits.INT0_BIT=1;
}
//INTCONbits.GIE=1;//开总中断
}
//--------------SPI程序-------------------------
void WriteSPI(unsigned char OutData)
{
SSPBUF = OutData;//启动发送
do{
ClrWdt();
}while(PIR1bits.SSPIF==0);//等待发送结束
PIR1bits.SSPIF=0;//清除标志位
}
//从一地址读一个字节
unsigned char ReadSPI(void)
{
unsigned char spidata;
SSPBUF = 0x00; //清除SSPSTAT的BF位
TestTryTime=100;
while(TestTryTime--)
{
if(SSPSTATbits.BF==1)
{
spidata = SSPBUF;//读出数据
PIR1bits.SSPIF=0;
}
}
return(spidata);
}
//--------------MCP2510程序--------------------
//复位程序,复位后,自动进入配置模式
void CAN2510Reset(void)
{
ClrWdt();
CAN2510Enable();
Nop();
MCP2510REST=0;
Delay100TCYx(2);
MCP2510REST=1;
Delay100TCYx(2);
CAN2510Disable();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -