|
小弟最近在弄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, 杜汶泽)
|