[已解决] APP Designer APP内串口中断回调函数无法调用“无法找到该字段”

[复制链接]
hkt_guet 发表于 2022-5-9 13:20:38
本帖最后由 hkt_guet 于 2022-5-9 13:39 编辑

最近用app designer写了一个串口数据实时监测的app,为了实现实时读取串口的数据然后在app内的坐标轴窗口显示波形,我在“打开串口”按键回调函数中指定了app内定义的串口中断回调函数,但是软件报错:用了不存在的字段 'usart_callback'。于是我把串口中断回调函数封装成".m"文件,发现可以正常调用,但是由于无法显示数据在app内的图窗,所以又把它改回来app内定义的函数,问题:请问如何解决?
代码:

定义ser为app内的全局变量
[
properties (Access = public)
      
        ser; % Serial
            serialname;
            baud ; % baud rate
  end
]

打开串口按键回调函数
[
            clear
            delete(instrfindall);
            % 创建串口变量
            app.ser = serial('COM5');
            app.ser.BaudRate = 115200;
            app.ser.timeout=1;
            app.ser.Parity='none';
            app.ser.StopBits=1;
            app.ser.Terminator='CR/LF';
            app.ser.FlowControl='none';
            app.ser.BytesAvailableFcnMode='byte'; %设置事件触发为接受触发
            app.ser.InputBufferSize=300; %设置接受缓冲区大小为 300 个字节
            app.ser.BytesAvailableFcnCount=300; %每次接受到 300 个数据时候触发事件
            app.ser.BytesAvailableFcn=@app.usart_callback; %指向触发事件函数
            fopen(app.ser); %打开串口
            fprintf(app.ser,'o');%发送"开始发送数据"的命令给下位机

]

自定义的公共属性串口中断回调函数
[function usart_callback(app,obj,event)
            temp=fscanf(obj,'%s');%由于发送了握手命令,先把第一个返回来的的握手数据读出来
            for i=1:300
                A{i}=fscanf(obj,'%s');
                A1{i} = textscan(A{i},'%d %f ','Delimiter','=');
                B(i)=cell2mat(A1{1,i}(1,1));
                C(i)=cell2mat(A1{1,i}(1,2));
            end
            B=cast(B,'double');
            B1=ditong(B);       %低通滤波
            B2=mean5_3(B1,300); %平滑加矫正基准线
            clf(app.ppgandpressure)  %app.ppgandpressure是我定义再app内的一个坐标轴窗口
            plot(app.ppgandpressure,B2)
            hold(app.ppgandpressure);
            plot(app.ppgandpressure,C)
        end
]
错误信息:引用了不存在的字段 'usart_callback'。

出错 usart>@(varargin)app.usart_callback(varargin{:}) (line 78)
            app.ser.BytesAvailableFcn=@app.usart_callback; %指向触发事件函数

出错 instrcb (line 42)
        feval(val{1}, obj, eventStruct, val{2:end});

警告: The BytesAvailableFcn is being disabled. To enable the callback property
either connect to the hardware with FOPEN or set the BytesAvailableFcn property.






最佳答案


1119093102 发表于 2022-5-10 09:26:49
本帖最后由 1119093102 于 2022-5-10 09:32 编辑
hkt_guet 发表于 2022-5-9 18:56
我这里还存在一个问题,我这里除了写了一个“打开串口”按键,还写了一个“关闭串口”按键,如图所见我在 ...

1、你的串口问题解决了吗?如果不行,将函数属性换成私有的试试,按道理应该都行的。建议:界面内的属性换成私有的,传递到外面用公有,好整理。
2、关闭串口问题。你逻辑有错误,instrfindall就是找到所有串口,delete就会删除所有串口,关闭~=删除,所以正确做法是delete放在界面的关闭函数去。非逻辑需要也不要放clear、clearvar这些函数浪费时间,所有控件函数运行完成自动清除。建议:串口对象、定时器对象界面启动时就建立,控件负责打开关闭就行,delete这种少用,一般是关闭界面或者try catch中用,要不然你都不知道啥问题。
3、定时器问题。上官网找对应matlab版本仔细看一下它的属性,中文的,有一个属性是控制运行模式,换一下模式就可以了,start、stop控制就行。

15 条回复


1119093102 发表于 2022-5-9 14:22:19
你函数应该没放对位置,你在app类定义那里要可以看到usart_callback,就是左边的函数框那里,如果看不到,就是你的函数并没有识别到,也就是你建立的方式不对

hkt_guet 发表于 2022-5-9 14:23:59
1119093102 发表于 2022-5-9 14:22
你函数应该没放对位置,你在app类定义那里要可以看到usart_callback,就是左边的函数框那里,如果看不到, ...

,这个倒是识别到了

