基于STM32F1挂载四个激光测距模块分时轮流工作

基于STM32F1挂载四个激光测距模块分时轮流工作(不通过IIC版本)

第一次写“回忆录”,请多多指教,阿里嘎多,那我下面就按自己做的来喽!

1.硬件资源:

正点原子的一块STM32F1精英版,四个激光测距模块,当然为了方便起见,我还买了stlink仿真器和lcd显示屏(价格多150元左右,当然大佬可以不买哦,譬如可以用串口看距离值啥的)

2.软件资源:

Keil uVision5 (用来敲代码控制硬件资源的平台),最好还有个C语言编译器如visual C++或Dev-C++等等,都行(主要是为了调试有些C程序,里面的有些逻辑可能忘了可以在这个C语言平台上先调试调试,免得经常烧板子……)

3.阅读资料:

1.买完32板子,正点原子送你一大堆关于32的文件(我就看了里面的“STM32F1开发指南(精英版)-库函数版本_V1.2 ” 和 “程序源码中的库函数版本” 这两份pdf……)。
2.买完激光测距模块,又是一堆关于激光测距模块的资料(我又就看了“模块使用说明”中的适用于对应板子的资料(我用的是“ATK-VL53L0X激光传感器模块使用说明( 战舰V3&精英板 )_AN1703A”)和“ATK-VL53L0X激光测距模块用户手册_V1.0” 这两份……)。
3.一本大一学的非计算机专业的C语言教材。
不过,这三份资料够用了。

4.开始入手一个激光模块:

*1.*学习商家给的激光测距的程序源码

首先,你会发现当你买完激光测距模块,商家给了你一堆资料,里面有一个很重要的文件——程序源码,双击,找到适合你板子的扩展实验,我这里用的是“标准库版本,适合精英STM32开发板”,继续双击,里面就有了已经编写好的代码,这时候你只需要把激光模块正确插到板子上,点击运行即可。你可以按照下图将板子与激光模块对应的端口用杜邦线连起来,或者也可以直接把激光模块的六个端口直接插到板子的右中侧(ATK MODULE),其实这两种方法连的位置是一样的,因为板子上的这六个端口是一一对应的,用的是同一个IO口,只是在电路板制作过程中通过内置的电路连在了一起(我啰嗦了……)

图一正点原子激光模块中给的文档里截的
当然这只能让一个激光测距模块工作。如果你有lcd显示屏,你会发现上面写了三个主要内容供你选择:校准,普通测量,中断测量。显然,刚刚把东西买到手的你或许不是很清楚这都是些啥,所以,现在开始,你需要:
1.认真阅读商家给的这个程序代码,代码有很多,但是我只用了其中一点点就够了(如果你不打算掌握其中的原理啥的话……可以参考我看的这几个):

图二:
基于STM32F1挂载四个激光测距模块分时轮流工作_第1张图片
基于STM32F1挂载四个激光测距模块分时轮流工作_第2张图片
上面加绿色圈圈的.c文件和对应的.h文件。

2.并且结合商家给的激光模块的资料,主要是“模块使用说明”中的适用于对应板子的资料(我用的是“ATK-VL53L0X激光传感器模块使用说明( 战舰V3&精英板 )_AN1703A”)和“ATK-VL53L0X激光测距模块用户手册_V1.0” 这两份。

3.你得边看代码、边看pdf、边多试试它怎么工作的,随便按按键,再看对应屏幕的显示,然后你会发现它的工作流程,从而也能大致知道程序代码的框架。

图三:
基于STM32F1挂载四个激光测距模块分时轮流工作_第3张图片

4.你得有一个比较好的C语言基础,有较好逻辑思路,因为我在改代码的时候经常得去翻翻当年的C语言教材,好几次没有思路不知道怎么改的时候就是在随意翻看C语言教材的时候迸发了灵感,你可以先看一下位运算、函数定义与调用(有参函数、无参函数、有输出函数、无输出函数)、循环结构、选择结构、宏定义、变量的作用域(如全局变量、局部变量,需要用到static)。

好了,在这个环节中,主要要搞清楚程序代码的大致结构,尤其是我圈出来的那一些,并且知道实现某部分功能对应了上面的哪部分圈圈即可,顺便又复习了一下C语言的那一些内容,然后就可以信心满满的进入下一个过程。

*2.*开始逐步修改原来的能控制单个模块工作的代码

