原创 can调试经验和总结

2009-8-6 11:08 3005 1 4 分类: MCU/ 嵌入式

         大家好,这是我第一次发表技术文章,入道不久,感谢大虾们写的文章自己才能做出点东西来,所以我也是做一个回馈也对自己的做一个总结。


        powerd by happyxzxin


       我做的时候是用面包板搭的电路,老板说会不会有串扰,我告诉你,应该是不会的。


       搭电路搭的只是saj1000和82c250的外围电路,单片机外围电路是从三恒星买的51实验板。


      电路图如下:8c5476af-0af9-44c7-97ab-4b5fd10fd226.jpg


注意了,不是按原图的,其中要做一些修改也加了一些我的看法:


      匹配电阻接一和两个124的都一样。两个30pf(总线上的)不接也行,他们只是起到去干扰的问题,晶振用的是16m的,rx1接的是2.5v左右的电压,不是直接接地,接地了就不好使了,这个问题一会再研究。


 


电路大概是这样了,不过如果发现有小变动的话请提出来,可能我说漏了。我一会在整理一下电路,在发个出来。如果时间允许的话,嘿嘿


 


   我用的是paie的程序,贴出来



//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//描述:
//      INT0按键程序+显示程序+CAN自收发程序                                      &
//      数码管1-2(从右至左)显示本节点计数结果,数码管3-4显示接收到的数据     &
//      十进制显示                                                             &
//      CAN主要参数:       PeliCAN模式,扩展帧EFF模式                          &
//      29位标示码结构:                                                       &
//      发送数据结构:计数结果,0x02,0x03,0x04,0x05,0x06,0x07,0x08              &
//      接收数据结构: 待显示数据+其它7个字节的数据                             &
//      本节点的地址: 0x11,0x22,0x33,0x00;可以接收全部节点的数据               &
//      目的节点地址:0x01,0x02,0x03,0x00;可以被能接收全部节点数据的节点接收   &



//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//【声明】 此程序仅用于学习与参考,引用请注明版权和作者信息!                   &
//【声明】 作者: PIAE小组                                                      &


#include <reg52.h>
#include <intrins.h>
#include <can_selfdef.h>


void INT0_Counter( void ) interrupt 0 using 1
{//INT0按键为计数按键
unsigned int i;
i=1000;
    EA = 0;
    Txd_data++; //存储计数结果,并为待发送的数据
    TXD_flag = 1;//要发送数据标志位



 while(i--);
 while(i--);
    EA = 1;
}


void CAN_RXD( void ) interrupt 2
{//接收数据函数,在中断服务程序中调用


    uchar data Judge;
    EA = 0;//关CPU中断
    IE0 = 0;


    Judge = IR;
    if( Judge & 0x01)
    {//IR.0 = 1 接收中断
        RX_buffer[0] =  RBSR;
        RX_buffer[1] =  RBSR1;
        RX_buffer[2] =  RBSR2;
        RX_buffer[3] =  RBSR3;
        RX_buffer[4] =  RBSR4;
        RX_buffer[5] =  RBSR5;
        RX_buffer[6] =  RBSR6;
        RX_buffer[7] =  RBSR7;
        RX_buffer[8] =  RBSR8;
        RX_buffer[9] =  RBSR9;
        RX_buffer[10] =  RBSR10;
        RX_buffer[11] =  RBSR11;
        RX_buffer[12] =  RBSR12;
        RXD_flag = 1;//置有接收标志
        CMR = 0X04;
        Judge = ALC;//释放仲裁随时捕捉寄存器
        Judge = ECC;//释放错误代码捕捉寄存器
    }
    IER = 0x01;// .0=1--接收中断使能;
    EA = 1;//打开CPU中断
}


void main(void)
{    uchar bdata Judge;
//CPU初始化/*
  /*  SJA_RST = 0;//CAN总线复位管脚,复位无效
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
*/


    SJA_RST = 1;//CAN总线复位管脚,复位无效
    SJA_CS = 0;//CAN总线片选有效


/* CHECK1 = 0xAA;
 


 


 Judge = CHECK1 ;
P3=CHECK1>>2;
*/
    EX1 = 1;//
    IT1 = 0;//CAN总线接收中断  电平触发
    IT0 = 1;//外部中断0负边沿触发
    EX0 = 1;//打开外部中断0
    EA = 1; //打开总中断
    SJA_CS = 1;//CAN总线片选无效,使对数据总线的操作不会影响SJA1000。
//CPU初始化


    CAN_init(  ); //SJA1000初始化,对 SJA1000寄存器的读写是采用外部寄存器寻址方式,所以不需要程序单独控制片选有效无效
    _nop_();
    _nop_();
    while(1)
    {
        _nop_();
        _nop_();
        Rxd_deal();//接收处理程序
        Txd_deal();//发送处理程序
        led_seg7(1,Txd_data);
        led_seg7(3,Rxd_data);


    }


}



