【CAPL】发送固定数的帧后恢复原状态

发送固定数的帧的使用场景

  • 后视镜折叠功能

    • 持续发送折叠信号的话,电机堵转容易烧掉,因此仅发送有限帧数据
    • 举例,仅发送3帧数据恢复原值

CANoe工程设置

需求分析

  • 仅发送3帧数据恢复原值
  • 3帧数据:循环3次,并重复发送动作
  • 恢复原值:循环结束后,发送的数据值恢复为原来的值
  • 需要触发:设置一个trigger变量,并关联到开关控件

DBC设置

  • 明确收发节点和触发数据的所在信号
  • 本工程:switch节点发,light节点收,trigger位于报文0x123的bit1
    图片
    图片

创建系统变量trigger

  • 选中space-new
  • 设置属性值:name,初始值、最值等
  • 在系统变量界面apply后才能使用
    图片

panel设置

  • 添加开关控件
  • 关联到系统变量trigger
    图片

CAPL设置

  • 报文0x123的帧率:200ms循环帧
    图片
  • 分析:发送3帧,需要循环;如下图的触发可能会不太方便
    图片
  • 监控报文0x123:监控系统变量trigger的值
    • 设置计数器i=0;
    • 当trigger==1时:将报文下的信号switch赋值为1
      • 进行三次循环
      • 循环结束后,将trigger赋值为0
    • 当trigger==0时:将信号switch赋值为0,计数器归零
  • 代码示例
    //light.can
    //奇怪的是,在其他代码全部注释,MyMSG不设为循环帧的情况下,仍然可以实现发3帧1
    on message MyMSG//改为on signal_update `switch 也可实现
      //注意:on signal `switch 不行
    {
      int i = 0;
      if(@sysvar::MyNameSpace::trigger == 1){
        write("active!!");
        i++;
        if(i<3){
          write("count less than 3:%d",i);
          //@sysvar::MyNameSpace::trigger = 1;
          $`switch=1;
        }else{
          write("count done: %d",i);
          @sysvar::MyNameSpace::trigger = 0;
        }    
      }else if(@sysvar::MyNameSpace::trigger == 0){
        write("inactive...");
        $`switch = 0;
        i = 0;
      }
      
    }
    

运行效果

  • 开关按下,发3帧,开关自动恢复为关闭,发送是数据恢复为0
    图片

调试

调试:报文MyMSG是否为循环帧

  • DBC中MyMSG改为非cycle,cycletime改为0后,trace无更新,panel开关无反应
    图片
  • 注意:报文attribute每次修改后,应用-确定,不生效,需要在DBC界面保存后才生效!!
    图片

调试:添加timeNow()的报文200ms循环帧

  • 代码示例:
    on message MSG_LS
    {
      int i = 0;
      if(@sysvar::MyNameSpace::trigger == 1){
        write("active!!");
        i++;
        if(i<3){     
          write("count less than 3:%d, timenow = %d",i,timeNow());
          //@sysvar::MyNameSpace::trigger = 1;
          $`switch=234;
        }else{
          write("count done: %d, timenow = %d",i,timeNow());
          @sysvar::MyNameSpace::trigger = 0;
        }    
      }else if(@sysvar::MyNameSpace::trigger == 0){
        write("inactive...timenow = %d",timeNow());
        $`switch = 0;
        i = 0;
      }
    }
    
  • 运行结果:i 的更新均为200ms间隔,没有提前跳出
    image

问题

1.报文是否是循环帧,与trace持续发送的关系

  • 不管设置报文MyMSG为循环帧还是默认未定义帧,trace中都会一直不停地发报文
    • trace中为什么没有output都会一直不停地发呢?
  • DONE:DBC中报文属性更新,apply之后,仍需在DBC保存才能生效!!

2.代码中用if就实现了循环,执行顺序?为什么会?

  • CAPL中的局部变量:静态地被创建,并且可以再次进入程序时保留上一次的值

    • 因此这里的int i虽然是局部变量,但是有种全局变量的属性,可以用if扭曲地实现循环
      image

注意:代码应有可读性更强的实现方法

如使用循环语句,使用全局变量等

可读性也是很重要的!!!

END

posted @ 2025-08-14 14:37  anliux  阅读(32)  评论(0)    收藏  举报