论坛里不知道有没有用过MCP2510的CANBUS的通信IC,本人初学者。
对于MCP2510和CAN都不太了解,自己用STC15F2K60S2的IC写了一个软件测试MCP2510通信的软件,用CAN分析仪模拟数据接收发送。
用端口模拟的SPI通信,(规划时没有规划到SPI通信模块)。
环回模式下数据是可以被发送(TXB0CTRL寄存器bit3=0;TXB0D0-7全部为0)但是在正常模式下,连接CAN分析仪后,TXCAN引脚并没有数据发送出去并出现总线错误。
使能发送后TXCAN引脚一直输出11ms高0.26ms低的脉冲。程序代码编写是参考网上的MCP2510例程。不知道现在那部份有问题。
用CAN分析仪发送数据,RXCAN引脚是有数据输出的,所以电路上应该没问题 ,却不能接收数据。
有哪位朋友有空帮忙分析分析
主控晶体:24M
MCP2510的晶体:8M
CAN的波特率:125K
配置的源代码
//***************************************************************************
//初始化MCP2510
//***************************************************************************
void Mcp2510Initial(void)
{
u8 n = 0;
P0M0 = P0M0|0x00;
P0M1 = P0M1|0x04; ;SPI_MISO设为输入
MCP2510_RESET = 1; //端口复位
SPI_CS = 1;
SPI_SCK = 0;
SPI_MOSI = 0;
SPI_MISO = 0;
delayx1ms(500); //初始化SPI端口状态
Mcp2510RESET(); //复位命令
Mcp2510Write(CANCTRL,0x80); //设定为配置模式
n = Mcp2510Read(CANSTAT); //读取CANSTAT
UARTTx(n);
Mcp2510Write(CNF1,0x03); //晶振8MHZ,CAN总 线速度125KHZ
n = Mcp2510Read(CNF1); //读取CNF1
UARTTx(n);
Mcp2510Write(CNF2,0x90);//相位段2位时间长度有CNF3中的PHSEG22:PHSEG20确定
//(PHSEG1 + 1) x TQ = (2+1)*TQ
n = Mcp2510Read(CNF2); //读取CNF2
UARTTx(n);
Mcp2510Write(CNF3,0x02); //(PHSEG2 + 1) x TQ = (2+1)*TQ
n = Mcp2510Read(CNF3); //读取CNF3
UARTTx(n);
Mcp2510Write(TXRTSCTRL,0x00); //TX2RTS作为数字输入
//TX1RTS作为数字输入
//TX0RTS作为数字输入
Mcp2510Write(TXB0CTRL,0x03); //TBB0报文发送优先级最高
Mcp2510Write(TXB1CTRL,0x00); //TBB1报文发送优先级最低
Mcp2510Write(TXB2CTRL,0x00); //TBB1报文发送优先级最低
Mcp2510Write(TXB0SIDH,0xFF); //TXB0标准标识符bit10-bit3
Mcp2510Write(TXB0SIDL,0xE0); //TXB0标准标识符bit2-bit0,标准标识符
Mcp2510Write(TXB1SIDH,0xFF); //TXB1标准标识符bit10-bit3
Mcp2510Write(TXB1SIDL,0xE0); //TXB1标准标识符bit2-bit0,标准标识符
Mcp2510Write(TXB2SIDH,0xFF); //TXB2标准标识符bit10-bit3
Mcp2510Write(TXB2SIDL,0xE0); //TXB2标准标识符bit2-bit0,标准标识符
Mcp2510Write(TXB0DLC,0x08); //TXB0数据帧,长度为8个字节
Mcp2510Write(TXB1DLC,0x08); //TXB1数据帧,长度为8个字节
Mcp2510Write(TXB2DLC,0x08); //TXB2数据帧,长度为8个字节
Mcp2510Write(TXB0D0,0x00); //清空TXB0发送缓存器
Mcp2510Write(TXB0D1,0x00); //清空TXB1发送缓存器
Mcp2510Write(TXB0D2,0x00); //清空TXB2发送缓存器
Mcp2510Write(TXB0D3,0x00); //清空TXB3发送缓存器
Mcp2510Write(TXB0D4,0x00); //清空TXB4发送缓存器
Mcp2510Write(TXB0D5,0x00); //清空TXB5发送缓存器
Mcp2510Write(TXB0D6,0x00); //清空TXB6发送缓存器
Mcp2510Write(TXB0D7,0x00); //清空TXB7发送缓存器
Mcp2510Write(CANINTE,0xFF); //使能所有总线状态和错误中断
Mcp2510Write(CANINTF,0x00); //清0所有总线状态和错误中断标志
Mcp2510ModifyBit(CANCTRL,0xE0,0x00); //进入正常模式
n = Mcp2510Read(CANSTAT)&0xE0; //读取CANSTAT
UARTTx(n);
}
//***************************************************************************
//MCP2510数据接收
//***************************************************************************
void Mcp2510RedData(void)
{
u8 n = 0;
u8 m[2] ={0,0};
n = Mcp2510Read(EFLG); //读取中断标志
UARTTx(n);
n = Mcp2510Read(CANINTF); //读取中断标志
UARTTx(n);
n = n&0x01;
if(n==1)
{
Mcp2510ModifyBit(CANINTF,0x01,(0<<RX0IF)); //RX0IF 清0 中断
Mcp2510SerialReadByte(RXB0SIDH,&m,2); //读取ID
u16_ID = m[0];
u16_ID = u16_ID << 8;
u16_ID = u16_ID |( m[1]&0xE0);
Mcp2510SerialReadByte(RXB0DLC,&m,1); //数据长度
u8_DLC = m[0]&0x0F;
Mcp2510SerialReadByte(RXB0D0,&u8_CANdata[0],u8_DLC); //读取数据
UARTTx(u16_ID>>8);
UARTTx(u16_ID>>0);
UARTTx(u8_DLC);
UARTTx(u8_CANdata[0]);
UARTTx(u8_CANdata[1]);
UARTTx(u8_CANdata[2]);
UARTTx(u8_CANdata[3]);
UARTTx(u8_CANdata[4]);
UARTTx(u8_CANdata[5]);
UARTTx(u8_CANdata[6]);
UARTTx(u8_CANdata[7]);
}
}
//***************************************************************************
//MCP2510数据发送
//***************************************************************************
void Mcp2510TxData(u8 *dat,u8 length)
{
u8 n = 0;
Mcp2510SerialWriteByte(TXB0D0,dat,length); //装载发送数据
n = Mcp2510Read(TXB0D0);
UARTTx(n);
n = Mcp2510Read(TXB0D1);
UARTTx(n);
n = Mcp2510Read(TXB0D2);
UARTTx(n);
n = Mcp2510Read(TXB0D3);
UARTTx(n);
n = Mcp2510Read(TXB0D4);
UARTTx(n);
n = Mcp2510Read(TXB0D5);
UARTTx(n);
n = Mcp2510Read(TXB0D6);
UARTTx(n);
n = Mcp2510Read(TXB0D7);
UARTTx(n);
Mcp2510Write(TXB0DLC,length); //设置为发送8个字节
Mcp2510Write(TXB0CTRL,0x03); //设置为中偏低的报文发送优先级
Mcp2510Write(TXB0SIDH,u16_ID>>8); //TXB0SIDH 标识符高位 ID
Mcp2510Write(TXB0SIDL,u16_ID>>0); //TXB0SIDL 标识符低位 ID
Mcp2510RTS(); //请求发送
delayx1ms(1000);
Mcp2510WaitTxEnd(TXB0CTRL); //等待发送完成
n = Mcp2510Read(TXB0D0);
UARTTx(n);
n = Mcp2510Read(TXB0D1);
UARTTx(n);
n = Mcp2510Read(TXB0D2);
UARTTx(n);
n = Mcp2510Read(TXB0D3);
UARTTx(n);
n = Mcp2510Read(TXB0D4);
UARTTx(n);
n = Mcp2510Read(TXB0D5);
UARTTx(n);
n = Mcp2510Read(TXB0D6);
UARTTx(n);
n = Mcp2510Read(TXB0D7);
UARTTx(n);
}
//***************************************************************************
//MCP2510请求发送命令
//***************************************************************************
void Mcp2510RTS(void)
{
SPI_CS = 0;
spi_write(SPI_RTS|0x01);
SPI_CS = 1; //发送请求命令
delayx1ms(1);
}
//***************************************************************************
//读取MCP2510芯片的状态
//***************************************************************************
u8 Mcp2510ReadStatus(void)
{
uchar n = 0;
SPI_CS = 0;
spi_write(SPI_READ_STATUS);
n = spi_write(0x00);
SPI_CS = 1;
delayx1ms(1);
return(n);
}
//***************************************************************************
//等待MCP2510发送结束
//addr : 读取地址
//***************************************************************************
void Mcp2510WaitTxEnd(u8 addr)
{
u8 n = 0;
do
{
n = Mcp2510Read(CANINTF);
UARTTx(n);
n = Mcp2510Read(EFLG);
UARTTx(n);
SPI_CS = 0;
spi_write(SPI_READ);
spi_write(addr);
n = spi_write(0x00);
SPI_CS = 1;
n=n&0x08;
delayx1ms(1);
}
while(n);
}
//***************************************************************************
//MCP2510 写数据
//addr: MCP2510的寄存器地址
//dat: 写入MCP2510寄存器地址的数据
//SPI_WRITE:写命令
//***************************************************************************
void Mcp2510Write(u8 addr,u8 dat)
{
SPI_CS = 0;
spi_write(SPI_WRITE);
spi_write(addr);
spi_write(dat);
SPI_CS = 1;
delayx1ms(1);
}
//***************************************************************************
//MCP2510 读数据
//addr: MCP2510的寄存器地址
//SPI_READ:读命令
//返回值: 读取地址对应的数据
//***************************************************************************
u8 Mcp2510Read(u8 addr)
{
u8 n = 0;
SPI_CS = 0;
spi_write(SPI_READ);
spi_write(addr);
n = spi_write(0x00);
SPI_CS = 1;
delayx1ms(1);
return(n);
}
//***************************************************************************
//MCP2510 位修改
//addr: MCP2510的寄存器地址
//mask: 屏蔽位
//dat: 写入MCP2510寄存器地址的数据
//SPI_BIT_MODIFY:位修改命令
//***************************************************************************
void Mcp2510ModifyBit(u8 addr,u8 mask,u8 dat)
{
SPI_CS = 0;
spi_write(SPI_BIT_MODIFY);
spi_write(addr);
spi_write(mask);
spi_write(dat);
SPI_CS = 1;
delayx1ms(1);
}
//***************************************************************************
//MCP2510 连续写字节
//addr: MCP2510的寄存器地址
//dat: 写入MCP2510寄存器地址的连续数据
//length:数据长度
//***************************************************************************
void Mcp2510SerialWriteByte(u8 addr,u8 *dat,u8 length)
{
u8 n = 0;
SPI_CS = 0;
spi_write(SPI_WRITE);
spi_write(addr);
for(n=0;n<length;n=n+1)
{
spi_write(*dat);
dat = dat+1;
}
SPI_CS = 1;
delayx1ms(1);
}
//***************************************************************************
//MCP2510 连续读字节
//addr: MCP2510的寄存器地址
//dat: 读出MCP2510寄存器地址的连续数据
//length:数据长度
//***************************************************************************
void Mcp2510SerialReadByte(u8 addr,u8 *dat,u8 length)
{
u8 n = 0;
SPI_CS = 0;
spi_write(SPI_READ);
spi_write(addr);
for(n=0;n<length;n=n+1)
{
dat = dat+n;
*dat = spi_write(0x00);
}
SPI_CS = 1;
delayx1ms(1);
}
/*
*****************************************************************************
* SPI write
*****************************************************************************
*/
uchar spi_write(uchar spidata)
{
uchar i;
uchar j;
for(i=8;i>0;i=i-1)
{
if(spidata&0x80)
{
SPI_MOSI = 1;
}
else
{
SPI_MOSI = 0;
}
SPI_SCK = 1;
spi_delay();
j = j<<1;
if(SPI_MISO)
{
j = j|0x01;
}
else
{
j = j&0xFE;
}
spidata = spidata<<1;
SPI_SCK = 0;
spi_delay();
}
return(j);
}
/*****************************************************************************
*SPI 时钟延时
******************************************************************************/
void spi_delay(void)
{
uchar i;
for(i=255;i!=0;i--)
{
}
}
现场总线,工业以太网,工业交换机通信产品:(手机13072208083,网址www.tj-sange.com 天津)
(1)CAN CANOpen DeviceNet 总线
CAN转光纤(点对点)、CAN转光纤(环网 手拉手)
CAN集线器(8路)、CAN总线延长 中继器器、CAN转Modbus 485. CAN转网口
(2)Modbus 485总线
485转光纤(点对点)、485转光纤(环网 手拉手)
485集线器(8路)、485总线延长 中继器器、CAN转Modbus 485. 485转网口
(3)Profibus总线
Profibus转光纤(点对点)、Profibus转光纤(环网 手拉手)
Profibus集线器(4路)、Profibus总线延长 中继器器、Profibus转Modbus 485。
(4)模拟量转光纤4-20mA 、模拟量转光纤0-10V、 开关量转光纤
(5)HART转Modbus 485.
(6)4-20mA 、0-10V采集卡( 485接口Modbus协议)
(7)手持信号发生器 电荷测量仪
(8)CC-LINK转光纤
(9)485 CAN PRIFIBUS 转网口
(10)485 4-20MA 0-10V转LORA
(11) Profinet 转Modbus网关