1、非智能型 ISA 总线 CAN 适配卡的总体结构CAN 控制器 SJA1000 的地址数据总线是分时复用的,通过 ALE 信号的下降沿可锁存总线上的地址信号;ISA总线上的地址和数据总线是单独提供的,它不能直接和 SJA1000 的地址数据总线相连。本设计利用地址译码电路来对地址信号线进行译码,从而为 CAN 适配卡分配出一定的端口地址。然后再利用 74HC373 芯片的数据锁存功能锁存第一次 IO 操作中通过 ISA 数据总线传送的数据信号,以便作为访问 CAN 控制器SJA1000 中寄存器的地址信号,最后在第二次 IO 操作中完成对 SJA1000 中相应地址寄存器的读写操作。其适配卡的
2、总体结构如图 1 所示。图 1 中,地址锁存器 74HC373 可看作 SJA1000 的地址端口,而 SJA1000 本身可看作 SJA1000 的数据端口,另外还有对 SJA1000 进行硬件复位的复位端口。图中的基地址译码电路以 AEN 作为使能信号,对 A2A9 地址信号进行译码就可得到适配卡的基地址;组合 AO 和 A1 地址信号可得到各端口的偏移地址。SJA1000 与 ISA的通讯采用两次 IO 操作的方法,第一次先往地址端口送地址,第二次再对数据端口进行访问。这里所说的地址及数据端口都是对 SJAl000 而言的,通过 ISA 总线的数据线可获得被访问的 SJA1000 寄存器
3、的地址及所传送的数据。控制端口译码电路可将 CPU 送来的控制信号和地址信号按一定的逻辑关系进行组合,从而生成一组新的功能信号作为接口控制信号。通过 SJA1000 复位电路可对 SAJ1000 进行复位,具体操作可采用上电复位、程序复位及按键复位三种硬件复位方式。适配卡硬件的设计基地址译码电路设计图 2 所示是一种具体的基地址译码电路。一般情况下,根据系统需要,地址译码电路可对 ISA 地址线的端口地址译码,并可用 AOA9 来表示。基地址译码电路对 A9A2 进行译码,则可作为卡上端口的基地址。图 2 中,74HC688 是一个 8 位量值比较器,当时 Pi=Qi(i=07),P=Q 的反
4、端输出低电平。当 ISA 总线的 AEN为高电平时,总线工作在 DMA 方式;而当 AEN 为低电平时,CPU 拥有对总线的控制权。非智能型适配卡的工作过程实际上就是 CPU 对 IO 的操作过程,期间,AEN 始终为低电平,可用于控制 74HC688 的选通端 G 反。只有在 IO 操作时,才允许它选择地址。由于使用的是拨码开关,用户可预先设定适配卡的基地址。卡上各端口的偏移由 A1 和 A0 选择,并可通过软件控制,本设计中的定义地址端口偏移为 00,数据端口偏移为 01,复位端口偏移为 11。 控制信号产生电路该适配卡的控制信号产生电路如图 3 所示。该电路的主要作用是把 CPU 送来的
5、控制线和地址线按照一定的逻辑关系进行组合,以生成一组新的功能信号输出。该信号可作为接口控制信号去控制SJA1000、74HC373、74HC245 等芯片的工作状态。由于基地址译码电路的输出信号为 P=Q 的反(低电平有效),SJA1000 地址端口偏移地址为 00H,数据端口偏移地址为 01H,因此,根据控制逻辑,适配卡中各芯片的控制信号逻辑表达式为:适配卡在工作过程中,各芯片的逻辑时序关系是:当 74HC373 输出数据有效时,74HC245 输出为高阻态;当74HC373 输出呈高阻态,且 SJA1000 的数据直接传回 ISA 总线时,74HC245 输入输出工作正常。具体来讲,假设
6、CAN 的基地址为 300H,且访问 SJA1000 是分两次 IO 操作完成的,那么,第一次往端口 300H 送出的数据可在写信号的后沿被锁存在 74HC373 中,这个操作中,74HC245 的 E 与 74HC373 的 LE 端有效,而 74HC373 的OE 端为高电平,74HC373 输出端为高阻态;当第二次访问数据端口 301H 时,SJA1000 被选中,此时 CPU 可对SJA1000 的相应单元进行读写操作。具体的操作过程分为读、写两种情况。当第二次 IO 操作到来时,SJA1000 会在 BALE 信号下降沿将第一次 IO 操作时锁存在 74HC373 中的数据作为地址锁
7、存,该过程中,74HC245 的 E 反为高电平,输出呈高阻态,74HC373 的 OE 的反为低电平,输出端有效,可向 SJA1000 传送地址信号。当地址被 SJA1000 锁存以后,此时如果进行的是读操作,那么,在读信号有效期间(低电平),74HC373的输出允许 OE 反端为高电平,74HC373 输出端呈高阻态,这时 SJA1000 可将选中单元的寄存器内容输出到数据总线,并通过 74HC245 驱动送入 CPU 中。而在地址锁存后,如果进行的是写操作,那么,74HC373 的输出允许端始终有效,此时可在写信号有效期间,将数据写入 SJA1000 的相应单元中。 计算机通过 ISA
8、总线对CAN 控制器 SJA1000 进行读写的时序分别如图 4 和图 5 所示。复位电路SJA1000 正常工作前,只有通过复位引脚对其进行可靠的硬件复位,才能对 SJA1000 中的寄存器进行正确的读写操作。使 SJA1000 可靠复位的电平持续最小时间为 0.1s,PC 系统复位电平持续时间可达几微秒。系统复位信号 RESET 在系统电源接通时为高电平,经反向器后可直接用于对 SJA1000 进行复位。图 6 所示是适配卡的复位电路,对 SJA1000 的复位具有开机上电复位、程序复位以及按键复位等三种方式。在图 6 中,A1 和 A0 经过与非门 74LSl0 后,为复位电路产生的偏移
9、地址为 11,该地址信号与 IOW 反、P=Q 反等信号经过逻辑组合,同时配合程序设计可产生对 SJA1000 的复位信号。程序设计时只需对复位端口写入一个数据即可实现程序复位。而按键复位则可在系统运行出现通信故障时,直接用于对 CAN 控制器SJA1000 进行硬件复位。适配卡的软件设计软件设计的关键部分是 CAN 通信程序的设计。通信程序(流程如图 7、8、9 所示)可分为三部分:CAN 初始化程序、接收程序、发送程序。初始化是通信的前提,主要完成对 CAN 控制器的一些寄存器的设置。由于SJA1000 支持中断操作,因此可以用中断服务程序来完成数据的接收和发送,以提高系统的工作效率。 实
10、际上,只有在复位模式下才可以对 SJA1000 进行初始化,初始化主要包括工作方式的设置、接收滤波方式的设置、接收屏蔽寄存器和接收代码寄存器的设置、波特率参数设置和中断允许寄存器的设置等。完成初始化后,即可将 SJA1000 设置为工作状态,以进行正常的通信。发送子程序负责节点报文的发送。发送时,读取状态寄存器并对各位进行适当判断,并将待发送的数据按特定格式组合成一帧报文,送入 SJA1000 发送缓存区中,然后启动 SJA1000 发送;接收子程序则负责节点报文的接收以及其它情况的处理。在处理接收报文的过程中,还要对总线关闭、错误报警、接收溢出等情况进行处理。CAN 适配卡与计算机可采用中断
11、方式通信。但在 WIN API 中不能直接控制中断,只有在操作系统底层为 CAN适配卡编写虚拟设备驱动程序(VxD)才可以利用中断。这需要在虚拟设备驱动程序中将中断虚拟化,并在中断事件响应函数中编写所需代码,同时为应用程序提供访问接口。应当注意的是:计算机通过 ISA 总线对CAN 适配卡上的 SJA1000 进行访问采用的是两次 IO 操作,第一次往地址端口送地址,第二次对数据端口进行访问。其具体的实现代码如下:向指定的 SJA1000 寄存器(地址为 addr)写一个字节数据(data),CAN_BASE 为基地址void CanIRQ:writeByte(int CAN_BASE,uns
12、igned char addr,unsigned char data)_outp(CAN_BASE,addr);_outp(CAN_BASE+1,data);/从指定的 SJA1000 寄存器(地址为 addr)读一个字节数据(data)unsigned char CanIRQ:ReadByte(int CAN_BASE,unsigned char addr)unsigned char result;_outp(CAN_BASE,addr);result=_inp(CAN_BASE+1);return result;在访问 SJA1000 的程序中,可以直接调用以上两子函数。这样,其发送程序段代码为:Bool CanIRQ:CanTrans(int CAN_BASE,unsigned char*pTransBuf)status=ReadByte(CAN_BASE,SR); SR 为状态寄存器地址for(i=0;ilength;i+) length 为发送的报文长度WriteByte (CAN_BASE,*pTFansBuf,ptbuf;pTransBuf 为发送缓冲区地址ptbuf+;pTransBuf+;