📄 canjishou.c
字号:
/*中断方式接收CAN数据*/
#include<reg52.h>
#include<intrins.h>
#include "SJA100REG.H"
sfr CKCON=0xb6; //定义时钟控制寄存器
sfr IPH=0xb7; //中断器优先级高位
sbit RST_SJA1000=P1^7;//SJA1000硬件复位
sbit CS_SJA1000= P2^7;//片选信号
sbit SHANGDIAN_ID1= P1^3;//
sbit STATE_ID2= P1^4;//
sbit STATE_ID3= P1^5;//
sbit STATE_ID4= P1^6;//
sbit LED0= P1^0;//
sbit LED1= P1^1;//
sbit LED2= P1^2;//
unsigned char TIME_counter=0;
unsigned char TIME_counter1=0;
unsigned char TIME_counter2=0;
unsigned char counter=0;
unsigned char BTR0,BTR1;
//unsigned char xdata CAN_SJA_BaseAdr _at_ 0x7f00; //定义SJA1000的片选基址
#define CAN_SJA_BaseAdr 0x7f00 //定义sja1000的片选基址
unsigned char xdata *SJA_CS_Point ; //指针指向空
unsigned char Send_CAN_Filter[8]={0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff};//验收及屏蔽数据
//unsigned char Send_CAN_Filter[8]={0x07,0x80,0x07,0xF7,0xE0,0x00,0xE0,0x00};//验收及屏蔽数据 /此数据是根据已知四个
//四个PGN定义的,如果再加,还得变化
unsigned char Rev_CAN_data[13]; //07 f7 88 00CAN总线通讯接受存储单元
unsigned char Rev_COM_data[13]={0x88,0x07,0xF7,0x88,0x00,0x11,0x01,0x66,0x55,0x44,0x33,0x22,0x11}; //串口通讯接受存储单元
unsigned char Signal_Stor_data[6];//要传给串口需要上传的信息 ,0 1字节 速度、
// 2字节状态信号 ,BIT4上电 BIT3状态4 BIT2状态3 BIT1状态2 BIT0刹车
// 3 4字节 发动机转速。
// 5 6字节 水温
//unsigned char Extand_Stor_ID[10];//0存放可选信号的状态(需要采哪些信号1需要,0不需要)
//1字节存可选信号的类型(CAN没有固定的,看是用CAN采1,还是脉冲采0)
//2 3字节存状态1信号的ID 上电信号
//4 5字节存状态2信号的ID
//6 7字节存状态3信号的ID
//8 9字节存状态4信号的ID
bit CAN_INT_bz=0; //看有无报文
bit Com_Begin_bz=0; //串口数据开始接受
//bit error_bz=0;
bit txcs_bz=0; //串口通讯超时标志
bit ID_Config_bz=0; //ID初始化标志,进入正常通讯之后还要判断是否进行过了上电初始化。
/*
void Delay_ms(unsigned char j)
{
unsigned char k,l;
for(l=0;l<=j;l++)
{
for(k=0;k<=250;k++)
{
;
}
}
}
------------------------------------------------------------------------------------------------------*/
/*硬件复位SJA1000*/
void SJA1000_HardwareRst(void)
{ RST_SJA1000=0;
// Delay_ms(50);
// Delay_ms(50);
// Delay_ms(50);
// RST_SJA1000=1;
// Delay_ms(50);
// Delay_ms(50);
// Delay_ms(10);
RST_SJA1000=0;
}
/*--------------------------------------------------------------------------------------------------------
** 函数原型: unsigned char SJAEntryResetMode(void)
** 功能描述: 该函数用于使sja1000进入复位模式
** 参数说明: 无
** 返回值: 1 表示SJA1000进入复位模式成功
** 0 表示SJA1000进入复位模式失败
/*------------------------------------------------------------------------------------------------------*/
bit SJAEntryResetMode(void)
{
unsigned char TempData;
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_MOD; //访问地址指向控制寄存器
TempData= *SJA_CS_Point; //保存原始值
*SJA_CS_Point=(TempData|0x01); //置位复位请求
_nop_();
_nop_();
if((*SJA_CS_Point&0x01) == 1)
{
return 0;
}
else
{
return 1;
}
}
/*--------------------------------------------------------------------------------------------------------
** 函数原型: unsigned char SJAQuitResetMode(void)
** 功能描述: 该函数用于使sja1000退出复位模式,进入工作模式
** 参数说明: 无
** 返回值: 1 表示SJA1000退出复位模式成功
** 0 表示SJA1000退出复位模式失败
/*------------------------------------------------------------------------------------------------------*/
bit SJAQuitResetMode(void)
{
unsigned char TempData;
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_MOD; //
TempData= *SJA_CS_Point; //保存原始值
*SJA_CS_Point=(TempData&0xfe); //释放复位请求
_nop_();
_nop_();
if((*SJA_CS_Point&0x01) == 0)
{
return 0;
}
else
{
return 1;
}
}
/*--------------------------------------------------------------------------------------------------------
** 函数原型: unsigned char WriteSJARegBlock(unsigned char RegAdr,unsigned char *ValueBuf,unsigned char len)
** 功能描述: 该函数用于将指定的数值写入sja1000的指定的寄存器
** 参数说明: RegAdr 要写入的sja1000的内部寄存器地址
** ValueBuf 要写入寄存器的值的存储器地址
** len 要写入sja1000内部寄存器的长度
** 返回值: 1 写入正确
** 0 写入不正确
/*------------------------------------------------------------------------------------------------------*/
WriteSJARegBlock(unsigned char RegAdr,unsigned char *ValueBuf,unsigned char len)
{ unsigned char TempData;
for(TempData=0;TempData<len;TempData++)
{ SJA_CS_Point = CAN_SJA_BaseAdr+RegAdr+TempData; //
*SJA_CS_Point = ValueBuf[TempData];
}
}
/*--------------------------------------------------------------------------------------------------------
** 函数原型: WriteSJAReg(unsigned char RegAdr,unsigned char Value)
** 功能描述: 该函数用于将指定的数值写入sja1000的指定的寄存器
** 参数说明: RegAdr 要读的sja1000的内部寄存器地址
** Value 写入寄存器的值
** 返回值: 1 写入正确
** 0 写入不正确
/*------------------------------------------------------------------------------------------------------*/
bit WriteSJAReg(unsigned char RegAdr,unsigned char Value)
{
SJA_CS_Point = CAN_SJA_BaseAdr+RegAdr; //
*SJA_CS_Point =(*SJA_CS_Point|Value);
_nop_();
_nop_();
if(*SJA_CS_Point ==(*SJA_CS_Point|Value))
{
return 0;
}
else
{
return 1;
}
}
/*--------------------------------------------------------------------------------------------------------
** 函数原型: WriteSJAReg(unsigned char RegAdr,unsigned char Value)
** 功能描述: 该函数用于将指定的数值写入sja1000的指定的寄存器
** 参数说明: RegAdr 要读的sja1000的内部寄存器地址
** Value 写入寄存器的值
** 返回值: 1 写入正确
** 0 写入不正确
适合于向内部寄存器中某存储单元写数据。写入的是一个字节
/*------------------------------------------------------------------------------------------------------*/
bit WriteSJARegByte(unsigned char RegAdr,unsigned char Value)
{
SJA_CS_Point = CAN_SJA_BaseAdr+RegAdr; //
*SJA_CS_Point =Value;
_nop_();
_nop_();
if(*SJA_CS_Point ==Value)
{
return 0;
}
else
{
return 1;
}
}
/*串口发送子程序
void Comout(unsigned char OutData)
{
EA=0;
SBUF = OutData; //输出字符
while(!TI); //空语句判断字符是否发完
TI = 0; //清TI
EA=1;
} */
/*--------------------------------------------------------------------------------------------------------
** 函数原型: void SJA1000_Config_Normal(void)
** 功能描述: 对SJA1000的正常模式的初始化配置
** 参数说明: 无
** 返回值: 无
/*------------------------------------------------------------------------------------------------------*/
void SJA1000_Config_Normal(void) //正常模式的初始化
{ bit SJAReg_bz=1;
BTR0=0x01;
BTR1=0x1c; //设置为250kb波特率通信
while(SJAReg_bz)
{SJAReg_bz=WriteSJARegByte(REG_CAN_TEST,0xaa);} //测试接口
//SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_TEST;
//Comout(*SJA_CS_Point);
SJAReg_bz=1;
while(SJAReg_bz)
{SJAReg_bz=WriteSJARegByte(REG_CAN_TEST,0x55);}
//SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_TEST;
//Comout(*SJA_CS_Point);
SJAReg_bz=1;
while(SJAReg_bz)
{SJAReg_bz=SJAEntryResetMode();} //进入复位模式
//SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_MOD;
//Comout(*SJA_CS_Point);
WriteSJARegByte(REG_CAN_CDR,0xc8); //配置时钟分频寄存器,选择PeliCAN模式
SJAReg_bz=1;
while(SJAReg_bz)
{SJAReg_bz=WriteSJAReg(REG_CAN_MOD,0x01);} //配置模式寄存器,选择双滤波、正常模式
WriteSJARegBlock(16,Send_CAN_Filter,8); //配置验收代码/屏蔽寄存器
SJAReg_bz=1;
while(SJAReg_bz)
{SJAReg_bz=WriteSJARegByte(REG_CAN_BTR0,BTR0);} //配置总线定时器0
//SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_BTR0;
// Comout(*SJA_CS_Point);
SJAReg_bz=1;
while(SJAReg_bz)
{SJAReg_bz=WriteSJARegByte(REG_CAN_BTR1,BTR1);} //配置总线定时器1
//SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_BTR1;
// Comout(*SJA_CS_Point);
WriteSJARegByte(REG_CAN_OCR,0x1a); //配置输出管脚
//SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_OCR;
// Comout(*SJA_CS_Point);
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_TXERR; //清发送错误计数寄存器.
*SJA_CS_Point = 0;
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_ECC; // 错误代码捕捉寄存器
TIME_counter = *SJA_CS_Point;
TIME_counter=0; //清除错误代码捕捉寄存器
SJAReg_bz=1;
while(SJAReg_bz)
{SJAReg_bz=SJAQuitResetMode();} //退出复位模式,进入工作模式
//SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_MOD;
// Comout(*SJA_CS_Point);
}
/*------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------*/
main()
{
//CKCON=0x04;
IP=1;
IPH=1;
TMOD=0x21; // 定时器T0为方式1,T1为方式2
TH0=0x00;
TL0=0x00; //定时器0设置,暂时先开开,可能用不上
TR0=1;
ET0=1;
TH1=0x00;
TL1=0x00; //定时器1设置,暂时先开开,可能用不上
TR1=1;
ET1=1;
RCLK=1;
TCLK=1; //定时器2用作波特率发生器 T2CON中的值
RCAP2H=0xff;
//RCAP2L=0xB8; //初步设定波特率为9600
RCAP2L=0xDC; //初步设定波特率为19200
//RCAP2L=0xEE; //jiabei
SCON=0x50; //串口方式为模式1,无校验,定时器2产生波特率
TR2=1; //开定时器2
//ET2=1; //使能定时器2
IT0=1; // 负边缘触发
//EX0=1; //外部中断使能
ES=1; //使能串口
// EA=1;
CS_SJA1000=0;//开片选信号
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
// SJA_CS_Point=CAN_SJA_BaseAdr; //确定基址指针的值
SJA1000_HardwareRst();
SJA1000_Config_Normal(); //调用SJA1000初始化配置函数
//WriteSJAReg(REG_CAN_IER,RIE_BIT); //使能SJA1000jieshou中断
EX0=1; //打开INT0中断
EA=1;
while (1)
{
//使能MCU总中断
/*if( CAN_INT_bz==1)
{
unsigned char j;
//EA=0;
CAN_INT_bz=0;
LED0=!LED0;
for(j=0;j<13;j++)
{
Comout(Rev_CAN_data[j]);
Rev_CAN_data[j]=0;
}
//EA=1;
}*/
if(counter>=1)
{
counter=0;
Rev_COM_data[7]++;
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_SR;
if((*SJA_CS_Point&0x04) == TBS_BIT)
{ unsigned char j;
for(j=0;j<13;j++) //开始将接收到的TempData个字节的数据存到CPU的数据缓冲区里
{
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_RXFMINFO+j;
*SJA_CS_Point=Rev_COM_data[j];
}
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_CMR;
*SJA_CS_Point = TR_BIT;
}
}
}
}
/* void CAN(void) interrupt 0 using 0
{ LED1=!LED1;
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_IR;
while((*SJA_CS_Point&0x01) == RI_BIT)
{ unsigned char j; //TempData,j;
// TempData=*SJA_CS_Point&0x0F; //取数据字节数目
//TempData=TempData+0x04; //ID29位加上数据的字节数 ,不用要信息帧。
for(j=0;j<13;j++) //开始将接收到的TempData个字节的数据存到CPU的数据缓冲区里
{
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_RXFMINFO+j;
Rev_CAN_data[j] = *SJA_CS_Point;
}
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_CMR; //释放接收缓冲区,可以直接接收了
*SJA_CS_Point = RRB_BIT;
CAN_INT_bz=1;
}
}
*/
void Timer0() interrupt 1 using 1 //主要作用是定时当一定时间到了可以检测应该完成的任务完成了么
{
TH0 = 0x99;
TL0 = 0x99;
TIME_counter++;
counter++;
if(TIME_counter>=10)
{
TIME_counter=0;
LED2=!LED2;
}
}
void Timer1() interrupt 3 using 2
{
TH1 = 0X00;
TL1 = 0x00;
TIME_counter1++;
TIME_counter2++;
if(TIME_counter1>=254)
{
TIME_counter1=0;
//STATE_ID4=!STATE_ID4;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -