Linux CAN通讯(MCP2515)开发记录

回顾一下Linux平台下外挂MCP2515实现CAN通讯

Linux内核本身就已经包含MCP2515器件的驱动,因此只需要简单配置一下相关的硬件接口即可,如SPI接口,中断接口。并使能驱动即可。

mcp2515硬件介绍:

使用的接口主要是
  INT 中断线  --->   GPIOA(10)
  SCK 时钟线  --->   SPI0_CLK
  SI         --->   SPI0_MOSI
  SO         --->   SPI0_MISO
  CS         --->   SPI0_CS0
  GND        --->   GND
  VCC        --->   3.3v
对应的驱动文件目录:

kernel/drivers/net/can/spi/mcp251x.c

以RK3399平台为例,设备树配置如下:

mcp251x_clk: mcp251x-clk {
        compatible = "fixed-clock";
        #clock-cells = <0>;
        clock-frequency = <20000000>;
    };

&spi1 {
    status = "okay";
    max-freq = <48000000>;

	mcp2515_2: can@0 {
		status = "okay";
		compatible = "microchip,mcp2515";
		reg = <0x00>;
		clocks = <&mcp251x_clk>;
        pinctrl-names = "default";
		pinctrl-0 = <&can1_pins>;
		interrupt-parent = <&gpio2>;
		interrupts = <24 IRQ_TYPE_EDGE_FALLING>;//GPIO2_D0
		spi-max-frequency = <2000000>;
		poll_mode = <0>;
		enable_dma = <1>;
        vdd-supply = <&vcc3v3_sys>;
        xceiver-supply = <&vcc3v3_sys>;
	};
};

需要注意的问题点:

1、CAN波特率无法达到1M

需要提高MCP2515的晶振频率,8M无法实现,推荐20M.

2、在高速通讯时报,No buffer space available

需要修改发送缓冲区大小,默认为10 ,可以根据需要扩大,如1000

在static int mcp251x_can_probe(struct spi_device *spi)中添加:

net->netdev_ops = &mcp251x_netdev_ops;
net->flags |= IFF_ECHO;
net->tx_queue_len=1000;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
由于mcp2515是一种CAN控制器,因此我们需要一个CAN总线控制器来和mcp2515交互,这里以socketCAN为例进行说明。socketCAN是一个基于AF_CAN协议簇的套接字接口,可以用它来实现一个虚拟的CAN总线,并通过can-utils等工具来进行CAN数据的发送和接收。 下面是一个简单的mcp2515驱动代码示例: ```c #include <linux/module.h> #include <linux/version.h> #include <linux/kernel.h> #include <linux/spi/spi.h> #include <linux/can.h> #include <linux/skbuff.h> #include <linux/netlink.h> static struct spi_device *spi_dev; static struct net_device *can_dev; static struct can_priv *can_priv; static const struct spi_device_id mcp2515_id[] = { {"mcp2515", 0}, {} }; MODULE_DEVICE_TABLE(spi, mcp2515_id); static int mcp2515_probe(struct spi_device *spi) { int ret; struct net_device *dev; struct can_priv *priv; spi_dev = spi; dev = alloc_can_dev(&spi->dev); if (!dev) { dev_err(&spi->dev, "Failed to allocate CAN device\n"); return -ENOMEM; } priv = netdev_priv(dev); can_priv = priv; /* 修改设备名称 */ strcpy(dev->name, "can0"); /* 设置设备参数 */ priv->can.state = CAN_STATE_STOPPED; priv->can.bittiming = &mcp2515_bittiming_const; priv->can.do_set_mode = mcp2515_do_set_mode; priv->can.echo_skb = mcp2515_echo_skb; priv->can.do_tx = mcp2515_do_tx; priv->can.do_rx = mcp2515_do_rx; /* 初始化SPI设备 */ ret = spi_setup(spi); if (ret < 0) { dev_err(&spi->dev, "Failed to setup SPI device\n"); free_can_dev(dev); return ret; } ret = register_netdev(dev); if (ret < 0) { dev_err(&spi->dev, "Failed to register CAN device\n"); free_can_dev(dev); return ret; } can_dev = dev; return 0; } static int mcp2515_remove(struct spi_device *spi) { unregister_netdev(can_dev); free_can_dev(can_dev); return 0; } static const struct of_device_id mcp2515_of_match[] = { { .compatible = "microchip,mcp2515", }, {}, }; MODULE_DEVICE_TABLE(of, mcp2515_of_match); static struct spi_driver mcp2515_driver = { .driver = { .name = "mcp2515", .owner = THIS_MODULE, .of_match_table = mcp2515_of_match, }, .probe = mcp2515_probe, .remove = mcp2515_remove, .id_table = mcp2515_id, }; module_spi_driver(mcp2515_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux_Studio"); MODULE_DESCRIPTION("MCP2515 CAN driver"); ``` 在这里我们主要是定义了一个SPI控制器的驱动程序,并在其probe函数中完成了CAN设备的初始化,包括设备的名称、参数和相关的回调函数等。在这里我们只是演示了一些基本的操作,实际的驱动程序应该还需要实现数据的接收和发送等核心功能。 需要注意的是,在这个驱动程序中,我们使用了一个can_priv结构体来存储CAN控制器的私有数据,这个结构体的定义如下: ```c struct can_priv { struct can_dev can; struct net_device *dev; struct net_device_stats stats; spinlock_t lock; struct sk_buff_head rx_queue; }; ``` 我们还需要实现一些CAN控制器的回调函数,包括mcp2515_bittiming_const、mcp2515_do_set_mode、mcp2515_echo_skb、mcp2515_do_tx和mcp2515_do_rx等函数,这里就不再给出具体的代码了。需要注意的是,这些回调函数可以根据实际需求来修改或扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值