利用MCP2515的多路CAN总线接口及驱动程序设计

发布者:彭勇最新更新时间:2016-05-31 来源: eefocus关键字:MCP2515  CAN总线接口  驱动程序 手机看文章 扫描二维码
随时随地手机看文章
引言

  在铁路系统中,为了保证列车的安全运行,需要对铁轨及周围状况进行实时检测。目前采用的方法是在铁路沿线安装多个检测设备,用于检测洪水、大风、泥石流等自然灾害及轨温等参数。这些设备一般采用的通信方式是RS232、RS485或CAN,并通过专线连接至监控中心的各个监控设备。这种方式极大浪费了线路资源,也不易于设备的统一管理。因此,需要一种安装在铁路沿线的设备,它将附近的检测设备发送的信息统一收集并通过一条专线直接送往监控中心。为了与多个检测设备通信,必须同时具有多个RS232、RS485和CAN接口。基于这种应用需要,本文提出了扩展多个CAN总线接口的方法。

1  系统结构

1.1  芯片介绍系统

  采用Atmel公司的AT91RM9200(以下简称“9200”)作为MCU。该处理器基于ARM920T内核,主频为180 MHz时,性能可达到200MIPS;最高主频为209 MHz。该处理器还具有丰富的外设资源,非常适合工业控制领域的应用[1];采用的操作系统是ARMLinux,内核版本为2.4.19。

  目前主流的CAN协议控制器一般采用I/O总线(SJA1000等)或SPI接口(MCP2515等)与MCU进行通信。由于本设计采用PC/104总线扩展卡的方式来扩展多个RS232和RS485接口,没有多余的I/O片选线可用,因此最终选用9200的SPI接口与MCP2515进行多路CAN总线接口的扩展。

  MCP2515是Microchip公司推出的具有SPI接口的独立CAN控制器。它完全支持CAN V2.0B技术规范,通信速率最高可达1 Mbps,内含3个发送缓冲器、2个接收缓冲器、6个29位验收滤波寄存器和2个29位验收屏蔽寄存器[2];它的SPI接口时钟频率最高可达10 MHz,可满足一个SPI主机接口扩展多路CAN总线接口的需要。

1.2  系统硬件接口

  图1是9200与MCP2515的接口原理框图,通过9200的SPI接口,连接了5个MCP2515。由于9200的SPI从设备片选线数量有限,故采用片选译码方式,NPCS0可作为普通的外部中断线使用(NPCS0与IRQ5复用引脚)。由于9200的外部中断线资源有限,故采用中断线共享的方式,即分别有两个MCP2515共享同一中断线,最后一个MCP2515独占一条中断线,以满足不同通信速率下数据处理的需要。


图1  AT91RM9200与MCP2515接口原理框图


图2  MCP2515 CAN总线接口电路

  图2是MCP2515的外围CAN总线接口框图,图中省略了MCP2515和9200的接口部分。由于设备需要安装在铁路沿线,必须具有防雷击的能力。因此MCP2515与CAN总线收发器(TJA1050)之间采用高速光耦进行完全的电气隔离,并且光耦两端电路的电源也必须用电源隔离模块隔离开,这样才能真正起到隔离的作用。在TJA1050的CANH和CANL引脚与地之间连接2个30 pF的电容,可以过滤CAN总线上的高频干扰;2个二极管可以在总线电压发生瞬变干扰时起保护作用。光耦正常工作时输入电流为10 mA左右,内部发光二极管的正向电压降为1.7 V左右,因此要特别注意输入端串联电阻的阻值选择。

2  SPI主机的工作方式

  9200通过SPI接口与5个MCP2515进行通信,9200的SPI控制器工作在主机模式,MCP2515工作在从机模式。MCP2515支持多个指令(如复位指令、读指令、写指令等),以便于9200通过SPI接口对MCP2515的内部寄存器进行读/写操作。9200 SPI控制器作为主机时工作模式流程如图3所示[1]。


