打印
[CAN-bus/DeviceNet]

急求:can节点通信问题(stc+2515+82c250)

[复制链接]
2576|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
futao_uestc|  楼主 | 2010-6-27 15:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 futao_uestc 于 2010-6-27 16:00 编辑

本人原本打算实现4节点通信问题,A、B、C节点连于总线:单片机通过模拟SPI与2515相连,2515的TXCAN和RXCAN与250相连,250连于总线,终端电阻120欧姆,没有加电容,另外在外部中断1连一按钮,按钮按下发送一数据帧;D节点除了上述连接,在STC自带的SPI通过MAX3232连串口通于计算机。
现在是测试D节点和B节点的通信,D节点:总线差分电压一直处于1.52~1.44V之间,TXCAN是400mV~-480mV之间,RXCAN是4.08V~4V之间。B节点的CANH和CANL直接与D节点对应相连,RXCAN是800mV~-880mV之间,TXCAN是2.96V~2.8V之间。请问问题是出在哪里,现在用串口助手发数据一直收不到数据??????
程序是发送两个字节数据,只发送扩展数据帧,并通过数据帧的第一字节判断数据操作,高4位为命令,低4位为节点代号!!!


//节点D
#include<reg51.h>

#define RXFNSIDHADD 0x40  //0x10代表A节点,0x20代表B节点,0x30代表C节点,0x40代表D节点  
#define RXFNSIDH 0x0A  //标准标识符为****1010101,其中最高四位代表节点,扩展标识符为110011001100110011
#define RXFNSIDL 0xAB  //报文滤波仅用于扩展帧
#define RXFNEID8 0x33  //屏蔽位全为1
#define RXFNEID0 0x33
#define RXMNSIDH 0xFF
#define RXMNSIDL 0xE3
#define RXMNEID8 0xFF
#define RXMNEID0 0xFF
#define TXBNSIDH 0x0A      //发送数据帧,扩展帧,标识符为****1010101,110011001100110011
#define TXBNSIDL 0xAB
#define TXBNEID8 0x33
#define TXBNEID0 0x33
#define TXBNDLC 0x02      //数据长度为2
#define JIEDIAN 0x04    //节点D
#define MAXNUM 8        //队列长度

//队列结构定义
typedef struct queue_type
{
  char queue[ MAXNUM ]; //队列元素
  char front;      //队头指针
  char rear;      //队尾指针
} queuetype;

void writeuartbuffer( queuetype *queuesed, char datah, char datal );
void readuartbuffer( queuetype *queuerec );