//*********************处理函数********************************



void Rxd_deal(void)
{//////// 接收处理程序//////////////
    if( RXD_flag )
    {
        EA = 0;//关闭CPU中断
        RXD_flag = 0;
        Rxd_data = RX_buffer[5];
        EA = 1;
     }
}//////// 接收处理程序//////////////


void Txd_deal(void)
{//发送处理函数,主要是准备数据,并且调用发送函数
    if( TXD_flag == 1 )
    {
        _nop_();
        TXD_flag = 0;
        TX_buffer[5]  = Txd_data;//
        CAN_TXD();
        _nop_();
        _nop_();
     }
}


//*********************处理函数********************************



//*********************CAN子函数***********************


void CAN_init( void )
{//SJA1000 的初始化
    uchar bdata Judge;
    uchar ACRR[4];
    uchar AMRR[4];
    ACRR[0] = 0x11;
    ACRR[1] = 0x22;
    ACRR[2] = 0x33;
    ACRR[3] = 0x44;//接收代码寄存器,节点1
    AMRR[0] = 0xff;
    AMRR[1] = 0Xff;
    AMRR[2] = 0xff;
    AMRR[3] = 0xff;//接收屏蔽寄存器。 只接收主机发送的信息
    do
    {//  .0=1---reset MODRe,进入复位模式,以便设置相应的寄存器
     //防止未进入复位模式,重复写入
        MODR   = 0x09;
 Judge = MODR ;
    }
    while( !(Judge & 0x01) );
    CDR  = 0x88;// CDR.3=1--时钟关闭, .7=0---basic CAN, .7=1---Peli CAN
    BTR0 = 0x31;
    BTR1 = 0x1c;//总线波特率设定
    IER  = 0x01;// .0=1--接收中断使能;  .1=0--关闭发送中断使能
    OCR  = 0xaa;// 配置输出控制寄存器
    CMR  = 0x04;//释放接收缓冲器


    ACR  = ACRR[0];
    ACR1 = ACRR[1];
    ACR2 = ACRR[2];
    ACR3 = ACRR[3];//初始化标示码


    AMR  = AMRR[0];
    AMR1 = AMRR[1];
    AMR2 = AMRR[2];
    AMR3 = AMRR[3];//初始化掩码
    do
    {//确保进入自接收模式
 MODR   = 0x04;
 Judge  = MODR;
     }
    while( !(Judge & 0x04) );


}//SJA1000 的初始化



void CAN_TXD( void )
{
    uchar data Judge;
    uchar data TX_buffer[ N_can ] ;


//初始化标示码头信息
    TX_buffer[0] = 0x88;//.7=0扩展帧;.6=0数据帧; .3=1数据长度
    TX_buffer[1] = 0x01;//本节点地址
    TX_buffer[2] = 0x02;//
    TX_buffer[3] = 0x03;//
    TX_buffer[4] = 0x00;//
//初始化标示码头信息


//初始化发送数据单元
    TX_buffer[5]  = Txd_data;
    TX_buffer[6]  = 0x22;
    TX_buffer[7]  = 0x33;
    TX_buffer[8]  = 0x44;//
    TX_buffer[9]  = 0x55;//
    TX_buffer[10] = 0x66;//
    TX_buffer[11] = 0x77;//
    TX_buffer[12] = 0x88;//



//初始化数据信息
    EA = 0; //关中断
    do
    {
        Judge = SR;// 状态寄存器
        LED_RED = 0;//
    }
    while( Judge & 0x10 );  //SR.4=1 正在接收,等待
   
    do
    {
        Judge = SR;
        LED_RED = 0;//
    }
    while(!(Judge & 0x08)); //SR.3=0,发送请求未处理完,等待


    do
    {
        Judge = SR;
        LED_RED = 0;//
    }
    while(!(Judge & 0x04)); //SR.2=0,发送缓冲器被锁。等待


    LED_RED = !LED_RED;
    LED_GRE = !LED_GRE;//灯闪烁


    TBSR   = TX_buffer[0];
    TBSR1  = TX_buffer[1];
    TBSR2  = TX_buffer[2];
    TBSR3  = TX_buffer[3];
    TBSR4  = TX_buffer[4];
    TBSR5  = TX_buffer[5];
    TBSR6  = TX_buffer[6];
    TBSR7  = TX_buffer[7];
    TBSR8  = TX_buffer[8];
    TBSR9  = TX_buffer[9];
    TBSR10 = TX_buffer[10];
    TBSR11 = TX_buffer[11];
    TBSR12  = TX_buffer[12];


    CMR = 0x10;//置位自发送接收请求  // 命令寄存器
    EA  = 1;


}


