📄 can_z.c
字号:
return 0;
}
/************************************************************************
*函数原型: bit BCAN_CMD_PRG(unsigned char cmd) *
*参数说明: cmd:sja1000运行的命令字 *
* 01:发送请求 *
* 02:中止发送 *
* 04:释放接收缓冲区 *
* 08:清除超载状态 *
* 0x10:进入睡眠状态 *
* *
*返回值: *
* 0 ; 表示命令执行成功 *
* 1 ; 表示命令执行失败 *
* *
*说明: 执行sja1000命令 *
************************************************************************/
bit BCAN_CMD_PRG(unsigned char cmd)
{
SJA_BCANAdr=REG_COMMAND; //访问地址指向命令寄存器
*SJA_BCANAdr=cmd; //启动命令字
switch(cmd)
{
case TR_CMD: //发送请求命令
return 0;
break;
case AT_CMD: //中止发送命令
SJA_BCANAdr = REG_STATUS; //访问地址指向状态寄存器
if((*SJA_BCANAdr & 0x20)==0)//判断是否正在发送
{
return 0;
}
else
{
return 1;
}
break;
case RRB_CMD: //释放接收缓冲区
SJA_BCANAdr = REG_STATUS; //访问地址指向状态寄存器
if((*SJA_BCANAdr & 0x01)==1)//判断是否释放成功
{
return 1;
}
else
{
return 0;
}
break;
case COS_CMD: //清除超载状态
SJA_BCANAdr = REG_STATUS; //访问地址指向状态寄存器
if((*SJA_BCANAdr & 0x02)==0)//判断清除超载是否成功
{
return 0;
}
else
{
return 1;
}
break;
case GTS_CMD: //进入睡眠状态命令
return 0;
break;
default:
return 1;
break;
}
}
void InitialCAN()
{
SJA_reset=0;
delay(100);
SJA_reset=1;
SJA_BCANAdr=REG_CONTROL; //设置控制寄存器
*SJA_BCANAdr=0x02; //接收中断使能
do{;}while(BCAN_ENTER_RETMODEL()); //进入复位模式
do{;}while(BCAN_CREATE_COMMUNATION()); //建立连接
do{;}while(BCAN_SET_BANDRATE()); //设置BTR0,BTR1,配置波特率
do{;}while(BCAN_SET_OBJECT(0x00,0x00)); //设置验收代码寄存器ACR,验收屏蔽寄存器AMR,
//自身节点ID号为00000000!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
do{;}while(BCAN_SET_OUTCLK(0xda,0x08)); //设置输出控制寄存器OC,时钟分频器CDR
do{;}while(BCAN_QUIT_RETMODEL()); //进入工作模式
}
void DataReceive() interrupt 0 using 1
{
red=0; //接受指示
EX0=0;
SJA_BCANAdr=REG_INTERRUPT; //读取中断寄存器值,判断中断类型
interrupt_flag=*SJA_BCANAdr;
if((interrupt_flag&0x01)==1)//接收中断
{
BCAN_DATA_RECEIVE(SystemBuf); //读取缓冲区数据
BCAN_CMD_PRG(RRB_CMD); //释放接收缓冲区
request_flag=1;
}
if((interrupt_flag&0x04)==1)//错误中断
{
SJA_reset=0; //复位
}
EX0=1;
}
void request_data()
{
green=0; //发送指示
SendBuf[0]=0x01; //从机点ID!!!!!!!!!!!!!!!!!!!!!!!!!
SendBuf[1]=0x08;
SendBuf[2]=0x00; //自身ID
SendBuf[3]=0x01;
SendBuf[4]=0x02;
SendBuf[5]=0x03;
SendBuf[6]=0x04; //测试用
SendBuf[7]=0x05; //测试用
SendBuf[8]=0x06; //测试用
SendBuf[9]=0x07; //测试用
BCAN_DATA_WRITE(SendBuf);
BCAN_CMD_PRG(TR_CMD);
}
/***************************lcd********************************/
void bit8_serial_input(uchar ix) //~~液晶八位串输入信号行
{ //~~ix串行输入的数
data uchar i,j,nc;
P_E=0; //clk=0;
ab=ix;
for(i=0;i<8;i++){
P_RW=abit7; //din=abit7; ~~输入最高位
ab<<=1;
P_E=1; //~~锁存输入一位
for(j=0;j<10;j++)nc=0;//~~ 延时
P_E=0;
}
}
/*---------------------------------------------------------*/
void instruct(uchar dat) //??光标显示,显示控制
{
data uchar ch;
P_RS=1; //选通
ch=0xf8; //~~???
bit8_serial_input(ch);
ch=dat&0xf0; //~~高四位不变低四位请零
bit8_serial_input(ch);
ch=dat<<4;
bit8_serial_input(ch);
P_RS=0; //结束作业
}
void write_abyte(uchar dat) //~~写入一位数据
{
data uchar ch;
P_RS=1; //读数据--不选通
ch=0xfa; //RS=1 RW=0; ~~莫非还有寄存器CH就为写状态字的
bit8_serial_input(ch);
ch=dat&0xf0; //RS=1 RW=0; ~~??写两次还是状态字高几位q
bit8_serial_input(ch);
ch=dat<<4;
bit8_serial_input(ch);
P_RS=0; //结束作业
}
/*
写一个汉字到x,Y坐标处其中X为8列y为4行
*/
void write_word(uint w)
{
data uchar ch,cl;
ch=w>>8; //取高八位ch怎么看不出来
cl=w;
write_abyte(ch);
write_abyte(cl);
}
/*-------------------------------------------*/
/*-------------------------------------------*/
dis_hz_str(uchar x, uchar y, uchar *p_hz) //~~显示函数可
{ //~~能是显示文字(也可是字母)串一共
data uchar loc,*p; //可显示4行汉字由x决定
data uint xi;
code uchar xline[5]={0,1,3,2,4};
x=xline[x];
instruct(home);
loc=((x<<3)+y-9)|0x80;//~~
instruct(loc); p=p_hz;
xi=((*p++)<<8)|*p++;
while(xi){
write_word(xi); //*p++;// );
xi=((*p++)<<8)|*p++; //*p++; xi=xi|*p++;
}
}
/*显示字母数字在x,y处
*/
void dis_str(uchar x, uchar y, uchar *str)
{
data uchar loc,*p;
code uchar xline[5]={0,1,3,2,4};
p=str;
x=xline[x];
instruct(home);
loc=(16*(x-1)+y-1);
if(loc&0x01){
loc/=2;
instruct(loc|0x80);
//ch=' '; //字符串前加空格(0x20 )
write_abyte(' ');
}else{
loc/=2;
instruct(loc|0x80);
}
while(*p){
write_abyte(*p++);
}
//instruct(0x9e); write_abyte(' ');
}
void initial_screen(void)//~~初始化显示屏
{
data uchar i,j;
P0=0xff;
P_RS=0; //串行--不选通
//P_PSB=0;
P_E=0; //串行方式
instruct(f_set); //0x30; //8位并行接口 基本指令
for(i=0;i<30;i++){} //~~~延时何用???
for(i=0;i<250;i++){}
for(i=0;i<250;i++){}
instruct(f_set); //0x30; //8位并行接口 基本指令
for(i=0;i<30;i++){}
for(i=0;i<250;i++){}
for(i=0;i<250;i++){}
instruct(dis_on); //0x0f); //开启屏幕 光标 闪烁
for(i=0;i<30;i++){}
instruct(clear); //0x01); //清屏幕 clear
for(j=0;j<10;j++){
for(i=0;i<250;i++){}
}
instruct(in_mode); //0x06); //光标右移、地址增1 方式
for(i=0;i<30;i++){}
instruct(home);
}
/*---------------------------------------------------------*/
/*---------------------------------------------------------*/
void itoa(int x,unsigned char *str)//BCD码到ASCII码
{
unsigned int n;
unsigned char chn,*p,str1[5];
data unsigned char i,j;
if(x<0){
*str++='-';
x=-x;
}
n=x;
p=str1;
j=0;
while(n!=0){
chn=n%10;
n=n/10;
*p++=chn+'0';
j++;
}
if(j!=0){
p--;
for(i=0;i<j;i++)*str++=*p--;
}
else *str++='0';
*str=0;
return;
}
//------------------------------------------------------------------
void b2hex(char ch,char *p)
{
char c1,c2;
c1=((ch&0xf0)>>4)&0x0f;
//c1=c1>>4;
c2=ch&0x0f; //二进制变16进制
if(c1<=9)c1=c1+'0'; else c1=c1-10+'A';
if(c2<=9)c2=c2+'0'; else c2=c2-10+'A';
*p++=c1; *p=c2;
}
//------------------------------------------------------------------
void dis_bin(uchar *buff,uchar n)
{
data uchar i,j,ch,*p,*p1;
idata uchar str[20],str1[3];
p=buff; p1=str; j=0;
for(i=0;i<n;i++){
ch=*p++;
b2hex(ch,str1); //char ch,char *p)
*p1++=str1[0]; *p1++=str1[1];
j=j+2;
}
p=buff;
for(i=0;i<j;i++)*p++=str[i];
}
/*-----------------------------------------------------------------*/
/*---------------------------------------------------------*/
void main(void)
{
red=1;
green=1;
initial_screen();
instruct(0x0c); //关闭光标
InitialCAN();
EX0=1; // 开外部中断
IT0=0; // 外部中断源采用边沿触发方式
EA=1;//总线初始化后开中断
request_data();
while(1)
{ dis_str(1,4,"CAN");
dis_hz_str(1,4,"总线主\0\0");
if(request_flag==1)
{
dis_bin(SystemBuf,10);
dis_str(2,1,SystemBuf);
request_flag=0;
delay(49990);
red=1;
request_data();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -