📄 sja_interface.c
字号:
/******************************************************************************************/
//声明部分
#include <REGX51.H>
/******************************************************************************************/
//声明
#define base_adr 0x00 /*对SJA1000寻址的基址*/
#define error 0 /*错误标志*/
#define right 1 /*正确标志*/
#define sja_btr0 0x18
#define sja_btr1 0x1c
#define sja_acr 0xaa
#define sja_amr 0x00
#define sja_ocr 0xaa
#define sja_cdr 0x48
#define sja_oie 0
#define sja_eie 0
#define sja_tie 1 //发送中断
#define sja_rie 1 //接收中断
/******************************************************************************************/
//函数声明
void weakup_sev(void);
void data_over_sev(void);
void wrong_sev(void);
void send_sev(void);
void receive_sev(void);
/******************************************************************************************/
//位定义
bit send_bit=0; //发送程序执行标志位,1执行;0不执行
bit rece_bit=0; //接收程序执行标志位,1执行;0不执行
bit CAN_bit=0; //CAN模块动作,1动作;0不动作
/******************************************************************************************/
//全局变量的定义
unsigned char xdata *sja_base_adr=base_adr; /*定义地址指针,指向基址*/
bit bdata sja_mode=1; /*此位是1时SJA工作在工作模式,为0时工作在复位模式*/
unsigned char bdata inttemp=0x00;
/******************************************************************************************/
//端口定义
sbit cs=P1^0;
sbit inttemp_4=inttemp^4;
sbit inttemp_3=inttemp^3;
sbit inttemp_2=inttemp^2;
sbit inttemp_1=inttemp^1;
/******************************************************************************************/
//函数名称:write_can
//函数功能:向CAN控制器写数据
//入口参数:sja_adr,set_num(SJA的地址,向该地址写入的数据值)
//出口参数:无
//****备注:底层的硬件操作
void write_can(unsigned char sja_adr,set_num)
{
cs=0; /*使能SJA1000*/
*(sja_base_adr+sja_adr)=set_num;
}
/*******************************************************************************************/
//函数名称:read_can
//函数功能:从CAN控制器读数据
//入口参数:SJA的偏移地址
//出口参数:读出的数据
//****备注:底层的硬件操作
unsigned char read_can(unsigned char sja_adr)
{
unsigned char get_data; /*读出数据的暂存器*/
cs=0; /*使能SJA1000*/
get_data=*(sja_base_adr+sja_adr);
return(get_data);
}
/********************************************************************************************/
//函数名称:sja_connect_judge
//函数功能:判断单片机与CAN控制器的通讯是否成功
//入口参数:无
//出口参数:连接是否成功
//****备注:SJA1000的基本操作,和硬件有关,操作测试寄存器(地址:9)
bit sja_connect_judge(void)
{
write_can(0x09,0xcf);
if(read_can(0x09)==0xcf)
{
return(right);
}
else
{
return(error);
}
}
/********************************************************************************************/
//函数名称:set_rst_mode
//函数功能:设置SJA工作在复位模式
//入口参数:无
//出口参数:无
//****备注:SJA1000的基本操作,和硬件有关,操作控制寄存器(地址:0)
void set_rst_mode(void)
{
unsigned char control_reg_num; /*定义变量,用于存放向控制寄存器写入的数据*/
control_reg_num=read_can(0x00); /*先读控制寄存器的值*/
control_reg_num=control_reg_num|0x01; /*将(控制寄存器.0)置1,即设为复位模式*/
write_can(0x00,control_reg_num); /*写入SJA1000*/
while(sja_mode)
{
if(read_can(0x00)&0x01==1)
{
sja_mode=0; /*置复位成功*/
}
else
{
sja_mode=1; /*置复位失败*/
}
}
}
/********************************************************************************************/
//函数名称:set_work_mode
//函数功能:设置SJA工作在工作模式
//入口参数:无
//出口参数:无
//****备注:SJA1000的基本操作,和硬件有关,操作控制寄存器(地址:0)
void set_work_mode(void)
{
unsigned char control_reg_num;
control_reg_num=read_can(0x00);
control_reg_num=control_reg_num&0xfe; /*设置工作模式的数值,允许各个中断*/
while(sja_mode==0)
{
write_can(0x00,control_reg_num);
if((read_can(0x00)&0x01)==0)
{
sja_mode=1;
}
else
{
sja_mode=0;
}
}
}
/********************************************************************************************/
//函数名称:set_tra_rate
//函数功能:设置SJA的数据传输速率
//入口参数;sja_btr0,sja_btr1
//出口参数:设置是否成功
//****备注:SJA1000的基本操作,和硬件有关,操作总线定时器0、1(地址:6、7)
// *只能在复位模式下设置
// BTR0(地址:6)定义了数据传输速率预设值BRP和同步跳变宽度SJW,各位如下:
// ---------------------------------------------------------------
// 位 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 |
// ---------------------------------------------------------------
// 功能 | SJW1 | SJW0 | BRP5 | BRP4 | BRP3 | BRP2 | BRP1 | BRP0 |
// ---------------------------------------------------------------
// CAN的系统时钟Tscl=2*Tclk*(BRP+1),Tclk是SJA1000外部晶振的周期.同步跳变宽度SJW是为
// 补偿其在不同的总线控制的时钟振荡器之间的相位偏移,任何总线控制器必须在当前传送的
// 相位信号边沿重新同步。同步跳转宽度定义了每一位周期误差量。Tsjw=Tscl*(SJW+1)
// BTR1(地址:7)定义每个位的长度、采样点的位置和采样点的采样数目,各位如下:
// ----------------------------------------------------------------------
// 位 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 |
// ----------------------------------------------------------------------
// 功能 | SAM |TSEG2.2|TSEG2.1|TSEG2.0|TSEG1.3|TSEG1.2|TSEG1.1|TSEG1.0|
// ----------------------------------------------------------------------
// SAM为1,总线采样3次,用在低/中速总线,起到数字滤波的作用。SAM为0,总线采样1次,在
// 高速总线上使用。TSEG1和TSEG2确定每一位占用的时间和具体采样点的位置
// Tsyncseg=Tscl;Ttseg1=Tscl*TSEG1;Ttseg2=Tscl*TSEG2;
// 位周期: Tbit=(Tsyncseg+Ttseg1+Ttseg2)加减Tsjw
// 数据传输速率:f=1/Tbit
bit set_tra_rate(void)
{
while(sja_mode)
{
set_rst_mode();
}
write_can(0x06,sja_btr0);
write_can(0x07,sja_btr1);
if((read_can(0x06)==sja_btr0)&(read_can(0x07)==sja_btr1))
{
return(right);
}
else
{
return(error);
}
}
/********************************************************************************************/
//函数名称:set_data_sel
//函数功能:设置SJA接受数据类型
//入口参数:sja_acr,sja_amr
//出口参数:是否设置成功
//****备注:SJA1000的基本操作,和硬件有关,操作验收代码寄存器ACR(地址:4)和验收屏蔽寄存器AMR(地址:5)
// *只能在复位模式下设置
// CAN总线的数据不带目标地址,以广播的形式在总线上传播.每个设备通过设置验收代码寄存器ACR和
// 验收屏蔽寄存器AMR选择来自特定设备的数据.总线上的信息首先进入过滤逻辑,只有当信息的标识
// 符位和接收过滤寄存器中的值相同时才送入RXFIFO。接收过滤寄存器的值由验收代码寄存器和验收
// 屏蔽寄存器的内容决定。当屏蔽寄存器的某个位为0时,表示接收时对应位接受检测;当屏蔽寄存器
// 的某位为1时,表示对应位被屏蔽(不接受检测)。接收信息的标识符必须满足最高8位与屏蔽寄存
// 器的8位对应,没有被屏蔽的位必须与接收码寄存器的对应位一致,才被接收并送入RXFIFO,信息才
// 被接受。通过过滤的信息被存入RXFIFO中,当整个信息完全被接收后,接收状态标志位被置为1;当
// 接收中断请求允许时,置位接收中断请求标志将发送接收中断请求。
bit set_data_sel(void)
{
while(sja_mode)
{
set_rst_mode();
}
write_can(0x04,sja_acr);
write_can(0x05,sja_amr);
if((read_can(0x04)==sja_acr)&(read_can(0x05)==sja_amr))
{
return(right);
}
else
{
return(error);
}
}
/********************************************************************************************/
//函数名称:set_clk_mode
//函数功能:设置CAN的工作模式,输出信号形式和输出时钟的形式
//入口参数:sja_ocr,sja_cdr
//出口参数:设置是否成功
//****备注:SJA1000的基本操作,和硬件有关,操作输出控制寄存器OCR(地址:8)和时钟分频寄存器CDR(地址:31)
// *只能在复位模式下设置
// 输出控制寄存器实现由软件控制不同输出驱动配置的建立,各位如下:
// ---------------------------------------------------------------------
// 位 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 |
// ---------------------------------------------------------------------
// 功能| OCTP1 | OCTN1 |OCPOL1 | OCTP0 | OCTN0 |OCPOL0 |OCMODE1|OCMODE0|
// ---------------------------------------------------------------------
// 当SJA1000在睡眠模式时,TX0和TX1引脚根据输出控制寄存器的内容输出隐性电平.当SJA1000在复位
// 状态时,TX0和TX1引脚悬空。发送数据的时候可以有不同的输出方式,列如下:
// ---------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -