CAPL学习之路-信息、类的实例化、数组、结构体、枚举、字典

1.获取工程信息

  • %NODE_NAME%  仿真节点名称
  • on key 'a'
    {
      write("the node name: %NODE_NAME%");
    } 
    
  • %CHANNEL% 仿真节点分配的通道
  • %NETWORK_NAME% 仿真节点分配的网络名称
  • %FILE_NAME% 源文件名称
  • %FILE_NAME_NO_EXT%   源文件名称(没有扩展名)
  • %BASE_FILE_NAME_NO_EXT% 编译的文件名称(没有扩展名)

2.%FILE_NAME%获取源文件的名称,%BASE_FILE_NAME%获取编译的文件名称,这两者有何区别?

 

 

 

对于网络节点,只有加载的capl文件才是主文件,而这个capl文件又可能引用多个capl文件

%FILE_NAME%是获取所在文件的名称,而%BASE_FILE_NAME%只会获取主文件的名称

3.类得实例化

  1. capl虽然无法自定义类,然后通过实例化的方式调用类中的方法
  2. 可以对capl中预定义的类进行实例化,然后调用里面的方法
  • 可以对capl中预定义的类进行实例化,然后调用里面的方法
  • 类名 对象名;然后用这个对象调用函数
  • 对象名.函数名(参数1,参数2,...)

Timer, MsTimer:这两个类用于定期执行特定的功能,其中,Timer以秒为单位,MsTimer以毫秒为单位

File    这个类用于读取或写入文件

TcpSocket  这个类用于实现tcp网络通信

UdpSocket 这个类用于实现udp网络通信

TestCheck  这个类是与测试序列或模拟节点并行运行,目的是持续检查是否遵守指定条件

TestStimulus 这个类可以为信号或环境变量生成特定值模式以刺激设备

DiagRequest  这个类表示诊断请求

DiagRespons 这个类表示诊断响应

Associative fields  关联字段

CAN  提供对总线指定信息的访问

Classes of CAN Disturbance Interface    CAN干扰接口的类

Classes of Scope   范围类

4.数组

和其他编程语言一样,capl也有数组类型,需要注意的是,字符串是CHAR类型的数组,另外也支持多维数组

例如:

int num1[5] = {1,2,3,4,5};
byte num[3]={0x01,0x02,0x03};
int num3[2][2]={{1,2},{3,4}};
char str=[6]="hello";

对于char类型的数组,数组长度要是字符串字符个数加1,因为默认还有一个换行符,也算一个字符

消息可以使用id或dbmsg来定义并进行初始化

 

message 0x5c0 msg_wakeup = {dlc = 8, byte(0) = 0x11, byte(1) = 0x22, byte(2) = 0x33, byte(3) = 0x44, byte(4) = 0x55, byte(5) = 0x66, byte(6) = 0x77, byte(7) = 0x88};  
message IgnitionOn msg_wakeup = {dlc = 8, byte(0) = 0x11, byte(1) = 0x22, byte(2) = 0x33, byte(3) = 0x44, byte(4) = 0x55, byte(5) = 0x66, byte(6) = 0x77, byte(7) = 0x88};

 

如果是多个消息的集合,可以用message *

message * msgArray[4] = {msgABSdata, motbus::EngineData, msgGearBoxInfo, {dlc = 8}};

数组元素个数可以用elcount()获取  

除了下标来获取数组的元素以外,还可以用访问数据的选择器来获取

on key 'a'
{
  byte num1[4] = {0x11, 0x22, 0x33, 0x44};
  write("value1: 0x%2x", num1.byte(0));
  write("value2: 0x%4x", num1.word(2));
  write("value3: 0x%8x", num1.dword(0));
}  

打印结果:

 

 

 可以看出

 

 

byte(i)、word(i)、dword(i)、int(i)、double(i)等传入的参数i代表的是从第i个byte开始,所以能调用它们的数组也只能是byte数组

 

byte(i)是从第i个byte开始的一个byte值

 

word(i)是从第i个byte开始的一个word值

 

dword(i)是从第i个byte开始的一个dword值

 

byte数组是存入的window电脑,采用的是小端存储,那么低位下标的值表示低位,高位下标的值表示高位,所以0x33,0x44才会变成4433

