📄 can.c.bak
字号:
/*****************************************************************************
;Institue of Automation, Chinese Academy of Sciences
;Beijing Hengyi Embedded System Co.,Ltd (www.hyesco.com)
;File Name:
;Description: source for can sja1000
;Date: 2006-03-15
;Author: Wujh origin from jzm
;E_mail: wujh@hyesco.com
*****************************************************************************/
#include "can.h"
#include <stdlib.h>
#include <string.h>
extern void AT91F_DBGU_Printk(char *buf,...);
//发送缓存,接受缓存
unsigned char TXdata[12]={3,4,5,6,7,8,9,10,11,12,13,14};
unsigned char RXdata[100];
unsigned char bNewData=0;//接收到新的数据
unsigned char NewDataLength=0;//接收到新的数据长度
unsigned char NewDataMode=0;//接收到新的数据格式
//定义了16M晶体下,波特率预设值
unsigned char SJA_BTR_CODETAB[]={
0x18,0x1C, //;20KBPS的预设值
0x87,0xFF, //;40KBPS的预设值
0x09,0x1C, //;50KBPS的预设值
0x83,0xFF, //;80KBPS的预设值
0x04,0x1C, //;100KBPS的预设值
0x03,0x1c, //;125KBPS的预设值
0X81,0xfa, //;200KBPS的预设值
0x01,0x1c, //;250KBPS的预设值
0x80,0xfa, //;400KBPS的预设值
0x00,0x1c, //;500KBPS的预设值
0x80,0xb6, //;666KBPS的预设值
0x00,0x16, //;800KBPS的预设值
0x00,0x14, //;1000KBPS的预设值
};
#define BTR_INDEX 0
//延时函数
void Delay(char x,char y)
{
char z;
do {
z=y;
do {; } while(--z);
}while(--x);
}
//写can寄存器
void Write_CAN_REG(unsigned char can_reg_addr, unsigned char data)
{
WRITE_CAN_ADDR(can_reg_addr);//写寄存器抵制
WRITE_CAN_DATA(data);//写数据
}
//读CAN寄存器
unsigned char Read_CAN_REG(unsigned char can_reg_addr)
{
unsigned char data;
WRITE_CAN_ADDR(can_reg_addr);//写寄存器抵制
data=READ_CAN_REG();
return data;
}
//初始化can
/*
初始化程序主要完成以下寄存器的设计:
(1)通过对SJA1000的时钟分频寄存器定义,判断是使用BassicCAN模式还是使用PeliCAN模式;
是否使能CLOCKOUT及输出时钟频率;是否使用旁路CAN输入比较器;
TX1输出是否采用专门的接收中断。
(2)通过写验收码寄存器和验收屏蔽寄存器定义接收报文的验收码,
以及对报文和验收码进行比较的相关位定义验收屏蔽码。
(3)通过写总线定时寄存器定义总线的位速率、位周期内的采样点和一个位周期内的采样数量。
(4)通过写输出寄存器定义CAN总线输出管脚TX0、TX1的输出模式和输出配置。
(5)清除SJA1000的复位请求标志,进入正常工作模式,这样SJA1000方可进行报文的发送和接收。
*/
unsigned char Init_CAN(void)
{
unsigned char reg;
int i;
unsigned char ucFlag;
//检测sja1000存在
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_TEST,0x5a);
reg=Read_CAN_REG(CAN_REG_TEST);
if(reg==0x5a)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_NO_CAN;//没有找到sja1000
//初始化模式寄存器进入复位模式,选择单滤波方式
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_MOD,0x01);
reg=Read_CAN_REG(CAN_REG_MOD);
if(reg & 0x01)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_RESET;//进入复位状态
//设置总线控制,btr0
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_BTR0,SJA_BTR_CODETAB[BTR_INDEX]);//设置波特率,现在设置成20kbps
reg=Read_CAN_REG(CAN_REG_BTR0);
if(reg==SJA_BTR_CODETAB[BTR_INDEX])
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_BTR;
//btr1
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_BTR1,SJA_BTR_CODETAB[BTR_INDEX+1]);
reg=Read_CAN_REG(CAN_REG_BTR1);
if(reg==SJA_BTR_CODETAB[BTR_INDEX+1])
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_BTR;//错误返回错误代码
//设置输出控制
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_OCR,PARAM_OCR);//设置成正常模式,0xda
reg=Read_CAN_REG(CAN_REG_OCR);
if(reg==PARAM_OCR)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_OCR;
//时钟分频器
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_CDR,PARAM_CDR);//设置成pelican模式,cbp=1,关闭时钟输出
reg=Read_CAN_REG(CAN_REG_CDR);
if(reg==PARAM_CDR)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_CDR;
//接收错误计数器清零
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_RXERR,0x00);
reg=Read_CAN_REG(CAN_REG_RXERR);
if(reg==0x00)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_RXERR;
//发送错误计数器清零
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_TXERR,0x00);
reg=Read_CAN_REG(CAN_REG_TXERR);
if(reg==0x00)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_TXERR;
//初始化接收代码寄存器 0x0000
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_ACR0,PARAM_ACR0);
reg=Read_CAN_REG(CAN_REG_ACR0);
if(reg==PARAM_ACR0)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_ACR;
//ACR1
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_ACR1,PARAM_ACR1);
reg=Read_CAN_REG(CAN_REG_ACR1);
if(reg==PARAM_ACR1)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_ACR;
//ACR2
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_ACR2,PARAM_ACR2);
reg=Read_CAN_REG(CAN_REG_ACR2);
if(reg==PARAM_ACR2)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_ACR;
//ACR3
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_ACR3,PARAM_ACR3);
reg=Read_CAN_REG(CAN_REG_ACR3);
if(reg==PARAM_ACR3)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_ACR;
//验收屏蔽,0xffff
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_AMR0,PARAM_AMR0);
reg=Read_CAN_REG(CAN_REG_AMR0);
if(reg==PARAM_AMR0)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_AMR;
//AMR1
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_AMR1,PARAM_AMR1);
reg=Read_CAN_REG(CAN_REG_AMR1);
if(reg==PARAM_AMR1)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_AMR;
//AMR2
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_AMR2,PARAM_AMR2);
reg=Read_CAN_REG(CAN_REG_AMR2);
if(reg==PARAM_AMR2)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_AMR;
//AMR3
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_AMR3,PARAM_AMR3);
reg=Read_CAN_REG(CAN_REG_AMR3);
if(reg==PARAM_AMR3)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_AMR;
//中断
//中断使能寄存器
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_IER,PARAM_IER);
reg=Read_CAN_REG(CAN_REG_IER);
if(reg==PARAM_IER)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_IER;
//接收缓存器起始地址设为0
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_RBSA,PARAM_RBSA);
reg=Read_CAN_REG(CAN_REG_RBSA);
if(reg==PARAM_RBSA)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_RBSA;
//返回工作模式,选择单滤波模式,
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_MOD,PARAM_RET_MOD);
reg=Read_CAN_REG(CAN_REG_MOD);
if((reg & 0x09)==0x08)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_MOD;
return 0;
}
//发送数据
int CAN_TRANSMIT(void)
{
unsigned char reg;
unsigned char ucFlag;//错误标志位
int i;
unsigned char ucRegTXSFF;
//发送缓存器锁定否
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
reg=Read_CAN_REG(CAN_REG_SR);
if((reg==0x0c))
{
ucFlag=0;
break;
}
}
if(ucFlag)
return STATUS_TBS;
#ifndef SEND_EFF_DATA
//写TX桢信息SFF
ucRegTXSFF=PARAM_DATA_LENGTH | PARAM_TX_FF_SFF;
Write_CAN_REG(CAN_REG_TX_SFF,ucRegTXSFF);//发送数据,数据长度8,标准桢格式
//写TX桢信息id0和id1
Write_CAN_REG(CAN_REG_TX_ID0,PARAM_TX_ID0);//发送数据识别码
Write_CAN_REG(CAN_REG_TX_ID1,PARAM_TX_ID1);//发送数据识别码
//填写发送数据缓存
for(i=0;i<8;i++)
Write_CAN_REG((CAN_REG_TX_SFF_BUFFER+i),TXdata[i]);//包头
#else
//写TX桢信息SFF
ucRegTXSFF=PARAM_DATA_LENGTH | PARAM_TX_FF_EFF;
Write_CAN_REG(CAN_REG_TX_SFF,ucRegTXSFF);//发送数据,数据长度8,EFF桢格式
//写TX桢信息id0和id1
Write_CAN_REG(CAN_REG_TX_ID0,PARAM_TX_ID0);//发送数据识别码
Write_CAN_REG(CAN_REG_TX_ID1,PARAM_TX_ID1);//发送数据识别码
Write_CAN_REG(CAN_REG_TX_ID2,PARAM_TX_ID2);//发送数据识别码
Write_CAN_REG(CAN_REG_TX_ID3,PARAM_TX_ID3);//发送数据识别码
//填写发送数据缓存
for(i=0;i<8;i++)
Write_CAN_REG((CAN_REG_TX_EFF_BUFFER+i),TXdata[i]);//包头
#endif
//发送数据
Write_CAN_REG(CAN_REG_CMR,0x01);//正常发送数据
//判断发送数据失败
ucFlag=1;
for(i=0;i<REPEART_TIMES*10;i++)
{
reg=Read_CAN_REG(CAN_REG_SR);
if((reg & 0x08))
{
ucFlag=0;
break;
}
Delay(200,200);
}
if(ucFlag)
return STATUS_TCS;
return 0;
}
//CAN接收数据
//can中断分发向量函数
void Eint2CanInt(void)
{
unsigned char reg,i;
//重新打开中断
//ClearPending(BIT_EINT2);
//访问地址指向状态寄存器,判断FIFO中的数据有没有,其实在查询的时候需要,在中断的时候
//不需要
/*
reg=Read_CAN_REG(CAN_REG_SR);//
if((reg&0x01)==0) //判断报文是否有效
{
exit(0);//
}*/
//读出中断状态寄存器内容,判断当前是那种中断发生,并转到响应的中断处理
//当然必须在初始化过程中将相应的中断屏蔽位打开了。
reg=Read_CAN_REG(CAN_REG_IR);//读出中断状态寄存器内容
switch(reg)
{
//置位;当CAN控制器检测到总线错误且中断使能寄存器中的BEIE被置位时此位被置位
case 0x80:
break;//自己添加处理程序了
//置位;当CAN控制器丢失仲裁,变为接收器和中断使能寄存器的ALIE为被置位时,此位被置位
case 0x40:
break;//自己添加处理程序了
//置位;当CAN控制器到达错误消极状态(至少一个错误计数器超过协议规定的值127)或从错误消极状态又进入错误活动状态以及中断
//寄存器的EPIE位被置位时此位被置1
case 0x20:
break;//自己添加处理程序了
//置位;当CAN控制器在睡眠模式中检测到总线的活动且中断寄存器的WUIE位被置1时此位被置位
case 0x10:
break;//自己添加处理程序了
//置位;数据溢出状态位有0-1 跳变且中断寄存器的DOIE位被置位时此位被置1
case 0x08:
break;//自己添加处理程序了
//置位;错误状态位和总线状态位的改变和中断寄存器的EIE位被置位时此位被置1
case 0x04:
break;//自己添加处理程序了
//置位;发送缓冲器状态从’0-1’(释放)跳变且中断寄存器的TIE位被置位时此位被置1
case 0x02:
break;//自己添加处理程序了
//置位;接收FIFO不空且中断寄存器的RIE位被置位时此位被置1
case 0x01:
CanIntReceiveData();
break;
}
/*
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_IER,PARAM_IER);
reg=Read_CAN_REG(CAN_REG_IER);
if(reg==PARAM_IER)
{
break;
}
}*/
}
//响应中断接受数据
void CanIntReceiveData(void)
{
unsigned char TempCount;
unsigned char reg;
unsigned char i;
//判断桢信息SFF,EFF OR SFF
reg=Read_CAN_REG(CAN_REG_RX_SFF);
if((reg&0x80)==0x80)//eff,桢
{
if((reg & 0x40)==0x40)//远程桢
TempCount=2;////远程桢
else
TempCount=(reg & 0x0f)+4;////计算报文中数据的个数
for(i=0;i<TempCount;i++)
RXdata[i]=Read_CAN_REG(CAN_REG_RX_ID0+i);
Write_CAN_REG(CAN_REG_CMR,0x04);
bNewData=1;
NewDataMode=1;
NewDataLength=TempCount;
}
else//sff桢
{
if((reg & 0x40)==0x40)//远程桢
TempCount=2;////远程桢
else
TempCount=(reg & 0x0f)+2;////计算报文中数据的个数
for(i=0;i<TempCount;i++)
RXdata[i]=Read_CAN_REG(CAN_REG_RX_ID0+i);
Write_CAN_REG(CAN_REG_CMR,0x04);
bNewData=1;
NewDataMode=0;
NewDataLength=TempCount;
}
}
//不停发送数据主程序
void CanSendData(void)
{
int ret;
ret=CAN_TRANSMIT();
if(ret)
{
AT91F_DBGU_Printk("Can send data error,error id=%d!\n",ret);
}
else
{
AT91F_DBGU_Printk("Can send data success!\n");
}
}
//不停接收数据主程序
void CanReceiveData(void)
{
unsigned char i;
if(bNewData == 1)
{
bNewData=0;
if(NewDataMode)
AT91F_DBGU_Printk("EFF Data,Data Lenght=%d\n",NewDataLength);//数据格式和长度
else
AT91F_DBGU_Printk("SFF Data,Data Lenght=%d\n\r",NewDataLength);
for(i=0;i<NewDataLength;i++)
AT91F_DBGU_Printk("RXdata[%d]=0x%x\n\r",i,RXdata[i]);//输出数据
NewDataLength=0;
NewDataMode=0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -