搜索
bottom↓
回复: 8

can总线(mcp2515)环自收发可以,正常模式下总是仲裁失败

[复制链接]

出0入0汤圆

发表于 2013-7-30 16:34:55 | 显示全部楼层 |阅读模式
小弟最近在弄mcp2515,目前是环回模式下自收发可以调通,可是转到正常模式下的时候就出问题,读取寄存器值看了一下 总是提示仲裁失败,芯片用的是ATmega128,实在费解,初次接触can,还望各位大哥多多指教!
电路图如下:

初始化以及发送程序如下:

#include "mcp2515.h"
#include <avr/io.h>

/*============================================================
C file about MCP2515   V1.00
==============================================================
Chip:      MCP2515
Function:    The controller of CAN-BUS
Writer:     Fenghui Zhu
Data:      2009.3.31
Reference:   "mcp2515.c" of Fabian Greif
=============================================================*/

//*********************
//* 头 文 件 配 置 区 *
//*********************

//**********************
//*   函 数 声 明 区   *
//**********************
void SPI_MasterTransmit(unsigned char data)
{
        //SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);
        //DDRB |=0x40;//SCK为输出
        SPDR=data;
        while(!(SPSR & (1<<SPIF)));
}
unsigned char  SPI_MasterRead(void)
{
        //SPCR=(1<<SPE);
        SPDR=0;//DDRB &=0XDF;                //SCK为输入
        while(!(SPSR & (1<<SPIF)));

        return SPDR;

}
//**********************
//*   函 数 定 义 区   *
//**********************
/*void int0_init(void)//外部中断初始化函数
{
EICRA|=(1<<ISC01);  //外部中断0配置为下降沿触发
EIMSK|=(1<<INT0);//外部中断0使能

}*/

unsigned char  mcp2515_readstaus(void)
{
        unsigned char data;
        EN_SPICS;  //MCP2515的CS有效
        SPI_MasterTransmit(SPI_READ_STATUS); // 发送SPI写寄存器控制字
        data = SPI_MasterRead(); //回读寄存器数据
        DIS_SPICS;
        return data;

}