从现在开始,我们得试着去修改代码,逐步修改成能让四个激光模块分时工作,并且获得这四个距离值。听上去是不是觉得又有点复杂?别急,我们分几步走。

1.学会分配IO口,自己试着把原先图一中的IO口替换成其他IO口。

首先你得在我刚刚圈出来的几个.c和.h文件中找找哪边需要用到IO口,这里推荐看一下买32板子送的资料

2.选择其中一种测量方式进行深入研究。

这里我选了普通测量(vl53l0x_general_test)模式,在图三中可以进一步发现,这两种测量模式(中断测量和普通测量)是完全独立、互不影响的,我甚至在最后把用于中断测量的那个端口(INT)压根没接,普通测量模式依旧正常运行……

图四

你需要仔细研究vl53l0x_gen.c文件与vl53l0x.c文件和main.c文件以及这三个文件对应的.h文件之间的关系,并且大致知道这个工作流程,即main.c文件中的vl53l0x_test()是怎么到了vl53l0x.c文件,以及vl53l0x.c文件中的l53l0x_general_test(&vl53l0x_dev)又是怎么到了vl53l0x_gen.c文件(emmm我好像已经把最主要的说了……)。

还有你得大致知道这些文件中一个又一个函数大致起的啥作用,譬如vl53l0x_start_single_test()函数是在测一次距离,由于这个函数被包含在了while(1)这个无限循环函数中,所以才会导致你之前可以在显示屏上看到的连续测量。

你当然还得知道测量值放在哪个参数中(Distance_data),因为之后的操作都是围绕这个测量值展开的。

(选中某个被用到的函数名,双击,右键,多使用Go To Definition Of……和Go To Reference To……来查看函数的前世今生)

3.学会把测量值Distance_data值返回并能使用

我是把所有距离最终都返回到了主函数并在主函数中进行了使用,如图五:

图五:
基于STM32F1挂载四个激光测距模块分时轮流工作_第4张图片
文末有我写的代码,大家如果有需要的话可以下载 ^ _ ^

由于正点原子给的关于激光测距模块的程序源码中关于Distance_data的引用都是直接输出在lcd屏幕上,而没有对其数值进行引用(指没有拿这个距离值去做其他事情:譬如距离值大于XX时候led灯闪烁啥的,当然,如果是要引用一个激光模块使用它的距离值去做其他事情肯定不复杂,只要在出现Distance_data的地方引用一下就好了,但是,如果是四个激光模块数据,为了可以重复引用用于测量的那个函数,不如想办法把这个距离值像图五那样返回到主函数去使用……)

所以,如果你要像我这样做,你亟待解决的问题是:把好多void 函数名(void)或者void 函数名(形参) 分别转变为 vu16 函数名(void)或者vu16 函数名(形参),vu16是返回值的数值类型。最终一步步把这个距离Distance_data返回到主函数去使用。
为了检验是否返回成功,你可以在主函数写个if语句,譬如当Distance_data>40,红灯闪烁,else,绿灯闪烁。

好啦,这部分就交给你自己喽,相信你手头有一本C语言教材的话,这个问题是不难解决哒!

4.选择其中一种模式,让它能够自动循环测量