////////////////////////////////////////////////////////////////////////////////////////////////////
//变量设置
bit txflag = 0;
bit rxflag = 0;
bit errorflag = 0;
sbit SCK = P2^7;
sbit SI = P2^6;
sbit SO = P2^5;
sbit CS = P2^4;
sbit RESET = P2^3;
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
queuetype *queuerec,*queuesed; //定义接收和发送队列
//初始化队列
void initqueue( queuetype *q )
{
  q->front = 0;
  q->rear = 0;
}
//测试队列是否满,检验是否还可以装两个字节
char queueman( queuetype *q )
{
    if( ( ( q->rear + 1) % MAXNUM == q->front ) || ( ( q->rear + 2 ) % MAXNUM == q->front) )
     return 1;      //队列已满
  else
  return 0;
}
//入队列
void enterqueue( queuetype *q , char x )
{
q->rear = ( q->rear + 1 ) % MAXNUM;
    q->queue[ q->rear ] = x;
}
//测试队列是否空,检验队列中是否还有两个字节
char queuekong( queuetype *q )
{
   if( ( q->front == q->rear ) || ( q->front == ( q->rear + 1 ) % MAXNUM ) )
     return 1;       //队列为空
   else
     return 0;
}
//出队列
char deletequeue( queuetype *q )
{
q->front = ( q->front + 1 ) % MAXNUM;
    return( q->queue[ q->front ] );
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
void delay( void )
{
char i,j;
for( i = 0; i < 0x0F; i ++ )
  for( j = i; j < 0xFF; j ++);
}
void cancomhead( void )
{
EA = 0;
CS = 0;
}
void cancomend( void )
{
CS = 1;
EA = 1;
}
  
//模拟SPI向外接收一个字节
char simspiin( void )
{
char i, buffer;
SCK = 1;
for( i = 0x00; i < 0x08; i ++ )
{
  SCK = 0;
  buffer = buffer << 1;
  if( SO == 1 )
   buffer = buffer | 0x01;
  else
   buffer = buffer | 0x00;
  SCK = 1;
}
return buffer;
}
//模拟SPI向外发送一个字节
void simspiout( char buffer )
{
char i;
SCK = 1;
for( i = 0x00; i < 0x08; i ++ )
{
  SCK = 0;
  if( ( buffer & 0x80 ) == 0x00 ) SI = 0;
  else SI = 1;
  SCK = 1;
  buffer = buffer << 1;
}
}

//2515复位指令
void canreset(void)
{
cancomhead();
simspiout( 0xC0 );
cancomend();
}
//2515读指令
char canread( char add )
{
char dat;
cancomhead();
simspiout( 0x03 );
simspiout( add );
dat = simspiin();
cancomend();
return dat;
}
//2515写指令
void canwrite( char add,char dat )
{
  cancomhead();
  simspiout( 0x02 );
  simspiout( add );
  simspiout( dat );
  cancomend();
}
//2515请求发送rts
void canrts( char txbadd )
{
cancomhead();
simspiout(txbadd);
cancomend();
}
//2515读状态
char canreadstat( void )
{
char dat;
cancomhead();
simspiout( 0xA0 );
dat = simspiin();
cancomend();
return dat;
}
//2515位修改
void canbite( char address, char shadow, char dat)
{
cancomhead();
simspiout( 0x05 );
simspiout( address );
simspiout( shadow );
simspiout( dat );
cancomend();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//发送数据帧格式设置
void txinit( void )
{
canwrite( 0x32, TXBNSIDL );
canwrite( 0x42, TXBNSIDL );
canwrite( 0x52, TXBNSIDL );

canwrite( 0x33, TXBNEID8 );
canwrite( 0x43, TXBNEID8 );
canwrite( 0x53, TXBNEID8 );

canwrite( 0x34, TXBNEID0 );
canwrite( 0x44, TXBNEID0 );
canwrite( 0x54, TXBNEID0 );

canwrite( 0x35, TXBNDLC );
canwrite( 0x45, TXBNDLC );
canwrite( 0x55, TXBNDLC );
}

//屏蔽和滤波初始化
void filterinit( void )
{
canwrite( 0x00, RXFNSIDHADD+RXFNSIDH );
canwrite( 0x04, RXFNSIDHADD+RXFNSIDH );
canwrite( 0x08, RXFNSIDHADD+RXFNSIDH );
canwrite( 0x10, RXFNSIDHADD+RXFNSIDH );
canwrite( 0x14, RXFNSIDHADD+RXFNSIDH );
canwrite( 0x18, RXFNSIDHADD+RXFNSIDH );

canwrite( 0x01, RXFNSIDL );
canwrite( 0x05, RXFNSIDL );
canwrite( 0x09, RXFNSIDL );
canwrite( 0x11, RXFNSIDL );
canwrite( 0x15, RXFNSIDL );
canwrite( 0x19, RXFNSIDL );
canwrite( 0x02, RXFNEID8 );
canwrite( 0x06, RXFNEID8 );
canwrite( 0x0A, RXFNEID8 );
canwrite( 0x12, RXFNEID8 );
canwrite( 0x16, RXFNEID8 );
canwrite( 0x1A, RXFNEID8 );
canwrite( 0x03, RXFNEID0 );
canwrite( 0x07, RXFNEID0 );
canwrite( 0x0B, RXFNEID0 );
canwrite( 0x13, RXFNEID0 );
canwrite( 0x17, RXFNEID0 );
canwrite( 0x1B, RXFNEID0 );
canwrite( 0x20, RXMNSIDH );
canwrite( 0x24, RXMNSIDH );

canwrite( 0x21, RXMNSIDL );
canwrite( 0x25, RXMNSIDL );
canwrite( 0x22, RXMNEID8 );
canwrite( 0x26, RXMNEID8 );
canwrite( 0x23, RXMNEID0 );
canwrite( 0x27, RXMNEID0 );
}
//////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
//can初始化
void caninit( void )
{
RESET = 0;
delay();
RESET = 1;
canreset();
delay();
canwrite( 0x0F,0x80 );//CANCTRL:配置模式;终止发送中止;禁止单触发;禁止CLKOUT

canwrite( 0x2A, 0x04 );//SJW=1TQ,TQ=625ns;晶振16MHz,波特率为160KHz,位时间10TQ
canwrite( 0x29, 0xD9 );//PS2由CNF3的PHSEG22:PHSEG20决定;采样三次PS1=4TQ;传播段=2TQ
canwrite( 0x28, 0x02 );//禁止唤醒;PS2=3TQ
canbite( 0x60, 0x64, 0x40 );//RXB0CTL:接收扩展帧,滚存禁止
canbite( 0x70, 0x60, 0x40 );//RXB1CTL:接收扩展帧
filterinit(); //屏蔽和滤波设置
txinit();     //发送数据帧设置
canwrite( 0x2D, 0x00 );//E**复位
canwrite( 0x2B, 0x23 );//使能:错误条件变化中断;接收缓冲器满中断
canwrite( 0x2C, 0x00 );//清所有中断标志
canwrite( 0x0F, 0x00 );//CANCTRL:正常工作模式;终止发送中止;禁止单触发;禁止CLKOUT
}
//can报文发送
void cansend( char TXBNSIDHADD, char TXBND1, char TXBND2 )
{
     char state;
   state = canreadstat();    //读状态
   if( ( state & 0x80 ) == 0x80 )   //发送缓冲区2空
    {
      canbite( 0x50, 0x08, 0x00 ); //清报文发送请求位
   canwrite( 0x51, TXBNSIDH+TXBNSIDHADD );  //装载标志符
   canwrite( 0x56, TXBND1 );   //装载发送缓冲区数据
   canwrite( 0x57, TXBND2 );
   canrts( 0x84 );    //请求发送
   delay();
  }
   else if( ( state & 0x20 ) == 0x20 )
    {
   canbite( 0x40, 0x08, 0x00 );
   canwrite( 0x41, TXBNSIDH+TXBNSIDHADD );
   canwrite( 0x46, TXBND1 );
   canwrite( 0x47, TXBND2 );
   canrts( 0x82 );
   delay();
  }
   else if( ( state & 0x08 )==0x08 )
  {
   canbite( 0x30, 0x08, 0x00 );
   canwrite( 0x31, TXBNSIDH+TXBNSIDHADD );
   canwrite( 0x36, TXBND1 );
   canwrite( 0x37, TXBND2 );
   canrts( 0x81 );
   delay();
  }
}
//检验是否可以发送报文
char cansendinit( void )
{
char state;
state = canreadstat();//读状态
if( ( ( state & 0x80 ) == 0x80 )||( ( state & 0x20 ) == 0x20 )||( ( state & 0x08 ) == 0x08 ) )   //发送缓冲区有空
  {
   txinit();//发送数据帧设置
   return 1;
  }
else
     return 0;
}

//从接收缓冲器读数据,并对接收的数据进行处理判断
//如果要想总线发送数据,直接发送
//如果要上传上位机,将数据压入队列
void canreceive()
{
if( rxflag == 1 )
  {
   char state,datah,datal,databiteh,databitel;
   EA = 0;
   rxflag = 0;
   state = canreadstat();//读状态
   if( ( state & 0x01 ) == 0x01 )
    {
      datah=canread( 0x66 );//读取第1字节
      datal=canread( 0x67 );//读取第2字节
      canbite( 0x2C, 0x01, 0x00 );//清中断标志
    }
   else if( ( state & 0x02 ) == 0x02 )
    {
      datah = canread( 0x76 );
      datal = canread( 0x77 );
          canbite( 0x2C, 0x02, 0x00 );
    }
   databiteh = datah & 0xF0;
   databitel = datah & 0x0F;
   if( databiteh == 0x10 )
     {
     writeuartbuffer( queuesed, 0x30+JIEDIAN, datal ); //向上位机发送0011****,表示收到数据
     while( cansendinit() ) //判断是否有发送缓冲区为空
      cansend( databitel << 4, 0xF0+databitel, datal); //如果最高4位为0001,向规定节点发送数据帧
    }  
   else if( databiteh == 0xF0 )
    writeuartbuffer( queuesed, 0x30+JIEDIAN, datal );//向上位机发送0011****,表示收到数据
   else if( ( databiteh == 0x40 ) || ( databiteh == 0x00 ) || ( databiteh == 0x30 ) || ( databiteh == 0x20 ) )
    writeuartbuffer( queuesed, datah, datal ); //转发给uart
   
   EA = 1;
  }
}

//将队列中的数据送入发送缓冲器
void cantransmit()
{
    if( txflag == 1 )
  {
   EA = 0;
   txflag = 0;
      
   readuartbuffer( queuerec );
   EA = 1;
  }
}
//外部中断0
void canint0( void ) interrupt 0
{
char state,stateicod;
IE0 = 0; //清外部中断标志
state = canread( 0x0E );
stateicod = state & 0x0E; //读取CANSTAT.ICOD位,判断优先级
if( stateicod == 0x02 )
  errorflag = 1;
else
  rxflag = 1;
}
//错误处理
void error( void )
{
if( errorflag == 1 )
{
  char state;
  
  EA = 0;
  errorflag = 0;
  state = canread( 0x2D );      //读错误标志寄存器E**
  if( ( state & 0x80 ) == 0x80 )
   {
   writeuartbuffer( queuesed, JIEDIAN, 0x01 );  //接收缓冲器1溢出,向上位机发送0000**** 00000001
   canreceive();
   canbite( 0x2D, 0x80, 0x00 ); //复位E**的RX1OVR位
   canbite( 0x2C, 0x20, 0x00 );  //清除CANNINTF的错误中断标志位
  }
  else if((state & 0x40) == 0x40 )
   {
   writeuartbuffer( queuesed, JIEDIAN, 0x00 );  //接收缓冲器0溢出,向上位机发送0000**** 00000000
   canreceive();
   canbite( 0x2D, 0x40, 0x00 ); //复位E**的RX0OVR位
   canbite( 0x2C, 0x20, 0x00 );  //清除CANNINTF的错误中断标志位
  }
  else if( ( state & 0x20 ) == 0x20 )
   {
   caninit();      //若总线关闭,can复位
   TCON = 0x00;   //设置外部中断0为电平触发,并清外部中断标志
   IE = 0x91;     //开总中断,允许串口中断,禁止定时/计数器中断,允许外部中断0
  }
  else if( ( state & 0x1F ) != 0x00 )
   {
   writeuartbuffer( queuesed, JIEDIAN, 0x03 ); //错误数小于255且错误条件变化时,向上位机发送0000**** 00000011
   canbite( 0x2C, 0x20, 0x00); //清除CANNINTF的错误中断标志位
  }
  else
   {
   writeuartbuffer( queuesed, JIEDIAN, 0xFF );   //其他未知错误,向上位机发送0000**** 11111111
   canbite( 0x2C, 0x20, 0x00 ); //清除CANNINTF的错误中断标志位
  }
  
  EA = 1;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
//UART初始化
void uartinit( void )
{
//串口采用模式1,允许接收
SCON = 0x50;
//定时器1,模式2
TMOD = 0x20;
//定时器1付值,波特率9600
TH1 = 0xFD;
TL1 = 0xFD;
//定时器1启动
TCON = 0x40;
//设置串口中断
ES = 1;
}
//UART发送程序
void uartsend( queuetype *queuesed )
{
char temp;
ES = 0; //去除串口中断
while( queuekong( queuesed ) == 0 )
   {
   temp = deletequeue( queuerec );//只要队列非空,取队首元素
   SBUF = temp;  //发送数据
   while( TI == 0 ); //等待发送完成中断
   TI = 0; //去除发送完成中断
   queuesed->front = ( queuesed->front + 1 ) % MAXNUM;//指向下一个元素
  }
ES = 1;   //使能串口中断
}
//UART中断程序
void uartint( void ) interrupt 4
{
if( RI == 1 )
{
  char uartbuffer;
  //去除中断
  RI = 0;
  //接收数据
  uartbuffer = SBUF;
  if( queueman( queuerec ) == 0 )
   {
    enterqueue( queuerec, uartbuffer);//uart接收数据压入接收缓冲器
    txflag = 1;
   }
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//将接收队列的数据装入发送缓冲区发送
void readuartbuffer( queuetype *queuerec )
{
   char datacheckh,datacheckl,checkh,checkl;
   while( ( queuekong( queuerec ) == 0 ) )//队列中存在两字节时
    {
     datacheckh = deletequeue( queuerec );//取队首元素
  checkh = datacheckh & 0xF0;//取字节高四位
  checkl = datacheckh & 0x0F;
  //字节低四位为0x01/0x02/0x03/0x04且高四位为0x10/0x20/0x30/0x40/0x00/0xF0时,断定为数据帧的第一字节
  if( ( ( checkl == 0x01 ) || ( checkl == 0x02 ) || ( checkl == 0x03 ) || ( checkl == 0x04 ) ) && ( ( checkh == 0x10 ) || ( checkh == 0x20 ) || ( checkh == 0x30 ) || ( checkh == 0x40 ) || ( checkh == 0x00 ) || ( checkh == 0xF0 ) ) )
   {
    queuerec->front = ( queuerec->front + 1 ) % MAXNUM;//指向下一个元素
    datacheckl = deletequeue( queuerec ); //取下一字节数据
    while( cansendinit() )
     cansend( checkl << 4, datacheckh, datacheckl );   //将数据发往指定节点
   }
  else
   queuerec->front = ( queuerec->front + 1 ) % MAXNUM;//指向下一个元素
    }
}
//将接收缓冲区数据压入发送队列
void writeuartbuffer( queuetype *queuesed, char datah, char datal )
{
if( queueman( queuesed ) == 0 )
  {
   enterqueue( queuesed, datah );
   queuesed->rear = ( queuesed->rear + 1 ) % MAXNUM; //指向下一个元素
   enterqueue( queuesed, datal );
  }
// else
//  queuesed->front = ( queuesed->front + 1 ) % MAXNUM;//指向下一个元素
uartsend( queuesed );
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////

//主函数
void main()
{
initqueue( queuerec ); //初始化队列
initqueue( queuesed );
  
uartinit();  //UART初始化

//TCON = 0x00;//设置外部中断0为电平触发,并清外部中断标志
IT0 = 0;//外部中断0为电平触发
IE0 = 0;//清外部中断标志
//IE = 0x81;//开总中断,禁止串口中断,禁止定时/计数器中断,允许外部中断0
EX0 = 1;//允许外部中断0
EA = 1; //开总中断

caninit();   //can初始化
while( 1 )
{
    canreceive();
    cantransmit();
    error();
}
}

相关帖子

沙发
futao_uestc|  楼主 | 2010-6-27 15:45 | 只看该作者
下面是B节点程序:
//节点B(0010)程序,节点B、C只需改动JIEDIAN变量为0x02、0x03,改动RXFNSIDHADD为0x20、0x30

#include<reg51.h>


#define RXFNSIDHADD 0x20  //0x10代表A节点,0x20代表B节点,0x30代表C节点         
#define RXFNSIDH 0x0A         //标准标识符为****1010101,其中最高四位代表节点,扩展标识符为110011001100110011
#define RXFNSIDL 0xAB         //报文滤波仅用于扩展帧
#define RXFNEID8 0x33         //屏蔽位全为1
#define RXFNEID0 0x33
#define RXMNSIDH 0xFF
#define RXMNSIDL 0xE3
#define RXMNEID8 0xFF
#define RXMNEID0 0xFF

#define TXBNSIDH 0x0A           //发送数据帧,扩展帧,标识符为****1010101,110011001100110011
#define TXBNSIDL 0xAB
#define TXBNEID8 0x33
#define TXBNEID0 0x33

#define TXBNDLC 0x02             //数据长度为2

#define JIEDIAN 0x02           //节点B

bit errorflag = 0;
bit rxflag = 0;
bit txflag = 0;

sbit SCK = P2^7;
sbit SI = P2^6;
sbit SO = P2^5;
sbit CS = P2^4;
sbit RESET = P2^3;


//////////////////////////////////////////////////////////////////////////////////////////////////////
//模拟SPI向外接收一个字节
char simspiin( void )
{
        char i, buffer;
        SCK = 1;
        for( i = 0x00; i < 0x08; i ++ )
        {
                SCK = 0;
                buffer = buffer << 1;
                if( SO == 1 )
                        buffer = buffer | 0x01;
                else
                        buffer = buffer | 0x00;
                SCK = 1;
        }
        return buffer;
}

//模拟SPI向外发送一个字节
void simspiout( char buffer )
{
        char i;
        SCK = 1;
        for( i = 0x00; i < 0x08; i ++ )
        {
                SCK = 0;
                if( ( buffer & 0x80 ) == 0x00 ) SI = 0;
                else SI = 1;
                SCK = 1;
                buffer = buffer << 1;
        }
}

void delay( void )
{
        char i,j;
        for( i = 0; i < 0x0F; i ++ )
                for( j = i; j < 0xFF; j ++ );
}

void cancomhead( void )
{
        EA = 0;
        CS = 0;
}

void cancomend( void )
{
        CS = 1;
        EA = 1;
}

//2515读状态
char canreadstat( void )
{
        char dat;
        cancomhead();
        simspiout( 0xA0 );
        dat = simspiin();
        cancomend();
        return dat;
}


//2515位修改
void canbite( char address, char shadow, char dat)
{
        cancomhead();
        simspiout( 0x05 );
        simspiout( address );
        simspiout( shadow );
        simspiout( dat );
        cancomend();
}

//2515复位指令
void canreset(void)
{
        cancomhead();
        simspiout( 0xC0 );
        cancomend();
}

//2515读指令
char canread( char add )
{
        char dat;
        cancomhead();
        simspiout( 0x03 );
        simspiout( add );
        dat = simspiin();
        cancomend();
        return dat;
}


//2515写指令
void canwrite( char add, char dat )
{
  cancomhead();
  simspiout( 0x02 );
  simspiout( add );
  simspiout( dat );
  cancomend();
}

//2515请求发送rts
void canrts( char txbadd )
{
        cancomhead();
        simspiout(txbadd);
        cancomend();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////////////////////
//发送数据帧格式设置
void txinit( void )
{
        canwrite( 0x32, TXBNSIDL );
        canwrite( 0x42, TXBNSIDL );
        canwrite( 0x52, TXBNSIDL );
       
        canwrite( 0x33, TXBNEID8 );
        canwrite( 0x43, TXBNEID8 );
        canwrite( 0x53, TXBNEID8 );
       
        canwrite( 0x34, TXBNEID0 );
        canwrite( 0x44, TXBNEID0 );
        canwrite( 0x54, TXBNEID0 );
       
        canwrite( 0x35, TXBNDLC );
        canwrite( 0x45, TXBNDLC );
        canwrite( 0x55, TXBNDLC );
}


//屏蔽和滤波初始化
void filterinit( void )
{                                 
        canwrite( 0x00, RXFNSIDH + RXFNSIDHADD );
        canwrite( 0x04, RXFNSIDH + RXFNSIDHADD );
        canwrite( 0x08, RXFNSIDH + RXFNSIDHADD );
        canwrite( 0x10, RXFNSIDH + RXFNSIDHADD );
        canwrite( 0x14, RXFNSIDH + RXFNSIDHADD );
        canwrite( 0x18, RXFNSIDH + RXFNSIDHADD );
       
        canwrite( 0x01, RXFNSIDL );
        canwrite( 0x05, RXFNSIDL );
        canwrite( 0x09, RXFNSIDL );
        canwrite( 0x11, RXFNSIDL );
        canwrite( 0x15, RXFNSIDL );
        canwrite( 0x19, RXFNSIDL );

        canwrite( 0x02, RXFNEID8 );
        canwrite( 0x06, RXFNEID8 );
        canwrite( 0x0A, RXFNEID8 );
        canwrite( 0x12, RXFNEID8 );
        canwrite( 0x16, RXFNEID8 );
        canwrite( 0x1A, RXFNEID8 );

        canwrite( 0x03, RXFNEID0 );
        canwrite( 0x07, RXFNEID0 );
        canwrite( 0x0B, RXFNEID0 );
        canwrite( 0x13, RXFNEID0 );
        canwrite( 0x17, RXFNEID0 );
        canwrite( 0x1B, RXFNEID0 );

        canwrite( 0x20, RXMNSIDH );
        canwrite( 0x24, RXMNSIDH );
       
        canwrite( 0x21, RXMNSIDL );
        canwrite( 0x25, RXMNSIDL );

        canwrite( 0x22, RXMNEID8 );
        canwrite( 0x26, RXMNEID8 );

        canwrite( 0x23, RXMNEID0 );
        canwrite( 0x27, RXMNEID0 );
}


//can初始化
void caninit( void )
{
        RESET = 0;
        delay();
        RESET = 1;
        canreset();
        delay();

        canwrite( 0x0F,0x80 );//CANCTRL:配置模式;终止发送中止;禁止单触发;禁止CLKOUT
       
        canwrite( 0x2A, 0x04 );//SJW=1TQ,TQ=625ns;晶振16MHz,波特率为160KHz,位时间10TQ
        canwrite( 0x29, 0xD9 );//PS2由CNF3的PHSEG22:PHSEG20决定;采样三次PS1=4TQ;传播段=2TQ
        canwrite( 0x28, 0x02 );//禁止唤醒;PS2=3TQ

        canbite( 0x60, 0x64, 0x40 );//RXB0CTL:接收扩展帧,滚存禁止
        canbite( 0x70, 0x60, 0x40 );//RXB1CTL:接收扩展帧

        filterinit(); //屏蔽和滤波设置
        txinit(); //发送数据帧设置

        canwrite( 0x2D, 0x00 );//E**复位
        canwrite( 0x2B, 0x23);//使能:错误条件变化中断,接收缓冲器满中断
        canwrite( 0x2C, 0x00 );//清所有中断标志
        canwrite( 0x0F, 0x00 );//CANCTRL:正常工作模式;终止发送中止;禁止单触发;禁止CLKOUT
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//can数据发送前判断是否可以发送
char cansendinit( void )
{
        char state;
        state = canreadstat();//读状态
        if( ( ( state & 0x80 ) == 0x80 )||( ( state & 0x20 ) == 0x20 )||( ( state & 0x08 ) == 0x08 ) )          //发送缓冲区有空
                {
                        txinit();//发送数据帧设置
                        return 1;
                }
        else
            return 0;
}

//can报文发送
void cansend( char TXBNSIDHADD,char TXBND1,char TXBND2 )
{
            char state;
          state = canreadstat();    //读状态
          if( ( state & 0x80 ) == 0x80 )          //发送缓冲区2空
                  {
                           canbite( 0x50, 0x08, 0x00 ); //清报文发送请求位
                        canwrite( 0x51, TXBNSIDH+TXBNSIDHADD );  //装载标志符
                        canwrite( 0x56, TXBND1 );   //装载发送缓冲区数据
                        canwrite( 0x57, TXBND2 );
                        canrts( 0x84 );                  //请求发送
                        delay();
                }
          else if( ( state & 0x20 ) == 0x20 )
                  {
                        canbite( 0x40, 0x08, 0x00 );
                        canwrite( 0x41, TXBNSIDH+TXBNSIDHADD );
                        canwrite( 0x46, TXBND1 );
                        canwrite( 0x47, TXBND2 );
                        canrts( 0x82 );
                        delay();
                }

          else if( ( state & 0x08 )==0x08 )
                {
                        canbite( 0x30, 0x08, 0x00 );
                        canwrite( 0x31, TXBNSIDH+TXBNSIDHADD );
                        canwrite( 0x36, TXBND1 );
                        canwrite( 0x37, TXBND2 );
                        canrts( 0x81 );
                        delay();
                }
}


//can报文接收及处理
void canreceive( void )
{
   if( rxflag == 1 )
   {
        char state,datah,datal,databiteh,databitel;

        EA = 0;
        rxflag = 0;
       
        state = canreadstat();//读状态
        if( ( state & 0x01 ) == 0x01 )
                {
                         datah=canread( 0x66 );//读取第1字节
                         datal=canread( 0x67 );//读取第2字节
                         canbite( 0x2C, 0x01, 0x00 );//清中断标志
                }
        else if( ( state & 0x02 ) == 0x02 )
                {
                         datah = canread( 0x76 );
                         datal = canread( 0x77 );
                         canbite( 0x2C, 0x02, 0x00 );
                }
        databiteh = datah & 0xF0;
        databitel = datah & 0x0F;
        if( databiteh == 0x10 )
                 {
                        while( cansendinit() ) //判断是否有发送缓冲区为空
                                cansend( databitel << 4, 0xF0+databitel, datal);        //如果最高4位为0001,向规定节点发送数据帧
                        while( cansendinit() )               
                                cansend( 0x04 << 4, 0x30+JIEDIAN, datal);        //向上位机发送0011****,表示收到数据
                }                       
        else if( databiteh == 0xF0 )
                 while( cansendinit() )
                        cansend( 0x04 << 4, 0x30+JIEDIAN, datal);        //如果最高4位为1111,向上位机发送0011****
          
        EA = 1;
   }       
}

//按键发送函数
void cantransmit( void )
{
           if( txflag == 1 )
                 {
                        EA = 0;
                        txflag = 0;

                        while( cansendinit() )
                                   cansend( 0x04 << 4, JIEDIAN+0x20, 0xFF );        //向上位机发送0010****,数据字节为0xFF;

                        EA = 1;
                }
}


//错误处理
void error( void )
{
        if( errorflag ==1 )
        {
         char state;

         EA = 0;
         errorflag = 0;

         state = canread( 0x2D );      //读错误标志寄存器E**
         if( ( state & 0x80 ) == 0x80 )
                 {
                        while( cansendinit() )
                                cansend( 0x04 << 4, JIEDIAN, 0x01);  //接收缓冲器1溢出,向上位机发送0000**** 00000001
                        canreceive();
                        canbite( 0x2D, 0x80, 0x00 ); //复位E**的RX1OVR位
                        canbite( 0x2C, 0x20, 0x00 );  //清除CANNINTF的错误中断标志位
                }
         else if((state & 0x40) == 0x40 )
                 {
                        while( cansendinit() )
                                cansend( 0x04 << 4, JIEDIAN, 0x00 );  //接收缓冲器0溢出,向上位机发送0000**** 00000000
                        canreceive();
                        canbite( 0x2D, 0x40, 0x00 ); //复位E**的RX0OVR位
                        canbite( 0x2C, 0x20, 0x00 );  //清除CANNINTF的错误中断标志位
                }       
         else if( ( state & 0x20 ) == 0x20 ) //总线关闭,则复位
                 {
                        TCON = 0x00;   //设置外部中断0和1为电平触发,并清外部中断标志
                        caninit();     //can复位
                        IE = 0x85;     //开总中断,禁止串口中断,禁止定时/计数器中断,允许外部中断
                }
         else if( ( state & 0x1F ) != 0x00 )
                 {
                        while( cansendinit() )
                                cansend( 0x04 << 4, JIEDIAN, 0x03);        //错误数小于255且错误条件变化时,向上位机发送0000**** 00000011
                        canbite( 0x2C, 0x20, 0x00); //清除CANNINTF的错误中断标志位
                }
         else
                 {
                        while( cansendinit() )
                                cansend( 0x04 << 4, JIEDIAN, 0xFF);   //其他未知错误,向上位机发送0000**** 11111111
                        canbite( 0x2C, 0x20, 0x00); //清除CANNINTF的错误中断标志位
                }
       
         EA = 1;
        }
}

//外部中断0
void canint0( void ) interrupt 0
{
           char state,stateicod;
        IE0 = 0; //清外部中断标志
        state = canread( 0x0E );
        stateicod = state & 0x0E;        //读取CANSTAT.ICOD位,判断优先级
        if( stateicod == 0x02 )
                errorflag = 1;
        else
                rxflag = 1;
}

//外部中断1
void canint1( void ) interrupt 2
{
        IE1 = 0;        //清中断标志
        delay();        //消除抖动

        if( INT1 == 0 )
                txflag = 1;
}

void main()
{
        TCON = 0x04;//设置外部中断0为电平触发,外部中断1为负跳变触发,并清外部中断标志
        caninit();
        IE = 0x85;//开总中断,禁止串口中断,禁止定时/计数器中断,允许外部中断0和1
        while( 1 )
                 {
                           canreceive();
                        cantransmit();
                           error();
                }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

2

帖子

1

粉丝