打印
[LKS32 软件]

LKS_SCOPE上位机如何使用串口连接模式

[复制链接]
142|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 ZDRenlc 于 2025-1-5 13:48 编辑

#申请原创#LKS_SCOPE使用串口的连接方式好像用的人很少,也没怎么在网上看到有人发教程帖。本来Jlink挺方便的,但是没办法领导要求使用串口连接。我也是折腾了老半天和售后工程师问了好几次,才最终实现功能。发个帖留个痕迹,让和我一样的小白少踩一点坑。

一、下位机配置
连接方式:串口连接
1、首先在工程文件中添加以下几个.c文件和串口适配,如下图:
(这几个文件,在官网上下载凌鸥lks_scope上位机的软件包解压后。里面会有一个08x的示例工程,直接从示例工程里拷出来用就行。)

2、找到想要连接的串口定义处,记下波特率
(串口的连接一定要和自己定义的一致,这里不作赘述)

3、在串口中断处理程序中添加如下代码并添加头文件comdata.h,然后在hardware_init函数中打开设置好串口中断优先级并打开中断。
(中断处理函数中的这段代码,其实就是把串口接收到的数据打包起来,等到收满一包数据后comdata.c里面会有函数进行处理,后面会对此代码进行分析)

4、在主函数的循环里添加CheckRecv()这句代码并添加头文件comdata.h,另外由于暂时用不到任务调度函数Task_Scheduler()所以先将其注释掉并添加一个变量,以方便在上位机中观察变量的变化状态。
CheckRecv()这句代码是必须添加的,不添加的话串口和上位机是连接不上的,后续分析代码时会解释为什么。另外这里是暂时CheckRecv()放在主循环里,实际后面测试放在中断里也是可以的。


二、上位机使用教程
1、打开LKS_SCOPE上位机软件,点击左下角图标添加项目工程的.axf文件。此时整个工程的所有全局变量都会添加进来,如下图:

2、双击左侧数值窗口、曲线窗口和参数调整窗口(没有的话就自己右键新建然后双击),此时右侧会弹出相应的显示界面,如下图:

3、在搜索框中搜索自己想要查看的变量名,这里搜索刚刚在主函数中添加的变量test_speed_set,然后拖动至右侧的数值窗口和参数调整窗口,见下图:

4、在连接设置中选择正确的串口端口,波特率和程序中设置一致,如下图:

5、点击启动连接,此时如果串口连接成功的话,左下角会显示串口打开,如下图:

6、此时曲线窗口已经有变量test_speed_set的变化曲线开始显示了,数值窗口也显示test_speed_set变量在迅速的变化。我们在参数调整窗口中拖动设定值的光标,可以看到曲线窗口中变量的变化曲线也在改变。
到此为止,利用串口和LKS_SCOPE上位机的连接算是成功实现了。


三、错误处理
如果按照上述步骤把下位机配置完后,打开上位机软件点击启动连接,却没法实现相应的功能,可以通过下面的方法验证串口和上位机是否连通。
1、打开串口调试助手,选择相应端口和波特率。参考示例发送报文,看看MCU有没有正确应答。(示例报文来自官方的lksscope使用说明.pdf)

于是向串口调试助手依次发送68、01、06、29、01、0C、00、00、20、04,可以看到此时串口调试助手收到了MCU的应答信息:68 01 05 64 01 09 7D 11 00,如下图:
我们通过串口调试助手向MCU发送的一帧报文表示:读0x2000000C开始的4字节内存数据。MCU发回的一帧报文表示:响应帧序号为01的读请求,返回四字节内存数据09 7D 11 00。

2、有应答说明串口是通的,此时看看是不是上位机连接配置里面端口号和波特率选择出错。没有应答说明串口不通,要么是程序中对串口的配置不对(引脚、波特率、中断等),要么是硬件接线不对。


四、补充说明
1、由于我们使用的是串口连接上位机,所以RTT命令行和RTT数据这两个功能均无法使用,这两个功能仅在使用JLINK连接方式下才能激活。

2、电机控制这个功能一直没测试过,这里测试一下。双击左侧选项,右下角弹出电机控制窗口,选择参数设置-关联变量,将test_speed_set变量和速度设定这个电机参数关联在一起。启动连接后可以看到电机控制窗口的速度码表发生变化,如下图:
上面的测试说明电机控制这个功能和JLINK连接没有关系,所以串口连接下也可以正常使用。另外数值都是随便设置的仅作测试,所以可能会有不合理的地方。