图3  AT91RM9200 SPI控制器主机模式流程

  需要注意的是,SPI使能后,只有在SPI_TDR(发送数据寄存器)中有数据时,才会根据片选配置(固定外设或可变外设)使能相应片选;而SPI_TDR中无数据时,则片选自动禁用。因此,9200向MCP2515连续发送多个字节时,要保证在前一个字节传输完毕前,后一个字节就被写入到SPI_TDR中,以避免片选被自动禁用;同时,在传输完每一个字节后,还要读取SPI_RDR(接收数据寄存器)。

  下面以MCP2515的读指令为例,说明图4所示的驱动程序完成一次读指令操作(只读一个字节数据)的过程,并假设9200 SPI采用固定外设的片选配置方式。其他指令的软件实现流程与读指令类似。


图4  SPI读指令操作软件流程

3  驱动程序设计

  驱动程序是应用程序与硬件之间的中间软件层,它完全隐蔽了设备工作的细节。Linux操作系统根据设备中信息传送方式的不同,将设备分成3种类型:字符设备、块设备和网络设备[3]。9200与MCP2515的通信都是通过SPI接口以字节为单位进行的,因此MCP2515属于字符设备。由于5个MCP2515共享9200的一个SPI接口,因此采用一个驱动程序来管理所有的MCP2515,这样做有利于对所有设备进行统一管理。

3.1  驱动程序中定义的主要数据结构

  CAN总线通信是基于报文帧的,在驱动程序中,无论发送数据还是接收数据都是基于报文帧的操作[4],因此需要设计合适的数据结构以满足数据操作的需要。

3.1.1接收与发送CAN报文帧结构体

  typedef struct {
    unsigned char node_num;
    unsigned intid;
    unsigned char dlc;
    unsigned char data[8];
    int ext_flag;
    int rtr_flag;
  } CanFrame;

  其中,node_num为MCP2515的节点号(0~4),id为CAN报文帧的标识符,dlc为数据长度(0~8),data为CAN报文帧的数据缓冲区,ext_flag用于标识CAN报文帧是否为扩展帧,rtr_flag用于标识CAN报文帧是否为远程帧。

3.1.2  设备配置结构体

(1)  波特率和报文滤波配置结构体

  typedef struct{
    unsigned charnode_num;
    CanBaudRatebaudrate;
    CanFilter filter;
    int br_flag;
    int fi_flag;
  } CanDevConfig;

  其中,node_num为MCP2515的节点号(0~4),baudrate为CAN总线通信速率,filter为报文滤波配置结构,br_flag用于标识波特率配置是否有效,fi_flag用于标识报文滤波配置是否有效。 baudrate和filter的数据结构类型定义如下:

  typedef enum {
    _125kbps,
    _250kbps,
    _500kbps,
    _1Mbps
  } CanBaudRate;
  typedef struct{
    unsigned int mask_0;
    unsigned int mask_1;
    unsigned int filter_0;
    unsigned int filter_1;
    unsigned int filter_2;
    unsigned int filter_3;
    unsigned int filter_4;
    unsigned int filter_5;
  }CanFilter;

(2)  工作模式配置结构体

  typedef struct{
    unsigned char node_num;
    unsigned char oper_mode;
  } CanDevMode;

  其中,node_num意义同上,oper_mode表示该节点的工作模式。MCP2515共有5种工作模式,分别是配置模式、休眠模式、仅监听模式、回环模式和正常模式。一般设备都工作在正常模式。

3.1.3  环形数据接收缓冲区结构体

  typedef struct {
    CanFrame can_recv_buf[RECV_BUF_SIZE];
    int recv_pos;
    int read_pos;
    wait_queue_head_twq;
  } CanDev;

  其中,can_recv_buf为接收CAN报文帧环形数据缓冲区,recv_pos和read_pos分别表示数据存入和读出缓冲区的位置;wq定义的是一个等待队列,用于实现阻塞型read操作。