对于消息来说,它里面的值也是以byte为单位的,所以也可以用这些选择器获取索引值

msg_wakeup.byte(0) = 0x01;
msg_wakeup.word(1) = 0x1234

 swapWord(num1.word(2))   大小端转

由于网络传输采用的是大端存储,那么低位下标的值表示高位,高位下标的值表示低位,所以0x33,0x44就会写成3344  

5.结构体

定义一个结构体

struct Date {
  int type;
  long l;
  cahr name[50];
}; 

注意:中括号得后面需要有分号

定义这个结构体后,还需要声明这个结构体变量

struct Date data;

然后用这个结构体变量调用里面的元素,比如data.type

你会发现结构体从定义到使用,都和类的实例化比较像

反过来想,其实类的实例化也是声明变量类型的一种形式

对类的实例化,其实就是声明这个类的类型的变量

而声明变量也是类的实例化的表现,比如声明一个int类型的变量,其实也是对int类实例化一个对象,所以很多时候,可以直接用变量调用某些方法,这些方法其实就是变量类型的类里的方法

结构体的常见用法是可以定义协议头部里的各种字段,而对结构体里的元素赋值后,需要把报头以数组的形式发出去,结构体和数组的转换,在capl中也是提供了方法的

 

 

 计算机系统为了简化处理器与内存之间的传输,以及提升读取数据的速度,对数据在内存中的存储的位置进行了限制,要求是某个数k的倍数,这就是所谓的内存对齐

结构体中的元素由于大小不一,就需要设置这个k值

capl中用_align()来设置对齐方式,只允许使用值1、2、4、8,默认是8

_align(2) struct Point2 
{
  byte x;    // offset 0, size 1, (alignment 1)
  qword y;   // alignment 2, offset 2, size 8, padding before: 1
};         // size 10, alignment (of the struct) 2

设置对齐方式,并不意味着结构体的长度/大小发生了变化,可以用__size_of(struct Data)来获取结构体长度,注意传入的参数是结构体而非结构体变量

6.枚举

结构体类型是对不同变量的定义,而枚举类型是对不同值的定义

怎么说,举个例子

某校统计学生信息,各班报上来的信息有

名字:xxx
年级:xxx

姓名:xxx
年龄:xxx

称呼:xxx
岁数:xxx

这样统计到一起时会显得杂乱无序

聪明的校长想到了可以用结构体来定义各信息的变量名

struct INFO
{
  char name[10];
  int age;
};  

 

这样我在统一的时候只需要声明这个结构体变量,然后调用里面的元素变量即可实现统一

虽然解决了变量的统一,但是对于有些值又可能造成不统一,比如在统计性别时,有的班级用男/女,有的班级用公/母,有的班级用雌/雄,这又要如何统一呢?

就可以用枚举类型,把值固定

enum GENDER
{
  male = 1,
  female = 0
}; 

用关键字enum定义枚举,枚举可以赋值,也可以不赋值,如果不赋值,则第一个元素默认0值,后面依次加1  

这里有个注意点,里面的元素用逗号隔开,最后一个元素后面不需要符号

枚举里的值可以直接使用,无需声明枚举变量后调用,这点貌似和C#不同

int i;
i = male; 

7.关联字段

在capl中叫Associative Fields,我大概的了解了下,和字典类型相似,也是通过键值对的方式,快速访问值

int m[float];
m[3.1] = 2;
m[4.3] = 5;

键的数据类型可以是long、int64、float、double、字符换和枚举,值的数据类型就是简单的数据类型都可以,包括枚举和结构体  

关联字段的大小可以动态增加或减小,你也可以在声明时指定初始大小

int m[float, 30];  //为30个元素保留的初始空间

当然,它也提供了几种方法 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

上面的例子,x放在0这个位置的内存上,它只占有一个字节,y如果紧挨着它,放在了1的位置上,就不行了,因为1不是2的倍数,所以它只能放在2的位置上,1的位置就需要空着

设置对齐方式,并不意味着结构体的长度/大小发生了变化,可以用__size_of(struct Data)来获取结构体长度,注意传入的参数是结构体而非结构体变量

 

posted @ 2021-07-10 22:06  albert11  阅读(2413)  评论(0编辑  收藏  举报