//**********************************************************//
//   函数说明:MCP2515初始化程序                            //
//   输入:    无                                   //
//   输出:    无                                          //
//   调用函数:                                  //
//**********************************************************//
void mcp2515_init(void)
{
        //初始化MCU的SPI总线
        //spi_init();
        unsigned char temprxm[4] = { 0x00, 0x00, 0x00, 0x00 };//屏蔽寄存器的设置参数
        unsigned char temp0[4] = { 0xa2, 0xc0, 0x00, 0 };//寄存器的设置参数
        // unsigned char temp1[4] = { 0xa2, 0xc0, 0x00, 0 };
        // unsigned char temp2[4] = { 0xa2, 0xc0, 0x00, 0 };
        // unsigned char temp3[4] = { 0xa2, 0xc0, 0x00, 0 };
        // unsigned char temp4[4] = { 0xa2, 0xc0, 0x00, 0 };
        // unsigned char temp5[4] = { 0xa2, 0xc0, 0x00, 0 };
        // MCP2515 启动前进行软件复位
        EN_SPICS;  //MCP2515的CS有效
        SPI_MasterTransmit( SPI_RESET );//复位指令发送后也是进入了配置模式
        DIS_SPICS;  //MCP2515的CS无效

        //tempdata= mcp2515_readstaus(); //读状态寄存器--读发送状态
        // mcp2515_bit_modify( CANCTRL, 0x07, 0x00 );



        //使用位修改指令将MCP2515设置为配置模式
        //也就是将CANCTRL寄存器的REQOP[2:0]设置为100
        mcp2515_bit_modify( CANCTRL, 0xE0, (1<<REQOP2) );
        //配置模式下,设置单次发送,OSM=0,则是若发送失败会一直尝试发送
        //mcp2515_bit_modify( CANCTRL, 0xE0, (1<<OSM) );
        //tempdata= mcp2515_readstaus(); //读状态寄存器--读发送状态



        //计算并设置MCP2515的位时间

        // 时钟频率:Fosc  = 8MHz
        // 分频控制器 CNF1.BRP[5:0] = 3
        // 最小时间份额 TQ = 2 * ( BRP + 1 ) / Fosc   = 2*(3+1)/8M = 1uS
        // 同步段 Sync Seg   = 1TQ
        // 传播段 Prop Seg   = ( PRSEG + 1 ) * TQ  = 1 TQ
        // 相位缓冲段 Phase Seg1 = ( PHSEG1 + 1 ) * TQ = 1 TQ
        // 相位缓冲段 Phase Seg2 = ( PHSEG2 + 1 ) * TQ = 1 TQ
        // 同步跳转长度设置为 CNF1.SJW[1:0] = 00, 即 1TQ
        // 总线波特率 NBR = Fbit =  1/(sync seg + Prop seg + PS1 + PS2 )
        //                       = 1/(4TQ) = 1/4uS = 250kHz

        //设置分频控制器CNF1.BRP[5:0] = 3,同步跳转长度设置为 CNF1.SJW[1:0] = 00
        mcp2515_write_register( CNF1, (1<<BRP0)|(1<<BRP1));
        //mcp2515_write_register( CNF1, (1<<BRP0)|(1<<BRP1)|(1<<BRP2));
        // 设置传播段 Prop Seg 为00,即1TQ,相位缓冲段 Phase Seg1的长度1TQ
        mcp2515_write_register( CNF2, (1<<BTLMODE) );
        // 设置 相位缓冲段 Phase Seg2为 1TQ , 禁用唤醒滤波器
        mcp2515_write_register( CNF3, 0 );



        // 设置MCP2515中断使能寄存器,禁用所有中断
        //mcp2515_write_register( CANINTE,  0 );

        // 设置MCP2515中断使能寄存器,使能接收缓冲器中断,使能错误中断
        mcp2515_write_register( CANINTE, (1<<RX1IE)|(1<<RX0IE));//|(1<<MERRE)|(1<<ERRIE) );


        //设置数据接收相关寄存器 接收使用2个寄存器接收

        // 设置RXM[1:0]=11,关闭接收缓冲器0屏蔽/滤波功能,接收所有报文;禁止滚存功能
        //mcp2515_write_register( RXB0CTRL, (1<<RXM1)|(1<<RXM0) );
        mcp2515_write_register( RXB0CTRL,0);//接收缓冲器0 启动,就收符合条件的数据

        // 设置RXM[1:0]=11,关闭接收缓冲器1屏蔽/滤波功能,接收所有报文;
        //mcp2515_write_register( RXB1CTRL, (1<<RXM1)|(1<<RXM0) );
        mcp2515_write_register( RXB1CTRL,0);//接收缓冲器0 启动,就收符合条件的数据


        //设置6个验收滤波寄存器为0,
        mcp2515_write_register_p( RXF0SIDH, temp0, 4 );//是对标准和扩展滤波寄存器赋值。
        mcp2515_write_register_p( RXF1SIDH, temp0, 4 );
        mcp2515_write_register_p( RXF2SIDH, temp0, 4 );
        mcp2515_write_register_p( RXF3SIDH, temp0, 4 );
        mcp2515_write_register_p( RXF4SIDH, temp0, 4 );
        mcp2515_write_register_p( RXF5SIDH, temp0, 4 );

        //设置2个验收屏蔽寄存器为0,
        mcp2515_write_register_p( RXM0SIDH, temprxm, 4 );
        mcp2515_write_register_p( RXM1SIDH, temprxm, 4 );



        //配置引脚
        //设置接收相关引脚控制寄存器,配置它们禁用第二功能
        mcp2515_write_register( BFPCTRL, 0 );

        //调试使用,设置BFPCTRL使RX0BF,RX1BF设置为数字输出。只能通过SPI来修改,主要用于调试。
        //mcp2515_bit_modify( BFPCTRL, (1<<B1BFE)|(1<<B0BFE)|(1<<B1BFM)|(1<<B0BFM), (1<<B1BFE)|(1<<B0BFE) );

        //mcp2515_bit_modify( BFPCTRL, (1<<B1BFS)|(1<<B0BFS), 0x30 );
        //设置发送相关引脚控制寄存器,配置它们禁用第二功能// 暂时的禁用  硬件设计时候是有使用的**************************************************
        mcp2515_write_register( TXRTSCTRL, 0 );  //数字输入功能,读出值为该引脚的电平

        //MCP2515进入环回模式,进行功能测试
        // mcp2515_bit_modify( CANCTRL, 0XE0, (1<<REQOP1) );

        //MCP2515进入正常模式
        mcp2515_bit_modify( CANCTRL, 0xE0, 0);


}