3.2  驱动程序接口

  驱动程序的接口主要分为3个部分: 初始化与退出函数接口,完成设备安装和卸载等操作;文件系统接口,由file_operations数据结构来完成;与设备的接口,完成对设备的读/写等操作。

3.2.1  初始化与退出函数

  在安装驱动程序时,操作系统会调用初始化函数进行设备注册、设备初始化以及安装中断处理例程等操作。参考文献[3]详细论述了设备注册的方法,而这里主要讨论设备初始化时的配置方法。在本驱动程序中,设备初始化分两步:一是对9200的SPI控制器初始化,二是对5个MCP2515初始化。

  在卸载设备驱动程序时会调用退出函数,退出函数主要完成设备的注销和中断释放。

  参考文献[3]详细论述了中断处理例程的安装、设备注销和中断释放的方法,此处不再详述。

3.2.2  中断接收服务例程

  MCP2515收到CAN报文帧后,产生中断并将INT引脚置低。9200响应外部中断,并调用和外部中断相对应的中断处理例程。中断处理例程共有3个: at91_mcp2515_irq_handler_0响应IRQ0的中断,at91_mcp2515_irq_handler_1_2响应IRQ1的中断,at91_mcp2515_irq_handler_3_4响应IRQ2的中断。其中IRQ0只和一个MCP2515相连,而IRQ1和IRQ2分别被两个MCP2515所共享。IRQ0和IRQ1的中断处理流程分别如图5和图6所示,IRQ2与IRQ1的中断处理流程相同。


图5  IRQ0中断处理流程


图6  IRQ1中断处理流程

  需要注意的是,在图5的处理流程中并没有清中断操作。这是因为采用了RX读缓冲区指令读取MCP2515 RX缓冲区中的数据。该指令操作结束后,MCP2515会自动清除相应的接收中断标志位。

3.2.3  文件系统接口定义

  文件系统接口struct file_operations的成员全部是函数指针,这些指针指出了设备驱动程序所提供的入口点位置。本驱动程序所定义的file_operations为:

  static struct file_operations at91_mcp2515_fops = {
    owner: THIS_MODULE,
    write: at91_mcp2515_write,
    read:at91_mcp2515_read,
    ioctl: at91_mcp2515_ioctl,
    open: at91_mcp2515_open,
    release:at91_mcp2515_release,
  };

3.2.4  ioctl函数

  ioctl函数用于对设备进行配置。我们在ioctl函数中实现了两个命令: IOCTRL_CONFIG_CAN_DEV用于配置节点的CAN总线波特率和报文滤波,IOCTRL_SET_OPER_MODE用于配置节点的工作模式。这两种配置命令所对应的配置参数都是指向应用层相应数据结构的指针,两个配置结构在3.1.2小节已经介绍过了。

  用IOCTRL_CONFIG_CAN_DEV命令配置波特率和报文滤波时,在配置完成后,如果节点处于INACTIVE状态,则需要使能节点内部的接收中断,使能节点所对应的外部中断,并将节点状态设置为ACTIVE。在通常情况下,通过ioctl函数对需要配置的节点执行完IOCTRL_CONFIG_CAN_DEV命令后,还要再对配置过的节点执行IOCTRL_SET_OPER_MODE命令,使节点处于正常的工作模式。

3.2.5  关于竞争问题

  本系统是单CPU系统,采用Linux 2.4.19内核,且是非抢占式的;同时,此设计的驱动程序也只允许一个进程打开并操作该设备。在这种情况下,驱动程序中所涉及的竞争问题主要就是中断处理程序内核代码和其他设备操作的内核代码之间的资源竞争。在上文中所提到的所有设备操作中,都要通过9200的SPI接口与MCP2515进行通信。9200与MCP2515进行通信都是以命令字节开始的,并且在一个命令操作过程中(一般会连续传输多个字节),片选和时钟是不能被禁用的,否则操作就会失败。因此,MCP2515的一个完整的命令操作就是一个临界区域,在对MCP2515进行一个命令操作的过程中必须禁用所有的中断,以保证命令操作的正常执行。在驱动程序中,采用local_irq_save和local_irq_restore函数对中断禁用和恢复,在这两个函数调用之间,就是对MCP2515执行一个命令操作的代码。

