ESE模块14 CAN-Bus 通讯
使用mySTM32 light板来使用CAN总线。这个练习需要两个人一起完成,或者至少需要两个mySTM32 light板。
在之前的教程中,您已经了解了I²C总线。这种总线用于连接同一块电路板上的不同控制器。如果要连接的控制器分布在较远的位置,例如在建筑机械上的传感器和执行器,可能需要几米的电缆长度,那么就会使用其他现场总线系统。特别是在车辆领域,CAN总线CAN-Bus是一种常用的总线系统。CAN代表Controller Area Network。因此,这个名字已经表明了它是一个面向微控制器的网络协议。与I²C协议不同,CAN发送的是所谓的帧。Frames这些帧包含了诸如消息ID和要传输的有效负载等控制信息。在标准模式下,每个帧提供8字节或8×8 = 64位的有效负载。在CAN中,信息通常不是一次性事件导向的,而是按照特定的更新速率周期性地发送,例如每20或100毫秒一次。更新速率与消息的重要性相关。消息的缺失意味着相应节点的故障。
任务
两个控制器板将通过CAN总线联网。 每个板都应有一个按钮和一个LED。 当按一个板的按钮时,另一块板上的LED就会亮。
解决方案要求:
- 发送按钮针脚A0
- 接收LED针脚B0
- CAN更新速率100毫秒
- 消息ID板1 = 1,板2 = 2
准备工作
如果仍有一个类图已经打开,请在该图的上下文菜单(鼠标右键)中选择菜单项“上”。 如果没有,请再次打开SiSy UML项目。 进行以下准备工作:
- 创建一个新的类图
- 目标语言ARM C ++
- 目标平台STM32F042 mySTM32板灯HAL
- 为PEC的应用模板(XMC,STM32,AVR)加载应用程序的基本结构
- 为STM32F0分配驱动程序包
- (可选)分配模板stm32F042_48Mhz
解决路径
实现一个CAN总线解决方案稍微复杂一些。在开始之前,我们应该对以下几个方面有清晰的认识:
- 系统状态作为消息循环放置(发送)在总线上
- 消息没有接收方的地址,但显示了系统状态的ID
- 每个控制器都可以接收对其重要的系统状态并对它们做出反应
- 控制器可以/必须过滤出所需的消息(ID)
- 系统状态以64位用户数据(8字节)编码
让我们试着找出系统设计中的重要组件。要发送的系统状态是一个按钮状态。值得注意的是,用于编码按钮状态的消息只需要一个位。控制器周期性地检测按钮状态,例如每100毫秒一次,将状态(0/1)编码在一个CAN消息中,并将其发送到CAN总线上。接收控制器过滤和解码来自CAN总线的接收消息,并相应地切换LED。
软件包“ Middleware / CanSupport / pec_Can”包含适合当下任务的库模块。CAN总线以及发送和接收消息都有构建块。下图标记了对解决方案重要的元素。
以下CAN解决方案的设计图可以从系统组件中得出。
首先是发送方解决方案的设计图。
再是接收方解决方案的设计图。
CAN协议不是PEC基本软件包的一部分,而是包含在中间件软件包中。 要使用CAN库块,必须使用文件夹“ Middleware / CanSupport”中的相应驱动程序包“ pec_can”包含在类图中。
注意:使用中间件=分配适当的软件包
现实
首先实现发送方的解决方案。
请注意,在类图中包含pec_can包。
操作中的简要总结:
- • 准备一个新的类图
- • 包含pec_Can软件包
- • 创建并连接类SendButton,CanBus和SendMessage
- • 连接库块PecButtonClickAndHold,PecCanBus,PecCanMsgSend
- • 连接特定的控制器资源pinA0和canPortA11A12_stm32f0
- • 覆盖类控制器onEvent100ms的操作
- • 覆盖SendMessage类的onConfig操作
在MessageReceiver类的onConfig()操作中,我们将ID 1分配给消息对象。
SendMessage::onConfig():voidmsgId=0x01;
我们使用类控制器的100毫秒事件来循环发送按钮状态。 我们在消息的第一个数据字节中编码按钮状态,其中0表示未激活,1表示按钮已激活。
Controller::onEvent100ms():voidif (sendButton.isPressed()) { canBus.sendMessage.msgData.data8[0] = 1; } else { canBus.sendMessage.msgData.data8[0] = 0; } canBus.sendMessage.send();
然后再做接收方的解决方案(和发送的解决方案 几乎相近)。
同样,请注意,在类图中包含pec_can包。
操作中的简要总结:
- • 准备一个新的类图
- • 包含pec_Can软件包
- • 创建并连接类ReciveLED,CanBus和ReciveMessag
- • 连接库块PecLed,PecCanBus,PecCanMsgRecv
- • 连接特定的控制器资源pinB0和canPortA11A12_stm32f0
- • 覆盖ReceiveMessage类的onReceive操作
- • 覆盖ReciveMessage类的onConfig操作
为了接收正确的消息,我们将ID 1分配给期望的接收消息。
ReciveMessage::onConfig():voidmsgId=0x01;
我们只是在消息对象的接收事件中对消息进行解码。
ReciveMessage::onRecive():voidif (msgData.data8[0] == 1) { app.reciveLED.on(); } else { app.reciveLED.off(); }
测试
翻译解决方案。将可执行程序传送到控制器的程序存储器中。
- 1. 创建(编译和链接)
- 2. 烧录
- 3. 将板上的按钮1连接到A0,将红色LED连接到B0
- 4. 在板之间建立CAN连接,注意CAN Hi = Hi,GND = GND,Lo = Lo
视频总结
- 1. 创建并打开类图
- 2. 选择PEC应用程序的图模板
- 3. 加载正确的驱动程序包
- 4. 包含中间件软件包
- 5. 在资源管理器中找到所需的构建块并将其拖动到图中
- 6. 聚合类, 组件连接
- 7. 覆盖操作
- 8. 在操作中创建必要的源代码
- 9. 在类图中创建并刻录ARM应用程序
练习12
扩展两个解决方案,以使它们每个都有一个发送按钮和一个接收LED,将板1发送到板2,将板2再发送到板1。