1119093102 发表于 2022-5-9 14:31:08
也还有方法,你可以建立公共属性,存储信息,在m文件中绘图,绘图时使用指定控件绘图的方式进行绘图,而且我不建议你在串口中断中处理绘图,那样子绘图会增加数据解析时常,如果频率低还好,一高就可能处理滞后,也就是队列排序,你可以做个定时器,定时绘图,达到绘图条件就绘图。

hkt_guet 发表于 2022-5-9 14:45:24
1119093102 发表于 2022-5-9 14:31
也还有方法,你可以建立公共属性,存储信息,在m文件中绘图,绘图时使用指定控件绘图的方式进行绘图,而且 ...

确实,我也遇到了数据解析异常的情况,就是绘图偶尔会发生严重滞后i情况,原来是发生了队列排序,我马上改一下。但是我还有一个疑问:在m文件中可以指定绘图到app上的窗口吗,我之前就是把串口中断封装成".m"文件然后调用该函数绘图到app的窗口,但是软件提示我找不到该窗口控件

1119093102 发表于 2022-5-9 15:03:14
hkt_guet 发表于 2022-5-9 14:45
确实,我也遇到了数据解析异常的情况,就是绘图偶尔会发生严重滞后i情况,原来是发生了队列排序,我马上 ...

可以啊,公用属性就行。你这个函数识别也好弄,就是在代码视图-代码浏览器-函数,如果没有识别你写的function,按+增加一个function模板,将模板替换成你写的函数,就解决了。绘图频率也要结合你的串口频率来做,频率高时定时频率不要超过串口频率,最好就是将多次串口数据组合成到一次绘图数据进行绘图,从而降低定时频率

hkt_guet 发表于 2022-5-9 15:21:24
本帖最后由 hkt_guet 于 2022-5-9 15:31 编辑
1119093102 发表于 2022-5-9 15:03
可以啊,公用属性就行。你这个函数识别也好弄,就是在代码视图-代码浏览器-函数,如果没有识别你写的func ...

不好意思,我没理解你的话,你的意思是这样吗?把存放从串口读取出来的、要拿来绘图的数据的变量定义成公共属性,然后把串口中断函数以及定时器绘图函数全部写成m文件,把他们跟app文件放在同一个文件夹里吗?还是说只有串口中断函数封装成m文件跟app放到同一个文件夹里,而定时器绘图函数写在app内?

1119093102 发表于 2022-5-9 15:31:25
本帖最后由 1119093102 于 2022-5-9 15:32 编辑
hkt_guet 发表于 2022-5-9 15:21
不好意思,我没理解你的话,你的意思是这样吗?把存放从串口读取出来的、要拿来绘图的数据的变量定义成公 ...

控件都是公共属性,你能把定时器写在app内,那串口也可以,你要写到外面的话就需要一个地方存储数据,数据变量要是在类似全局,global可以实现,但是有app属性干嘛不用呢?你先把matlab重启试试,看看是不是软件问题。
你可按我的方法调试一下,不行就截个图我看看你是怎么定义函数的

hkt_guet 发表于 2022-5-9 18:37:31
1119093102 发表于 2022-5-9 15:31
控件都是公共属性,你能把定时器写在app内,那串口也可以,你要写到外面的话就需要一个地方存储数据,数据 ...

重启了,还是不行

hkt_guet 发表于 2022-5-9 18:38:12
本帖最后由 hkt_guet 于 2022-5-9 18:39 编辑
hkt_guet 发表于 2022-5-9 18:37
重启了,还是不行

