基于C8051F040单片机的CAN总线通信

基于c8051f040单片机的can总线通信硬件部分硬件部分电路结构如下:
can收发模块原本采用的是ata6660高速can收发芯片,电路连接如下:
设计电路为:当单片机发送数据时,d18闪烁,并将数据传送给ata6660芯片;当ata6660芯片接受到总线上的数据时,d17闪烁,并将数据传送给单片机。
实际调试时,发现c8051f040单片机既没办法发送数据到总线上,也没办法从总线上接收到数据。
用示波器对电路检测发现,当单片机需要发送数据时,ata6660芯片的txd引脚上能检测到数据,且d18闪烁。示波器检测总线上的电压,没有变化。pc端显示总线上的数据为fe。当pc端给总线发送数据时,总线上能检测到电压的变化,而ata6660芯片的rxd引脚电压为0。故怀疑为can收发部分硬件存在问题。
因此,将can收发模块换为直接购买的tja1050can收发模块,电路如下图所示。通过测试,can模块工作正常。而单片机能够成功发送数据,接收数据失败。
对比前后两个电路可以发现,区别在于can收发芯片的rs引脚。ata6660芯片的rs引脚悬空,而tja1050芯片的rs引脚接地。
查阅ata6660芯片数据手册,发现rs引脚的功能为switch standby mode/normal mode。而standy mode的解释为:
故使用ata6660模块时无法正常收发数据。而正确的电路应为:
软件部分程序参考自童长飞编著的《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; /* if1 command mask registers =0x00b3 wr/rd=1,mask=0,arb=1,control=1,clrintpnd=0,txrqst=0,dataa=1,datab=1,一次发送8字节数据*/ can0adr = if1arb1; can0dat = 0x0000; /*if1 arbitration registers1 =0x0000,即id15-0=0*/ temp=id<<2;//标准id为id28-id18,所以要左移2位 temp&=0x1fff; temp|=0xa000; can0dat = temp; //地址自增,指向if1 arbitration registers2 /*if1 arbitration registers2=101(id)00b msgval=1,xtd=0,为标准模式,扩展id无效,dir=1,为发送*/ can0dat = 0x0088; /*if1 message control registers=0x0088 newdat=0,msglst=0,intpnd=0,umask=0,txie=0,rxie=0,rmten=0,txrqst=0 eob=1,dlc3-0=1000,即数据长度为8*/ can0adr = if1cmdrqst; can0dat = msgnum; /*if1 command request registers=msgnum,将以上配置写入msgnum号消息*/}4.can接收初始化
void init_msg_object_rx (char msgnum,uchar id) { uint temp; sfrpage = can0_page; can0adr = if2cmdmsk; can0dat = 0x00fb; /* if2 command mask registers =0x00fb wr/rd=1,mask=1,arb=1,control=1,clrintpnd=1,txrqst=0,dataa=1,datab=1,一次接收8字节数据*/ can0adr = if2msk1; can0dat = 0x0000; can0dat = 0x0000; can0adr = if2arb1; can0dat = 0x0000; /*if2 arbitration registers1 =0x0000,即id15-0=0*/ temp=id<= 400 ns).
sync_seg = 1 tq
phase_seg1 + phase_seg2 = (11-6) tq = 5 tq
phase_seg1 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; /* if1 command mask registers =0x0087 wr/rd=1,mask=0,arb=0,control=0,clrintpnd=0,txrqst=1,dataa=1,datab=1,一次发送8字节数据*/ can0adr = if1data1; /*将8字节数据写入if1*/ 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; /* if1 command mask registers =0xxx0f wr/rd=0,mask=0,arb=0,control=0,clrintpnd=1,newdat=1,dataa=1,datab=1,一次发送8字节数据*/ 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’,但没有产生接收中断,接收消息对象中的数据也未改变。
其中0x02为发送消息对象,0x04为接收消息对象。
can0sta为status register寄存器中低8位。rxok为‘1’。
将单片机设置为测试模式,can control register寄存器中test位置1。使用回路静音模式时,将can test register寄存器lback和silent同时置1,使tx与rx自身形成回路,单片机自发自收。结果为单片机接收不到自己发送的数据。
使用测试模式中的基本模式时,将can test register寄存器basic位置1。此模式下,控制器不使用消息内存,即控制器不使用32个消息对象,而是将if1寄存器作为发送缓存区,将if2寄存器作为接收缓存区。此模式下,单片机发送数据正常,接收数据时,if2寄存器缓存区接收到的数据不正确。
最终,通信失败原因尚未得知。。。

如何用STM32让相对编码器说话?
iPhone8什么时候上市?iPhone8最新消息:iPhone8全面屏真惊艳,屏下指纹识别没有对手?
手机产业跨年大戏 2020开年就迎来了新硬战
工信部发布2020年通信业统计公报
干货!LED内置电源高低贵贱用眼睛就能看出来!
基于C8051F040单片机的CAN总线通信
区块链数字资产抵押借贷系统开发团队
Verizon预计到今年年底将会在60多个城市中推出5G服务
论AI的系统厂商vs系统厂商的AI
Google Play 游戏打造设备间的无缝切换体验
中国联通正式发布了总部ONS运营平台新建工程监控管理模块项目招标
DEKRA德凯扩建实验室新增声学及振动测试
戴尔:因英特尔CPU短缺造成产品供应紧张,将下调Q4季度的收入预期
备受广大果粉期待的2021全球开发者大会终于要来了
混合动力汽车电池均衡方案的研究
如何创建可以通过USB OTG电缆与Arduino通信的android应用程序
服务机器人企业云迹科技完成C轮融资
半导体芯片的升压芯片有哪些种类 升压芯片是如何升压的
HarmonyOS生态边界答疑 HarmonyOS如何给开发者提供技术支持
商用终端千兆级LTE正式到来!中国移动完成千兆级外场测试