五、代码分析
这里对凌鸥官方提供的串口连接上位机的适配代码做简要分析,并解释为什么必须要在主函数的循环里添加CheckRecv()这句代码,串口和上位机才能正常连接。

1、首先rtt_debug.h就不用过多关心了,它实际上应该是和RTT库的代码相配合的,和串口功能实际并不相关。可以看到这个文件实现的功能就是把SEGGER_RTT_printf()重定义到PRINTF()函数上了,这样打印调试信息只需使用PRINTF()来打印即可。

2、主要分析comdata.h和comdata.c里的函数。
打开comdata.h可以看到里面的函数很多,但实际只需要关心AddRecv()和CheckRecv()这两个函数。其它的函数都是被CheckRecv()调用,用来解析数据包的。

AddRecv()这个函数是放在串口中断处理函数下面的。转到它的函数定义,可以看到这个函数实现的功能是:判断接收到的数据是不是包头、判断接收数据长度是不是超出最大限度和接收数据。

但是看到这里又会疑问了,这里只判断包头那怎么知道什么时候才算接收到一包完整的数据包?这时想起还有一个函数CheckRecv()没看,转到它的定义。
可以看到这个函数会在最开始一直判断接收的数据包长度是否满足最低要求,不满足便会一直卡在这里,直至接收到符合最低长度要求的报文数据,然后才开始进行报文解析。
(上位机之所以能实现对MCU中变量的读取和修改,就是因为上位机在不断地向MCU发送报文信息,所以MCU中不添加CheckRecv()这个函数,就意味着上位机通过串口发来的指令消息根本没人处理,自然上位机就无法和MCU进行沟通了,这便是必须添加CheckRecv()这句代码的原因

这里也不用担心如果我的报文数据长11,但是刚输入完10个数据就开始处理了,会不会出错。因为发送的报文中会标明数据的长度,这边代码会进行核实,另外MCU这边也有CRC校验,双重保障一般不会出问题。


六、问题及探究
1、CheckRecv()这个函数由于有判断最短报文长度的要求,所以需要一直循环调用,这种阻塞式编程是不是不太好?是不是还有优化的可能?
CheckRecv()这个函数最大的妨碍点在于需要不断判断所接收报文长度是否达到要求。但是想了一下接收才需要考虑中断过长会不会导致数据丢失,而CheckRecv()这个函数是直接从数组中取出数据进行解析的,所以不用考虑数据丢失的问题。它需要考虑的点在于是否有必要一直卡在那里等这个函数判断完接收的数据长度是否符合最低要求。想了一下这个长度判断快一点还是慢一点影响其实并不大,所以它应该是可以被放进中断的,于是我又做了以下测试。
把主函数中的任务调度函数Task_Scheduler()取消注释,然后将CheckRecv()这个函数放在10ms时间,任务调度下。
此时打开上位机数值窗口、曲线窗口和参数调节窗口,可以看到变量有在不断变化。并且调节设定值光标也可以改变变量值,曲线也会跟着发生相应的变化。
也就是说把CheckRecv()这个函数放在中断里,也不影响MCU和上位机的沟通。

2、虽然经过测试CheckRecv()这个函数即使不放在循环里也能实现功能。但是不代表把它放哪都行,至少要放在很快的中断里。因为CheckRecv()执行过慢的话,肯定会影响对上位机报文指令的解析速度,这样可能会导致上位机发出多条指令却收不到应答而出现一些问题。

3、串口的传输速率是有限制的,所以说如果变量变化的太快,快到比串口的传输速度还快的程度。那么此时数据就不能及时上传至上位机,可能会出现上位机数据显示失真的情况。(具体变量变化多快会导致错误也没测算,但是有这种潜在的可能。)


七、小结
1、移植官方提供的串口连接上位机的代码,核心只要配置好AddRecv()和CheckRecv()这两个函数即可。AddRecv()放到串口接收中断中负责接收报文信息,CheckRecv()放到持续调用的地方负责解析报文和应答上位机。

2、上位机的串口连接成功的提示为啥要放在左下角,感觉应该和右下角的提示框全部整合在一起,放在左下角一直没注意到。


3、有时候点击退出程序就会卡死在这个界面上,这个问题的触发频率还挺高的,不知道是什么BUG。



使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

4

帖子

0

粉丝