📄 canceshi.c
字号:
/*查询方式接收CAN数据*/
#include<reg52.h>
#include<intrins.h>
#include "SJA100REG.H"
sbit RST_SJA1000=P1^7;//SJA1000硬件复位
sbit CS_SJA1000= P2^7;//片选信号
unsigned char BTR0,BTR1;
unsigned char xdata CAN_SJA_BaseAdr _at_ 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[12]; //CAN总线通讯接受存储单元
unsigned char xdata Rev_COM_data[12]; //串口通讯接受存储单元
unsigned char xdata Signal_Stor_data[6];//要传给串口需要上传的信息 ,0 1字节 速度、
// 2字节状态信号 ,BIT4上电 BIT3状态4 BIT2状态3 BIT1状态2 BIT0刹车
// 3 4字节 发动机转速。
// 5 6字节 水温
unsigned char xdata 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(5);
Delay_ms(5);
Delay_ms(5);
RST_SJA1000=1;
Delay_ms(5);
}
/*--------------------------------------------------------------------------------------------------------
** 函数原型: 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 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);} //测试接口
SJAReg_bz=1;
while(SJAReg_bz)
{SJAReg_bz=WriteSJARegByte(REG_CAN_TEST,0x55);}
SJAReg_bz=1;
while(SJAReg_bz)
{SJAReg_bz=SJAEntryResetMode();} //进入复位模式
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
SJAReg_bz=1;
while(SJAReg_bz)
{SJAReg_bz=WriteSJARegByte(REG_CAN_BTR1,BTR1);} //配置总线定时器1
WriteSJARegByte(REG_CAN_OCR,0x1a); //配置输出管脚
SJAReg_bz=1;
while(SJAReg_bz)
{SJAReg_bz=SJAQuitResetMode();} //退出复位模式,进入工作模式
}
/*------------------------------------------------------------------------------------------------------*/
main()
{ //IP=1;
//IPH=1;
//TMOD=0x21;
// TH0=0x00;
// TL0=0x00; //定时器0设置,暂时先开开,可能用不上
// TR0=1;
//ET0=1;
//RCLK=1;
//TCLK=1; //定时器2用作波特率发生器 T2CON中的值
//RCAP2H=0xff;
//RCAP2L=0xB8; //初步设定波特率为9600
//SCON=0x50; //串口方式为模式1,无校验,定时器2产生波特率
//TR2=1; //开定时器2
//ES=1; //使能串口
while (1)
{
CS_SJA1000=0;//开片选信号
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SJA_CS_Point=&CAN_SJA_BaseAdr; //确定基址指针的值
SJA1000_HardwareRst();
SJA1000_Config_Normal(); //调用SJA1000初始化配置函数
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_SR;
while((*SJA_CS_Point&0x01) == RBS_BIT)
{ unsigned char TempData,j;
TempData=*SJA_CS_Point&0x0F; //取数据字节数目
TempData=TempData+0x04; //ID29位加上数据的字节数 ,不用要信息帧。
for(j=0;j<TempData;j++) //开始将接收到的TempData个字节的数据存到CPU的数据缓冲区里
{
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_TXBUF1+j;
Rev_CAN_data[j] = *SJA_CS_Point;
}
SJA_CS_Point = CAN_SJA_BaseAdr+REG_CAN_CMR; //释放接收缓冲区,可以直接接收了
*SJA_CS_Point = RRB_BIT;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -