📄 sja1000.c
字号:
TX_Buff_Tail = 0; // 指针循环
} while((i<8) &&(TX_Buff_Head != TX_Buff_Tail));
if ((CANConfig.Mode & 0x04) == 0)
{//标准帧
REG_RxBuffer0 = i;
}
else
{//扩展帧
REG_RxBuffer0 = 0x80 + i;
}
REG_CMR = 0x01; //发送命令
}
ON_CAN_INT();
return TRUE;
}
/*******************************************************************
CAN初始化函数
参数:Mode:0:设置成basic模式 1:设置成PELICAN模式
返回: 初始化成功返回TRUE,否则FALSE
注:先调PeliCan,有时间再调BasicCan
*/
bit CAN_Init(void)
{
unsigned char Temp,i;
RESET_SJA1000(); //复位芯片
//设置之前先进入复位模式
/*00000001,进入复位模式, MOD | | | |SM|AFM|STM|LOM|RM|
SM: 睡眠模式 1 睡眠;没有CAN中断等待和总线活动时,CAN控制器进入睡眠模式 0 唤醒;从睡眠状态唤醒
AFM 验收滤波器模式 1 单;选择单个验收滤波器(32位长度) 0 双;选择两个验收滤波器(每个有16位激活)
STM 自检测模式 1 自检测; 此模式可以检测所有节点,没有任何活动的节点使用自接收命令;即使没有应答,CAN控制器也会成功发送
0 正常模式;成功发送时必需应答信号
LOM 只听模式 1只听;这种模式中,即使成功接收信息,CAN控制器也不向总线发应答信号;错误计数器停止在当 0 正常模式
RM 复位模式 1 复位;检测到复位模式位被置位,中止当前正在接收/发送的信息,进入复位模式
0 正常;复位模式位接收到’1-0’的跳变后,CAN控制器回到工作模式 */
i = 0;
do {
REG_MODE = 0x01;
Temp = REG_MODE;
if ((Temp & 0x01) == 0x01)
{
break; //成功进入复位模式
}
Delay(10); //延时一定时间
Temp = REG_MODE;
if ((Temp & 0x01) == 0x01)
{
break; //成功进入复位模式
}
i++;
} while(i< 10);
if (i > 9)
{
return FALSE;
}
/***至此芯片已经进入复位模式************/
if((CANConfig.Mode & 0x01) == CAN_MODE_BASICCAN)
{//确保进入工作模式,确保的时候,加一个超时显示
return TRUE;
}
else if ((CANConfig.Mode & 0x01) == CAN_MODE_PELICAN)
{
REG_IR_ABLE = 0x00; //禁止中断
REG_BTR0 = CANConfig.BTR0;// 设置波特率
REG_BTR1 = CANConfig.BTR1;// 设置波特率
/*00011010, 输出控制寄存器OCR |OCTP1|OCTN1|OCPOL1|OCTP0|OCTN0|OCPOL0|OCMODE1|OCMODE0|
OCMODE1=1,OCMODE=0 正常工作模式
驱动 TXD OCTPX OCTNX OCPOLX TXX
上拉 0 1 1 0 低
1 1 1 0 高
*/
REG_OCR = 0x1a;
//最高位是1,CAN 控制器工作于PeliCAN 模式.其它位暂不用管。
REG_CDR = 0xc0; //11000000 ,
REG_RBSA = 0x00; //硬件复位后就是0x00。
REG_ACR0 = CANConfig.ACR0;//根据ID号设置。当与ID号相等,并且与相应的AMR位(相关的话,置0。不相关置1)或运算等于1,则接受。
REG_ACR1 = CANConfig.ACR1; //接收屏蔽寄存器AMR的作用应该是可以接收相似的来自不同ID的数据。
REG_ACR2 = CANConfig.ACR2;
REG_ACR3 = CANConfig.ACR3;
REG_AMR0 = CANConfig.AMR0;
REG_AMR1 = CANConfig.AMR1;
REG_AMR2 = CANConfig.AMR2;
REG_AMR3 = CANConfig.AMR3;
if ((CANConfig.Mode & 0x02) == 0) //设置滤波器的模式
{
REG_MODE = 0x0;
}
else
{
REG_MODE = 0x08;
}
/*11111111, 中断使能寄存器IER |BEIE|ALIE|EPIE |WUIE|DOIE|EIE|TIE|RIE|
BEIE 总线错误中断使能 1 使能;如果检测到总线错误,则CAN控制器请求相应的中断
0 禁能
ALIE 仲裁丢失中断使能 1 使能;如果CAN控制器已丢失了仲裁,则请求相应的中断
0 禁能
EPIE 错误消极中断使能 1 使能;若CAN控制器的错误状态改变(从消极到活动或反之), 则请求相应的中断
0 禁能
WUIE 唤醒中断使能 1 使能;如果睡眠模式中的CAN控制器被唤醒,则请求相应的中断
0 禁能
DOIE 数据溢出中断使能 1 使能;如果数据溢出状态位被置位,CAN控制器请求相应的中断
0 禁能
EIE 错误报警中断使能 1 使能;如果错误或总线状态改变,CAN控制器请求相应的中断
0 禁能
TIE 发送中断使能 1使能;当信息被成功发送或发送缓冲器又可访问(例如,中止发送命令后)时,CAN控制器请求相应的中断
0 禁能
RIE 接收中断使能 1 使能;当接收缓冲器状态是’满’时,CAN控制器请求相应的中断
0 禁能 */
if ((CANConfig.Mode & 0x04) == 0) //帧类型
{//标准帧
REG_RxBuffer0 = 0x00;
}
else
{//扩展帧
REG_RxBuffer0 = 0x80;
}
REG_RxBuffer1 = CANConfig.EFF0;//0xac;//TX 识别码1
REG_RxBuffer2 = CANConfig.EFF1;//0xff;//TX 识别码2
REG_RxBuffer3 = CANConfig.EFF2;//0xff;//TX 识别码3
REG_RxBuffer4 = CANConfig.EFF3;//0x00;//TX 识别码4 末三位不影响
}
//进入工作模式
Temp = REG_MODE;
if ((Temp & 0x01) !=0)
{//没有进入工作模式
return FALSE;
}
//打开中断
REG_IR_ABLE = 0xff; //中断使能置0xff
ON_CAN_INT(); //打开CAN中断
return TRUE;
}
/************************************************************************
单片机初始化函数
参数:无
返回: 初始化成功返回TRUE.
注:
*/
bit MCU_Init(void)
{
TMOD = 0x20; //定时器1,工作模式2(8位自动重装TL1<-TH1)
TH1 = 0xfd; //JJ:装入的初始值要计算。 波特率为9600。
TL1 = 0xfd; // _______________________________
TR1 = 1; //TCON |TF1|TR1|TF0|TR0| | | | |
// TR1或TR0为1,而GATE(TMOD.7)=0时,T1或T0计数.复位时TMOD和TCON的所有位均清0.
// _______________________________
SCON = 0x50; //SCON: |SM0|SM1|SM2|REN|TB8|RB8|TI|RI|
// SM0=0,SM1=1 ,工作方式1,8位UART(异步收发),波特率:SMOD=0时,T1溢出率/32或SMOD=1时,T1溢出率/16.溢出率=1/溢出周期
PCON = 0x00; //当PCON = 0x80 时, SMOD=1 ,使串行口波特率加倍 。其它位不用管。
//当PCON = 0x00 时,SMOD=0, 使串行口波特率不加倍。
PS = 1;
// _______________________________
EA = 1; //IE: |EA| | |ES|ET1|EX1|ET0|EX0| ____ _____
//EA:中断允许总控制位,EA=1,开。 ES,串口断允许位。ES = 1,开. ET1或ET0,定时器/计时器T1或T0的溢出中断允许位。EX1或EX0,外部中断INT1或INT0的中断允许位
ES = 1;
return TRUE;
}
//--------------- 串口中断服务函数 --------------------//
void UART_int(void) interrupt 4 using 1
{
unsigned char Temp;
if(RI)
{
Temp = SBUF;
RI = 0;
// 数据存入接收缓冲区
if( (UART_RX_Buff_Head == (UART_RX_Buff_Tail-1)) ||
((UART_RX_Buff_Head == UART_RX_Buff_LEN-1) &&( UART_RX_Buff_Tail == 0) )) // 空了一个字节的位置
{ // 数据满
}
else
{
UART_RX_Buff[UART_RX_Buff_Head] = Temp;
UART_RX_Buff_Head++;
if(UART_RX_Buff_Head == UART_RX_Buff_LEN )
UART_RX_Buff_Head = 0; // 指针循环
}
}
else if(TI)
{
TI = 0;
if(UART_TX_Buff_Tail == UART_TX_Buff_Head) // 头、尾指针都为0,或相等时,数据为空
{
// Tx_Buff 空
// Do Nothing!
}
else
{
SBUF = UART_TX_Buff[UART_TX_Buff_Tail]; // 先发送,再加指针。
UART_TX_Buff_Tail++;
}
if(UART_TX_Buff_Tail == UART_TX_Buff_LEN)
UART_TX_Buff_Tail = 0; // 尾指针循环
}
}
/**************************************************************************
中断服务函数
*/
void CAN_INT_Serverce(void) interrupt 0 using 2
{
unsigned char Status,i;
unsigned char xdata * p;
Status=REG_IR; //读中断寄存器的同时,使REG_IR为0x00,除了接收中断(若RXFIFO中还有数据)。
//判断发送中断
if ((Status&0x02) == 0x02) //如果发送中断为1,
{
if(TX_Buff_Tail == TX_Buff_Head) // 头、尾指针都为0,或相等时,数据为空
{
//没有数据要发送了
}
else
{
p = (unsigned char xdata *)(SJA_REG_BaseADD + 0x15);
i = REG_SR;
if ((i & 0x04) == 0x04)
{//发送缓冲区处于释放状态时,可以将部分数据发送出去
i = 0;
do {
*p++ = TX_BUFF[TX_Buff_Tail++];
i++;
if(TX_Buff_Tail == TX_BUFF_LEN )
TX_Buff_Tail = 0; // 指针循环
} while((i<8) &&(TX_Buff_Head != TX_Buff_Tail));
if ((CANConfig.Mode & 0x04) == 0)
{//标准帧
REG_RxBuffer0 = i;
}
else
{//扩展帧
REG_RxBuffer0 = 0x80 + i;
}
REG_CMR = 0x01; //发送命令
}
}
}
//判断接受中断
if ((Status&0x01) == 0x01) //如果接收中断为1,
{
while(REG_Receive_Counter != 0) //RX信息计数器(RMC)
{
p = (unsigned char xdata *)(SJA_REG_BaseADD + 0x15);
i = REG_RxBuffer0 & 0x0f;
do {
RX_BUFF[RX_Buff_Head++] = *p++;
i--;
if(RX_Buff_Head == RX_BUFF_LEN )
RX_Buff_Head = 0; // 指针循环
if( (RX_Buff_Head == (RX_Buff_Tail-1)) ||
((RX_Buff_Head == RX_BUFF_LEN-1) &&( RX_Buff_Tail == 0) )) //
{//接受缓冲区满了,丢掉后面的数据
break;
}
} while(i);
REG_CMR = 0x04; //释放缓冲区
}
}
}
/**********************************************************************
主函数
*/
void main(void)
{
unsigned char i;
unsigned char Buf[8];
CANConfig.ACR0 = 0xac;
CANConfig.ACR1 = 0xff;
CANConfig.ACR2 = 0xff;
CANConfig.ACR3 = 0xff;
CANConfig.AMR0 = 0;
CANConfig.AMR1 = 0xff;
CANConfig.AMR2 = 0xff;
CANConfig.AMR3 = 0xff;
CANConfig.BTR0 = 0x43;
CANConfig.BTR1 = 0x2f;
CANConfig.EFF0 = 0xac;
CANConfig.EFF1 = 0xff;
CANConfig.EFF2 = 0xff;
CANConfig.EFF3 = 0xff;
CANConfig.Mode = 0x07; //扩展帧
CAN_Init(); //初始化SJA1000
MCU_Init(); //初始化单片机
while(1)
{
/******************/
//CAN_Send("Hello !",7); //发送到串口
//UART_Send("Hello !",7); //发送到串口
Delay(10000);
/**************************/
if((i = CAN_Read(Buf,8)) !=0)
{
UART_Send(Buf,i); //发送到串口
}
Delay(1000);
if((i = UART_Read(Buf,8)) !=0)
{
CAN_Send(Buf,i); //发送到串口
}
};
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -