can总线通信程序

合集下载

can总线常用通信协议

can总线常用通信协议

竭诚为您提供优质文档/双击可除can总线常用通信协议篇一:史上最全can总线协议规则一、can总线简介can是控制器局域网络(controllerareanetwork,can)的简称,是由研发和生产汽车电子产品著称的德国bosch公司开发了的,并最终成为国际标准(iso11898)。

是国际上应用最广泛的现场总线之一。

在建立之初,can总线就定位于汽车内部的现场总线,具有传输速度快、可靠性高、灵活性强等优点。

上世纪90年代can总线开始在汽车电子行业内逐步推广,目前已成为汽车电子行业首选的通信协议,并且在医疗设备、工业生产、楼宇设施、交通运输等领域中取得了广泛的应用。

二、can总线技术及其规范2.1性能特点(1)数据通信没有主从之分,任意一个节点可以向任何其他(一个或多个)节点发起数据通信,通信方式灵活,且无需站地址等节点信息;(2)can网络上的节点信息分成不停的优先级,可满足不同的实时要求,高优先级节点信息最快可在134μs内得到传输;(3)采用非破坏性总线仲裁技术,当多个节点同时向总线发送信息时,优先级较低的节点会主动退出发送,而高优先级的节点可不受影响的继续发送数据,从而大大节省了总线冲突仲裁时间。

尤其是在网络负载很重的情况下也不会出现网络瘫痪的情况;(3)通信距离最远可达10km(速率低于5kbps)速率可达到1mbps(通信距离小于40m);(4)通信的硬件接口简单,通信线少,传输介质可以是双绞线,同轴电缆或光缆。

can总线适用于大数据量短距离通信或者长距离小数据量,实时性要求比较高,多主多从或者各个节点平等的现场中使用。

(5)采用短帧结构,传输时间短,受干扰概率低,每帧信息都有cRc校验及其他检验措施,数据出错率极低;(6)节点在严重错误的情况下具有自动关闭输出的功能,以使总线上其他节点的操作不受影响。

(7)can总线使用两根信号线上的差分电压传递信号,显性电平可以覆盖隐形电平。

2.2技术规范2.2.1can的分层结构图1can的分层结构逻辑链路控制子层(llc)的功能:为数据传送和远程数据请求提供服务,确认由llc子层接收的报文实际上已被接收,为恢复管理和通知超载提供信息。

快速了解CAN通讯原理及应用

快速了解CAN通讯原理及应用

快速了解CAN通讯原理及应用一张图看懂CAN总线的原理图1根据图1中简单来说CAN总线就如两根黄线,通信的原理就好比开一个电话会议,大家都同时拨进来,然后有各种不同的状态,比如:一个人说话,其他人听;或者多个人同时想发言,但也会让其中一个人先说,其他人听;还有一个人要求另一个人来说;还有些掉线了,卡顿了等等。

为了确保每次电话会议针对上述情况正确有效地进行,我们需要一些每个人都应该遵守的规则或协议。

CAN总线通信与这种电话会议形式既有相似之处,也有不同之处。

那究竟什么是CAN总线通信?CAN总线架构简介CAN总线是一种用于不同控制单元之间数据传输的导线。

CAN总线协议是ISO国际标准化的串行通信协议,由两个系列组成:ISO-11898和ISO-11519。

其定义有:ISO-11898定义了通信速率为125kbps~1Mbps的高速CAN通信标准,属于闭环总线,传输速率可达1Mbps,总线长度≤40米,如图2。

ISO11519定义了通信速率为10~125kbps的低速CAN通信标准,属于开环总线,传输速率为40kbps时,总线长度可达1000米,如图2。

图2CAN总线的应用CAN总线会有终端电阻,一般来说都是120欧姆,实际上在设计的时候,也是两个60欧姆的电阻串起来的,而总线上一般有两个120欧姆的节点。

终端电阻的作用有三个:1、提高干扰防护能力,快速消除高频低能量信号2、确保总线快速进入隐藏状态,这样寄生电容器的能量可以更快地耗散。

3、通过将它们放置在总线两端以减少反射能量来提高信号质量。

图3在学习CAN总线时,经常会看到CAN总线的电平分为显性电平与隐性电平,那么什么是显性的和隐性的呢?显式和隐式逻辑0与逻辑1之间的对应关系是什么?CAN通信逻辑0和1,显式和隐式。

电信号的传输是通过区分高电压和低电压来进行的,就像CAN通信一样。

CAN总线的两条信号线是CAN高(CAN_H)和CAN低(CAN_L)。

CAN总线的原理及使用教程

CAN总线的原理及使用教程