//**********************************************************//
//   函数说明:MCP2515写控制寄存器程序                      //
//   输入:    寄存器地址,写入数据                         //
//   输出:    无                                          //
//   调用函数:SPI发送程序SPI_MasterTransmit                //
//**********************************************************//

void mcp2515_write_register( unsigned char adress, unsigned char data )
{
        // CS low ,MCP2515 enable
        EN_SPICS;

        SPI_MasterTransmit(SPI_WRITE); // 发送SPI写寄存器控制字

        SPI_MasterTransmit(adress);  //发送寄存器地址

        SPI_MasterTransmit(data);   //发送寄存器数据

        //CS high ,MCP2515 disable
        DIS_SPICS;
}

//**********************************************************//
//   函数说明:MCP2515读控制寄存器程序                      //
//   输入:    寄存器地址,                             //
//   输出:    寄存器数据                                  //
//   调用函数:SPI发送程序SPI_MasterTransmit                //
//**********************************************************//

unsigned char mcp2515_read_register(unsigned char adress)
{
        unsigned char data;

        // CS low ,MCP2515 enable
        EN_SPICS;

        SPI_MasterTransmit(SPI_READ); // 发送SPI写寄存器控制字

        SPI_MasterTransmit(adress); //发送寄存器地址

        data = SPI_MasterRead(); //回读寄存器数据

        //CS high ,MCP2515 disable
        DIS_SPICS;

        return data;
}

//**********************************************************//
//   函数说明:读MCP2515接收缓冲器程序                      //
//   输入:    缓冲器地址,                             //
//   输出:    缓冲器数据                                  //
//   调用函数:SPI发送程序SPI_MasterTransmit                //
//**********************************************************//

/*unsigned char mcp2515_read_rx_buffer(unsigned char adress)
{
unsigned char data;

// 判断adress是否有效,除了1,2位,其余都应为0
if (adress & 0xF9)
return 0;

// CS low ,MCP2515 enable
EN_SPICS;

SPI_MasterTransmit(SPI_READ_RX | adress); //发送读取控制字

data = SPI_MasterRead(); //读回数据

//CS high ,MCP2515 disable
DIS_SPICS;

return data;
}*/

//**********************************************************//
//   函数说明:MCP2515控制寄存器位修改程序                //
//   输入:    寄存器地址,修改位,修改数据                //
//   输出:    无                                      //
//   调用函数:SPI发送程序SPI_MasterTransmit                //
//**********************************************************//

void mcp2515_bit_modify(unsigned char adress, unsigned char mask, unsigned char data)
{
        // CS low ,MCP2515 enable
        EN_SPICS;

        SPI_MasterTransmit(SPI_BIT_MODIFY); //SPI位修改指令

        SPI_MasterTransmit(adress);    //发送寄存器地址

        SPI_MasterTransmit(mask);     //发送屏蔽字节,
        //屏蔽字节中“1”表示允许对相应位修改,“0”表示禁止修改
        SPI_MasterTransmit(data);     //发送数据字节

        //CS high ,MCP2515 disable
        DIS_SPICS;
}

