淘先锋技术网

首页 1 2 3 4 5 6 7

硬件部分

硬件部分电路结构如下:

b232c1d563d7de3069beb3fc7380a1ba.png

CAN收发模块原本采用的是ATA6660高速CAN收发芯片,电路连接如下:

0b1e05d528bf405ee495b6ae2eb61ce3.png

设计电路为:当单片机发送数据时,D18闪烁,并将数据传送给ATA6660芯片;当ATA6660芯片接受到总线上的数据时,D17闪烁,并将数据传送给单片机。

实际调试时,发现C8051F040单片机既没办法发送数据到总线上,也没办法从总线上接收到数据。

用示波器对电路检测发现,当单片机需要发送数据时,ATA6660芯片的TXD引脚上能检测到数据,且D18闪烁。示波器检测总线上的电压,没有变化。PC端显示总线上的数据为FE。当PC端给总线发送数据时,总线上能检测到电压的变化,而ATA6660芯片的RXD引脚电压为0。故怀疑为CAN收发部分硬件存在问题。

因此,将CAN收发模块换为直接购买的TJA1050CAN收发模块,电路如下图所示。通过测试,CAN模块工作正常。而单片机能够成功发送数据,接收数据失败。

96cfcaad58667848d0cd18a8696f8df1.png

对比前后两个电路可以发现,区别在于CAN收发芯片的RS引脚。ATA6660芯片的RS引脚悬空,而TJA1050芯片的RS引脚接地。

查阅ATA6660芯片数据手册,发现RS引脚的功能为Switch Standby Mode/Normal Mode。而Standy Mode的解释为:

c047791d2bcfc5fe69b84d3b882df793.png

故使用ATA6660模块时无法正常收发数据。而正确的电路应为:

09d840ddc3f0b49bbb509ee2512d2ef3.png

软件部分

程序参考自童长飞编著的《C8051F系列单片机开发与C语言编程》例程12-1。

1.基本设置

int n;

//看门狗禁止

WDTCN = 0x07;

WDTCN = 0xDE;

WDTCN = 0xAD;

SFRPAGE = 0x0F;

//交叉开关使能,但没有进行外围设备配置

XBR0 = 0x00;

XBR1 = 0x00;

XBR2 = 0x40;

XBR3 = 0x00;

//管脚输出配置,P0口为开漏输出,其中P0.6接上拉电阻,P0为数字输入口

SFRPAGE = 0x0F;

P0MDOUT = 0x00;

P1MDIN = 0xFF;

//晶振配置

OSCXCN  = 0x77;//选择外部晶振22.1MHz。

//系统时钟为外部时钟二分频:22.1 MHz / 2 = 11.05 MHz

for (n = 0; n < 255; n++);

while ((OSCXCN & 0x80) == 0);

CLKSEL |= 0x01;

2.CAN消息对象清零

void clear_msg_objects (void) //将所有消息清零

{

uchar i;

SFRPAGE = CAN0_PAGE;

CAN0ADR = IF1CMDMSK;

CAN0DATL = 0xFF;

for (i=1;i<33;i++)

{

CAN0ADR = IF1CMDRQST;

CAN0DATL = i;

}

}

3.CAN发送初始化

void init_msg_object_TX (char MsgNum,uint id)

{

uint temp;

SFRPAGE = CAN0_PAGE;

CAN0ADR = IF1CMDMSK; //指向IF1 Command Mask Registers

CAN0DAT = 0x00b3;

CAN0ADR = IF1ARB1;

CAN0DAT = 0x0000;

temp=id<<2;//标准id为ID28-ID18,所以要左移2位

temp&=0x1fff;

temp|=0xa000;

CAN0DAT = temp; //地址自增,指向IF1 Arbitration Registers2

CAN0DAT = 0x0088;

CAN0ADR = IF1CMDRQST;

CAN0DAT = MsgNum;

}

4.CAN接收初始化

void init_msg_object_RX (char MsgNum,uchar id)

{

uint temp;

SFRPAGE = CAN0_PAGE;

CAN0ADR = IF2CMDMSK;

CAN0DAT = 0x00fb;

CAN0ADR = IF2MSK1;

CAN0DAT = 0x0000;

CAN0DAT = 0x0000;

CAN0ADR = IF2ARB1;

CAN0DAT = 0x0000;

temp=id<<2;//标准id为ID28-ID18,所以要左移2位

temp&=0x1fff;

temp|=0x8000;

CAN0DAT = temp;

CAN0DAT = 0x0488;

CAN0ADR = IF2CMDRQST;

CAN0DATL = MsgNum;

}