void Delay(uchar delay_time)
{//延时程序
    while(delay_time--)
    {}
}


//*********************CAN子函数*************************


 void led_seg7(uchar from,uchar number)  //from(1_4):数码管显示起始位置(从右到左),number:显示的数
{
    uchar digit,temp_l;
    uchar temp_h=0x7f;
    temp_h = _cror_(temp_h,from-1);   //确定从哪一位开始显示,即确定高四位
    temp_h = temp_h & 0xf0;           //取高四位
    temp_l = P2 & 0x0f;               //取P2的低四位
    P2 = temp_h | temp_l;             //设定P2口


    if(number==0)
    {
        P0 = led[0];
        Delay(5);
        P0 = 0xff;
    }
    else
    {
        while(number)
 {
            digit = number%10 ;
     number /= 10;
            P0 = led[digit] ;
     Delay(5);
            temp_h = P2 & 0xf0;               //取P2的高四位
            temp_h = temp_h | 0x0f;           //拼装 temp_h,进行位选
     temp_h = _cror_(temp_h,1);
     temp_h = temp_h & 0xf0;           //取高四位
            temp_l = P2 & 0x0f;               //取P2的低四位
            P0 = 0xff;
            P2 = temp_h | temp_l;             //设定P2口
        }//while结束
    }//else结束
}


int0是按键,正常现象是按一下数码管1-2加一,同时3-4也加一,表示传输成功。


在调试过程中,按一下int0有时候1-2加一,3-4不加;有时候8个数码管全部都成乱码。如果在第一中情况1-2加一,3-4不加的话,在用低电平触发int1发送和接受灯(82c250上)就不断的闪,一般闪7-8下就停了,在触发在闪;有时候就会不断的闪下去,看起来很有成就感,像路由器一样。


最后发现,还是自己的电路搭建不够严密,面包板有问题,sja1000晶振的电容很奇怪的没接上地。


恩,以后做电路一定要胆大心细,要相信自己能做出来,不要有那种要调试很久才出来的感觉,相信自己能做出来,很快的做出来,如果很细心的话。


 


    

PARTNER CONTENT

文章评论3条评论)

登录后参与讨论

用户377235 2014-5-19 21:24

我想问一下你们为什么不发对寄存器的定义的头文件出来呢,就是这个can_selfdef.h文件,没了这个你这调试还能成功?对新手来说可能直接就以为只用你贴出来的这个程序就行了,你这不是捉弄人么,发这个程序有**用,都不齐全

用户377235 2014-4-13 17:38

需要数码管显示吗,数码管怎么接。不用数码管可以吗,

用户405983 2009-11-9 22:29

写的不错,谢谢分享

用户213153 2009-8-19 09:56

那位高人啊,这么好的程序,谢过了.....
相关推荐阅读
用户1476610 2009-08-12 16:20
请帮我分析一下315m发射和接收电路
p>来源 CEPARK网站http://www.cepark.com/Index.html  作者: hnrain由上图可见,外部振荡信号由XTAL2引入,XTAL1接地。为了提高输入电路的驱劝...
用户1476610 2009-07-31 09:58
超级电容容量及放电时间计算方法
 在超级电容的应用中,很多用户都遇到相同的问题,就是怎样计算一定容量的超级电容在以一定电流放电时的放电时间,或者根据放电电流及放电时间,怎么选择超级电容的容量,下面给出简单的计算公式,根据这个公式,就...
EE直播间
更多
我要评论
3
1
关闭 站长推荐上一条 /3 下一条