//**********************************************************//
//   函数说明:对MCP2515连续寄存器进行连续写操作            //
//   输入:    连续寄存器起始地址,数据指针,数据长度      //
//   输出:    无                                      //
//   调用函数:SPI发送程序SPI_MasterTransmit                //
//**********************************************************//
void mcp2515_write_register_p( unsigned char adress, unsigned char *data, unsigned char length )
{
        unsigned char i;

        // CS low ,MCP2515 enable
        EN_SPICS;

        SPI_MasterTransmit(SPI_WRITE);  //发送SPI写指令

        SPI_MasterTransmit(adress);    //发送起始寄存器地址

        for (i=0; i<length ;i++ )
        SPI_MasterTransmit(*data++);  //发送数据

        //CS high ,MCP2515 disable
        DIS_SPICS;
}

//**********************************************************//
//   函数说明:对MCP2515连续寄存器进行连续读操作            //
//   输入:    连续寄存器起始地址,数据指针,数据长度      //
//   输出:    无                                      //
//   调用函数:SPI发送程序SPI_MasterTransmit                //
//**********************************************************//
void mcp2515_read_register_p( unsigned char adress, unsigned char *data, unsigned char length )
{
        unsigned char i;

        // CS low ,MCP2515 enable
        EN_SPICS;

        SPI_MasterTransmit(SPI_READ);  //发送SPI读指令

        SPI_MasterTransmit(adress);   //发送起始寄存器地址

        for (i=0; i<length ;i++ )
        *data++ = SPI_MasterRead();  //数据保存

        //CS high ,MCP2515 disable
        DIS_SPICS;
}
//**********************************************************//
//   函数说明:对MCP2515启动发送            //
//   输入:   n:设置启动的发送缓存器序号  n=0 忽略该命令   //
//   输出:    无                                      //
//   调用函数:SPI发送程序SPI_MasterTransmit                //
//**********************************************************//
/*void mcp2515_send_start(unsigned char n)
{

mcp2515_bit_modify( CANCTRL, 0x10, 0);//将ABAT位清零,使能发送
EN_SPICS;  //MCP2515的CS有效
SPI_MasterTransmit( SPI_RTS|n);
DIS_SPICS;
}*/

/*void mcp2515_end_send(void)
{
EN_SPICS;  //MCP2515的CS有效
mcp2515_bit_modify( CANCTRL, 0x10, (1<<ABAT) );//设置ABTA位为一可以中止所有的发送。
DIS_SPICS;

}*/

/*void canbus_address(unsigned int address)
{
can.id_h=address>>3;
can.id_l=((address&0x007)<<5);

}*/
volatile unsigned char temp=0,readBuff[15],regBuff[0x70];
unsigned char canbus_send(unsigned int address,unsigned char length,unsigned char *data)
{
        mcp2515_bit_modify( TXB0CTRL, (1<<TXP1)|(1<<TXP0), (1<<TXP1)|(1<<TXP0) ); //设置发送的最高优先级

        //mcp2515_write_register( TXB0SIDH, can.id_h  );//id3-id10
        // mcp2515_write_register( TXB0SIDL, can.id_l ); //设置ID   id0-id2(高字节高3位)发送的是标准标识符
        mcp2515_write_register( TXB0SIDH, address>>3 );//id3-id10
        mcp2515_write_register( TXB0SIDL, ((address&0x007)<<5) ); //设置ID   id0-id2(高字节高3位)发送的是标准标识符
        mcp2515_write_register( TXB0DLC, length );
        mcp2515_write_register_p( TXB0D0, data,  length );

        mcp2515_bit_modify( TXB0CTRL, 0x08, 0);//将TXEQ位清零,表示无
        mcp2515_bit_modify( CANCTRL, 0x10, 0);//将ABAT位清零,中止对所有报文中止发送的请求
        EN_SPICS;  //MCP2515的CS有效
        SPI_MasterTransmit( SPI_RTS|0x01);  //启动发送胡重启0
        DIS_SPICS;

        //mcp2515_bit_modify(TXB0CTRL,0x08,0x08);   //发送缓冲器0请求发送

        while((mcp2515_read_register(TXB0CTRL)& 0x08) == 0x08) // 等待发送完毕
        {
                mcp2515_read_register_p( TXB0SIDH,readBuff,14);
                for(temp = 0;temp<0x70;temp++)
                {
                        regBuff[temp] = mcp2515_read_register(temp);
                }
                if(((mcp2515_read_register(TXB0CTRL) & 0x30))) //出现发送数据错误了 报文发送出现错误
                return 0;
        }
        return 1;

}