5.CAN波特率设置

Calculation of the CAN bit timing :

System clock f_sys = 22.1184 MHz/2 = 11.0592 MHz.

System clock period t_sys = 1/f_sys = 90.422454 ns.

CAN time quantum tq = t_sys (at BRP = 0)

Desired bit rate is 1 MBit/s, desired bit time is 1000 ns.

Actual bit time = 11 tq = 996.65ns ~ 1000 ns

Actual bit rate is 1.005381818 MBit/s = Desired bit rate+0.5381%

CAN bus length = 10 m, with 5 ns/m signal delay time.

Propagation delay time : 2*(transceiver loop delay + bus line delay) = 400 ns

(maximum loop delay between CAN nodes)

Prop_Seg = 5 tq = 452 ns ( >= 400 ns).

Sync_Seg = 1 tq

Phase_seg1 + Phase_Seg2 = (11-6) tq = 5 tq

Phase_seg1 <= Phase_Seg2, => Phase_seg1 = 2 tq and Phase_Seg2 = 3 tq

SJW = (min(Phase_Seg1, 4) tq = 2 tq

TSEG1 = (Prop_Seg + Phase_Seg1 - 1) = 6

TSEG2 = (Phase_Seg2 - 1) = 2

SJW_p = (SJW - 1) = 1

Bit Timing Register = BRP + SJW_p*0x0040 = TSEG1*0x0100 + TSEG2*0x1000 = 2640

Clock tolerance df :

A: df < min(Phase_Seg1, Phase_Seg2) / (2 * (13*bit_time - Phase_Seg2))

B: df < SJW / (20 * bit_time)

A: df < 2/(2*(13*11-3)) = 1/(141-3) = 1/138 = 0.7246%

B: df < 2/(20*11) = 1/110 = 0.9091%

Actual clock tolerance is 0.7246% - 0.5381% = 0.1865% (no problem for quartz)

SFRPAGE = CAN0_PAGE;

CAN0CN=0X41;

CAN0ADR=BITREG;

CAN0DAT=0x2640;//调波特率

6.发送函数

void transmit (char MsgNum)

{   uchar num;

SFRPAGE = CAN0_PAGE;

CAN0ADR = IF1CMDMSK;

CAN0DAT = 0x0087;

CAN0ADR = IF1DATA1;

for(num=0;num<4;num++)

{

CAN0DATH=sdata[2*num+1];

CAN0DATL=sdata[2*num];

}

CAN0ADR = IF1CMDRQST;

CAN0DATL = MsgNum; //将以上配置写入MsgNum号CAN消息

}

7.接收函数

void receive_data (uchar MsgNum)

{

uchar i;

SFRPAGE = CAN0_PAGE;

CAN0ADR = IF2CMDMSK;

CAN0DATL = 0x0f;

CAN0ADR = IF2CMDRQST;

CAN0DATL = MsgNum; //指向MsgNum号消息

CAN0ADR = IF2DATA1;

for(i=0;i<4;i++)

rdata[i].tempval=CAN0DAT;//接收数据

isnewdata=1;

}

最后现象:单片机发送成功,PC端能成功接收发送的数据。而单片机接收CAN总线数据时异常。TJA1050芯片的RXD引脚能检测到电压变化,而单片机Status Register寄存器中RxOk位为‘1’,但没有产生接收中断,接收消息对象中的数据也未改变。

6ce48b4c5155c8110dcb82282e5090f0.png 

其中0x02为发送消息对象,0x04为接收消息对象。

d295d89a41b62bbf868d2dfc9402bc06.png 

CAN0STA为Status Register寄存器中低8位。RxOk为‘1’。

  将单片机设置为测试模式,CAN Control Register寄存器中Test位置1。使用回路静音模式时,将CAN Test Register寄存器LBack和Silent同时置1,使TX与RX自身形成回路,单片机自发自收。结果为单片机接收不到自己发送的数据。21807a0417cc2a6b487db0a7955e064f.png

使用测试模式中的基本模式时,将CAN Test Register寄存器Basic位置1。此模式下,控制器不使用消息内存,即控制器不使用32个消息对象,而是将IF1寄存器作为发送缓存区,将IF2寄存器作为接收缓存区。此模式下,单片机发送数据正常,接收数据时,IF2寄存器缓存区接收到的数据不正确。