编写一个 CAN 总线设备
本例程演示如何利用 librm 中的 CAN 总线设备框架实现一个通过 CAN 总线接收数据的设备。
librm 对 CAN 总线和设备的封装使用观察者模式,如果不熟悉这种设计模式,建议先自行了解一下。
CAN 设备向 CAN 总线类"注册"自己,并且告知自己要接收哪些 ID 的报文; 基于具体平台实现,CAN 总线类会用轮询或接管中断的方式接收所有报文,每接收到一条报文,它就会寻找有没有注册过想要接收这条报文的设备, 如果有,这个设备的 RxCallback()函数就会被 CAN 总线类调用。
整个过程分为以下几个步骤:
-
继承
rm::device::CanDevice
-
在构造函数的初始化列表中代理构造,向 CAN 总线类表明自己要注册到这一条 CAN 总线上、说明自己要接收哪些 ID 的报文
-
实现
private void RxCallback(const hal::CanMsg *msg)
成员函数,在这个回调函数中编写收到报文时的处理逻辑
下面是一段在 Linux 平台下的例程代码,例程实现了一个最基本的 CAN 设备,它接收can0
总线上的0x123
标准帧 ID 的报文,并且把报文的内容打印到屏幕上。
代码
#include "librm.hpp"
#include <iostream>
using rm::device::CanDevice;
using rm::hal::Can;
class BasicCanDevice : public CanDevice {
public:
BasicCanDevice(rm::hal::CanInterface &can, uint32_t rx_std_id)
: CanDevice{can, rx_std_id} {}
private:
void RxCallback(const rm::hal::CanMsg *msg) override {
// 在这里处理接收到的报文
std::printf("Received a message! stdid=%d, dlc=%d\n", msg->rx_std_id,
msg->dlc);
for (int i = 0; i < msg->dlc; i++) {
std::printf("%02X ", msg->data[i]);
}
std::printf("\n");
}
};
int main() {
Can can0{"can0"};
BasicCanDevice device{can0, 0x123}; // 我想要接收can0上的0x123标准帧ID的报文!
can0.Begin();
while (true) {
}
return 0;
}