void canbus_receive()  //接收函数可以放在mcu的外部中断函数中进行
{
        //  unchar id_l,id_h;//可用来判断接收的数据是否正确
        //mcp2515_write_register(RXB0CTRL,0X00);
        // mcp2515_bit_modify(CANINTF, 0x01,0x00);
        unsigned char *p;
        p=&can.singledata[0];
       
        can.id_h= mcp2515_read_register(RXB0SIDH);
        can.id_l=mcp2515_read_register(RXB0SIDL);
        can.length= mcp2515_read_register(RXB0DLC);
        mcp2515_read_register_p( RXB0D0,p,can.length);
        mcp2515_bit_modify( CANINTF, 0XE3, 0X00 ); //读取万数据 清楚中断,只清除接受中断标志0x33,即bit1,bit0;
        //还有bit7,bit6,bit5是一些错误中断标志,需要MCU清楚后,才能使中断复位

}

void cansendmode(unsigned char mode)
{
        //can.senddata[0]=load_buf[0];
        can.data[1]=0x81;
        can.data[2]=mode;
        can.data[3]=3;
        //can.senddata[4]=load_buf[1];
        //can.senddata[5]=load_buf[2];
        //can.senddata[6]=load_buf[3];
        can.length=0x07;

        canbus_send(0X517,can.length,&can.data[0]);   //本身是0x516

        //mcp2515_bit_modify( CANINTF, 0X03, 0X00 ); //读取万数据 清楚中断
}


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2013-7-31 09:21:23 | 显示全部楼层
R276接100欧电阻试试

出0入0汤圆

 楼主| 发表于 2013-7-31 16:36:18 | 显示全部楼层
lcw_swust 发表于 2013-7-31 09:21
R276接100欧电阻试试

接了。目前TXB0CTRL的值,总是提示缓冲区有数据等待发送,然后就这么一直等待了……

出0入0汤圆

 楼主| 发表于 2013-8-1 09:43:51 | 显示全部楼层
唉,都三天了,mcp2515的TXD波形是这样的

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-8-1 09:44:24 | 显示全部楼层
而且一开始是不出现的,将txd和rxd短接一下,才会不停的发出这个波形

出0入0汤圆

 楼主| 发表于 2013-8-1 09:44:58 | 显示全部楼层
有没有用过这个芯片的,帮一下……

出0入0汤圆

发表于 2013-8-1 10:26:29 | 显示全部楼层
user_hzp 发表于 2013-8-1 09:44
有没有用过这个芯片的,帮一下……

你的电路有问题吧,我看你怎么是MCP2515跟外面连接啊,应该是CAN收发器,,而不是控制器MCP2515

出0入0汤圆

发表于 2013-8-1 10:29:57 | 显示全部楼层
splfsp 发表于 2013-8-1 10:26
你的电路有问题吧,我看你怎么是MCP2515跟外面连接啊,应该是CAN收发器,,而不是控制器MCP2515 ...

我看错了,U6原来是MCP2551,我看错成MCP2515了

出0入0汤圆

发表于 2013-8-1 10:30:49 | 显示全部楼层
我前几天刚调过MCP2515,
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 01:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表