MSCAN08/MSCAN12
24
MSCAN08通信实现
发送和接收函数
//--------------函数声明--------------------------// //发送1帧远程帧 unsigned char CANsnd1RFrm(unsigned int rid); //CAN发送1帧数据帧(数据长度<=8) unsigned char CANsnd1DFrm(unsigned int rid, unsigned char * databuf,unsigned char len); //查找空闲发送缓冲区 unsigned char GetSndBuf(void); //接收1帧
MSCAN08/MSCAN12
6
位速率
位速率(Bit Rate) 指总线的传输速率,下表列出了距离与 位速率的相关数据。这里的最大距离是指 不接中继器的两个单元之间的距离。
MSCAN08/MSCAN12
7
位定位与同步
标称位速率(Nominal Bit Rate):理想的发送 器在没有重新同步的情况下每秒发送的位数量。 标称位时间(Nominal Bit Time):是标称位速 率的倒数。分成几个不重叠的片段:同步段 (SYNC_SEG ) 、 传 播 段 (PROG_SEG) 、 相 位 段 1(PHASE_SEG1)、相位段2(PHASE_SEG2)。
unsigned char CANrcv1Frm(unsigned char * canrcvbuf);
MSCAN08/MSCAN12 25
MSCAN08自环通信测试实例
(1).回环工作方式测试工程文件列表
表 17-8 回环工作方式测试工程文件列表 工程文件名 所在路径 文件类型 文件名 GZ60C.h Includes.h Type.h 头文件 CANInit.h CAN.h Commsubs.h vectors.c C语言 子函数文件 C语言主函数 MCUInit.c CANInit.c CAN.c Main.c CANSelfTest.prj MC08Ex2007\GP32\GP32C\C16_CAN\01_SelfTest 功能简述 芯片头文件 总头文件 数据类型头文件 声明CAN初始化函数 CAN收发子函数头文件 串行通信等通用子函数头 文件 中断向量表 芯片系统初始化函数定义 MSCAN08初始化函数定义 CAN收发子函数定义 主函数 讲解章节 参见工程实例 [08C工程文件组织] 5.3 [08C工程文件组织]5.3 本章 本章 参见工程实例 参见工程实例 参见工程实例 [本章] [本章] [本章]

基于DSPACE的CAN总线通讯程序开发-任务书

基于DSPACE的CAN总线通讯程序开发-任务书
五、主要参考资料
六、备注
指导教师签字:
年月日
教研室主任签字:
年月日
用于控制器开发流程的直观的软件产品:dSPACE产品拥有统一的接口界面。不管是开发、编程还是测试电控单元,都是在同一个综合环境下进行。这样可以加快并简化开发流程。
二、设计(论文)内容、技术要求(研究方法)
(一)主要内容
1、熟悉matlab/dspace软件。
2、研究车用CAN总线。
3、设计硬件部分即SAPACE的接口连接。
(3)编制程序及中期检查:第7~8周(4月12日~4月25日)
(4)编程序:第9~10周(4月26日~5月9日)
(5)整理文档并提交图纸和设计说明书初稿:第11~12周(5月10日~5月23日)
(6)毕业论文总结、评阅、审核及修改不足:第15~16周(5月24日~6月6日)
(7)为毕业论文答辩做准备及答辩:第17周(6月7日~6月13日)
毕业设计(论文)任务书
学生姓名
系部
汽车与交通工程学院
专业、班级
指导教师姓名
职称
实验师
从事
专业
车辆工程
是否外聘
□是 否
题目名称
基于DSPACE的CAN总线通讯程序开发
一、设计(论文)目的、意义
CAN总线是德国BOSCH公司80年代为解决现代汽车中众多的控制与测试仪器之间的数据交换而-开发的一种串行数据通信协议,其总线规范已被ISO国际标准组织制定为国际标准。现代汽车越来越多的采用电子控制装置,如发动机的喷油控制、ABS等。由于这些控制装置需检测及交换大量数据,采用连接信号线的方法不但烦琐而且昂贵,采用CAN总线上述问题可以得到很好的解决。世界上一些著名的汽车厂商都已开始采用CAN总线束实现汽车内部控制系统与各检测和执行机构间的数据通讯。

基于单片机的CAN总线通讯实现

基于单片机的CAN总线通讯实现

基于单片机的CAN总线通讯实现CAN(Controller Area Network)总线是一种现代的串行通信总线,广泛应用于汽车电子系统和工控领域。

它具有高可靠性、抗干扰能力强、高速传输、多节点连接等特点,成为实时控制系统的首选通信方式。

实现基于单片机的CAN总线通讯,需要经过以下几个步骤:1.硬件准备:选择合适的CAN控制器和单片机,常用的CAN控制器有MCP2515、SJA1000等。

接下来需要连接CAN控制器和单片机,包括连接CAN高低线路、配置引脚等。

