一、SLCAN协议
slcan 即serial line CAN interface driver (using tty line discipline)
通用标准协议参考:http://www.mirrorservice.org/sites/downloads.sourceforge.net/s/so/socketcan.berlios/SLCAN-API.pdf
SLCAN 帧的ASCII 描述如下:
<type> <id> <dlc> <data>
type的定义:
t => 11 bit data frame 标准帧
r => 11 bit RTR frame 带RTR的标准帧
T => 29 bit data frame ID扩展帧
R => 29 bit RTR frame 带RTR的ID扩展帧
id 为3个字节的ASCII Hex,扩展为8个字节的ASCII Hex。
dlc 一个字节的ASCII 数字 ('0'~'8')
data ASCII的16进制,个数为dlc。
例:
t1230 : can_id 0x123, can_dlc 0, no data
t4563112233 : can_id 0x456, can_dlc 3, data 0x11 0x22 0x33
T12ABCDEF2AA55 : extended can_id 0x12ABCDEF, can_dlc 2, data 0xAA 0x55
r1230 : can_id 0x123, can_dlc 0, no data, remote transmission request
二、SLCAN驱动
文件路径:linux/drivers/net/can/slcan.c
1. 串口线路规程
驱动初始化函数:slcan_init(void);
线路规程接口:tty_register_ldisc(N_SLCAN, &slc_ldisc);
slc_ldisc can操作定义如下:
static struct tty_ldisc_ops slc_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "slcan",
.open = slcan_open,
.close = slcan_close,
.hangup = slcan_hangup,
.ioctl = slcan_ioctl,
.receive_buf = slcan_receive_buf,
.write_wakeup = slcan_write_wakeup,
};
2. 注册网络接口
选择空闲的通道,关联对应的tty接口,注册网络接口.
slcan_open(struct tty_struct *tty);
收集悬空的通道。
slc_sync();
/* OK. Find a free SLCAN channel to use. */
把tty接口关联到空闲的通道。
sl = slc_alloc(tty_devnum(tty));
sl->tty = tty;
tty->disc_data = sl;
注册网络设备
register_netdevice(sl->dev);
struct slcan {
int magic;
/* Various fields. */
struct tty_struct *tty; /* ptr to TTY structure */
struct net_device *dev; /* easy for intr handling */
spinlock_t lock;
/* These are pointers to the malloc()ed frame buffers. */
unsigned char rbuff[SLC_MTU]; /* receiver buffer */
int rcount; /* received chars counter */
unsigned char xbuff[SLC_MTU]; /* transmitter buffer */
unsigned char *xhead; /* pointer to next XMIT byte */
int xleft; /* bytes left in XMIT queue */
unsigned long flags; /* Flag values/ mode etc */
#define SLF_INUSE 0 /* Channel in use */
#define SLF_ERROR 1 /* Parity, etc. error */
};
3. 发送数据
从串口接收数据并发送到网络层.
static void slcan_receive_buf(struct tty_struct *tty,
const unsigned char *cp, char *fp, int count)
/* parse tty input stream */
slcan_unesc(sl, *cp++);
发送一个CAN帧到网络层.
slc_bump(struct slcan *sl)
netif_rx_ni(skb);
-------------------------------------------------------------------
/*
* Called by the driver when there's room for more data. If we have
* more packets to send, we send them here.
*/
4. 读取数据
static void slcan_write_wakeup(struct tty_struct *tty)
actual = tty->ops->write(tty, sl->xhead, sl->xleft);
---------------------------------------------------------------------
三、操作及应用
1. 获取CAN 工具
$git clone https://git.gitorious.org/linux-can/can-utils.git
编译并安装
2. 设置串口参数
$sudo stty -F /dev/ttyS0 921600 -parity -cstopb
3. 设置CAN参数
$sudo slcan_attach -w -o -s6 /dev/ttyS0
4. 发送数据
$sudo ifconfig slcan0 up
$sudo cangen slcan0 –g 100
5. 接收数据
$sudo ifconfig slcan0 up
$sudo candump slcan0
本文详细介绍了SLCAN协议,包括11位和29位帧类型的描述,以及SLCAN帧的ASCII格式。此外,还解析了SLCAN驱动的实现,包括串口线路规程、注册网络接口和数据的发送与读取。最后,提供了设置CAN工具、串口参数、CAN参数以及数据收发的实际操作步骤。
2959

被折叠的 条评论
为什么被折叠?



