can总线驱动的编写

本文介绍了S3C2410开发板上CAN总线的硬件结构,包括SPI接口、MCP2551收发器和MCP2515控制器的功能。详细阐述了S3C2410的SPI特性,MCP2551作为CAN物理接口的功能,以及MCP2515的结构和主要组成部分。随后,文章转向驱动程序的设计,讨论了驱动源码的相关内容。
摘要由CSDN通过智能技术生成

一.系统硬件结构介绍

       系统中 CAN 总线主要用来完成 S3C2410 开发板和 CAN 总线分析仪的数据传输。在S3C2410 开发平台上,MCP2515 芯片用作 CAN 控制器,MCP2551 芯片用作 CAN 收发器,S3C2410 微处理器用作节点控制器。如下图1所示。


1.1 S3C2410 的 SPI 接口简介
           SPI( Serial Peripheral Interface) 是一个同步串行外围接口,允许 MCU 与各种外围设备以串行方式进行通信。S3C2410 微处理器包括两路 SPI,每一路分别有两个 8 位转移寄存器,用来发送和接收数据。在 SPI 进行传输时,数据同时发送和接收。如果只想发送数据,接收到的数据将是无效的;如果只想接收数据,应当发送全是 1 的数据。
1.2 MCP2551 功能简介
         MCP2551 是 CAN 协议控制器和物理总线之间的接口。这个器件向总线提供了差动的发送能力,向 CAN 控制器提供了差动的接收能力。
1.3 MCP2515 功能简介
         MCP2515是一款独立CAN控制器,是为简化连接CAN总线的应用而开发的。图2 简要显示了MCP2515的结构框图[3]。该器件主要由三个部分组成:

(1)CAN 协议引擎(处理所有总线上的报文发送和接收) ;
(2)用来为器件及其运行进行配置的控制逻辑和SRAM寄存器;
(3 )SPI协议模块,用来实现SPI通信模式。
二. 驱动程序设计

驱动源码:

/*
 * Microchip MCP2515 CAN controller driver.
 *
 * Copyright (C) 2007 Embedall Technology Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/cdev.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/workqueue.h>
#include <linux/spi/spi.h>
#include <linux/can/can.h>
#include <linux/delay.h>
#include <linux/can/mcp251x.h>
#include <linux/semaphore.h>
#include <asm/gpio.h>

/* SPI interface instruction set */
#define INSTRUCTION_WRITE       0x02
#define INSTRUCTION_READ        0x03
#define INSTRUCTION_BIT_MODIFY  0x05
#define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n))
#define INSTRUCTION_READ_RXB(n) (0x90 + 4 * (n))
#define INSTRUCTION_RESET       0xc0
#define INSTRUCTION_RTS(n)	(0x80 + (1<<n))
#define INSTRUCTION_RX_STATE    0xb0
#  define RX_STATE_RTR		 0x04
#  define RX_STATE_IDE		 0x08
#define INSTRUCTION_CAN_STATE   0xa0
#  define CAN_STATE_TX2IF	 0x01
#  define CAN_STATE_TX2REQ 	 0x02
#  define CAN_STATE_TX1IF	 0x04
#  define CAN_STATE_TX1REQ       0x08
#  define CAN_STATE_TX0IF        0x10
#  define CAN_STATE_TX0REQ 	 0x20
#  define CAN_STATE_RX1IF	 0x40
#  define CAN_STATE_RX0IF	 0x80

/* MPC251x registers */
#define CANSTAT           0x0e
#define CANCTRL           0x0f
#  define CANCTRL_REQOP_MASK        0xe0
#  define CANCTRL_REQOP_CONF        0x80
#  define CANCTRL_REQOP_LISTEN_ONLY 0x60
#  define CANCTRL_REQOP_LOOPBACK    0x40
#  define CANCTRL_REQOP_SLEEP       0x20
#  define CANCTRL_REQOP_NORMAL      0x00
#  define CANCTRL_OSM               0x08
#  define CANCTRL_ABAT              0x10
#define TEC           0x1c
#define REC           0x1d
#define CNF1          0x2a
#define CNF2          0x29
#  define CNF2_BTLMODE  0x80
#define CNF3          0x28
#  define CNF3_SOF      0x08
#  define CNF3_WAKFIL   0x04
#  define CNF3_PHSEG2_MASK 0x07
#define CANINTE       0x2b
#  define CANINTE_MERRE 0x80
#  define CANINTE_WAKIE 0x40
#  define CANINTE_ERRIE 0x20
#  define CANINTE_TX2IE 0x10
#  define CANINTE_TX1IE 0x08
#  define CANINTE_TX0IE 0x04
#  define CANINTE_RX1IE 0x02
#  define CANINTE_RX0IE 0x01
#define CANINTF       0x2c
#  define CANINTF_MERRF 0x80
#  define CANINTF_WAKIF 0x40
#  define CANINTF_ERRIF 0x20
#  define CANINTF_TX2IF 0x10
#  define CANINTF_TX1IF 0x08
#  define CANINTF_TX0IF 0x04
#  define CANINTF_RX1IF 0x02
#  define CANINTF_RX0IF 0x01
#define EFLG          0x2d
#  define EFLG_RX1OVR   0x80
#  define EFLG_RX0OVR   0x40
#define TXBCTRL(n)  ((n * 0x10) + 0x30)
#  define TXBCTRL_TXREQ  0x08
#  define TXBCTRL_TXPRI(n) (n)
#  define TXBCTRL_TXERR	   (1 << 4)
#  define TXBCTRL_MLOA     (1 << 5)
#  define TXBCTRL_ABTF     (1 << 6)
#define RXBCTRL(n)  ((n * 0x10) + 0x60)
#  define RXBCTRL_MASK   0x60
#  define RXBCTRL_RXRTR  0x08
#  define RXBCTRL_BULK	(1 << 2)
#  define RXBCTRL_RXM_MACH_ALL	(0 << 6)
#  define RXBCTRL_RXM_MACH_STD	(1 << 6)
#  define RXBCTRL_RXM_MACH_EXT	(2 << 6)
#  define RXBCTRL_TXM_MACH_OFF	(3 << 6)
#  define RXBCTRL_FILHIT_MASK    0x07
#define RXM_BASE(n)   (0x20 + (n *  4))
#define RXF_BASE(n)   ((n>2)?(0x10 + (n-3)*4):(0x00 + (n*4)))
	
	