2.引脚配置:根据所使用的单片机和CAN控制器的规格,配置相应的引脚。

通常需要配置CAN_TX、CAN_RX引脚,同时还需要配置中断引脚。

3. 初始化CAN总线:初始化CAN总线的过程包括设置波特率、模式选择、滤波器设置等。

波特率是通信的重要参数,需要保证发送和接收端的波特率一致,通常使用比较常见的波特率如500kbps。

4.发送数据:CAN总线通信是基于消息的,发送数据需要构建CAN消息帧。

消息帧包括标识符、数据长度、数据内容等。

在发送数据之前,需要准备好发送的数据,并将数据放入CAN消息帧中,最后将消息帧发送到总线上。

5.接收数据:接收数据需要配置CAN总线的工作模式和接收过滤器。

当有数据从总线上接收时,CAN控制器将数据存入接收缓冲器,并产生中断或者置位标志位来提醒主控处理接收到的数据。

6.数据处理:接收到的数据可以根据需要进行处理,包括解析、判断、存储等。

根据数据的标识符和长度等信息,可以将数据分发给不同的处理程序进行处理。

7.错误处理:在CAN总线通信过程中,可能会出现数据错误、通信超时等问题。

需要设置相应的错误处理机制,包括错误标志位的监测、错误计数器的清零等。

8.电源管理:在使用CAN总线通信时,需要合理管理系统的功耗和电源。

对于低功耗应用,可以将CAN控制器和单片机配置为睡眠模式,待接收到唤醒信号后再恢复正常工作。

总结:基于单片机的CAN总线通讯实现需要进行硬件准备、引脚配置、初始化CAN总线、发送数据、接收数据、数据处理、错误处理和电源管理等一系列步骤。

canopen通信流程

canopen通信流程

canopen通信流程CanOpen是一个开放式通信协议,用于在实时应用中控制和采集数据。

它是属于CAN总线的一种协议。

CanOpen通讯流程涉及到一些基本的概念和过程。

以下是CanOpen通信流程的详细介绍。

CanOpen协议的底层使用了CAN总线作为物理传输层,因此首先需要进行CAN总线的初始化。

CAN总线由两个主要部分组成,即通信周期和数据通信。

通信周期定时发送同步信息,这样所有节点可以以相同的时钟步进同步自己的操作。

数据通信则涉及其他高级的CanOpen对象,如节点状态,SDO(Service Data Object),PDO(Process Data Object)等。

CanOpen通信流程的具体步骤如下:1.初始化CAN总线:首先需要初始化CAN总线,包括设置波特率、过滤器和接收缓冲区等参数。

每个节点都必须进行这个步骤以确保与总线的正常通信。

2. 设置节点ID:每个CanOpen节点都需要有唯一的标识符,用于在总线上进行通信。

节点ID可以是一个独立的32位数值,也可以是一个组合的16位ID和8位的子标识符。

3. 节点状态管理:CanOpen节点有几种不同的状态,包括pre-operational、operational和stopped等。

在通信之前,节点必须进入pre-operational状态,并执行一些配置和初始化任务。

然后,节点可以进入operational状态,开始正常的数据通信。

4. SDO(Service Data Object)通信:SDO是CanOpen协议中用于传输配置和控制信息的对象。

它可以用于读取或写入节点的参数和数据。

SDO通信需要一个主节点和一个从节点。

主节点发送请求(Read或Write),从节点则返回响应。

这样可以方便地配置和控制节点。

5. PDO(Process Data Object)通信:PDO用于实时传输节点的实际过程数据。

PDO通信是基于事件触发的,其中一个节点可以发送对另一个节点的数据更改请求。

can总线的通信硬软件源码

can总线的通信硬软件源码

can总线的通信硬软件源码CAN通讯的优点在此就不多说了,10公里,5Kb/s的速度是能保证的。

第一步:硬件环境的建立。

这里采用的是SJA1000作为总线控制器,CTM8251模块作为总线驱动器。

MCU采用的是MEGA16:利用I/O口模拟数据总线,当然也可以使用有总线的MCU:MCS-51,MEGA8515等。

原理图如下:第二步:SJA1000的控制首先阅读下SJA1000的手册,基本了解下SJA1000的结构,主要是寄存器方面的。

还要了解下CA N总线方面的东西:BasicCAN,Peli CAN,远程帧,数据帧等等……SJA1000工作之前需要配置一下,才能正常工作,没有经过配置的SJA1000回拉坏总线的:组成网络的时候,如果其中有的SJA1000没有正确配置,这个设备会干扰总线,使其它设备的数据发送不出去。