结语

  本文针对特有的应用需求提出的多路CAN总线接口和驱动程序设计,经过测试,可以稳定正常地运行。关于驱动程序的编译和运行方法,参考文献[3]有很好的说明。上层的测试程序编写也比较简单,但要注意数据结构的定义和底层驱动程序的一致性。本文侧重介绍设计的基本方法和实现基本的功能。MCP2515本身提供了许多的功能,在实现基本功能的基础上,也可以根据自己的应用需要再进行功能扩展。

关键字:MCP2515  CAN总线接口  驱动程序 引用地址:利用MCP2515的多路CAN总线接口及驱动程序设计

上一篇:CAN标准中的时钟容差修正建议
下一篇:汽车CAN/LIN总线测试流程和测试工具解析

推荐阅读最新更新时间:2024-05-03 00:25

STM32开发笔记64: STM32F4 UART4-5移植驱动程序应注意的问题
单片机型号:STM32F407VGT6 使用通用串口驱动程序分别运行UART1和UART4,则UART1正常,UART5不正常,本文解释具体原因。 先看STM32F407VGT6的串口配置情况,如下图所示,串口1、2、3、6为USART(同异步串口),串口4、5为UART(异步串口)。 在启动文件startup_stm32f407xx.s定义的中断矢量入口地址不同,可参看下面程序。 DCD USART1_IRQHandler ; USART1 DCD USART2_IRQHandler ; USA
[单片机]
STM32开发笔记64: STM32F4 UART4-5移植<font color='red'>驱动程序</font>应注意的问题
ARM和WinCE6.0下nRF24L01的驱动设计
引言 nRF24L01是一款工作在2.4~2.5 GHz世界通用ISM频段的单片无线收发器芯片。它在无线数据通讯、无线门禁、遥感勘测、工业传感器和玩具中都有应用。 随着测控技术的发展,nRF24L01与单片机组成的系统进行无线测控的实例已经有很多,如基于nRF24L01的无线温度监测系统、基于nRF24 L01的近距离无线数据传输系统等等。近年来,随着ARM和嵌入式WinCE系统的迅速发展,由于在WinCE系统下nRF24L01和ARM的通信缺乏驱动,致使两者之间不能直接通信,一般的解决方法是借助于第三方单片机的串行口来进行两者的通信。这种方式的不足之处在于,由于要借助于第三方单片机,使得成本增加且通信速度下降。nRF24
[电源管理]
ARM和WinCE6.0下nRF24L01的驱动设计
HD4478U显示LCD与51单片机驱动程序
#include SST89x5x4.H #include absacc.h #include intrins.h sbit LCDRSPIN = P3^7; sbit LCDRWPIN = P3^6; sbit LCDEPIN = P2^6; #define UCHAR unsigned char void delay(unsigned int i) { UCHAR j; for(i; i 0; i--) for(j = 200; j 0; j--); } /////////////////////////////// //控制LCD unsigned char XPOS,YPOS; //测
[单片机]
HT1621驱动程序
;LCD 设定(命令模式字的低8位数据) BIAS EQU 52H 1/3 偏压4背极 RC256 EQU 30H 系统时钟选用片 内RC振荡器 SYSEN EQU 02H 打开系统时钟 LCDON EQU 06H 打开偏压发生器 SYSDIS EQU 00H 关闭系统时钟和 偏压发生器 X32K EQU 28H 系统时钟选择为 片外晶振 ToneOn EQU 12H 打开音频输出 ToneOff EQU 10H 关闭音频输出 Tone4k EQU 80H 音频输出频率为 4K Tone2k EQU 0C0H 音频输出频率为2K TIMEREN EQU 0CH 时基输出使能 TIMERDIS EQU 08H 时基输
[单片机]
Silicon Labs Simplicity Studio支持MIKROE mikroSDK 2.0 Click Board驱动程序
Silicon Labs Simplicity Studio支持MIKROE mikroSDK 2.0 Click Board驱动程序,缩短嵌入式工程师的软件开发时间 是第一家在Click boards™开发版上将mikroSDK Click驱动程序集成到自己的软件开发环境中的IC供应商 2023年5月4日: MikroElektronika (MIKROE) ,作为一家通过提供基于成熟标准的创新式硬软件产品来大幅缩短开发时间的嵌入式解决方案公司, 今天宣布为更互联的世界提供安全、智能无线技术的领导者Silicon Labs成为第一家支持mikroSDK 2.0 Click Board的IC供应商。 这是通过在MIKROE
[工业控制]
Silicon Labs Simplicity Studio支持MIKROE mikroSDK 2.0 Click Board<font color='red'>驱动程序</font>
基于STM32F103的任意I/O口矩阵键盘驱动程序
网上的矩阵键盘代码非常非常多,但绝大部分都是要连续I/O口的,就比如PA0-PA7、PB3-PB10等等等,这些都要用到一排的连续的单片机引脚。用过STM32单片机的都知道,STM32单片机一排过去连续的引脚的不是很多,就算刚好出现了一排PA0-PA10,可是呢,PA2、PA3串口2要用,PA9、PA10串口1要用,这就显得比较局限。而且市面上的那些很多都是修改引脚要全文上下一处处修改,麻烦且容易错漏。所以如果我矩阵键盘的引脚可以随便定义的话那么是不是就不用愁这个问题了? 所以,这就是我给大家带来的任意可用的I/O的矩阵键盘程序,按键扫描代码直接操纵IO口,得出按键值。用法很简单:先看下图 我们看到,在key4_4.c中已经
[单片机]
基于STM32F103的任意I/O口矩阵键盘<font color='red'>驱动程序</font>
51单片机DS1302实时时钟驱动程序
DS1302是低功耗实时时钟芯片,它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能。主要特点是采用串行数据传输,可为掉电保护电源提供可编程的充电功能,并且可以关闭充电功能。 一.基本原理 1.引脚分析 2.时序分析 (1)写字节 第一个字节是地址字节,第二个字节是数据字节。RST信号必须拉高,否则数据的输入是无效的。换一句话说,RST信号控制数据|时间信号输入的开始和结束。地址字节和数据字节的读取时上升沿有效,而且是由LSB开始读入。 (2)读字节 读一个字节和写一个字节有明显的不一样,先是写地址字节,然后再读数据字节,写地址字节时上升沿有效,而读数据字节时下降沿有效,当然前提是RST信号必须拉高
[单片机]
51单片机DS1302实时时钟<font color='red'>驱动程序</font>
11-S3C2440驱动学习(八)嵌入式linux-块设备驱动程序
一、回顾字符设备驱动 主要分为简单字符设备驱动程序,和复杂字符设备驱动 1、简单字符设备驱动 对于简单的字符设备驱动,不需要采用分离分层的思想,主要包括以下几个部分。 2、复杂字符设备驱动 对于复杂的字符设备驱动,采用分离分层的思想,内核中已经实现好了核心层部分,我们只需要实现与硬件相关的部分就可以,最后形成一个总体。这样就是一个通用的字符驱动框架。如LCD驱动、V4L2驱动,当然有时候我们可以选择不采用分离分层的思想,按简单驱动程序的框架来实现一个驱动。 3、字符设备驱动常用技巧 (1) 查询方式 (2) 休眠唤醒,APP-read drv_read (3) poll机制 (4) 异步通知发信号
[单片机]
11-S3C2440驱动学习(八)嵌入式linux-块设备<font color='red'>驱动程序</font>
小广播
最新嵌入式文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved