25年研电赛个人经历记录与经验总结_25电赛
昨天晚上终于是把所有需要提交的资料提交了,现在空了下来,趁热打铁写个总结吧,回顾一下这一个月的经历和取得的收获。
我们小队选择的是优利德的企业题的方向1,要求如下:
这个赛题与我的情况比较接近,也符合我的方向。(简单来说就是DDS,我本科的毕设也跟这个相关,但当时才接触FPGA,能力也有限,没有实际做出来)
这是一个自定义脉冲波算法的实现,还要有调制的功能。硬件方面呢不需要考虑,因为赛题要求是在优利德公司的硬件平台实现(我猜测这可能是为了给他们公司解决实际问题提供方案或者灵感)。发过来的就是一个信号发生器,需要自己拆除外壳才能进行代码的烧录。实际板子长这样。
采用的是FPGA+32的架构,32负责接收用户发送的指令,通过FMC与FPGA进行通信,FPGA将按键等值通过FMC传输至ARM进行处理,ARM再计算出波形所需参数再发送给FPGA。
我在本次竞赛中所完成的是脉冲算法的移植+ARM通信+上位机+系统测试。
下面总结本次竞赛:
一、编程思想:本次选的是优利德企业题,官方给我们提供了这个信号发生器的demo,作用是:一个可调频率的正弦波信号发生器,如下图。
这实际就是一个完整的产品,但demo只给出了其中的一部分,而按键、通信等等都是一个完整的框架,所以代码的参考意义非常大。
我始终认为,在我们这个领域,做一个项目,如果能寻找到一个公司的解决方案,那一定是最好的,性价比最高的。一个公司会从很多方面考虑这个项目,包括且不限于:可行性、性价比、可移植性。我这里主要是学一下编程思想。
以ARM端的FMC通信代码为例:
对于FMC通信的写操作,如果只是按照理论的话,下图这个就足够用了
考虑到实际,FPGA端接收数据是需要时间的,所以需要引入一个延时。如果是我来写,那么多半会是这样,直接在这个函数里面加一个延时。
下面来看下企业是怎么做的:
是再定义一个函数,再例化最开始定义的函数。
这样做是否是多此一举呢?
我最开始看代码的时候也是这个疑问。这个例子还只是非常简单的,只套了一层。在整个demo中,一层套一层的代码不在少数,之间还有很多是分布在不同的.c文件中,这使我最开始阅读代码的时候有些痛苦,一直在思考这样的写法是否有必要。
但是在我看完了代码准备自己编写的时候,我就明白了这种代码的好处:
清晰,结构层次分明。我作为一个接手这个工程的新人,能够在这种代码结构下,很清晰(但可能不快)找到我所需要的功能代码。
可更改性强。在我后续的编写中,有一个地方漏写了一些功能代码,这个功能在底层和顶层之间。而我所需要做的只是改变或者增加中间的一层函数,即可完成对应功能的改变,而且可以做到互不影响。
可拓展性强。回到之前的例子,这只是发送一个单字节的通信,那实现多字节的通信只需要再仿照这个格式再写一个代码即可。
所以我在后续的自己编写代码的过程中,也按照这样的风格编写。(个人感觉还不错)
这个编写代码的风格不止体现在ARM端,也体现在FPGA端,并且在FPGA端着重使用了模块化编程的思想,把每个功能模块区分得非常清楚。这里我就不展开讲了。
二、通信编程
通信对我来说一直是一道坎。每次做一个项目,可能是时间原因,也可能是能力原因,似乎从来没有把一个通信系统完整地搭建起来,最多只完成单独的通信验证,最后也没有深入。
这次比赛我们完整地完成了通信,完成了由串口屏发送数据到ARM端,ARM端通过FMC将数据发送至FPGA端。下面先说一下代码编写的经历。
最开始并没有想过使用串口屏,而是直接在信号发生器已有的框架上进行实现,但由于我们的个人能力实在有限,此前也没有接触过LVGL+RTOS,两者似乎又嵌套在一起进行编程,没有理清楚了按键值获取以及在如何计算的过程,再加上做到这里的时候离竞赛截止只有不到两个星期了,还有很多事情没有完成(最后调试也会花很多时间),所以最终决定使用串口屏进行上位机的数据发送。
我们首先是这样的:先编写一个非常简单的收发程序,验证是否可行。串口屏发送一个字节的数据,ARM端接收到了数据通过FMC发送个某个特定地址,最后通过ILA进行验证。
验证结果是可行。我们也理所应当觉得我们完成了通信的功能(这里埋个伏笔),所以直接开始了通信的编程。
由于我们所需要发送的数据实在是太多了,可以看一下我们的上位机
每一个选择框都要对应一个数据,这些数据有的是单字节,有的是多字节。如果不进行系统的编写,结果肯定是:数据是乱的,人也乱的。
所以我们专门制作了一个EXCEL表格
在这个表格中,详细写明了每个数据的信息,包括:帧头、位宽、地址、帧尾等。表格一共有4页,分别对应上图串口屏的四个界面,这样不管是编写上位机、ARM、FPGA,都可以清晰地编写。并且我们是小队分工,由我负责上位机数据发送+ARM端接收,另一位队员负责FPGA端接收并应用,根据这个表格我们也能在互相对照,确保最后合并的时候不容易出现问题。
最后我们完成了各自的代码编写,进行整合调试,不出意外的话意外发生了。
一开始进行通信,并没有成功。这也正常,毕竟一次就能成功的情况还是太靠经验和技术(显然我们还没这个水平哈哈哈),所以进行测试和找错误。
首先我们一起检查了各自写的代码,串口屏的编写软件是有调试功能的,我们通过调试,再一一对照ARM端和FPGA端,没有发现问题,这也得益于我们之前的表格。
既然看着像是代码没有问题,那就只有通过调试来判断是哪里有问题了。首先我想先验证ARM端是否与串口屏正常通信,虽然串口比较简单,但想着还是验证一下最好,所以我又写了一个串口收发程序进行验证,(最开始想直接通过debug来调试,但是实在没理解到底该如何调试串口,所以最后放弃了)。
ARM端没有问题,那就是ARM与FPGA之间的FMC通信有问题了。我们通过在FPGA端使用ILA进行观察,将触发条件设置为FMC接收有效位。最后我们终于发现了错误:
数据确实是按照我们需要的顺序发送的,并且FPGA端也接收到了,但问题是,并没有按照我们所希望的,对应数据发在对应地址上,而已在一个地址接收到了多个数据,所以这个地址的值一直在被不断替换。
这就让我们很纳闷了,为什么会出现这种情况呢?
后面我看到这个东西,想起来以前我在学习野火FPGA的串口收发的时候,似乎有相似之处
在发送了每位数据后,都按照系统时钟和波特率,进行了计数延时。
那对应到这里,就是我们没有对FMC发送的数据进行延时!
因为无论我们是最初进行通信测试时,还是现在发送数据,都是直接用的这个函数
我们最开始测试只发送了一位的数据,进行观察,现象能对。
但是当发送多个数据时,如果不延时,那一个地址就会接收到很多数据,结果当然就不对了。
所以我们将写操作的函数换成了带有延时的函数(第一点提到编写的便利性也在这里有所体现)
结果就正确了。
到这里通信大概就结束了,但最后还有一个问题是:在发送数据后,系统会莫名地通信卡住,似乎是卡在了ARM端的某个部分。
我们调试的时候是通过串口小助手代替串口屏发送数据,后面我们发现原因:由于我们的“发送”按键是直接发送这一页所需的所有数据,如下图
后面在测试中,我们发现分别只发送一个帧头帧尾,现象就正常。我们推测出是因为同时发送帧尾帧头的原因。所以在串口屏的发送端的帧尾帧头连接处,进行了一个10ms的延时,这个问题也就解决了(至于为何会出现这种情况,还没有排查清楚)。
三、经验累积
串口屏开发这个也没啥说的,之前接触过一点,只不过这次用了很多新函数,新东西。增加一个看似简单的让用户体验更好的功能,实际上可能会增加很多代码。这个还是得考经验积累。
在想给串口屏供电的时候,由于开发板没有额外引出引脚,只留有JTAG和串口通信的接口,但这些都是3.3V的,而串口屏供电是需要5V的,我想过这个供电的问题。我们最开始调试的时候,是用USB转TTL的那个模块,有一个5V的接口,共地之后也能勉强用,但是后面使用的,总是不稳定,甚至屏幕也一直在闪,多半是这个模块的输出电流不够的原因。所以得找一个供电方案。最开始我想的是淘宝买一个USB供电的模块,我外接到电脑进行供电,但总是不方便;后面又想买个锂电池供电的模块,放在板子里面,但这样又会带来一个续航的问题。
最后的最后,我把目光转移到了风扇那一块,我们以前也用过风扇,但大多都是12V的,我抱着试一下的心态用万用表测了一下电压,居然是5V的,能够供电。但是只有一个接口且用热熔胶密封了,不好取下来。我又没有板子的原理图,所以我瞄准了接口前方的那个电容,一般放在这里的会是一个去耦电容,多半也是5V的,我一,果然是5V,那供电的问题也就解决了(只不过风扇会因为分压变小,但也没办法了)。下图是示意图,此处焊的有点丑和危险,后面重新焊了一遍,但没拍照,就拿这个凑合吧。
还有一点要注意,这个电容可能也不是去耦电容,因为我最初在两边一端接5V,一段接GND,在通电前又拿万用表打了一遍,结果发现我以为的GND并没有与其他GND相连,到底是什么我没有原理图也不知道,为了保险起见,我还是将GND引到了一个已知的引脚。
最后总结一下吧,我们两个人应该前前后后用了一个月左右的时间,完成了这次研电赛的初赛。收获还是很大,可能有些地方忘写了,但先这样吧,后续结果出来了或者我空下来再想想是否需要添加其他东西