你是不是发现,每次只能测一个值了,或许你可以把这个值让它显示在初始界面上(也就是在main.c文件的 while(1) 中加一行LCD_ShowxNum(110,140+110,Distance_data0,4,16,0);
而且初始界面一直在闪烁,但是内容一样,它还需要你按按键来选择工作模式,但是按键有时候似乎不那么灵敏了,你可以想想为啥?

这样反倒有点不大方便了,所以,为了让它能自动测量,你可以选择其中某种模式,譬如这里我选了“普通测量”模式,然后在它扫描哪个按键按下的地方(有两处,用的是case语句)让某个按键按下的代码恒成立,这样它就不需要等你按下按键再去执行测量啦!

如果你感觉有些你想要看到的内容闪去得太快,你还可以在任意你想延时的地方加一堆delay_ms( )

至此,你应该已经掌握了
1.功能和程序代码之间的对应关系(刚刚那几个圈圈)
2.如何分配IO端口
3.如果让距离值返回并使用
4.如何让某种测量模式自动循环进行

—————————————————————————————————

5.逐步修改程序让两个激光模块分时自动循环工作:

恭喜你来到第五个步骤,你离成功已经很近了

在这个环节里,我们只需要解决一个问题,就是在原本main.c函数中红圈2的基础上多一个标志flag,如红圈3,这个flag只有一个作用,那就是选择端口。

图六基于STM32F1挂载四个激光测距模块分时轮流工作_第5张图片
如图六,很容易猜到,flag0代表了第一个激光模块,由于函数vl53l0x_test()输入的参数是flag0,所以相当于第一个激光模块工作,这个模块对应的IO口进行配置,类似,如输入的是flag1,则第二个激光模块工作,对应IO口配置,而和第一个激光模块的IO口完全无关。类似于这样:

图七:
基于STM32F1挂载四个激光测距模块分时轮流工作_第6张图片
所以你需要合理的将main.c中的flag引入到你需要的地方
如果这一步遇到了困难,回去可以再翻翻C语言教材哦(我说的就是我……),里面那个static变量超级好用,或者你也可以用到!
是不是很通俗易懂?嘿嘿嘿

对了,很重要的一点注意啦:
虽然刚刚提过,但是小伙伴们可能没有注意哦,如果你选择了普通测量模式(vl53l0x_general_test),并且让它能自动循环工作了,那么其实你只用了图三右边三个.c文件中的第三个(vl53l0x.gen.c),前两个其实都没用,所以你可以完全不必在意前两个.c及其.h文件中的端口配置,只需要修改第三个.c及.h文件中的端口配置即可。当然,不管你选的是哪种测量模式,图三左边那个vl53l0x.c文件和对应的.h文件都还是需要改的……

所以,狠心点,如果你选了普通测量模式,直接把激光测距模块INT口的那根线压根别连了。

还有一个很重要的方法可以让部分代码不使用flag:
当你在加入flag的时候,你会发现有些在.h文件中的宏定义好烦哦,它常常把某个端口名定义通过宏定义定义为另一个名字来提高代码的可读性,譬如:

图八:
基于STM32F1挂载四个激光测距模块分时轮流工作_第7张图片但是如何在宏定义中使用flag还是有点困难的,所以我突发奇想……不使用宏定义了,直接端口拿来用,要选择也去.c文件中选择,所以我这样干了:
1.首先查找这些宏定义都用在哪里,是在干甚么用:
Ctrl+F,弹出用于 查找Find、替换Replace 的对话框,然后你可以查查他们用在哪,怎么用,拿笔记一下,并找找规律,然后才能想出对应的方法。

2.通过寻找共性来方便修改
譬如图八中的VL_IIC_SCL来代替的PBout(11),查找后你会发现,它只用来赋值0或1,即让这个端口显示高电平或低电平,所以如果这里你觉得用flag有点麻烦,不如VL_IIC_SCL做函数名,里面让所有你要用到的端口都高电平或低电平……如图九:

图九:
基于STM32F1挂载四个激光测距模块分时轮流工作_第8张图片
3.把.h文件中不需要的地方注释掉,别忘了

至此,你应该 完全 知道了如何实现两个激光模块分时工作的方法,并且在你自己的不断努力和反复修改、调试之后,实现了让两个激光模块分时自动循环工作,并且能把两个距离值都正确返回到主函数并可以被调用,类似于图六。

6.增加选择语句内容,让四个激光模块分时自动循环工作:

恭喜恭喜,你已经完成了95per的内容,在有了成功编写两个激光模块的基础之后,你只要再半个小时,就可以把其他两个模块装上去啦!
即:
1.分配引脚
这是我的,大家当然可以都不一样,但自己配置时推荐使用独立IO口:
模块一:SCL—PB11 ;SDA—PB10 ;XSH—PA15
模块二:SCL—PA6 ;SDA—PA5 ;XSH—PD12
模块三:SCL—PF1 ;SDA—PF0 ;XSH—PD13
模块四:SCL—PE2 ;SDA—PE1 ;XSH—PE0
每个模块都需要各自连VCC(5V或3.3V都可),GND,INT如果你选的是普通测量,可以不连。
2.代码增加选择内容
说白了就是像case语句后面多两选择内容等一些重复操作

这部分内容相信你可以自己做出来的,如果做不出来,那再回过去仔细看看步骤五(让两个激光模块工作的方法)

7.我的代码和板子工作视频

我好像还不会把视频、文件啥的直接上传……抱拳 抱拳
大家如果需要,只能给大家提供百度网盘啦
网盘链接:
链接:https://pan.baidu.com/s/1cy-7hMbe-qO4nLNvhwwhWQ
提取码:GHQQ

你可能感兴趣的:(嵌入式,嵌入式,c语言,经验分享)