怎么才能控制SJA1000呢,请看下面的SJA1000读写的时序图:写的时序根据时序要求,可以利用I/O口模拟总线了://**************************读SJA1000*************************// uint Read_SJA1000(uint address){uchar data;asm("nop");ALE_off;WR_on;RD_on;CAN_cs_on;DDRA=0xff; //数据口为输出PORTA=address; //输出数据的地址asm("nop");//delay5us(1);ALE_on;asm("nop");//delay5us(1);//DDRA=0xff; //数据口为输出PORTA=address; //输出数据的地址 //再次输出地址,确保一致。

asm("nop");//delay5us(1);ALE_off;//delay5us(1);CAN_cs_off;RD_off;asm("nop");//delay5us(2);asm("nop");DDRA=0x00; //数据口为输入PORTA=0xff; //上拉asm("nop");data=PINA; //获得数据asm("nop");//delay5us(1);RD_on;CAN_cs_on;asm("nop");//delay5us(2);//dog();return data;}//**************************写SJA10000*************************// void Write_SJA1000(uint address,uint data){ asm("nop");//uint temp1,temp2;DDRA=0xff; //数据口为输出PORTA=address; //输出数据的地址CAN_cs_on;ALE_off;WR_on;RD_on;asm("nop");//delay5us(1);ALE_on;asm("nop");//delay5us(1);//DDRA=0xff; //数据口为输出PORTA=address; //输出数据的地址再次输出地址,确保数据准确asm("nop");//delay5us(1);ALE_off;//delay5us(1);CAN_cs_off;WR_off;asm("nop");//delay5us(1);asm("nop");//DDRA=0xff;PORTA=data; //输出数据asm("nop");//delay5us(2);WR_on;PORTA=data; //再次输出数据,取保一致CAN_cs_on;asm("nop");//delay5us(2);asm("nop");//dog();}现在可以读写SJA1000了。

MSCAN应用

MSCAN应用

控制局域网CAN (controllerareanetwork)是国际上应用最广泛的现场总线之一,是德国Bosch公司为解决现代汽车中众多的控制与测试仪器之间的数据交换而开发的一种通讯协议,它作为汽车环境中的微控制器通讯,在车载各电子控制装置ECU之间交换信息,形成汽车电子控制网络。

比如:发动机管理系统、变速箱控制器、仪表装备、电子主干系统中,均嵌入CAN控制装置。

CAN是一种多主方式的串行通讯总线,基本设计规范要求有高的位速率,高抗电磁干扰性,而且能够检测出产生的任何错误。

当信号传输距离达到10Km时,CAN仍可提供高达50 kbit/s的数据传输速率。

它是一种有效支持分布式控制或实时控制的串行通讯网络。

CAN的应用范围遍及从高速网络到低成本的多线路网络。

在自动化电子领域的汽车发动机控制部件、传感器、抗滑系统等应用中,CAN的位速率可高达1 Mbps。

CAN网络具有反映快,可靠度高的特性,应用于要求实时处理的场合,例如汽车刹车防锁死系统安全气囊等。

今天此项通信协议已得到广泛应用,成为现代汽车设计中必须采用的装置,奔驰、宝马、大众、沃尔沃及雷诺汽车都将CAN作为控制器联网的手段。

1 CAN总线的特点及通讯协议1.1 CAN总线的特点CAN总线是一种有效支持分布式控制或实时控制的串行通信网络。

其通讯介质可以是双绞线、同轴电缆或光纤。

在汽车发动机控制部件、传感器等应用中,总线的位速率最大可达1Mbit/s。

CAN总线具有以下主要特性:a. 无破坏性的基于优先权竞争的总线仲裁b. 可借助接收滤波的多地址帧传送c. 具有错误检测与出错帧自动重发功能d. 数据传送方式可分为数据广播式和远程数据请求式1.2 CAN总线帧格式[1]CAN总线通信协议包括CAN2.0A和CAN2.0B两种,它们的帧格式如下:(1)CAN2.0A通信协议规定了4种不同的帧格式:数据帧用于节点间传递数据,是网络信息的主体,其帧格式依次包括:帧起始、仲裁场、控制场、数据场、CRC场、ACK场和帧结束。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