#define SJW1            0x00
#define SJW2            0x40
#define SJW3            0x80
#define SJW4            0xC0

#define BTLMODE_CNF3    0x80

#define SEG1            0x00
#define SEG2            0x01
#define SEG3            0x02
#define SEG4            0x03
#define SEG5            0x04
#define SEG6            0x05
#define SEG7            0x06
#define SEG8            0x07

#define BRP1            0x00
#define BRP2            0x01
#define BRP3            0x02
#define BRP4            0x03
#define BRP5            0x04
#define BRP6            0x05
#define BRP7            0x06
#define BRP8            0x07

//#define CAN_FOSC_12MHZ
#define CAN_FOSC_16MHZ

#if defined(CAN_FOSC_12MHZ)
#define CAN_CNF1_10K		(SJW3 | 0x1d)
#define CAN_CNF2_10K		(BTLMODE_CNF3|(SEG6<<3)|SEG7)
#define CAN_CNF3_10K		(SEG6)

#define CAN_CNF1_20K		(SJW2 | 0x0E)
#define CAN_CNF2_20K		(BTLMODE_CNF3|(SEG6<<3)|SEG7)
#define CAN_CNF3_20K		(SEG6)

#define CAN_CNF1_50K		(SJW1 | 0x05)
#define CAN_CNF2_50K		(BTLMODE_CNF3|(SEG6<<3)|SEG7)
#define CAN_CNF3_50K		(SEG6)

#define CAN_CNF1_100K		(SJW1 | BRP3)
#define CAN_CNF2_100K		(BTLMODE_CNF3|(SEG6<<3)|SEG7)
#define CAN_CNF3_100K		(SEG6)

#define CAN_CNF1_125K		(SJW1 | BRP3)
#define CAN_CNF2_125K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_125K		(SEG4)

#define CAN_CNF1_250K		(SJW1 | BRP2)
#define CAN_CNF2_250K		(BTLMODE_CNF3|(SEG3<<3)|SEG5)
#define CAN_CNF3_250K		(SEG3)

#define CAN_CNF1_500K		(SJW1 | BRP1)
#define CAN_CNF2_500K		(BTLMODE_CNF3|(SEG3<<3)|SEG5)
#define CAN_CNF3_500K		(SEG3)

#define CAN_CNF1_750K		(SJW1 | BRP1)
#define CAN_CNF2_750K		(BTLMODE_CNF3|(SEG3<<2)|SEG1)
#define CAN_CNF3_750K		(SEG3)

#define CAN_CNF1_1000K  	(SJW1 | BRP1)
#define CAN_CNF2_1000K  	(BTLMODE_CNF3|(SEG2<<3)|SEG1)
#define CAN_CNF3_1000K		(SEG2)
#elif defined(CAN_FOSC_16MHZ)
#define CAN_CNF1_10K		(SJW1 | 0x31)
#define CAN_CNF2_10K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_10K		(SEG4)

#define CAN_CNF1_20K		(SJW1 | 0x18)
#define CAN_CNF2_20K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_20K		(SEG4)

#define CAN_CNF1_50K		(SJW1 | 0x09)
#define CAN_CNF2_50K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_50K		(SEG4)

#define CAN_CNF1_100K		(SJW1 | BRP5)
#define CAN_CNF2_100K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_100K		(SEG4)

#define CAN_CNF1_125K		(SJW1 | BRP4)
#define CAN_CNF2_125K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_125K		(SEG4)

#define CAN_CNF1_250K		(SJW1 | BRP2)
#define CAN_CNF2_250K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_250K		(SEG4)

#define CAN_CNF1_500K		(SJW1 | BRP1)
#define CAN_CNF2_500K		(BTLMODE_CNF3|(SEG4<<3)|SEG7)
#define CAN_CNF3_500K		(SEG4)

#define CAN_CNF1_750K		(SJW1 | BRP1)
#define CAN_CNF2_750K		(BTLMODE_CNF3|(SEG3<<3)|SEG4)
#define CAN_CNF3_750K		(SEG3)

#define CAN_CNF1_800K		(SJW1 | BRP1)
#define CAN_CNF2_800K		(BTLMODE_CNF3|(SEG3<<3)|SEG3)
#define CAN_CNF3_800K		(SEG3)

#define CAN_CNF1_1000K  	(SJW1 | BRP1)
#define CAN_CNF2_1000K  	(BTLMODE_CNF3|(SEG2<<3)|SEG3)
#define CAN_CNF3_1000K		(SEG2)
#endif	/* end define CAN_FOSC_12MHZ */

/* Buffer size required for the largest SPI transfer (i.e., reading a frame).
 */
#de
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值