前言

上一篇文章介绍了如何创建CANoe工程,需要先阅读这篇文章,才能对整个工程有所了解,包括节点、报文、信号等关键信息。

本文的重点是分析该工程中各个节点CAPL语言是怎么编写的,主要目的在于理解整个工程的实现,具体关于CAPL语言的理论知识总结等以后再分享。

CAPL就是Communication Application Programming Laguage的缩写,CAPL类似于C语言的语法。CAPL语法是C语言的,又有一些C++的特性,this指针,事件等,我觉得和我之前学的JavaScript语言有一些互通的地方。

如图,我们会分别介绍三个节点的CAPL程序。

Engine.can

首先来看一下Engine节点engine.can的代码。

​/*@!Encoding:936*/
includes
{}variables
{//The following three messages are defined for transmissionmessage EngineStatus EngineStat; //定义一个在DBC中message name为EngineStatus的报文变量EngineStatmessage LockingRq LkCtrlRq;message WindowRq WindowCtrl;//The following timer is for simulating the cyclic message transmission   msTimer msTimer_EngineStatus;   //定义一个ms定时器msTimer_EngineStatus}on start
{setTimerCyclic(msTimer_EngineStatus,100);
}on timer msTimer_EngineStatus{       //响应定时器事件msTimer_EngineStatus,将报文发送到总线EngineStat.Velocity = @sysvar::testNS::Velocity; //获取面板中变量输入的值EngineStat.IgnitionStatus = @sysvar::testNS::IgnitionStart;output(EngineStat);  //将报文发送到总线中
}

程序结构

先从宏观的角度来看,这个CAPL程序的结构包含了头文件、全局变量、事件函数,没有自定义函数。

includes{ }头文件是对其他文件及dll文件的包含说明,variables{ }是对全局变量的声明定义,on start{ },on timer{ }是工程中用到的各类事件。

全局变量

  1. message 报文变量

CAPL提供了各种网络对应的报文类。本文以CAN message为例,报文变量定义格式:message + message ID/message name + variable

使用message关键字来声明一个报文变量,message后是message ID或CANoe工程导入DBC后的message name,然后是在CAPL程序中要使用的报文变量名。

  message EngineStatus EngineStat; 

如上,定义一个在DBC中message name为EngineStatus的报文变量EngineStat,此外还定义了报文LockingRq和报文WindowRq。

2. msTimer 定时器变量

CAPL提供两种定时器变量: timer:基于秒(s)的定时器 、msTimer:基于毫秒(ms)的定时器。

msTimer msTimer_EngineStatus;

如上,定义了一个ms定时器msTimer_EngineStatus。

事件函数

CAPL是一种面向过程、由事件驱动的类C语言。

事件驱动针对于顺序执行,其区别如下:

顺序执行:顺序执行流程中,子例程或过程函数按照代码编写顺序逐句执行。

事件驱动:CAPL程序由事件驱动,工程运行过程中发生指定的事件时才会运行相应的事件处理函数。

事件起始关键字 on

on后加某种事件,工程运行时条件触发,则执行函数体内的语句。

关键字this

系统变量、环境变量或CAN报文事件中,可以用this关键字访问其指代的数据内容。

on start
{setTimerCyclic(msTimer_EngineStatus,100);
}

如上,on start{ }函数在工程开始时调用,setTimerCyclic(msTimer_EngineStatus,100) 设置定时器msTimer_EngineStatus为一个100ms为周期的循环定时器;

on timer msTimer_EngineStatus{       //响应定时器事件msTimer_EngineStatus,将报文发送到总线EngineStat.Velocity = @sysvar::testNS::Velocity; //获取面板中变量输入的值EngineStat.IgnitionStatus = @sysvar::testNS::IgnitionStart;output(EngineStat);  //将报文发送到总线中
}

如上,定义了一个响应定时器事件,函数中EngineStat.Velocity = @sysvar::testNS::Velocity;表示面板panel中的系统变量Velocity变化后,将其赋值给EngineStat报文的Velocity 信号。最后的output()函数将报文发送到总线中。

整段engine.can的代码,实现了周期(100ms)循环执行msTimer_EngineStatus事件,将EngineStatus报文每100ms发送到总线中。如果面板panel中报文的两个信号有变化的话,会实时更新。

Doors.can

includes
{}variables
{byte WindowState = 0;byte IgnitionState;message LockingState LockingStat;message WindowState WindowStat;
}on message EngineStatus
{//Storing Ignition Stateif(this.IgnitionStatus) IgnitionState = 1; //Ignition is onelse IgnitionState = 0; // Ignition is off//Locking based on velocityif(IgnitionState == 1 && this.Velocity > 15 && LockingStat.LockState == 0){LockingStat.LockState = 1;output(LockingStat);}
}on message WindowRq{if(IgnitionState){if(this.WindowRequest == 1) //Roll up windowif(WindowState > 0) WindowState--;if(this.WindowRequest == 2) //Roll down windowif(WindowState<15) WindowState++;}WindowStat.WindowPosition = WindowState;output(WindowStat);
}on message LockingRq{if(this.LockRequest)  LockingStat.LockState = 0;else LockingStat.LockState = 1;output(LockingStat);
}

数据结构

variables
{byte WindowState = 0;byte IgnitionState;message LockingState LockingStat;message WindowState WindowStat;
}

如上,定义了两个报文变量LockingStat和WindowStat,以及用byte声明了一个字节的变量WindowState和IgnitionState。

事件函数

CAN消息事件

通过”on message”定义消息事件,该事件会在指定的报文消息被接收时被调用

on message EngineStatus
{//Storing Ignition Stateif(this.IgnitionStatus) IgnitionState = 1; //Ignition is onelse IgnitionState = 0; // Ignition is off//Locking based on velocityif(IgnitionState == 1 && this.Velocity > 15 && LockingStat.LockState == 0){LockingStat.LockState = 1;output(LockingStat);}
}

如上,当收到报文EngineStatus后,执行函数括号中的内容。当报文中的信号IgnitionStatus为1时,IgnitionState变量赋值为1,表示汽车已经启动,反之变量赋值为0。

第二个if语句表示,当汽车已经启动IgnitionState == 1,车速大于15this.Velocity > 15,车是解锁状态LockingStat.LockState,同时符合这三个条件的时候,将LockingStat.LockState置为1,即将车上锁。随后将LockingState报文发送到总线。

其余两个消息事件的内容同理,这边就不赘述了。

console.can

/*@!Encoding:936*/
includes
{}variables
{message LockingRq LkCtrlRq;message WindowRq WinRq;
}on sysvar_update testNS::LockRq{if(@sysvar::testNS::LockRq) LkCtrlRq.LockRequest = 1; //request unlock doorselse LkCtrlRq.LockRequest = 0; //request Lock Doorsoutput(LkCtrlRq); //Outputs message onto the bus
}on sysvar_update testNS::WindowRequest{WinRq.WindowRequest = @sysvar::testNS::WindowRequest;output(WinRq); //Outputs message onto the bus
}on message WindowState{@sysvar::testNS::WindowState = this.WindowPosition;
}

事件函数

on message WindowState{@sysvar::testNS::WindowState = this.WindowPosition;
}

如上,当收到报文WindowState后,将信号WindowPosition的值赋值给系统变量WindowState,即在面板上可以看到该值的变化。

读取或者设置系统变量的值,用 ‘@’ 或者 sysGetVariable,系统变量要通过 域操作符"::" 在前面加上他的域空间才行。

on sysvar_update testNS::WindowRequest{WinRq.WindowRequest = @sysvar::testNS::WindowRequest;output(WinRq); //Outputs message onto the bus
}

如上,当在面板panel对系统变量WindowRequest进行操作后,会执行函数括号里的内容,将系统变量的值赋值给报文的WindowRequest信号,然后将报文发送到总线。

on sysvar 和 on sysvar_update的区别
on sysvar :值变化才会触发
on sysvar_update :只要对系统变量操作了,值不变化也会触发

深入浅出学习CAN系列-了解CAPL编程语言相关推荐

  1. 零基础 ABAP 学习教程系列文章的目录

    零基础 ABAP 学习教程系列文章的目录 ABAP 标准培训教程 BC400 学习笔记之一:ABAP 服务器的架构和一个典型的 ABAP 程序结构介绍 ABAP 标准培训教程 BC400 学习笔记之二 ...

  2. LSTM长短记,长序依赖可追忆(深度学习入门系列之十四)

    摘要:如果你是一名单身狗,不要伤心,或许是因为你的记忆太好了.有时,遗忘是件好事,它让你对琐碎之事不再斤斤计较.然而每当自己记不住单词而"问候亲人"时,也确实气死个人.于是你懂得了 ...

  3. 如何学习 C++ 如何学习一门较复杂的编程语言 【转】

    何学习 C++ 如何学习一门较复杂的编程语言 前言 呵呵,大家好,我又来了,其实我天天在,大多数时候总是回答一些套话,比如"同意上传.文件名:......文件夹:......",或 ...

  4. 局部连接来减参,权值共享肩并肩(深度学习入门系列之十一)

    系列文章: 一入侯门"深"似海,深度学习深几许(深度学习入门系列之一) 人工"碳"索意犹尽,智能"硅"来未可知(深度学习入门系列之二) 神经 ...

  5. 2020 年最值得学习的 5 大 AI 编程语言

    来源:学术头条 本文约1571字,建议阅读4分钟. 本文介绍2020 年最值得学习的 5 大 AI 编程语言,希望对想学习人工智能的读者有帮助. 人工智能是当今世界最具需求的一个领域,人工智能通过编程 ...

  6. SQL Server 2008/2012中SQL应用系列及BI学习笔记系列--目录索引

    SQL Server 2008中的一些特性总结及BI学习笔记系列,欢迎与邀月交流. 3w@live.cn  ◆0.SQL应用系列 1.SQL Server 2008中SQL增强之一:Values新用途 ...

  7. BP算法双向传_链式求导最缠绵(深度学习入门系列之八)

    摘要: 说到BP(Back Propagation)算法,人们通常强调的是反向传播,其实它是一个双向算法:正向传播输入信号,反向传播误差信息.接下来,你将看到的,可能是史上最为通俗易懂的BP图文讲解, ...

  8. 【深入浅出Node.js系列十一】Node.js开发框架Express4.x

    为什么80%的码农都做不了架构师?>>>    #0 系列目录# 深入浅出Node.js系列 [深入浅出Node.js系列一]什么是Node.js [深入浅出Node.js系列二]N ...

  9. BizTalk学习笔记系列之二:实例说明如何使用BizTalk

    BizTalk学习笔记系列之二:实例说明如何使用BizTalk --.BizTalk学习笔记系列之二<?XML:NAMESPACE PREFIX = O /> Aaron.Gao,2006 ...

  10. 从0开始学习GitHub系列之「Git 速成」

    从0开始学习GitHub系列之「Git 速成」 糖果果| 2016-06-24 10:55    浏览量(32)    评论(0)   推荐(0) 数据 小编注:[从0开始学习 GitHub]是一个系 ...

最新文章

  1. 数据包构造分析工具Hping3常用命令集合大学霸IT达人
  2. 字节跳动2018校招算法方向(第一批) —— 1-最外层点
  3. R可视化lend_club 全球最大的P2P平台数据75W条
  4. VC++ 深入详解 学习笔记(5) -- 修改窗口样式续
  5. Microsoft Deployment Toolkit 2008部署操作系统系列(一)
  6. kafka(一)设计分析
  7. dynamic的使用
  8. 大数据应用智能交通有哪些意义
  9. 如何使用Windows Live Alerts服务
  10. 数据库系统概论第五版 (第 1 章 绪论 ) 笔记
  11. 软件体系结构期末复习(快速入门考试)
  12. python算法爬楼梯
  13. 上古卷轴5:重制版Skyrim Together用MO无法替换游戏菜单Menu图像LOGO的问题解决
  14. uniapp 消息提示框
  15. ubuntu mate 18.04官网下载,烧录及安装 SSH VNC ROS MAVROS librealsense realsense-ros vision_to_mavros(我自己亲自弄的)
  16. 基于SpringBoot的影视/短视频网站系统
  17. 号外:Axure导入有了!思维导图也正式上线了!
  18. 荒岛求生游戏显示服务器不行,荒岛求生连接服务器失败怎么办
  19. python挖矿木马_记一次阿里云被植入挖矿木马的事件
  20. java ikanalyzer分词_利用ikanalyzer分词

热门文章

  1. eltable 无数据文案修改_element-table 无数据的时候,把“暂无数据” 改成其他文字或图片...
  2. EasyUi之书籍功能(CRUD)
  3. 更换tomcat 地址栏图标
  4. 如何下载矢量建筑轮廓
  5. 毕业设计 - 题目:基于深度学习的人脸表情识别 - 卷积神经网络 毕设 代码
  6. C#身份证号码验证器(检验格式是否正确)
  7. 关于算法竞赛入门经典3.4.2思考题题目1必要的存储量的思考
  8. ubuntu(乌班图)常用命令大全
  9. Mac 查看jdk版本
  10. Apizza在线接口调试文档工具如何方便的设置线上线下环境变量