CAN总线通信程序// CAN <==> UART的协议转换器// 说明:// 1,单片机使用P89C61X2BA// --晶振11.0592MHZ// --CAN总线中断使用单片机的中断0,外部有上拉电阻,波特率可以设定// 2,CAN总线发送采用查询方式,接收采用中断方式// 3,看门狗复位时间1.2S// 4,SJA1000晶振8MHZ,Peil模式// 5,串口中断接收,查询发送,波特率可设置// 6,×××当串口收到数据后,每8个数一组打包,通过CAN总线发送出去//// -----10.16日,重新修改程序完成以下功能-----// ----此功能已经改为,每收到一帧数据,启动一次CAN传输,传输字节数等于串口收到的数据// ----串行帧的帧间界定通过当前波特率下传输5个字节为时间间隔,具体为当顺序接收到的任意两个数据,它们之间的时间间隔大于5个字节传送时间,认为这两个数据分属于两个不同的帧// 7,当CAN总线每接收一帧信息后,通过串口发送出去// 改为可以识别CAN的报文字节长度,即串口只发送CAN报文长度个字节// 8,看门狗芯片MAX1232CPA,硬件溢出时间1.2S////-------------------------------------------------------#include#include#include#include "CANCOM.h"unsigned char UART_TX_Data[8] = {0,1,2,3,4,5,6,7};unsigned char CAN_TX_Data[8] = {0,1,2,3,4,5,6,7};unsigned char xdata UART_RX_Data[255]; //串口接收到的串行帧unsigned char xdata CAN_TX_Data[255]; //待发送的数据缓冲区unsigned char code ACR_ID[4] = {0,0,0,0}; //CAN初始设置验收滤波值unsigned char code AMR_ID[4] = {0xff,0xff,0xff,0xff};unsigned char CAN_TX_ID[4] = {0,0,0,0}; //待发送的目标的ID unsigned char CAN_RX_ID[4] = {0,0,0,0}; //接收到的信息来自何ID unsigned char CAN_RX_Data[8] = {7,6,5,4,3,2,1,0}; //接受到的数据缓冲unsigned char code CAN_BTR0[10] ={0xdf,0xcf,0xc7,0xc3,0x43,0xc1,0xc1,0 xc0,0xc0,0x80};unsigned char code CAN_BTR1[10] = {0x7f,0x7f,0x7f,0x7f,0x2f,0x7f,0x4d,0 x3e,0x3a,0x23};// 5K 10K 20K 40K 50K 80K 100K 200K 250K 500Kunsigned char code UART_BTR[4] = {0xe8,0xf4,0xfa};// 1.2K,2.4K,4.8Kunsigned char CAN_flag; //CAN发送标志位unsigned char UART_flag; //unsigned char CAN_ERROR_flag = NOT; //unsigned char CAN_DataLength = 8; //CAN信息的报文长度unsigned char UART_DataLength = 0; //串口接收时的当前指示unsigned char UART_Length = 0; //串口接收区的长度指示//sbit AAA = P1^4;void main(void){EA = 0;System_init(); //系统初始化Timer_init(); //定时器初始化Interrupt_init(); //中断UART_ini();CAN_init();Delay(1);W_WDT();EA = 1;//Delay(1);//UART_Length = 8;//CAN_Transmit(0);//UART_Transmit();while (1){W_WDT();if (CAN_flag == YES){CAN_flag = NOT;CAN_Transmit(0);LED1 = !LED1;}else{CAN_flag = NOT;}/*if (UART_flag == YES){UART_flag = NOT;//Delay(50);UART_Transmit();//Clear_Buffer(CAN_RX_Data,8); //LED3 = !LED3;}else{UART_flag = NOT;}*/if ((CAN_ERROR_flag == YES)){CAN_ERROR_flag = NOT;CAN_init();}else{CAN_ERROR_flag = NOT;}}}//---------------------------// 功能:系统设置// --外部数据存储区访问使能// --LED指示灯关(1=on,0=off)// --流程控制标志置为无效NOT// --清空串口,CAN的相关数据缓冲区//---------------------------void System_init(void){CKCON = 0x00; //Fosc devide 12AUXR = 0x00;//0x02; //EXM enableLED1 = 0; //LED0-3 off 指示灯,共阴接法,1时亮 LED2 = 0;LED3 = 0;LED4 = 0;WDT = 1; //WDT iniCAN_DataLength = 8;UART_DataLength = 0;UART_Length = 0;CAN_flag = NOT;CAN_ERROR_flag = NOT;//UART_flag = NOT;Clear_Buffer(UART_RX_Data,255); Clear_Buffer(CAN_TX_Data,255);Clear_Buffer(CAN_TX_ID,4);Clear_Buffer(CAN_RX_ID,4);Clear_Buffer(CAN_RX_Data,8);/*CAN_flag = YES;UART_flag = YES;*/}//-----------------------------//// 软件延时(非精确)// ----内置清看门狗定时器子函数// 防止多次调用延时过长导致// 看门狗复位////-----------------------------void Delay(unsigned char time){unsigned char i;unsigned int j;for (i = 0;i < time;i++){W_WDT();for (j=0;j<30000;j++){}}}//---------------------------------// 串行口初始化设置// 方式1,8数据位,一个停止位,无奇偶校验// 串口中断允许//------------------------------------void UART_ini(void){SCON = 0x50; //方式1,波特率可变,8bits,接受允许PCON&= 0x7F; //SMOD = 0TMOD |= 0x20; //timer1 mode 2TL1 = UART_BTR[2]; //| f//| 波特率=----------------------TH1 = UART_BTR[2]; //| 32*2^smod*12*(256-TL1) TCON |= 0x40; //startTI = 0;}//-----------------------------------------------//// 看门狗“喂狗”程序,WDT的一个下降沿触发一次////-----------------------------------------------void W_WDT(void) //triggle WDT{unsigned char i;WDT = 1;for (i=0;i<10;i++){}WDT = 0;}//---------------------------------------------------//// 中断初始化//// ----外部中断0有效,下降沿触发,用于SJA1000产生CAN事件中断// ----定时器中断,用于判定串口接收的顺序两个字节是否分属两帧// ----串口中断,RX使用中断,TX未使用// ----中断优先级暂时未设定////---------------------------------------------------void Interrupt_init(void){//IP = 0x00;IT0 = 0x01; //外部0中断沿触发ET0 = 1; //定时器0中断使能EX0 = 1; //外部中断使能ES = 1; //串行中断使能}//---------------------------------------------------//// 定时中断程序//// 一旦中断,说明一帧的接收已经结束,开始启动CAN发送程序// 把串口接收到的数据准备好给CAN总线发送// RX_buffer ===> CAN_TX_buffer////---------------------------------------------------void Timer0_ISR(void) interrupt 1 using 2{static unsigned char i;//unsigned char counter;//TH0 = temp_TH0;//TL0 = temp_TL0;/*counter += 1;if (counter == 20) //到1S了么?{//UART_flag = YES;}if (counter == 40) //到2S了么?{//CAN_flag = YES;counter = 0;}*///AAA = !AAA;TR0 = 0; //定时器关,开始次CAN信息传送for (i=0;i{CAN_TX_Data[i] = UART_RX_Data[i];}UART_Length = UART_DataLength;UART_DataLength = 0;CAN_flag = YES;}//--------------------------------------------------------------- //// 串口中断服务程序//// ----只有接收使用// ----每收一个数重新初始化定时器////----------------------------------------------------------------void RX_INT(void) interrupt 4 using 3{static unsigned char n;if (RI==1){do{RI = 0;}while (RI != 0);//UART_RX_Data[UART_DataLength++] = SBUF;n = SBUF;UART_Send_Byte(n);TH0 = temp_TH0;TL0 = temp_TL0;TR0 = 1; //启动数据间隔定时,判断是否分属两帧}else{//TX}}//--------------------------------------------------------------- //// 串口发送单字节程序////---------------------------------------------------------------- void UART_Send_Byte(unsigned char Data){SBUF = Data;while (TI == 0) //等待发送完毕{}TI = 0;}//--------------------------------------------------------------- //// 初始化定时器程序//// ----定时器0方式1,定时器1方式2留给串口////---------------------------------------------------------------- void Timer_init(void){TMOD |= 0x01; //使用定时器0-方式1TH0 = temp_TH0;TL0 = temp_TL0;//TR0 = 1; //这里不打开定时器}void CAN_init(void){EA = 0;MOD_CAN1 |= 0x08; //单滤波方式do{MOD_CAN1 |= 0x01; //request to reset mode }while ((MOD_CAN1&0x01) != 0x01);CDR_CAN1 = 0xc8; //选择PeliCAN模式,使用输入比较器,clk_out关闭 IER_CAN1 = 0x01; //允许发送中断,其他中断禁能ACR0_CAN1 = ACR_ID[0];ACR1_CAN1 = ACR_ID[1];ACR2_CAN1 = ACR_ID[2];ACR3_CAN1 = ACR_ID[3];AMR0_CAN1 = AMR_ID[0];AMR1_CAN1 = AMR_ID[1];AMR2_CAN1 = AMR_ID[2];AMR3_CAN1 = AMR_ID[3];//ECC_CAN1 = 0;//TXERR_CAN1 = 0;//RBSA_CAN1 = 0;BTR0_CAN1 = CAN_BTR0[0];BTR1_CAN1 = CAN_BTR1[0];OCR_CAN1 = 0xaa; //normal outputW_WDT();do{MOD_CAN1 &= 0xfe;}while ((MOD_CAN1&0x01) != 0x00);EA = 1;}//-----------------------------------//// 串口发送一帧接受到的CAN数据//// ----长度1-8,根据接收到的CAN信息来确定////-----------------------------------void UART_Transmit(void) //using 0unsigned char i;LED3 = !LED3;for (i=0;i{UART_Send_Byte(CAN_RX_Data[i]);}}//-----------------------------------//// CAN发送接受到的一帧串口数据//// ----最大长度255,根据接收到的串口信息的// 个数来确定// ----按每依次8个数据作为一个CAN帧的报文部分// 不足8个或超过8的倍数的部分按实际个数作// 为CAN报文// ----FarmeType = 1为扩展帧,FarmeType = 0为// 标准帧//-----------------------------------void CAN_Transmit(bit FarmeType){unsigned char i;unsigned char m;unsigned char can_status;unsigned char xdata *pointer;if (FarmeType == 0) //标准帧{for (m=0;m<(UART_Length/8);m++)W_WDT();do //发送缓冲区空么?{can_status = SR_CAN1;}while ((can_status&0x04) != 0x04);TXFrameInfo1 = 0x00 + 0x08;pointer = &TXID1;for (i=0;i<2;i++){*(pointer++) = CAN_TX_ID[i];}pointer = &TXID3;for (i=0;i<8;i++){*(pointer++) = CAN_TX_Data[i+8*m];}CMR_CAN1 = Request_TX;W_WDT();}if ((UART_Length%8) != 0){W_WDT();do //发送缓冲区空么?{can_status = SR_CAN1;}while ((can_status&0x04) != 0x04);TXFrameInfo1 = 0x00 + UART_Length%8;pointer = &TXID1;for (i=0;i<2;i++){*(pointer++) = CAN_TX_ID[i];}pointer = &TXID3;for (i=0;i<(UART_Length%8);i++){*(pointer++) = CAN_TX_Data[i+8*(UART_Length/8)]; }CMR_CAN1 = Request_TX;W_WDT();}else{}}else //扩展帧{for (m=0;m<(UART_Length/8);m++){W_WDT();do //发送缓冲区空么?{can_status = SR_CAN1;}while ((can_status&0x04) != 0x04);TXFrameInfo1 = 0x80 + 0x08;pointer = &TXID1;for (i=0;i<4;i++){*(pointer++) = CAN_TX_ID[i];}pointer = &TXDATA1;for (i=0;i<8;i++){*(pointer++) = CAN_TX_Data[i+8*m];}CMR_CAN1 = Request_TX;W_WDT();}if ((UART_Length%8) != 0){W_WDT();do //发送缓冲区空么?{can_status = SR_CAN1;}while ((can_status&0x04) != 0x04);TXFrameInfo1 = 0x80 + UART_Length%8;pointer = &TXID1;for (i=0;i<4;i++){*(pointer++) = CAN_TX_ID[i];}pointer = &TXDATA1;for (i=0;i<(UART_Length%8);i++){*(pointer++) = CAN_TX_Data[i+8*(UART_Length/8)]; }CMR_CAN1 = Request_TX;W_WDT();}else{}}UART_Length = 0;}//-----------------------------------//// CAN接收中断服务程序//// ----判断是否是RX中断,如果是// 把接受到的CAN信息通过串行口发送出去// ----其他的中断说明CAN总线出现错误或脱离////-----------------------------------void CAN_ISR(void) interrupt 0 using 1{unsigned char can_int;EA = 0;can_int = IR_CAN1;if ((can_int&0x01) == 0x01) //接收中断{CAN_Receive();CMR_CAN1 |= ReleaseRXBuf;}else{CAN_ERROR_flag = YES; //其他中断,暂时未用 }//UART_flag = YES;//CAN_flag = YES;UART_Transmit();EA = 1;}//-----------------------------------//// CAN接收数据函数//// ----根据接受到的帧信息,按不同的长度存储// 报文数据////-----------------------------------void CAN_Receive(void) using 1{unsigned char i;unsigned char xdata *pointer;unsigned char Info;Info = RXFrameInfo1;if ((Info&0x80) == 0) //standard Frame {//CAN_RX_ID[0] = RXID1;//CAN_RX_ID[1] = RXID2;CAN_DataLength = Info&0x0f;pointer = &RXID3;for (i=0;i{CAN_RX_Data[i] = *(pointer++);}for (;i<8;i++){CAN_RX_Data[i] = 0x00;}}else //Ex Frame{//CAN_RX_ID[0] = RXID1;//CAN_RX_ID[1] = RXID2;//CAN_RX_ID[2] = RXID3;//CAN_RX_ID[3] = RXID4;CAN_DataLength = Info&0x0f;pointer = &RXDATA1;for (i=0;i{CAN_RX_Data[i] = *(pointer++);//pointer += 1;}for (;i<8;i++){CAN_RX_Data[i] = 0x00;}}}//-----------------------------------//// 清0缓冲区//// ----pointer,指向待清0 的缓冲区首地址// ----length 清0 的长度//-----------------------------------void Clear_Buffer(unsigned char *pointer,unsigned char length) {unsigned char i;for (i=0;i{*(pointer++) = 0x00;}}另外头文件为:#ifndef _CANCOM_H#define _CANCOM_H#define CS1_SJA1000 0x7f00 //SJA1000 Pin /CS ----> P2.7,low le vel active#define MOD_CAN1 XBYTE[CS1_SJA1000+0] //Peli#define CMR_CAN1 XBYTE[CS1_SJA1000+1] //command#define SR_CAN1 XBYTE[CS1_SJA1000+2] //state#define IR_CAN1 XBYTE[CS1_SJA1000+3] //interrupt#define IER_CAN1 XBYTE[CS1_SJA1000+4] //interrupt enable //Peli#define BTR0_CAN1 XBYTE[CS1_SJA1000+6] //bus timing0#define BTR1_CAN1 XBYTE[CS1_SJA1000+7] //bus timing1#define OCR_CAN1 XBYTE[CS1_SJA1000+8]#define TEST_CAN1 XBYTE[CS1_SJA1000+9]#define ECC_CAN1 XBYTE[CS1_SJA1000+12] //error catch#define EWLR_CAN1 XBYTE[CS1_SJA1000+13] //error warning limit#define RXERR_CAN1 XBYTE[CS1_SJA1000+14] //#define TXERR_CAN1 XBYTE[CS1_SJA1000+15]#define ACR0_CAN1 XBYTE[CS1_SJA1000+16]#define ACR1_CAN1 XBYTE[CS1_SJA1000+17]#define ACR2_CAN1 XBYTE[CS1_SJA1000+18]#define ACR3_CAN1 XBYTE[CS1_SJA1000+19]#define AMR0_CAN1 XBYTE[CS1_SJA1000+20]#define AMR1_CAN1 XBYTE[CS1_SJA1000+21]#define AMR2_CAN1 XBYTE[CS1_SJA1000+22]#define AMR3_CAN1 XBYTE[CS1_SJA1000+23]#define RBSA_CAN1 XBYTE[CS1_SJA1000+30] //beginning of receive #define CDR_CAN1 XBYTE[CS1_SJA1000+31] //clock devide #define TXFrameInfo1 XBYTE[CS1_SJA1000+16]#define TXID1 XBYTE[CS1_SJA1000+17]#define TXID2 XBYTE[CS1_SJA1000+18]#define TXID3 XBYTE[CS1_SJA1000+19]#define TXID4 XBYTE[CS1_SJA1000+20]#define TXDATA1 XBYTE[CS1_SJA1000+21]#define TXDATA2 XBYTE[CS1_SJA1000+22]#define TXDATA3 XBYTE[CS1_SJA1000+23]#define TXDATA4 XBYTE[CS1_SJA1000+24]#define TXDATA5 XBYTE[CS1_SJA1000+25]#define TXDATA6 XBYTE[CS1_SJA1000+26]#define TXDATA7 XBYTE[CS1_SJA1000+27]#define TXDATA8 XBYTE[CS1_SJA1000+28]#define RXFrameInfo1 XBYTE[CS1_SJA1000+16]#define RXID1 XBYTE[CS1_SJA1000+17]#define RXID2 XBYTE[CS1_SJA1000+18]#define RXID3 XBYTE[CS1_SJA1000+19]#define RXID4 XBYTE[CS1_SJA1000+20]#define RXDATA1 XBYTE[CS1_SJA1000+21]#define RXDATA2 XBYTE[CS1_SJA1000+22]#define RXDATA3 XBYTE[CS1_SJA1000+23]#define RXDATA4 XBYTE[CS1_SJA1000+24]#define RXDATA5 XBYTE[CS1_SJA1000+25]#define RXDATA6 XBYTE[CS1_SJA1000+26]#define RXDATA7 XBYTE[CS1_SJA1000+27]#define RXDATA8 XBYTE[CS1_SJA1000+28]#define GoToRESET 0x01#define ReleaseRXBuf 0x04#define Request_TX 0x01#define NOT 0#define YES 1//4800bps 5bits 1.04mS#define TIME_MS 1#define temp_TH0 (0 - 922*TIME_MS)/256#define temp_TL0 (0 - 922*TIME_MS)%256sbit LED1 = P1^2;sbit LED2 = P1^3;sbit LED3 = P1^5;sbit LED4 = P1^4;sbit WDT = P3^4;void System_init(void);void Delay(unsigned char time);void W_WDT(void);void Interrupt_init(void);void CAN_init(void);//void CAN_Transmit(unsigned char Farmeinfo);void CAN_Transmit(bit FarmeType);void CAN_Receive(void);void Timer_init(void);void UART_ini(void);void UART_Send_Byte(unsigned char Data);void UART_Transmit(void);void Clear_Buffer(unsigned char *pointer,unsigned char length);#endif。

相关文档
最新文档