代码图片
Z~]J1RHDS]AHZ_V~CP(DU)K.png
FSO}VBQCX(0M6HPS2PCN{~Q.png

hkt_guet 发表于 2022-5-9 18:41:34
1119093102 发表于 2022-5-9 15:31
控件都是公共属性,你能把定时器写在app内,那串口也可以,你要写到外面的话就需要一个地方存储数据,数据 ...

代码图片

Z~]J1RHDS]AHZ_V~CP(DU)K.png
FSO}VBQCX(0M6HPS2PCN{~Q.png

hkt_guet 发表于 2022-5-9 18:56:08
本帖最后由 hkt_guet 于 2022-5-9 19:00 编辑
1119093102 发表于 2022-5-9 15:31
控件都是公共属性,你能把定时器写在app内,那串口也可以,你要写到外面的话就需要一个地方存储数据,数据 ...

我这里还存在一个问题,我这里除了写了一个“打开串口”按键,还写了一个“关闭串口”按键,如图所见我在”打开串口“回调函数里把public变量ser创建了一个serial对象存放起来后,fopen(ser)打开了串口对象ser。但是我调用”关闭串口“的回调函数直接fclose(ser),软件提示我要先fopen创建一个文件标识符。我不是已经创建了ser吗?还是说在“打开串口”回调函数中创建完之后ser存放的串口对象消失了?为了关闭串口我的做法是,又重新创建了一个serial对象,fopen之后再fclose,这样才能关闭串口。
$~R21~N@ZXLPHG2]X27~S4N.png

hkt_guet 发表于 2022-5-9 21:36:15
本帖最后由 hkt_guet 于 2022-5-9 21:49 编辑
1119093102 发表于 2022-5-9 14:31
也还有方法,你可以建立公共属性,存储信息,在m文件中绘图,绘图时使用指定控件绘图的方式进行绘图,而且 ...

我刚刚学习了一下timer,我发现计时器对象没法一直运行,它必须设置TasksToExecute(调用定时器中断执行函数的次数)这样就没法实现我想一直显示串口数据的目的了,难道说在StopFcn(计时器终止函数)里再次start计时器?
已解决:后面用简单的显示函数确认了一下,其实可以一直运行,不过这样就即无法用stop(timer)停下来也无法用delete(timer)停下来了,只能靠重新运行了


1119093102 发表于 2022-5-10 09:26:49
本帖最后由 1119093102 于 2022-5-10 09:32 编辑
hkt_guet 发表于 2022-5-9 18:56
我这里还存在一个问题,我这里除了写了一个“打开串口”按键,还写了一个“关闭串口”按键,如图所见我在 ...

1、你的串口问题解决了吗?如果不行,将函数属性换成私有的试试,按道理应该都行的。建议:界面内的属性换成私有的,传递到外面用公有,好整理。
2、关闭串口问题。你逻辑有错误,instrfindall就是找到所有串口,delete就会删除所有串口,关闭~=删除,所以正确做法是delete放在界面的关闭函数去。非逻辑需要也不要放clear、clearvar这些函数浪费时间,所有控件函数运行完成自动清除。建议:串口对象、定时器对象界面启动时就建立,控件负责打开关闭就行,delete这种少用,一般是关闭界面或者try catch中用,要不然你都不知道啥问题。
3、定时器问题。上官网找对应matlab版本仔细看一下它的属性,中文的,有一个属性是控制运行模式,换一下模式就可以了,start、stop控制就行。
回复此楼

hkt_guet 发表于 2022-5-10 12:35:31
本帖最后由 hkt_guet 于 2022-5-10 13:02 编辑
1119093102 发表于 2022-5-10 09:26
1、你的串口问题解决了吗?如果不行,将函数属性换成私有的试试,按道理应该都行的。建议:界面内的属性换 ...

刚刚九点开了个会,回复晚了实在抱歉
感谢不厌其烦的指导,目前的情况:
1、串口回调函数成功了。一开始我把函数改成私有的,还是不行,于是我把存放串口对象的变量改成私有后成功调用了,但是绘图会出来的波形不知道为什么发生异常(平的),我估计是坐标轴刻度没调对
2、关于关闭串口的问题,我还没解决,但是关于delete和clear的知识我学到了,感谢大佬。确实(关闭~=删除),但是我之所以加上delete(instrfindall),是软件一开始提示我串口被占用了,所以不得不先删掉,目前我的关闭串口函数只有
[fprintf(app.ser,'c');%发送“停止发送”握手命令
fclose(app.ser);
delete(app.ser);]
改完之后能关闭,但是很慢才反应过来,我怀疑是跟串口中断回调冲突了
3、另外关于初始化就建立串口对象的问题,我一开始打算设置一个“查找串口”按键和一个“设定波特率”的按键,所以打算查找到之后再通过“打开串口”按键回调来创立串口对象;其次我之前也尝试过通过startfun来创建初始化对象,但是我在编译器上运行的时候发现中途关闭串口后再打开串口不知道为什么会发生后面的绘图的数据读取异常(存放数组的赋值语句左右维度不一致),所以我每次打开串口都重新建立一次对象
4、、关于timer能否不断循环的问题,我自己就是通过matlab的帮助手册学习的,我只能找到设定定时器运行的模式属性:ExecutionMode('singleShot'、'fixedRate'、'fixedDelay'、'fixedSpacing')
以及“TasksToExecute”(大于 0 的数字,指示计时器对象要执行 TimerFcn 回调的次数。使用 TasksToExecute 属性设置执行次数。要使用 TasksToExecute,您必须设置 ExecutionMode 以排定多个计时器回调事件的执行。)即我没找到可以设定一直循环的属性

1119093102 发表于 2022-5-10 14:10:11
hkt_guet 发表于 2022-5-10 12:35
刚刚九点开了个会,回复晚了实在抱歉
感谢不厌其烦的指导,目前的情况:
1、串口回调函数成功了。一开始我 ...

2、建立定时器动态识别串口或者界面手动输入串口号操作,打开串口时使用try catch,异常就fclose等初始化操作、提醒,串口助手使用串口的话mat会打不开。
3、我没遇见过,毕竟关闭串口我也会发送停止指令。你可以再次调试查看串口状态。使用动态存储方式,建立一个足够存储空间,存储不定长的数据。
4、使用fixedRate,TasksToExecute用不上吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

相关帖子
相关文章
热门教程
站长推荐
快速回复 返回顶部 返回列表