📄 51
字号:
/*
描述: 独立的CAN 控制器SJA1000基本硬件头文件定义BasicCAN 工作方式
*/
#include <string.h>
#include<reg51.h>
#include<stdio.h>
#include<intrins.h>
#include <absacc.h>
#define uchar unsigned char
#define uint unsigned int
sbit CS7221 = P1^1; // 7221的片选
sbit DIN7221 = P1^0; // 7221的数据端
sbit CLK7221 = P1^2; // 7221的时钟端
sbit wr_0804=P3^7; //0804读端
sbit rd_0804=P3^6; //0804写端
sbit intr_0804=P2^2; //0804中断端
sbit cs_0804=P2^1; //0804片选端
uchar temp,c[4]; //温度暂存
uchar DATA_BUF[6]; //发送数据暂存
/************************************************************************
*SJA1000与微处理器的接口是以外部存储器的方式,所以以下的基址定义,用户 *
*应根据自己的实际电路来进行调整 *
************************************************************************/
#define SJA_Adr 0xfe00 //定义sja1000的片选基址
//计算SJA1000在电路中的实际地址:基址+内部寄存器地址
/************************************************************************
* 以下的定义为SJA1000的内部寄存器的地址,不可修改 *
* 各寄存器的具体功能清参阅sja1000的数据手册 *
************************************************************************/
#define REG_CONTROL SJA_Adr+0x00 //内部控制寄存器
#define REG_COMMAND SJA_Adr+0x01 //命令寄存器
#define REG_STATUS SJA_Adr+0x02 //状态寄存器
#define REG_INTERRUPT SJA_Adr+0x03 //中断寄存器
#define REG_ACR SJA_Adr+0x04 //验收代码寄存器
#define REG_AMR SJA_Adr+0x05 //验收屏蔽寄存器
#define REG_BTR0 SJA_Adr+0x06 //总线定时寄存器0
#define REG_BTR1 SJA_Adr+0x07 //总线定时寄存器1
#define REG_OCR SJA_Adr+0x08 //输出控制寄存器
#define REG_TEST SJA_Adr+0x09 //测试寄存器
//以下为发送缓冲区寄存器定义
#define REG_TxBuf1 SJA_Adr+0x0A //发送缓冲区1
#define REG_TxBuf2 SJA_Adr+0x0B //发送缓冲区2
#define REG_TxBuf3 SJA_Adr+0x0C //发送缓冲区3
#define REG_TxBuf4 SJA_Adr+0x0D //发送缓冲区4
#define REG_TxBuf5 SJA_Adr+0x0E //发送缓冲区5
#define REG_TxBuf6 SJA_Adr+0x0F //发送缓冲区6
#define REG_TxBuf7 SJA_Adr+0x10 //发送缓冲区7
#define REG_TxBuf8 SJA_Adr+0x11 //发送缓冲区8
#define REG_TxBuf9 SJA_Adr+0x12 //发送缓冲区9
#define REG_TxBuf10 SJA_Adr+0x13 //发送缓冲区10
//以下为接收缓冲区寄存器定义
#define REG_RxBuf1 SJA_Adr+0x14 //接收缓冲区1
#define REG_RxBuf2 SJA_Adr+0x15 //接收缓冲区2
#define REG_RxBuf3 SJA_Adr+0x16 //接收缓冲区3
#define REG_RxBuf4 SJA_Adr+0x17 //接收缓冲区4
#define REG_RxBuf5 SJA_Adr+0x18 //接收缓冲区5
#define REG_RxBuf6 SJA_Adr+0x19 //接收缓冲区6
#define REG_RxBuf7 SJA_Adr+0x1A //接收缓冲区7
#define REG_RxBuf8 SJA_Adr+0x1B //接收缓冲区8
#define REG_RxBuf9 SJA_Adr+0x1C //接收缓冲区9
#define REG_RxBuf10 SJA_Adr+0x1D //接收缓冲区10
/************************************************************************
*内部地址 01EH 备用 *
************************************************************************/
/************************************************************************
*时钟分频寄存器(内部地址01FH) *
************************************************************************/
#define REG_CDR SJA_Adr+0x1F //时钟分频寄存器
/************************************************************************
*定义指针 *
************************************************************************/
uchar xdata *SJA_BCANAdr;
/************************************************************************
*定义命令字 *
************************************************************************/
#define TR_CMD 0x01 //发送请求命令
#define AT_CMD 0x02 //夭折发送命令
#define RRB_CMD 0x04 //释放接收缓冲区
#define COS_CMD 0x08 //清除超载状态
#define GTS_CMD 0x10 //进入睡眠状态命令
/************************************************************************
*定义12M的晶体下,CAN总线波特率 *
************************************************************************/
#define bps_20k 0x00 //波特率20kbps
#define bps_40k 0x01 //波特率40kbps
#define bps_50k 0x02 //波特率50kbps
#define bps_80k 0x03 //波特率80kbps
#define bps_100k 0x04 //波特率100kbps
#define bps_125k 0x05 //波特率125kbps
#define bps_200k 0x06 //波特率200kbps
#define bps_250k 0x07 //波特率250kbps
#define bps_400k 0x08 //波特率400kbps
#define bps_500k 0x09 //波特率500kbps
#define bps_666k 0x0a //波特率666kbps
#define bps_800k 0x0b //波特率800kbps
#define bps_1000k 0x0c //波特率1000kbps
/*-------------------------------------------------------------------------------------------
* 以下为BASICCAN SJA1000的错误字 *
-------------------------------------------------------------------------------------------*/
#define INTERFACE_0K 0 //SJA1000接口正常
#define BUS_0K 0 //CAN总线工作正常
#define INTERFACE_ERR 0XFF //SJA1000接口错误?
#define ENTRESET_ERR 0XFE //SJA1000不能进入复位模式
#define QUITRESET_ERR 0XFD //SJA1000不能退出复位模式
#define INITOBJECT_ERR 0XFC //初始化报文验收滤波器错
#define INITBTR_ERR 0XFB //初始化总线定时器器错
#define INITOUTCTL_ERR 0XFA //初始化输出控制错误
#define INTCLKDIV_ERR 0XF9 //初始化时钟分频控制器错
#define BUS_ERR 0XF8 //SJA1000发送数据错
#define NO_BANDRATE_SIZE 0xe7 //
/************************************************************************
*以下为基本的函数说明(BasicCAN) *
************************************************************************/
bit CREATE_COMMUNATION(void); //检测CAN控制器的接口是否正常
bit ENTER_RETMODEL(void); //CAN控制器进入复位工作模式
bit QUIT_RETMODEL(void); //CAN控制器退出复位工作模式
bit SET_BANDRATE(uchar CAN_bps); //设置CAN控制器SJA1000通信波特率
bit SET_OBJECT(uchar BCAN_ACR,uchar BCAN_AMR); //设置CAN节点的通讯对象
bit SET_OUTCLK (uchar Out_Control,uchar Clock_Out);//设置SJA1000的输出模式和时钟分频
bit HW_INIT(uchar BCAN_ACR,uchar BCAN_AMR,uchar Bus_Timing0,
uchar Bus_Timing1,uchar Out_Control,uchar Clock_Out);
//CAN控制器的初始化
bit DATA_WRITE(uchar *SendDataBuf); //发送特定帧各式的数据
bit RECEIVE(uchar *RcvDataBuf); //CAN控制器接收数据
bit CMD_PRG(uchar cmd); //执行sja1000命令
void sja1000(); //SJA1000初始化
void Initial7221(void); //MAX7221初始化
void WR7221(uchar addr,uchar Data); //MAX7221写程序
void Max7221Display(uchar *buffer); //MAX7221显示程序
void read_0804(); //读AD转换电压值
void wdcl_0804(); //转换电压值
void delay(uint n); //延时程序
main()
{
sja1000(); //SJA1000初始化
while(1)
{
uchar k;
read_0804(); //读AD转换电压值
wdcl_0804(); //转换电压值
Max7221Display(&c[0]); //显示
DATA_BUF[0]=0xaa; //ID高8位为10101010=0xaa
DATA_BUF[1]=0xb4; //ID低3位为101 数据帧 数据长度为4位
for(k=0;k<=3;k++) //要发送的4位数据
{
DATA_BUF[2+k]=c[k]; //
}
DATA_WRITE(&DATA_BUF[0]); //通过CAN总线向计算机发送数据
delay(100); //延时
}
}
/****adc0804******/
void read_0804() //读AD转换电压值
{
intr_0804=1;
cs_0804=1;
wr_0804=1;
rd_0804=1;
intr_0804=0;
_nop_();_nop_();
cs_0804=0; //0804片选有效
wr_0804=0; //0804写地址
_nop_();_nop_();
intr_0804=1;
rd_0804=0; //0804读
_nop_();_nop_();
temp=P0; //读AD转换数据
cs_0804=1;
wr_0804=1;
rd_0804=1;
}
void wdcl_0804()
{
temp=(temp*2-273)*10; //提取一位小数
c[0]=temp/1000; //千位
c[1]=temp/100%10; //百位
c[2]=temp/10%10; //十位
c[3]=temp%10; //个位
}
void delay(uint n) //延时程序
{
uint i1,j1;
for (i1=0;i1<n;i1++)
for (j1=0;j1<1140;j1++);
}
void WR7221(uchar addr,uchar Data) //MAX7221的写子程序
{
uchar i;
CS7221 = 0; //片选有效
for (i=0;i<8;i++) //写8位地址
{
CLK7221 = 0; //时钟低
DIN7221 = (addr&(0x80>>i)) ? 1:0; //先发高位 依次到低位
_nop_();
_nop_();
CLK7221 = 1; //时钟高 上升沿锁数据
_nop_();
_nop_();
}
for (i=0;i<8;i++) //写8位数据
{
CLK7221 = 0; //时钟低
DIN7221 = (Data&(0x80>>i)) ? 1:0; //先发高位 依次到低位
_nop_();
_nop_();
CLK7221 = 1; //时钟高 上升沿锁数据
_nop_();
_nop_();
}
CS7221 = 1; //片选无效
}
void Initial7221(void) //MAX7221初始化
{
WR7221(0x0A,0x0A); //亮度地址0AH,0x00~0x0F,0x0F最亮
WR7221(0x0B,0x07); //扫描LED个数地址0BH,0x00~0x07,最多扫描8个数码管
WR7221(0x0C,0x01); //工作模式地址0x0C. 0x00:关断;0x01:正常
WR7221(0x09,0xFF); //编码模式地址0x09. 0x00~0xFF:哪一位为1,哪一位就支持编码
}
void Max7221Display(uchar *buffer) //MAX7221显示子程序
{
uchar i;
for (i=0;i<8;i++) //MAX7221的8个数码管显示
{
WR7221(i+1,*(buffer+i)); //调MAX7221的写子程序
}
}
void sja1000()
{
do{;}while(CREATE_COMMUNATION()==1); //检测CAN控制器的接口是否正常
do{;}while(ENTER_RETMODEL()==1); //进入复位工作模式
HW_INIT(0xaa,0x00,0xc9,0xc9,0xff,0x48); //CAN控制器的初始化
do{;}while(QUIT_RETMODEL()==1); //退出复位工作模式
}
/************************************************************************
*说明:该函数用于检测CAN控制器的接口是否正常 *
************************************************************************/
bit CREATE_COMMUNATION(void)
{
SJA_BCANAdr=REG_TEST; //访问测试寄存器
*SJA_BCANAdr =0xaa; //写入测试值
if(*SJA_BCANAdr == 0xaa)
{
return 0; //读测试正确
}
else
{
return 1;
}
}
/************************************************************************
*说明: CAN控制器进入复位工作模式 *
************************************************************************/
bit ENTER_RETMODEL(void)
{
uchar TempData;
SJA_BCANAdr = REG_CONTROL; //访问地址指向控制寄存器
TempData= *SJA_BCANAdr; //保存原始值
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -