毕设项目《基于STM32的智能乒乓球捡球小车的设计与实现》从零开始过程笔记

毕设项目《基于STM32的智能乒乓球捡球小车的设计与实现》从零开始过程笔记

小车实物

小车实物
前言
本文是后来记录而写,如有不足之处,欢迎批评指正。
如果您觉得文章写得不错,欢迎一键三连。(比心 orz)

目录

零、资料下载

正点原子资料:

参考文章:(115条消息) 学习stm32f103c8t6,如何从正点原子官网下载资料及资料使用_quxuexi的博客-CSDN博客

其他资料:

链接:https://pan.baidu.com/s/1u_wxi-8H6zIsLmtEf_jZqw?pwd=2023
提取码:2023

资料说明:感谢正点原子提供的资料。正点原子的资料讲解的很细致很全面,营养价值很高,比本文档重要的多。其他资料主要是对于正点原子资料的补充。

一、硬件购买与学习

1. 硬件清单

说明:

  1. 元件价格统计时间为2023.5.27,实际购买可能会遇到小幅改变。
  2. 单价为在淘宝上买一个时的花费,其中包含可能的运费。
  3. 除了这里列出来的零件,还需要剪刀、螺丝刀、电脑。(电烙铁和焊锡丝最好有,没有也行)
序号 元件名 数量 单价 总价
1 双层小车底盘 1个 29.8 29.8
2 L298N芯片 电机驱动模块 1个 6.8 6.8
3 3节12V锂电池 1个 30 30
4 STM32F103C8T6最小系统板 1个 15.4 15.4
5 Maix Dock开发板 1个 205 205
6 HC-05 蓝牙模块 1个 12.2 12.2
7 红外避障模块 3个 5.1 7.8
8 PWLINK2 Lite 调试下载器 1个 9.9 9.9
9 MB-102面包板 1个 3.6 3.6
10 公对公、母对母、公对母杜邦线,长20cm各一排 1套 10.68 10.68
11 六角铜柱M3(20个) 1包 2.8 2.8
12 铜丝杆黄铜通丝牙条全牙螺杆牙棒全螺纹 2根 2.3 4.6
13 不锈钢六角螺母304(20粒) 1包 1.72 1.72
14 不锈钢三角支架 1个 3.5 3.5
15 发光二极管(5mm,50只) 1包 4.8 4.8
16 镀锌垫片 半斤 4.5 4.5
17 尼龙扎带 1包 1.2 1.2
总计 342.1

2. 各元件购买介绍

如果想要买元件,我推荐是直接复制文件里的元件名去淘宝搜,然后找找价格适当,评价良好的进行购买。文档里的购买链接只是我当时个人购买的链接,现在不一定还是价格优秀,评价良好,所以鼓励大家科学网购。

交易快照的作用最重要的是”颜色分类“那一栏,那栏说明了买的东西的名称,型号等重要参数,是到商家店里购买时重要参考选项。

1). 双层小车底盘

  1. 元件实物:

    小车底座

  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):智能小车套件51单片机/STM32/UNO开发板寻迹避障遥控机器人底盘-淘宝网 (taobao.com)

  3. 交易快照:image-20230527143403372

  4. 元件作用:见淘宝商品页面“宝贝详情”

  5. 使用说明:见淘宝商品页面“宝贝详情”

  6. 学习资料:见淘宝商品页面“宝贝详情”

  7. 个人说明:这个元件没啥好学的,就是组装一下,注意一下电机的正负极,以及能接受的电源的电压。

2). L298N芯片 电机驱动模块

  1. 元件实物:L298N实物图
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):L298N芯片 电机驱动板模块 步进直流减速智能小车机器人 单片机红-tmall.com天猫
  3. 交易快照:image-20230527144315811
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:注意此元件使用哪种供电方式12V或5V供电,注意跳线帽是否应该拔掉,此款电机驱动可以驱动两台电机。

3). 3节12V锂电池

  1. 元件实物:12V锂电池
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):智能小车18650充电锂电池组12V大容量LED灯带路由器光猫酒吧灯7.4-淘宝网 (taobao.com)
  3. 交易快照:image-20230527144751517
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:做项目到了后期感觉可以用更为常见的充电宝代替这个锂电池,这样还能省下一笔经费,但是两者的供电方式不同,若想用充电宝达到锂电池这样使用端子线供电,还需要购买一个“USB公头转XH2.54-2P端子线”

4). STM32F103C8T6最小系统板

  1. 元件实物:stm32
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):STM32F103C8T6核心板 C6T6 STM32开发板ARM单片机最小系统实验板-淘宝网 (taobao.com)
  3. 交易快照:image-20230527145417024
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:我买的是焊接好排针的,这虽然比不焊接的贵一点,但省事。注意烧录代码时一定给板子断电。工作时,不用的引脚千万别瞎接线,烧录的那四个引脚也别接任何线,其中的GND也别用,如果板子两侧的GND引脚不够用了,就用根杜邦线或跳线将GND接到面包板上,增加GND的数量。它的供电方式可以使用5V的电源接到他的5V的那个引脚,也可以使用Micro口供电。使用时也要注意那两个跳线帽的使用,是否要拔掉。

5). Maix Dock开发板 (不是MAIX-II M2dock)

  1. 元件实物:k210M1W开发板

  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):Sipeed Maix Dock K210 AI+lOT 深度学习 视觉 开发板-淘宝网 (taobao.com)

  3. 交易快照:image-20230527150216403

  4. 元件作用:见淘宝商品页面“宝贝详情”

  5. 使用说明:见淘宝商品页面“宝贝详情”

  6. 学习资料:见淘宝商品页面“宝贝详情”

  7. 个人说明:我只使用它识别乒乓球,然后经过它一系列处理之后(通过编写内部程序实现),通过串口与STM32通信。他的供电方式我使用的时Micro口供电,一开始我也是用的5V的引脚给它供电,可是后来发现这样供电,工作一会儿后,芯片莫名断电,无法正常工作,索性后来直接用充电宝给它通过Micro口供电。

  8. 关于为什么选择这款开发板呢?过程有点戏剧性,先看一下MAIX的一些产品介绍:Sipeed 开源产品速览 - Sipeed Wiki 。我当时也在疑惑选哪一个,一开始我最先想到的使用openMV来识别乒乓球,后来问了老师说毕设不报销,而且openMV又那么贵(动辄300+,500+),于是就想换个板子,就偶然看到有人说k210可以平替openmv,而且算力还高,所以就想买k210。MAIX系列的产品使用k210的也就是Maix-I系列的,于是当时就想着在Maix-I系列里选一个,当时主要考虑了Sipeed Maix BitSipeed Maix Bit RISC-V AI+lOT K210 直插面包板 开发板 套件-淘宝网 (taobao.com)和Sipeed Maix DockSipeed Maix Dock K210 AI+lOT 深度学习 视觉 开发板-淘宝网 (taobao.com),两者价格差不多,都是185r左右,后来偶然看到一篇文章:(113条消息) MaixII-Dock(v831)学习笔记——初识v831_纸箱里的猫咪的博客-CSDN博客 它说Dock好,于是就买了Sipeed Maix Dock。当时没看清楚,它说的其实是MaixII-Dock (v831) ,哎,误打误撞了属于是。

    在购买链接里有M1 Dock和M1W Dock,他俩的区别是M1W Dock比M1 Dock多了个WIFI模块,所以价格贵了15r。

6). HC-05 蓝牙模块

  1. 元件实物:image-20230529113159299

  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):带底板HC-05主从机一体蓝牙模块 无线串口透传通讯 HC-05蓝牙模块-淘宝网 (taobao.com)

  3. 交易快照:image-20230527150618703

  4. 元件作用:见淘宝商品页面“宝贝详情”

  5. 使用说明:见淘宝商品页面“宝贝详情”

  6. 学习资料:见淘宝商品页面“宝贝详情”

  7. 个人说明:HC-05有三种型号兼容版、原装版、实惠版。实惠版最便宜,但只能作为从机被其他蓝牙设备连接,不能主动连接其他蓝夜设备,这就是单从模式;兼容版、原装版都可以作为主机连接其他蓝牙设备,也可以作为从机被其他蓝牙设备连接,就是主从模式,区别是兼容版比原装版便宜,因为它不是正版元件。

    HC-05是一款蓝牙串口模块,常用于无线通信。兼容版和原装版的区别在于:

    1. 原装版是指由HC-05的原始生产厂家生产的模块,兼容版则是由其他厂家生产的兼容模块。

    2. 在功能上,原装版和兼容版没有区别,都可以实现蓝牙串口通信。

    3. 在外观上,原装版和兼容版可能存在一些差异,如尺寸、颜色等。

    4. 在价格上,兼容版通常比原装版便宜一些。

    需要注意的是,由于兼容版是由其他厂家生产的,其质量和稳定性可能会有所不同,因此在选择时需要注意选择正规厂家的产品。

    如果蓝牙只是用来被动等待其他设别连接,可以选择实惠版,本项目可以选择购买实惠版。

    使用之前需要对这个元件进行配置,进入AT模式配置,设置波特率啥的。

7). 红外避障模块

  1. 元件实物:红外避障
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):红外壁障模块/避障小车避障传感器/黑白线识别 距离可调 光电开关-淘宝网 (taobao.com)
  3. 交易快照:image-20230527150757928
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:上面的蓝色正方体里有个十字螺丝,旋转这个可以调节红外检测距离,就是元件的精准度可能不大高,毕竟便宜。

8). PWLINK2 Lite 调试下载器

  1. 元件实物:PWLINK2 Lite
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):PowerWriter PWLINK2创芯工坊仿真STM32烧录stlink调试GD32下载器-tmall.com天猫
  3. 交易快照:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9tXZMr06-1688999686627)(https://article.biliimg.com/bfs/article/ad182f8fe94afed9213f7b832730368d9f476a66.png)]
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:我买的时候还是9.9元,现在涨价了竟然。不过找找那个旗舰店还是9.9元。烧录代码时需要在keil中的魔术棒里配置一些参数。在蓝牙串口调试时,因为蓝牙需要接5v的VCC,PWlink lite的VCC支持两种输出电压,3.3V和5V,默认是3.3V的输出,若想让它输出5V,可以在它配套的这个烧录软件里设置。image-20230527151618104

9). MB-102面包板

  1. 元件实物:面包板

  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):MB-102面包板 65条杜邦线830孔开发板电源模块电子DIY实验套件400-tmall.com天猫

  3. 交易快照:image-20230527151658578

  4. 元件作用:见淘宝商品页面“宝贝详情”

  5. 使用说明:见淘宝商品页面“宝贝详情”

  6. 学习资料:见淘宝商品页面“宝贝详情”

  7. 个人说明:这种面包板可以将STM32F103C8T6直接插进去,千万别买下图这种,我一开始买的就是这种,但是插不进去STM32,后询问客服,他说这种板子是用来插杜邦线和跳线的:image-20230527152347599

  8. 洞洞板电路板

    洞洞板电路板与面包板区别?

    洞洞板电路板和面包板都是电子原型设计中常用的工具。

    洞洞板电路板是一种基于玻璃纤维板的电路板,它的表面有许多小孔,可以通过这些小孔将电子元件插入到电路板上,并通过焊接等方式进行连接。洞洞板电路板适用于需要高密度布线的电路设计,但需要手工焊接,制作周期较长。

    面包板是一种基于塑料板的电路板,它的表面有许多小孔,可以通过这些小孔将电子元件插入到电路板上,并通过插座等方式进行连接。面包板适用于快速原型设计,不需要焊接,制作周期较短。

    总的来说,洞洞板电路板适用于需要高密度布线的电路设计,而面包板适用于快速原型设计。

    洞洞板电路板

10). 公对公、母对母、公对母杜邦线,长20cm各一排

  1. 元件实物:杜邦线
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):杜邦线母对母公对母公对公40P彩色排线连接线公母线10/30/20/40CM-tmall.com天猫
  3. 交易快照:image-20230528112449039
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:20cm长的足够用了,使用时不用撕成一根一根地用,例如,接蓝牙模块时,需要四根杜邦线,可以一次从上面撕下四根,这样不会显得很乱。

11). 六角铜柱M3(20个)

  1. 元件实物:六角铜柱
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):六角铜柱M3M4M5M6单头铜螺柱机箱主板螺丝柱铜柱隔离柱支柱M2M2.5-tmall.com天猫
  3. 交易快照:image-20230528112531466
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:六角铜柱用来固定其他元件,因为小车上钻的孔是3mm,所以就买的3mm。

12). 铜丝杆黄铜通丝牙条全牙螺杆牙棒全螺纹

  1. 元件实物:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QyDwiNpt-1688999686634)(C:/Users/周鑫/Documents/study 学习/计算机科学与技术(嵌入式)]四年学习资料/大四/毕业设计/2023毕业设计模板(供参考)/毕业设计材料/毕业论文插入图片/元件实物图/铜丝杆.jpg)
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):铜丝杆黄铜通丝牙条全牙螺杆牙棒全螺纹螺柱M3M4M5M6M8M10M12M14-淘宝网 (taobao.com)
  3. 交易快照:image-20230528112851735
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:铜丝杆一根用来作为小车滚筒地中心轴,另一根用来绑在小车上,当时是因为快递原因,买了两根。只买一根也行,就是另一端如何固定在小车上需要另想办法了。

13). 不锈钢六角螺母304(20粒)

  1. 元件实物:不锈钢六角螺母304
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):304 316不锈钢六角螺母螺栓螺帽螺丝帽大全M3M4M5M6M8M10M12M33-tmall.com天猫
  3. 交易快照:image-20230528113042960
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:六角螺母主要用在滚筒上,用来固定两边的透明亚克力板子。

14). 不锈钢三角支架

  1. 元件实物:不锈钢三角支架
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):加厚不锈钢三角支架置物架墙上支撑架隔板托架九比架搁板壁挂书架-淘宝网 (taobao.com)
  3. 交易快照:image-20230528113410363
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:支撑架的购买有点意外,最初是想买支撑架作为滚筒支架的,后来定制了亚克力的滚筒支架,就没用这个铁的支架。但是当我使用到Maix Dock识别乒乓球时,需要将摄像头放的高一点,就拿这个支架架起的摄像头。

15). 发光二极管(5mm,50只)

  1. 元件实物:发光二极管
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):发光二极管_淘宝搜索 (taobao.com)
  3. 交易快照:image-20230528114234638
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:这个元件可以用来做呼吸灯的实验,也可以检测某个电源引脚是否有电。千万注意,别用5v的电压接发光二极管,一接准烧坏,你可以看到它只闪一下,然后就灭了,然后这个二极管就永远地灭了。我最初买发光二极管主要是想测试某个GPIO口是否会输出高电平,主要是连接电机驱动的那四根线。STM32的某些GPIO口容易被我玩坏,我需要这样的方法来检测那个引脚是不是好的。

16). 镀锌垫片

  1. 元件实物:镀锌垫片
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):镀锌垫片_淘宝搜索 (taobao.com)
  3. 交易快照:image-20230528115336015
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:镀锌垫片也是用来固定两个透明亚克力板的,一开始我还用可乐瓶盖做了些垫片,但发现,塑料做的垫片容易变形,影响滚筒的形状,于是就买了坚硬的铁质垫片。

17). 尼龙扎带

  1. 元件实物:尼龙扎带
  2. 购买链接(可淘宝自行根据元件名搜索,综合考虑价格和销量):3*100透明扎带 尼龙扎带4×200 塑料卡扣捆绑条强力大号累死狗-淘宝网 (taobao.com)
  3. 交易快照:image-20230528174833282
  4. 元件作用:见淘宝商品页面“宝贝详情”
  5. 使用说明:见淘宝商品页面“宝贝详情”
  6. 学习资料:见淘宝商品页面“宝贝详情”
  7. 个人说明:扎带主要用来固定一些零件,属于一次性用品。

3. 各元件的资料获取与学习

1). 双层小车底盘

从小车组装开始,在组装之前可以先下载《3. 各元件的资料获取与学习.资料连接》里”附件1-小车底座安装说明文档.pdf“大致看一下小车的安装步骤,但是先不要动手安装,因为电机还没接线,组装好后电机不方便焊接铜线。焊接的铜线最好长一点,用20cm的公对公杜邦线就行。

我们只买了一个电机驱动,它只能驱动俩电机,所以我们需要把同侧的电机串联,同步工作。

给电机焊接铜线:

直流电机串联

没有电烙铁和焊锡可以购买,或者直接将铜丝系在电机的铜孔里,不过这样存在安全隐患,最好外面包上一层绝缘胶带。

给电机接好铜线后就开始组装小车底座。

底座电机接线

至此小车底座部分搞定。

2). L298N芯片 电机驱动模块

该元件的学习资料从

淘宝:L298N电机驱动板模块 步进电机 智能车 机器人-tmall.com天猫

csdn:(113条消息) L298N、电机、单片机的线路连接(51、stm32程序)_l298n电机驱动模块与单片机连接_霄耀在努力的博客-CSDN博客

B站:L298N模块驱动直流电机详细说明,以及PWM调速代码解析_哔哩哔哩_bilibili

关于L298N的电路原理图可以从《3. 各元件的资料获取与学习.资料连接》里下载

image-20230601204256018

这里我们只要关心倒数第二句话。

“模块可以使用内置的78M05通过驱动电源部分取电工作,但是为了避免稳压芯片损坏,当使用大于12V驱动电压的时候,请使用外置的5V逻辑供电。“

L298N是一款双H桥驱动芯片,它可以控制直流电机或步进电机的转动方向和速度。而78M05则是一款稳压器芯片,它可以将输入电压稳定输出为5V的直流电压。在L298N中,78M05的作用是为芯片提供稳定的5V电源,以保证芯片正常工作。同时,78M05还可以为外部电路提供5V电源,例如控制电路或传感器等。

“当使用大于12V驱动电压的时候,请使用外置的5V逻辑供电。“这句话什么意思?

这句话的意思是,L298N模块可以通过内置的78M05稳压芯片从驱动电源部分获取电源,但是当使用大于12V的驱动电压时,内置的稳压芯片可能会受到损坏。为了避免这种情况发生,需要使用外置的5V逻辑供电,以保证稳压芯片的正常工作。简单来说,就是为了保护L298N模块的稳压芯片,需要在使用高电压驱动电源时,额外提供一个5V的逻辑供电。

如果没理解,再来看看下面的讲解

L298N的几种供电方式。
1、使用5V电压给L298N供电
供电:L298N的12V和5V都接5V供电,GND不但要接驱动电源的GND(如果是和别的单片机或者其他系统连接在一起的时候,一定要从这里再引出一根GND和单片机或者系统的GND相连,使电压有参考电平),如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h6BozVB0-1688999686643)(https://article.biliimg.com/bfs/article/b66cbc902d55a807e4b5ba9d888b650a3cf30f00.png)]

(不建议该方法,可能发生提供电压较小,电机转速不足的情况)


虽然不建议,但是如果非要尝试一下,在买12V锂电池之前可以拿自己的充电宝代替12V的锂电池试一试,不过要额外购买一个USB公头转XH2.54-2P端子线。,具体在“第四阶段 让小车全速动起来”展示。

交易快照:

image-20230607215839994

购买链接:USB公头转XH2.54-2P端子线2芯电源USB插头对PH2.0mm端子电源导线-淘宝网 (taobao.com)

正常购买的充电宝的输出电压是5V,虽然充电宝有两个USB接口,但他俩输出电压相同,都是5V,区别在于一个是电流是1A,一个是2A,记得使用2A的那个USB接口。


L298N模块的工作电压一般为5V-35V,最大电流为2A。如果你使用充电宝供电,需要确保充电宝的输出电压在5V-35V之间,并且输出电流不小于L298N模块的工作电流,即2A。如果充电宝的输出电流只有1A,可能会导致L298N模块无法正常工作或者工作不稳定。因此,建议使用2A及以上的输出电流的充电宝来供电L298N模块。同时,为了保证电路的稳定性,建议使用质量可靠的充电宝。

2、电源输入7~12V电压时,5v的位置不用接电源,该位置可输出一个5v,用于给单片机供电,L298N的GND接单片机的GND,( 否则没有参考电压,不能进行正常控制 ),如下图

image-20230601205621618

(强烈建议使用该方法)
3、当输入电压大于12v时,需要拔掉电源旁的跳线帽,5V端需要接入5v的电压,GND还是接GND,如下图

image-20230601205643007

拔掉跳线帽原因:用5V电源给芯片供电。如果不断开板载使能跳线帽的话,可能会损坏内置的7805的稳压芯片。

image-20230601211807360

L298N

这里的前两段很好理解,特别是在知道L298N的三种供电方式之后,但是我们可以注意一下里面提到的指示灯,来验证一下是否符合。

最后一段讲了PWM调速,刚买来时,ENA和ENB都插上跳线帽,都被接于VCC,即在这种驱动下,电机是全速运转的。当我们想要给电机调速时,需要拔掉ENA和ENB的跳线帽并将单片机上的PWM输出信号接到ENA、ENB上,ENA和ENB是独立工作的,分别控制左边和右边的电机。

直流电机的驱动:
该驱动板可驱动 2 路直流电机,使能端 ENA、ENB 为高电平时有效,控制方式及直流电机状态表如下所示:

image-20230602205549122

若要对直流电机进行 PWM 调速,需设置 IN1 和 IN2,确定电机的转动方向,然后对使能端输出 PWM 脉冲,即可实现调速。注意当使能信号为 0 时,电机处于自由停止状态;当使能信号为 1,且IN1和 IN2 为 00 或 11 时,电机处于制动状态,阻止电机转动。

至此”L298N芯片 电机驱动模块“部分资料的获取的初步学习搞定。

3). 3节12V锂电池

image-20230602203444265

注意:红线是正极,黑线是负极。

至此”3节12V锂电池“部分的学习搞定。

4). STM32F103C8T6最小系统板

该元件的学习资料有很多,可以从

淘宝:STM32F103C8T6开发板C6T6核心板 实验板最小系统板套件 科协电子-tmall.com天猫

正点原子:资料盘 开发板资料A盘: https://pan.baidu.com/s/1gCnUaE9sqOMJQbXdq-LByw 提取码:izgd

关于STM32F103C8T6的电路原理图可以从《3. 各元件的资料获取与学习.资料连接》里下载,“毕业设计学习资料-电路原理图-stm32f103c8t6最小系统原理图原件”获取

首先看个实物介绍视频:STM32F103C8T6核心板使用专题讲解 带你轻松玩32【开放未来科技】_哔哩哔哩_bilibili

原理知识介绍:[1-2] STM32简介_哔哩哔哩_bilibili

至于这个视频简介里的资料链接,下不下载都无所谓,因为这个视频选择的STM32的开发方式是标准库开发(但是作为新手,更友好的开发方式是HAL库开发),里面的一些程序我们也不用,一些文档在正点原子那里也能下载。但是有一张图我一直在用:

ttttttttttttt

这张图可以在《3. 各元件的资料获取与学习.资料连接》的“STM32F103C8T6引脚定义.xlsx”下载

STM32有哪几种开发方式?(114条消息) STM32的四种开发方式_stm32开发_ONE_Day|的博客-CSDN博客

boot0和boot1的跳线帽如何放置?(直接给结论了喔,一般与烧录程序的方式有关)

烧录方式 boot0和boot1的操作 启动模式
usb转ttl boot0置1,boot1置0 系统存储器
jlink boot0置0,boot1任意 主闪存存储器
stlink boot0置0,boot1任意 主闪存存储器
daplink boot0置0,boot1任意 主闪存存储器

看一下这篇文章就懂了:(115条消息) STM32三种BOOT启动模式详解(全网最全)_果果小师弟的博客-CSDN博客


学习累了,我们来看一个小视频:单片机毕业设计 2023单片机实物快速上手 模块分类和课题推荐 毕设天花板级教程 答辩路上 面试路上 谈项目路上常备视频 6分钟快速进入状态 单片机毕设_哔哩哔哩_bilibili


本项目属于需要用到什么便去学习什么,如果想系统地学习,可以在网上找系列课程跟着详细地学习。

至此”STM32F103C8T6最小系统板“部分的学习搞定。

5). Maix Dock开发板

Maix Dock开发板到手后如何组装,初步了解:maix dock入门使用介绍-科技-高清完整正版视频在线观看-优酷 (tudou.com)

上面这个视频是个小孩讲的,还不错,

开发板的学习官网给出了中文文档教学,很详细,可以学习:

MaixPy 文档简介:MaixPy 文档简介 - Sipeed Wiki

至此”Maix Dock开发板“部分的学习搞定。

6). HC-05 蓝牙模块

资料去哪学?当然去淘宝,淘宝里卖这个,商品介绍里一般会介绍该商品的使用方法和注意事项。如果你是第一次通过淘宝学习,不用担心,因为对于该商品不够了解,淘宝里的使用说明有些地方可能会忽视掉,但随着学着学着对该元件足够了解,会针对性地注意一些小细节,例如供电这方面,因为搞错就意味着可能会烧坏,这里就hc-05蓝牙模块为例,对该元件进行细致地学习。

先找到蓝牙模块的淘宝购买链接:带底板HC-05主从机一体蓝牙模块 无线串口透传通讯 HC-05蓝牙模块-淘宝网 (taobao.com)

有时候,有的商家会偷懒,对该元件的介绍不够详细,甚至没介绍,不用担心,我们换个商家查看,总能找到负责人的一家。有的是以百度网盘的形式分享资料,有的则直接将内容放在宝贝详情里,这两种都可以学到知识。

上面的链接里宝贝详情里详细介绍了HC-05的电平逻辑、产品特性、产品用途、蓝牙模块如何与电脑连接(从模式有效)等。这里我直接复制过来并作笔记说明帮助学习该元件。


如果要进AT模式

一直按住按钮

直到设置完成

这句一开始可能不理解,我们先了解一下HC-05的几种模式:

HC-05蓝牙模块有以下几种模式:

  1. AT命令模式:在该模式下,可以通过串口发送AT命令来配置模块的各种参数,如波特率、名称、PIN码等。

  2. 透传模式:在该模式下,模块将串口接收到的数据通过蓝牙发送出去,同时也将蓝牙接收到的数据通过串口输出。

HC-05蓝牙模块的透传模式是一种简单的串口通信模式,可以将串口数据通过蓝牙无线传输到另一端,实现无线串口通信。在透传模式下,HC-05蓝牙模块会将接收到的数据直接通过蓝牙传输到对端,同时也会将对端传来的数据通过串口输出。这种模式非常适合需要无线传输数据的应用场景,比如智能家居、智能车辆等。要进入透传模式,需要将HC-05蓝牙模块的工作模式设置为透传模式,具体的设置方法可以参考HC-05蓝牙模块的使用手册。

  1. 主从模式:在该模式下,模块可以作为主机连接其他蓝牙设备,也可以作为从机被其他蓝牙设备连接。

  2. 主机模式:在该模式下,模块只能作为主机连接其他蓝牙设备。

  3. 从机模式:在该模式下,模块只能作为从机被其他蓝牙设备连接。

这里的AT模式可以理解为设置模式,主要是对波特率的设置。

波特率(Baud Rate)是指在数字通信中,每秒钟传输的符号数。它通常用于串口通信中,表示每秒钟传输的比特数。常见的波特率有9600、115200等。波特率越高,数据传输速度越快,但也会增加传输错误的可能性。在进行串口通信时,需要保证发送和接收双方的波特率一致,否则会导致数据传输错误。

img

试试

注意!!!请勿将电源接到信号脚上,会直接烧坏!

信号引脚是RXD、TXD两个引脚,分别是串口发送引脚和串口接收引脚,元件上有标注这两个引脚要接3.3V的信号,不能接5V的电源,所以不要接错了。而VCC那个引脚电压范围是3.6V~6V,接3.3V无法正常工作,一般接5V。

image-20230529115327289

1.1小常识(非常重要):
TXD:发送端,一般表示为自己的发送端,正常通信必须接另一个设备的RXD。
RXD:接收端,一般表示为自己的接收端,正常通信必须接另一个设备的TXD。
正常通信时候本身的TXD永远接设备的RXD!
自收自发:正常通信时RXD接其他设备的TXD,因此如果要接收自己发送的数据顾名思义,也就是自己接收自己发送的数据,即自身的TXD直接连接到RXD,用来测试本身的发送和接收是否正常,是最快最简单的测试方法,当出现问题时首先做该测试确定是否产品故障。也称回环测试。

这里就是提醒RXD和TXD的接法不要搞错了。

HC-05蓝牙通信发送的波是无线电波,无线电波是一种电磁波,属于2.4GHz的ISM频段。具体来说,它采用的是蓝牙协议,使用的是GFSK调制方式。GFSK是一种高频移相键控调制方式,可以在2.4GHz频段内实现高速数据传输和可靠的通信。


1.2电平逻辑:
TTL电平:通常数据表示采用二进制,规定+5V等价于逻辑"1",0V等价于逻辑"0",称作TTL信号系统,是正逻辑
RS232电平:采用-12V到-3V,等价于逻辑"0",+3V到+12V的逻辑电平,等价于逻辑"1",是负逻辑的

HC-05的电平逻辑是TTL电平。

1.3产品特性:
1、核心模块使用HC-05从模块,引出接口包括VCC,GND,TXD,RXD,KEY引脚、蓝牙连接状态引出脚(STATE),未连接输出低,连接后输出高
2、led指示蓝牙连接状态,快闪表示没有蓝牙连接,慢闪表示进入AT模式,双闪表示蓝牙已连接并打开了端口
3、底板设置防反接二极管,带3.3V LDO,输入电压3.6~6V,未配对时电流约30mA,配对后约10mA,输入电压禁止超过7V!
4、接口电平3.3V,可以直接连接各种单片机(51,AVR,PIC,ARM,MSP430等),5V单片机也可直接连接,无需MAX232也不能经过MAX232!
5、空旷地有效距离10米(功率等级为CLASS 2),超过10米也是可能的,但不对此距离的连接质量做保证
6、配对以后当全双工串口使用,无需了解任何蓝牙协议,支持8位数据位、1位停止位、可设置奇偶校验的通信格式,这也是最常用的通信格式,不支持其他格式。
7、可以通过拉高34脚进入AT命令模式设置参数和查询信息
8、体积小巧**(3.57cm*1.52cm),工厂贴片生产**,保证贴片质量。并套透明热缩管,防尘美观,且有一定的防静电能力。
9、可通过AT命令切换为主机或者从机模式,可通过AT命令连接指定设备
10、支持从4800bps~1382400bps间的标准波特率

第1点讲了HC-05的引脚,本项目只是用了VCC,GND,TXD,RXD,另外两个引脚没接啥东西。

第2点在使用的时候会得到理解

第3,4点:

这段话的意思是:

  1. HC-05模块的底板上设置了防反接二极管,可以防止用户在连接电源时接反导致模块损坏。

  2. 底板上还带有一个3.3V的LDO稳压器,可以将输入电压稳定在3.3V,以保证模块正常工作。

  3. HC-05模块的输入电压范围是3.6V到6V,如果输入电压超过这个范围,可能会损坏模块。

  4. 当HC-05模块未配对时,电流约为30mA,当配对后,电流约为10mA。这是因为在配对时,模块需要发送和接收数据,而在未配对时,模块只需要等待连接请求。

总之,这段话提醒用户在使用HC-05模块时,要注意输入电压范围,避免接反电源,以及注意模块的电流消耗。

第6点:全双工串口是指可以同时进行发送和接收数据的串口通信方式。

第7点:34脚是HC-05模块上的一个引脚,当该引脚被拉高时,HC-05模块会进入AT命令模式,此时可以通过串口发送AT命令来设置参数和查询信息。

image-20230529123606189

查看原理图了解到拉高34引脚其实就是按下元件上的按钮,此按钮就是第1点介绍里的KEY引脚 。

1.4产品用途:
配对后只需要当成固定波特率的串口一样使用即可,因此只要是以“固定波特率,8位数据位,无奇偶校验”通信格式的串口设备都可以直接取代原来的有线串口而不需要修改程序。如数据采集、智能车、串口打印机、户外点阵条屏控制等。
**与电脑配对使用:**适合电脑跟设备间通过蓝牙串口通信,使用方法与串口一样
**与手机配对使用:**适合手机跟设备间通过蓝牙串口通信,使用方法与串口一样
**与蓝牙主机配对使用:**适合两个设备直接通过蓝牙串口通信,如单片机与单片机之间,有线串口跟单片机间等,使用方法与串口一样

变通使用:
波特率变换,因为接收端和发送端可以选择各自的波特率,在数据量小的时候可以作为波特率变换的设备使用。

与电脑配对使用:电脑端通过串口调试助手“XCOM V2.8.exe”(在**资料链接**里下载)与HC-05通信,使用方法在下文介绍。

与手机配对使用:手机端通过串口助手“xnj.lazydog.btcontroller.apk”(在**资料链接**里下载)与HC-05通信,使用方法在下文价绍。

与蓝牙主机配对使用这一项没使用到。

在使用HC-05之前,我们先进入AT命令模式,进行一些配置,配置方法参考的淘宝下方介绍:

一、需要设备准备:

①HC05蓝牙模块一个

②USB转TTL模块一个

③杜邦线4根

二、接线

img

注意:蓝牙模块的VCC只能接5V,不能接3.3V!

三、测试

先按住HC05蓝牙模块上面的按键,再给蓝牙模块通电。蓝牙模块上面的LED进入慢闪模式(约1秒钟闪烁一次),即可进行AT命令测试

AT命令格式为:波特率38400,8个数据位,1个停止位,无校验。每条指令输入完成后,必须按一下回车键再发送!

例如:输入AT,按一下回车键发送,蓝牙模块会返回OK

①如何修改蓝牙模块为主机模式:

输入AT+ROLE=1之后按一下回车键发送,蓝牙返回OK,表示修改成功!断电之后再上电,蓝牙模块为主机模式,自动搜索周围从机

输入AT+ROLE=0,则修改为从机模式。(注:默认为从机模式,无需修改)

②如何修改蓝牙模块名称:

输入AT+NAME=Beijin之后按一下回车键发送,蓝牙返回OK,表示蓝牙名字修改为Beijin

③如何修改蓝牙模块配对密码:

输入AT+PSWD=2222之后按一下回车键发送,蓝牙返回OK,表示蓝牙配对密码修改为2222

④如何修改通信波特率(注:AT模式波特率为38400,正常通信时波特率为9600):

输入AT+UART=115200,1,2之后按一下回车键发送,蓝牙返回OK,表示蓝牙通信波特率修改为115200,2个停止位,Even校验(注:默认通信参数为9600,0,0)

温馨提示:

1.供电电压必须为5V,不能为3.3V

2.请勿将电源线引脚接到数据线上,接线之前请仔细确认好

3.LED必须进入慢闪模式后方可进行AT指令测试

4.每条AT指令输入完成后,都必须按一下回车键才可发送

5.如果不能返回OK,请交换一下RXD和TXD

6.请勿撕掉热缩管或者自行焊接,否则视为放弃保修及退换货服务

USB转TTL模块我们使用PWlink。

PWLink是一款USB转TTL串口转换器,可以将USB接口转换为TTL串口信号,用于连接和控制各种串口设备。

接线时,HC-05的VCC只能接5V,但是PWlink的两个VDD都默认输出3.3V,还需要在软件里设置一下,具体操作方法见:(106条消息) pwlink用作USB转TTL,进入HC-05的AT模式_hc05无法进入at模式_quxuexi的博客-CSDN博客

(1). 进入AT模式设置波特率

先按住HC05蓝牙模块上面的按键,再给蓝牙模块通电。蓝牙模块上面的LED进入慢闪模式(约1秒钟闪烁一次),即可进入AT命令模式

实物连接图如下:

image-20230613163811020

打开串口调试助手“XCOM V2.8.exe”(在**资料链接**里下载),串口选择那里选择对应的串口号,查看方法

验证:

我们在下方的输入框中输入“AT”,再按一下回车,再点击右边的“发送”,此时就能看到HC-05回发的“OK”,如下图:

image-20230529194057298

设置波特率:

输入“AT+UART=115200,0,0”(停止位0或者1,校验位0,1,2,)之后按一下回车键再点击发送,蓝牙返回OK,表示蓝牙通信波特率修改为115200,1个停止位,无校验。这样设置的原因是在STM32CubeMx中配置串口时的默认配置就是这样,在这里配置好,之后在STM32CubeMx中配置串口时可以保持默认。下图为STM32CubeMx中串口收发数据的默认配置:

image-20230613195414956

(注:【AT+UART= < param1 >,< param2 >,< param3 >  param1: 波特率  param2: 停止位, 0=1位,1=2位  param3: 校验位, 0=无校验(None),1=奇校验(Odd),2=偶校验(Even)  默认设置为9600,0,0】)

更多设置参考:(127条消息) 蓝牙模块如何进入AT模式_zs040红灯慢闪_john_crash的博客-CSDN博客

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OaNT5IXV-1688999686651)(https://article.biliimg.com/bfs/article/5786f71f62463f15ffe031f22896606207016d22.png)]

至此”HC-05 蓝牙模块“部分的学习搞定。

7). 红外避障模块

”红外避障模块“部分的学习在“第十阶段:红外避障模块的学习使用“处讲解,什么时候用什么时候再学也不迟。

8). PWLINK2 Lite 调试下载器

(1)为什么要买PWLINK2 Lite 调试下载器?

先来了解一下stm32单片机常见的下载器有哪些?

我了解到的有stlink、daplink、jlink、usb转ttl。

  • ST-Link是ST公司推出的一款仿真器,用于调试和烧录STM32系列单片机。
  • DAPLink是ARM公司推出的一款仿真器,支持多种MCU平台,包括ARM Cortex-M系列、Nordic nRF51/nRF52、NXP LPC等。
  • J-Link是SEGGER公司推出的一款仿真器,支持多种MCU平台,包括ARM Cortex-M系列、Renesas RX系列、NXP LPC等。
  • USB转TTL是一种串口转USB的设备,常用于与单片机进行通信,例如在调试和烧录时使用。

看个视频介绍:STM32必备烧录工具居然是它?三款新手入门烧录工具对比,附使用教程!_哔哩哔哩_bilibili

这个视频介绍了stlink、jlink、usb转ttl三种烧录工具并做了比较:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iYno6rab-1688999688885)(https://article.biliimg.com/bfs/article/88ab6d70e1c3a660b9e72b95be015a68aadf3126.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aoV3Mtbp-1688999688886)(https://article.biliimg.com/bfs/article/dd48fe939bf9190587945799d9ad6b8eafb825f3.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AVICGKmN-1688999688887)(https://article.biliimg.com/bfs/article/5630e5bd6d4bc9e84970e79d3291a410c7ebbd22.png)]

DAPLink是一种开源的调试和编程接口,它可以用于ARM Cortex-M微控制器的调试和编程。以下是DAPLink的一些特点:

  1. 开源:DAPLink是一个开源项目,任何人都可以查看和修改其代码。
  2. 多平台支持:DAPLink支持Windows、Linux和MacOS等多个操作系统。
  3. 多设备支持:DAPLink支持多种ARM Cortex-M微控制器,包括STMicroelectronics、NXP、Cypress、Silicon Labs等。
  4. 快速下载:DAPLink可以通过USB接口快速下载程序到微控制器中。
  5. 调试功能:DAPLink支持在线调试,可以通过调试器和IDE进行单步调试、断点调试等操作。
  6. 简单易用:DAPLink的使用非常简单,只需要将其连接到计算机和微控制器上即可开始调试和编程。

读读评论:

速度慢?一共就几kb的固件下载,再慢又怎样,何况stlink一点也不慢

——你暂时还没用过stm32f4系列吧,等你接触实时系统的程序,你就知道j-link有多香了。

——这一看就是没用过大型工程stlink下载那是真要命

新手一般需要烧录的程序不大,使用哪一款都可以

这这这,PWLINK没有,CHlink也没有?

——这俩本质都是dap

没错,我购买的PWLINK2 Lite 调试下载器就属于上面介绍中的DAPLink。关于PWLINK2 Lite 调试下载器的使用,在“三、从零开始,上手操作”章节进行学习使用。


无聊读个小故事:《一位职场人士的经历诉说》:STM32下载器调试器CMSIS-DAP、DAPLink、USB转串口下载 - 知乎 (zhihu.com)

所讲述的内容我大致同意,我买的PWlink也是使用的DAPLink的方式进行烧录。


(2)补充:关于串口烧录

串口烧录程序需要安装CH340驱动程序,买USB转TTL工具(大概5元左右),成本比仿真器低。烧录的时候需要将USB转TTL工具与单片机进行连接,

教学视频:

使用mcu给stm32c8t6最小系统板烧录程序的保姆级教程_哔哩哔哩_bilibili

stm32如何通过串口烧录_哔哩哔哩_bilibili(USB转TTL与STM32F103C8T6只连接两根线(TXD、RXD),VCC和GND不接,通过USB转Micro数据线(就是手机充电的数据线)给STM32F103C8T6供电)

教学文档:(113条消息) STM32芯片烧录的三种方式介绍,串口、STM32 ST-LINK Utility以及STM32CubeProgrammer_stm32程序烧录_重拾十年梦的博客-CSDN博客(只看“1.2 STM32串口烧录方式”即可)

USB转TTL与STM32F103C8T6连接方式见下表:

USB转TTL STM32F103C8T6
3V3 3V3
GND GND
TXD PA10
RXD PA9
BOOT1设为0,BOOT0设为1

串口烧录实物图:

image-20230601163552402

淘宝搜索“CH340”,查看USB转TTL工具:

image-20230601161839027

使用PWLINK2 Lite 调试下载器烧录代码属于第二种方法:基于仿真器下载。本项目中需要买仿真器,因为不仅是烧录程序,在测试蓝牙模块时也需要使用仿真器来调试。

不买它可不可以,买其他的呢?

可以。也可以买STLINK,就是本文档只介绍DAPlink这种烧录方式,STLINK的烧录方式很常见,资料也很多,读者可以上网查资料学习使用。

至此”PWLINK2 Lite 调试下载器“部分的学习搞定。

9). MB-102面包板

面包板的使用很简单,一张图就讲完了:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VWnn9Hpc-1688999686653)(https://article.biliimg.com/bfs/article/9caf6fdf5d23abc387fd9ec7f5bf3426f5b0cf73.png)]

如果非要觉得有必要再看一个教学视频的话,给出一个:你不一定知道的面包板使用方法_哔哩哔哩_bilibili

至此”MB-102面包板“部分的学习搞定。

10). 发光二极管(5mm,50只)

注意,长的那根是正极,短的那根是负极。可以用3.3v给小灯供电,千万不能用5v直接给小灯供电。

二、软件安装与学习

1. Keil uvision5软件安装及开发环境配置

我的Keil uvision5是在大三上学的一门课《MCS-51单片机》时安装的,当时只安装了51单片机相关的芯片环境,没安装MDK-ARM系列的。

img

keil C51的介绍:(114条消息) Keil(C51)介绍、下载、安装与注册_keil c51_strongerHuang的博客-CSDN博客

keil MDK的介绍:(114条消息) Keil uVision5 MDK(ARM)软件的介绍、下载、安装与注册_keil uvision5官网_Bornpride的博客-CSDN博客

现在想用keil编写STM32的程序,就需要安装MDK-ARM模块。我安装时参考的:[2-1] 软件安装_哔哩哔哩_bilibili

如果你啥也没有,之前也没有安装过Keil uvision5,可以参考这个视频去安装:2023年最新keil5 安装 升级 C51 V9.61 51单片机 最新更新 保姆级安装教程_哔哩哔哩_bilibili。视频里涉及的安装包可以下载**《3. 各元件的资料获取与学习.资料连接》**里的”Keil C51V961_MDK538a软件安装“。

如果你不知道自己的Keil uvision5上有没有安装MDK-ARM,可以查看一下。

keil uvision5查看是否安装keil MDK(用于编写stm32的开发板)?

答:按照下图查看,如果许可证里有MDK-ARM的,就算安装了。

image-20230602163608049

2. Keil uvision5软件使用

keil官方的一些使用手册文档:ARM Product Manuals (keil.com)

在上面的链接里,可以了解到软件的图形用户界面如何使用,各个按钮的功能,例如如何debug,如何软件仿真,如何编译程序,烧录程序。官方的说明文档系统全面,但可能对于一些问题说明地不够细致,可以再去百度或csdn上搜搜问题,搭配着学习。

如工程配置页面的说明:(113条消息) Keil-5_使用手册_keil5使用手册_零号0的博客-CSDN博客

keil编写代码时的uint8_t / uint16_t / uint32_t /uint64_t 这些数据类型是什么?

(118条消息) uint8_t / uint16_t / uint32_t /uint64_t 这些数据类型是什么?_一剃解千愁的博客-CSDN博客

keil中如何Debug调试

视频教程:(时间:2:57~5:17)STM32必备烧录工具居然是它?三款新手入门烧录工具对比,附使用教程!_哔哩哔哩_bilibili

3. STM32CubeMX软件安装及固件库下载

STM32CubeMX软件安装及固件库下载可以参考正点原子的“STM32F103 MINI开发指南V1.3.pdf”这个文件,在第十章

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hDbysPcq-1688999686656)(https://article.biliimg.com/bfs/article/f5d6f4dd72df02cd84d5e564e2c5db42aa6f12c8.png)]

下面的内容是参考的网上的资料,结合自己的实践经验做出的总结。网上的资料好多也是参考的正点原子的,所以根据自己的喜好选择跟着那个教学资料进行安装。

别着急,在安装之前,我们先简单了解一下,STM32CubeMX这个软件的安装路径我们可以修改,一般修改为D盘,使用软件进行不同单片机型号的开发,我们需要针对性地安装不同固件库,固件库系统默认安装路径是:“C:\Users\‘用户名’\STM32Cube\Repository”,如果我们不修改,随着使用次数越来越多,固件包下载地越来越多,可能很占用c盘空间,所以还是改一下固件库的安装路径吧。

参考下面这个安装教程进行安装,在下载固件库之前一定要将固件库的保存目录做一下修改,修改为D盘你知道的一个全英文路径(空格啥的也别带),最好是STM32CubeMax安装路径,我的在“D:\ProgramFiles\STM32CUBEMAX\Repository”。下图为固件库路径下的固件库。

image-20230602200717045

修改固件库路径的教程:(114条消息) stm32cubeIDE与stm32cubeMX库文件安装路径自定义设置_cubemx库地址_s2018307的博客-CSDN博客 (这个文章咱看一下,有个印象,在下面这个软件安装教程里,记得在下载固件库之前更改软件默认的固件库路径就行)

STM32CubeMax下载安装教程:(114条消息) (实测可用)STM32 CubeMx安装教程_stm32cubemx_智能小屋ZYXC的博客-CSDN博客

如果不确定自己的电脑有没有装过java环境,可以看看这篇文章里的如何检查是否安装了java环境(即JRE):JAVA环境_如何检查是否安装了java环境(即JRE) (cha138.com)

上面的安装教程里在“3、安装STM32 HAL库”部分只讲解了在线安装的方法,如果在线安装失败可以试试离线安装,离线安装可参考:(114条消息) STM32CubeMX——固件库下载以及安装_stm32固件库下载及安装_꧁花念ᝰ的博客-CSDN博客

我采取的是上面这个链接介绍的离线安装的方式,首先将固件库的路径改为D盘全英文,去官网下载STM32CubeF1的固件库(如果官网不好下,也可以在**《3. 各元件的资料获取与学习.资料连接》**里下载“STM32Cube_FW_F1_V1.8.4.zip”),我将下载好的固件库解压后放在“D:\ProgramFiles\STM32CUBEMAX\Repository”,然后在软件里操作从本地导入固件库。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wwgfDt8Q-1688999686657)(https://article.biliimg.com/bfs/article/05172b0f9cf31767bda890a278471c05a767cb76.png)]

上图为解压的固件库文件夹放在设置的固件库的目录,然后进入STM32CubeMax,点击“Help”,再选择“Manage embedded software packages”,点击”Refresh“。

image-20230602201437552

点击refresh,就会识别我们放在固件库目录下的固件包,

image-20230602195154589

4. STM32CubeMX软件使用

学习正点原子资料的“STM32F103 MINI开发指南V1.3.pdf”这个文件的第十章内容。

三、从零开始,上手操作

前言

学习资料哪里找?

第一:关于硬件的资料去淘宝找。一般商品介绍会给一些资料,如果给的网盘形式,但网盘链接是图片无法复制,就去联系客服要,不用管是不是买他家的商品。

第二:去b站。b站上大都是视频介绍,对于小白最友好。但不要过分依赖视频,跟着视频做是傻瓜式操作,对于刚起步的新手很有帮助,但也要去了解为什么要这样操作,以便出现问题自己也能找到解决的办法。

第三:去SCDN、博客园、百度等网站。这些网站搜索的内容很多也很杂,学习时做好甄别,取其精华,去其糟粕。

第四:去官网。像keil软件使用,Maix Dock使用等,官网的资料最全,也最权威,网上讲解的那些好多的源头不都是来自官网。

查看官网说明:µVision User’s Guide (arm.com)

第一阶段:小车底座的购买和搭建

这一阶段主要讲小车底座的购买和搭建。

先在淘宝上买个小车底座,顺便再把杜邦线也买了,因为在小车组装过程中需要对tt直流电机进行焊接连线,这个铜线基于可以使用杜邦线。用于焊接电机的铜线两端,一段是铜丝,就是用于焊接在电机上,另一端是杜邦线的公头或者铜丝,这一段主要用于连接L298N电机驱动。

按照一.2.1).双层小车底盘的讲解购买小车底座;按照一.2.10).公对公、母对母、公对母杜邦线,长20cm各一排的讲解购买杜邦线;按照一.3.1).双层小车底盘的讲解焊接并搭建小车底座;

至此第一阶段的内容告一段落,准备下一阶段的学习。

第二阶段:电机驱动L298N的购买与学习使用

上一阶段讲了小车底座的购买和搭建,这一阶段主要讲电机驱动L298N的购买与学习使用。

按照一.2.2).L298N芯片 电机驱动模块的讲解购买电机驱动,为节约成本,买一个驱动就够了(原因在一.2.1).双层小车底盘部分讲了)。在等快递的时候,我们学习一些关于这款电机驱动的知识。

用一个电机驱动四个电机的方法参考这个视频(不看也行):简易版智能小车《蓝牙版》,Arduino UNO + L298N电机驱动板 + 直流电机x4_哔哩哔哩_bilibili

从这个视频主要学到的就是电机的接线方法,包括将线焊接在电机上,将线连接在电机驱动上。

再看个L298N的介绍视频:简易版智能小车《蓝牙版》,Arduino UNO + L298N电机驱动板 + 直流电机x4_哔哩哔哩_bilibili

这个视频很好地讲解了L298N如何使用,最后还讲了PWM调速的原理

看完介绍视频后再回顾学习一.3.2).L298N芯片 电机驱动模块,了解那里讲的供电方式和PWM相关知识。

电机驱动使用注意事项

  1. L298N供电的5V如果是用另外电源供电的话,(即不是和单片机的电源共用,如使用锂电池给L298N供电),那么需要将单片机的GND和L298N模块上的GND连接在起,只有这样单片机上过来的逻辑信号才有个参考0点。板载5V稳压芯片的输入引脚和电机供电驱动接线端子导通的。

  2. l298n的板载5V稳压芯片的输入引脚和电机供电驱动接线端子导通的。这句话是什么意思?5V稳压芯片的输入引脚和电机驱动接线端子分别在l298N的哪个位置?

这句话的意思是,L298N电机驱动模块上的5V稳压芯片的输入引脚和电机供电驱动接线端子是连通的。也就是说,当5V稳压芯片输入电压时,电机供电驱动接线端子也会有电压输出。L298N电机驱动模块上的5V稳压芯片的输入引脚是VCC,一般位于模块的左上角。电机供电驱动接线端子则是OUT1、OUT2、OUT3和OUT4,分别对应4个电机驱动通道,一般位于模块的右侧。

L298N

  1. L298N上有三个跳线帽,分别为板核5V输出使能、A通道使能、B通道使能。板核5V输出使能是否应该拔掉应该看我们怎么给L298N供电,只有当供电电压高于12V时,板核5V输出使能跳线帽才拔掉。A通道使能和B通道使能的跳线帽都是使用到PWM调速时才拔掉,然后接单片机的PWM输出信号。

开始动手了

直流电机串联

按照这张图的方法将电机的铜线接到L298N上,例如由下面的两个电机引出的有2根线,L298N对应的下面有OUT1和OUT2,至于两根线哪根接OUT1哪根接OUT2一开始都行,两种接法的区别就是电机转动的方向不一样,假如通电后电机转动的方向与设想的相反,就将两根线对调一下就可以了。

现在还不能让电机转起来,因为L298N的IN1、IN2、IN3、IN4需要单片机提供高低电平,所以等我们的STM32F103C8T6最小系统板到手之后再着手让电机转动起来。

至此第二阶段的内容告一段落,准备下一阶段的学习。

第三阶段:STM32F103C8T6最小系统板的购买与学习使用

上一阶段讲了电机驱动L298N的购买与学习使用,这一阶段主要讲STM32F103C8T6最小系统板的购买与学习使用。

按照“一.2.4).STM32F103C8T6最小系统板”的讲解购买,再按照“一.2.9). MB-102面包板”的演示买个面包板。

在等快递的时候,先按照“二、软件安装与学习”部分,安装好Keil uvision5和STM32CubeMX。

下面我们通过编写程序控制STM32F103C8T6上LED灯闪烁的实验来介绍一下,项目开发的大致流程。

查看一下STM32F103C8T6的原理图(在**其他资料**里的“毕业设计学习资料/电路原理图/stm32f103c8t6最小系统原理图原件/stm32f103c8t6.pdf”),STM32F103C8T6上有两个板载LED灯,红色为电源指示灯,通电即亮;绿色为测试灯,右端接3.3V,左端接芯片的PC13引脚,PC13在STM32F103C8T6最小系统板的实物上并没有引出这个引脚,所以需要在代码里设置该引脚的高低电平来达到控制小灯的亮灭。当PC13为高电平时,绿色灯灭,为低电平时,绿色灯亮。我们可以在代码中设置让PC13高一会,低一会,来查看绿色灯是否为灭一会,亮一会。

image-20230603164511139

1. STM32CubeMX中的配置

这里的配置请参考**正点原子资料**的“STM32F103 MINI开发指南V1.3.pdf”的“10.3.3 新建工程 ” 的1~6小节:

image-20230603175327894

根据资料的讲解,结合本项目做出如下说明:

  1. 在”图 10.3.3.4 选择具体的芯片型号“ 中,我们选择的芯片型号为“STM32F103C8”

    image-20230603161149150

  2. 在“2 HSE 和 LSE 时钟源设置 ”部分,我们需要查看STM32F103C8T6的HSE和LSE,在**其他资料**里的“毕业设计学习资料/STM32F103C8T6参考文档/STM32F103x8B数据手册(中文).pdf”查看。结果也是外部高速晶振和外部低速晶振分别是: 8MHZ 和 32.768KHZ。

    image-20230603162839783

  3. 在“3 时钟系统(时钟树)配置 ”这节,前面讲解的是手动计算的方法,为了简单我们也已只看该节的最后一段文字:

    image-20230603163330101

    按照这里的操作,直接在“HCLK(MHz)”位置输入72,然后按回车,就会自动进行配置。如果跳出弹窗点击ok就行。

  4. 在“4 GPIO 功能引脚配置”,文档里介绍的PA8 和 PD2 两个GPIO口,将PA8 设为“GPIO_Output”即GPIO输出口,在System Core 下的 GPIO 选项里配置PA8为推挽输出、上拉 、高速 、别名为 LED0。 我们配置STM32F103C8T6的板载绿色LED灯,将PC13设为 “GPIO_Output” 即GPIO输出口,在System Core 下的 GPIO 选项里配置PC13为 默认输出低电平(Low)、推挽输出(Output Push Pull)、不上下拉(No pull-up and no pull-down) 、低速(Low) 、别名为 LED0。

    image-20230603170703862

  5. 在“5 配置 Debug 选项 ”这节也有所不同,文档那里给出的是使用JTAG Debug,本项目使用Serial Wire Debug。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tuwUiyIN-1688999686662)(https://article.biliimg.com/bfs/article/135918bd83ed5424b9e1b9511cb232b3a8c0b6ea.png)]

    SWD是Serial Wire Debug的简称,翻译成中文是”串行线调试”。 SWD是ARM目前支持的两种调试端口之一,另一个调试端口叫做JTAG Debug Port,也就是我们常用的J-link上面的调试端口(JTAG模式下)。SWD是用于访问ARM调试接口的双线协议。它是ARM调试接口规范(ARM Debug Interface Architecture Specification)的一部分,是JTAG的替代品。SWD的物理层由两条线组成:SWDIO: 双向数据线;SWCLK: host驱动的时钟线

    image-20230603172057965

    所以,我们在文档里的“图 10.3.3.14 打开 Debug 选项”的第4个标号那里选择“Serial Wire” 。

    image-20230603172500673

  6. 在“6 生成工程源码 ”中看图“图 10.3.3.15 工程配置 ”,序号2我们选择自己的文件保存路径,序号3我们自己设置文件名,序号4右边的”Min Version”选项我选的是“V5”(因为我的keil MDK不是最新的版本,我选个保险点的V5,事实证明,这样选没事),其他的和文档里的一样配置。我给出我的配置页面:

    image-20230603174727774

    image-20230603174753539


错误解决

提醒我们它想用V1.8.5版本的固件包,但是我们没有,它问我们需要下载吗?

image-20230603180735288

这种情况下果断选择“No”,先来搞清楚一下,我们之前安装过固件包,如果你按照正点原子的开发指南的文档安装的STM32CubeMx的固件包,它安装的是V1.8.3版本;如果你按照我给的方法安装的STM32CubeMx的固件包,我安装的是V1.8.4版本。无论如何我们都安装过了,我们想要它使用我们安装过的固件包生成代码。所以就查看一下生成工程源码的配置界面有没有关于固件库版本的设置。

image-20230603181703585

在“Project”选项页面的下面可以看到上面这张图,默认勾选的“Use latest available version”。我们把勾去掉,选择我们安装过的固件库版本,如下图:

image-20230603181851368


至此在STM32CubeMx中的工作就做完了,我们页得到了生成项目基本框架。准备下一步在keil中编写代码。

2. Keil uvision5中的操作

在Keil中的操作请参考**正点原子**资料的“STM32F103 MINI开发指南V1.3.pdf”的“10.3.3 新建工程 ” 的第7小节:用户程序

大致说明的是根据前面在STM32CubeMx中的操作生成的项目文件,我们点击编译,正常情况下会显示编译通过,然后我们编写代码要在注释的 BEGIN 和END 之间编写代码,这样重新生成工程之后,这些代码会保留而不会被覆盖(我们可能在编写一部分代码之后重新到STM32CubeMx添加配置新的引脚,所以需要再次生成工程)。

代码我们不用抄文档里代码,我给出一段控制STM32F103C8T6板载LED绿色小灯的代码:

while (1)
{
    
    	
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);//PC13引脚电平翻转
    HAL_Delay(100);//延迟100ms
}

我们打开工程,来到”Application/User”目录下,打开“main.c”文件,将main函数中的while(1){}段更换为上面给出的代码,然后点击编译。

image-20230603182243309

烧录参数配置

这里的配置请参考**正点原子资料**的“STM32F103 MINI开发指南V1.3.pdf”的“8.1.4 魔术棒设置 ” 的1~6小节:

image-20230603195539990

根据资料的讲解,结合本项目做出如下说明:

文档里没讲“Device”、”User“、“ASM”、“Linker”该怎么设置,保持默认不修改就好。

在“Device”一栏主要是选择芯片,核实一下是不是STM32F103C8系列的芯片就行,如下图所示。

Device选项卡详细界面各项介绍请看官方说明:µVision User’s Guide (arm.com)

image-20230603211306194

”User“一栏不用改。

User选项卡详细界面各项介绍请看官方说明:µVision User’s Guide (arm.com)

ASM选项卡详细界面各项介绍请看官方说明:µVision User’s Guide (arm.com)

Linker选项卡详细界面各项介绍请看官方说明:µVision User’s Guide (arm.com)

  1. 在“设置 Target 选项卡”小节里,我项目的设置和文档一致,如下图:

    Target选项卡详细界面各项介绍请看官方说明:µVision User’s Guide (arm.com)

    Xtal为外部晶振时钟设置,该项只影响仿真结果。On chip ROM设置为定义存放程序的flash的首地址及可用空间大小,当有IAP和APP时,两个的ROM的地址及空间要分开。RAM设置为定义程序所用的RAM的首地址及可用空间大小。

    image-20230603195845156

  2. 在“设置 Output 选项卡 ”小节里,我们可以不用修改,保持默认的就行,默认的设置如下图。

    Output 选项卡详细界面各项介绍请看官方说明:µVision User’s Guide (arm.com)

    image-20230603200638494

    当我们通过STM32CubeMx生成项目开发的基本框架时,会在工程项目的MDK-ARM文件夹下建立一个与工程同名的文件夹用于存放编译产生的调试信息、hex文件、预览信息、封装库等。编译输出文件,如下图所示,至于“Select Folder for Objects”选项,默认情况下就是下图中的”test“文件夹(工程名不同,此问价夹名称不同)。文档里之所以提醒将“Output”和“Listing”两栏中的“Select Folder for Objects”选项选择output文件夹,是因为文档的“8.1.4 魔术棒设置 ”小节的讲解不是基于STM32CubeMx生成的基本框架代码讲解的,我们往前翻一番可以看出(“8.1.2 新建一个工程框架 ”),它的项目基本框架都是在keil中新建生成,与我们使用的STM32CubeMx生成的基本框架有所区别。

    总结一下:本项目的“Output”和“Listing”两栏使用默认的就好,不用修改里面的参数。

    image-20230603201055946

  3. 在“设置 Listing 选项卡 ”小节里,如果我们不点击“Select Folder for Listings”对输出路径进行设置,它的默认输出路径也是在output那里提到的test文件夹。所以这里我们不动就好。

    Listing 选项卡详细界面各项介绍请看官方说明:µVision User’s Guide (arm.com)

    界面如下:

    image-20230603213302172

  4. 在“设置 C/C++选项卡 ”小节里,配置界面如下:

    image-20230604183321772

    “图 8.1.4.4 设置 C/C++选项卡 ”中序号2保持默认的就行;关于“图 8.1.4.4 设置 C/C++选项卡 ”中序号3优化等级的选择,可以看一下这篇介绍:(115条消息) 对 keil Mdk 优化等级的理解_keil优化等级_zhuimeng_ruili的博客-CSDN博客 文档里选择的是“Level 0(-O0)”,我选的是“<default>”,这两个都可以。序号5“设置头文件包含路径”,一开始我们不需要改动,保持默认的就行,如果后来我们为了实现某个功能,在项目中新建了一些“.c”和“.h”文件,可以把我们建立的“.h”文件的路径加入到这里。

    例如:为了实现小车运动的控制,我新建了两个文件(thread_run.c和thread_run.h),在main.c中需要包含“thread_run.h”这个头文件,

    image-20230604173527888

    如果直接在main.c中写#include “thread_run.h”,会报错:“fatal error:’thread_run.h’ file not found”。

    image-20230604173845449

    这时候我们就需要在”C/C++”那栏的“includes paths”里添加该头文件的所在文件夹的相对路径,下面是添加之前的样子,我们照着样子给加上。

    image-20230604173307735

    加上…/MDK-ARM,之后就看到报错消失了,编译也没报错。(找这么看在我们没添加这个路径之前给我们报错也可能说明我们新建的这俩文件thread_run.c和thread_run.h也许没放对地方,如果我们保存在原有的头文件包含路径里,也就不会报错)

    image-20230604174947420

    C/C++选项卡详细界面各项介绍请看官方说明:µVision User’s Guide (arm.com)

  5. 在“设置 Debug 选项卡 ”小节里,本项目和文档里的配置一致,配置结果如下:

    image-20230604183118948

    此选项卡界面被中间一条竖线一分为二,左边是软件调试,右边是硬件调试,两边参数选项种类相同。使用软件调试可以观看PWM输出波形,烧录程序时必须设置成硬件调试。

    我建议先看一下Debug 选项卡详细界面各项介绍请看官方说明:

    µVision User’s Guide (arm.com)

    µVision User’s Guide (arm.com)

    关于“选择用于调试目标硬件的驱动程序”及其有右边的“Setting”设置的介绍:CMSIS-DAP Debugger User’s Guide (arm.com)

    image-20230604192751355

    此选项卡最主要的配置就是硬件调试的“选择用于调试目标硬件的驱动程序”及其有右边的“Setting”设置。

    “一.3.8)PWLINK2 Lite 调试下载器“部分讲了stm32单片机常见的下载器有哪些,买的下载器不同,“选择用于调试目标硬件的驱动程序”那里选择也不同,我买的PWlink,使用的DAPLink的方式进行烧录,所以我选择“CMSIS-DAP Debugger”

    烧录器类型 选项 学习链接
    stlink ST-Link Debugger
    daplink CMSIS-DAP Debugger CMSIS-DAP Debugger User’s Guide (arm.com)
    jlink J-LINK/J-TRACE Cortex
    usb转ttl 不用设置,usb转ttl不使用keil烧录
  6. 在“设置 Utilities 选项卡 ”小节里,本项目和文档里的配置一致,配置结果如下:

    image-20230604193553961

    image-20230604193621739

补充:

Utilities选项卡里默认的选项如下图所示,文档中的配置相较于默认配置,只多勾了个“Reset and Run”,这个选项可以帮助我们每次点击烧录之后自动地“按”一下复位键,使板子中地程序重新启动。如果不勾选此项,我们每次烧录完需要手动按一下板子上地Reset按钮,板子才能正常工作。

image-20230604194751963

到这里恭喜你,你已经学习了很多知识,在STM32CubeMx和Keil中的配置基本完成,之后如果需要修改也只是微调,很多东西设置完一次后面就不用再改了。现在,我们已经使用STM32CubeMx生成了项目开发的基本框架,又到keil中编写了控制STM32F103C8T6最小系统板板载绿色LED每隔100ms闪烁一次的程序,在keil中的编译,调试,烧录选项也已经配置好了,接下来拿出我们的烧录器(我买的PWLINK Lite2),将烧录器一段与STM32F103C8T6最小系统板连接,一端与电脑连接,看一眼“Debug-Settings-SW Device”那里有没有检测到设备:

image-20230604200519135

如果有,我们先点击部分编译按钮,再点击烧录按钮,如下图。

image-20230604195716597

若烧录成功,你会看到绿色板载LED灯如期闪烁。

image-20230604200643144

补充:

如果烧录时报如下错,可以看一下这篇文章:(115条消息) STM32F103C8T6程序烧录方法_stm32f103c8t6烧录_流浪法师解剖鱼的博客-CSDN博客

image-20230604201134924

如果对于烧录时STM32F103C8T6最小系统板的两个BOOT引脚(boot0,boot1)的跳线帽如何放置还有疑问,

至此第三阶段的内容告一段落,准备下一阶段的学习。

第四阶段 让小车全速动起来

上一阶段讲了给STM32烧程序,控制小灯闪烁,这一阶段主要讲配置单片机的四个GPIO口,连接电机驱动和电机,调试一下电机转动。

1. 电机控制实现

如果给电机调速,使用四个GPIO口,连接L298N电机驱动的IN1,IN2,IN3,IN4四个接口,就可以驱动电机全速正反转。

image-20230607151710456

先来在STM32上选出4个GPIO口,参考“一.3.4).STM32F103C8T6最小系统板”的一张图:STM32F103C8T6引脚定义表

2. 电机控制在STM32CubeMx中的配置

打开工程目录下的“.ioc”文件

image-20230607153237072

做如下配置:

STM32上的GPIO口 功能 IO口输出方式
PA10 IN1 Output Push Pull(推挽输出)
PA9 IN2 Output Push Pull(推挽输出)
PB9 IN3 Output Push Pull(推挽输出)
PB6 IN4 Output Push Pull(推挽输出)

先在芯片图上选择PA10、PA9、PB9、PB6的GPIIO模式为输出模式:

image-20230607154730049

再来到“System Core-GPIO”,对PA10、PA9、PB9、PB6进行配置,默认情况下这些IO口都是初始输出低电平、推挽输出、不上拉不下拉、Maximum output speed:Low,我们只要给每个IO口设个User Lable就行。

image-20230607155231860

照着上图配置好之后,点击“GENERATE CODE”按钮生成代码,之后“Open Project”。

image-20230607155852159

3. 在Keil中编写控制小车运动的代码

打开之后我们可以看到上次编写的代码,注意:一定要将代码写在BEGIN 和END之间,不然下次我们点击“GENERATE CODE”按钮生成代码时,之前没有写在BEGIN 和END之间的代码会消失。

image-20230607160525580

在编写控制小车全速正反转的代码之前,先来认识一下HAL库开发的一些基础函数,参考(118条消息) STM32cubeide中文笔记_小 羊 君的博客-CSDN博客

//PA5设置高电平、低电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
//引脚别名为LED的引脚io口输出低电平
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
//延时200ms,单位ms
HAL_Delay(200);
//PA5引脚状态翻转:1变0,0变1
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
//读取PQ10口电平状态
HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_10);

除此之外,如果想学习或查询全面的函数知识,ST 官方给我们提供了快速查找 API 函数的帮助文档。在路径:
“ STM32Cube_FW_F1_V1.8.4\Drivers\STM32F1xx_HAL_Driver” 下有几个 chm 格式的文档,如下图

image-20230607162641803

参考这两篇文章

(118条消息) STM32不同容量,标准库和HAL库对应的启动文件总结:_stm32小容量启动文件_小飞侠123!的博客-CSDN博客

(118条消息) STM32F103小容量、中容量和大容量单片机介绍_stm32f103r6单片机介绍_王小琪0712的博客-CSDN博客

得知STM32F103C8T6和STM32F103xB被归为中等容量产品,固件库里没有STM32F103x8的.chm文件,我们可以参考STM32F103xB的.chm文件,打开“STM32F103xB_User_Manual.chm”。

作为新手,我只是用到一些基本函数,有不理解的地方就到里面去搜函数名,看里面的介绍。

正点原子的开发指南也介绍了这部分如何使用,具体操作请参考**正点原子资料**的“STM32F103 MINI开发指南V1.3.pdf”的“7.3.2 HAL库文件介绍” 的第86页下方开始:

image-20230607165332485

这几个函数用的挺多的

image-20230607165733884

main.c中编写的控制小车运动的代码如下:

/* USER CODE BEGIN 0 */
void Forward()
	{
    
    
    	//左正转
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);
    	//右正传
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
	}
	
void Backward()
	{
    
    
    	//左反转
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET);
    	//右反传
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
	}
void Leftward()
	{
    
    
    	//左反转
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET);
    	//右正传
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
	}
void Rightward()
	{
    
    
    	//左正转
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET); 
    	//右反传
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
	}
/* USER CODE END 0 */

将上面我们自己编写的函数放在“USER CODE BEGIN 0”和”USER CODE END 0“之间

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

main函数中的While(1)循环更改为下面代码:

while(1)
{
    
    
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
	HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);//板载绿色LED小灯引脚电平反转
	Forward();
	HAL_Delay(1000);
	Leftward();
	HAL_Delay(1000);
	Rightward();
	HAL_Delay(1000);
	Backward();
	HAL_Delay(1000);	
}

然后点击部分编译,编译成功。

image-20230607172429690

接着准备烧录到STM32F103C8T6中,因为之前已经弄过使用PWlink烧录的参数配置,这次烧录直接用PWlink连接电脑和STM32F103C8T6之后,再编译一遍无误后就可以点击烧录。

image-20230607212945137

4. 实物连接并通电测试

烧录完开始进行实物的连接,之前已经给四个tt直流电机焊接好电线,并各引出两根引线接到L298N的OUT1、OUT2、OUT3、OUT4上,

电池采12V锂电池供电,L298N的GND引出两根线,一根与锂电池连接,一根接到面包板上与stm32f103c8t6的GND连接。L298N供电方式如下:

image-20230601205621618

实物图如下:

image-20230608172506521

至此第四阶段的内容告一段落,准备下一阶段的学习。


如果采用充电宝给L298N电机驱动供电,实物连接图如下:

STM32-L298N-充电宝-电机

我们可以发现,小车的车轮转动缓慢,感觉上这种速度只有使用12V锂电池供电时的30%(目测),这还是小车上没加啥东西的情况,如果到了后期,随着零件的增多,小车的重量也将增大,运动时所受摩擦力也增大,到时候可能会卡住不动,所以我经实验建议使用额外的12V锂电池供电。

实物图如下:

image-20230607231936320


第五阶段 PWM给小车调速

上一阶段讲了如何使小车全速地正转、反转、左转、右转,但没办法调速,这一阶段主要讲如何使用PWM给小车调速。

1. PWM常见输出方式

1.新手(菜鸟)级别while循环中,阻塞延时,控制IO口高低输出:

image-20230608221455731

阻塞延时可以是:软件模拟延时,定时器阻塞延时等。

2.入门(初级)级别while循环中,非阻赛延时,控制IO口高低输出:

image-20230608221526776

非阻赛延时可以是:定时器标识检测、RTOS(系统)延时等。

3.熟悉(中级)级别定时器中断控制IO高低电平输出:

定时器中断配置 ——> 启动定时器 ——> 响应中断,控制IO高低电平···

4.熟练(中级+)级别

定时器PWM硬件控制输出:

配置PWM对应的IO,以及定时器PWM输出 ——> 启动PWM自动输出···

image-20230608221546937

比较:
上面几种PWM输出方式,前面三种都会CPU干预PWM的输出,也就是会占用CPU资源,特别是前面两种方式,不仅占用CPU,误差还比较大。

使用第三种中断方式,如果频率比较高,CPU消耗的也比较严重。这种情况适合于没有硬件PWM输出的单片机。

第四种就是单片机自带硬件PWM输出功能,只需要简单配置就可以自动输出PWM波形,无需CPU干预。

2. PWM实现原理

显然,我们就学PWM控制转速,先来了解一下PWM原理知识:

提问:pwm用timx实现的原理?

PWM(Pulse Width Modulation)是一种常用的模拟信号生成技术,可以通过改变信号的占空比来控制输出信号的电平。在STM32中,可以使用TIM(定时器)模块来实现PWM信号的生成。

具体实现原理如下:

  1. 配置TIMx的时钟源和分频系数,使其产生一个固定的计数频率。

  2. 配置TIMx的计数模式,使其以向上计数模式计数。

  3. 配置TIMx的自动重载寄存器ARR,使其等于计数器的最大值,即计数器溢出时自动重置。

  4. 配置TIMx的比较寄存器CCR,使其等于占空比所对应的计数值。

  5. 配置TIMx的输出比较模式,使其在计数器计数到CCR时输出高电平,在计数器溢出时输出低电平。

  6. 启动TIMx计数器,即可生成PWM信号。

需要注意的是,TIMx的时钟源和分频系数、ARR和CCR的值的设置需要根据具体的应用场景进行调整,以满足不同的需求。

补充:

  1. TIMx的时钟源(可以查看“STM32F0xxx参考手册(中文).pdf”)image-20230609210541475

  2. TIMx的自动重载寄存器ARR是一个16位的寄存器,用于存储TIMx计数器的自动重载值。当TIMx计数器计数达到ARR的值时,计数器会自动重置为0,并产生一个更新事件。这个寄存器的值可以通过编程的方式进行设置,以控制TIMx的计数范围和计数周期。在计数器向上计数模式下,ARR的值决定了计数器从0开始计数到最大值的范围;在计数器向下计数模式下,ARR的值决定了计数器从最大值开始计数到0的范围。需要注意的是,ARR的值不能超过TIMx计数器的最大值,否则会导致计数器溢出。

  3. TIMx的比较寄存器CCR(Capture/Compare Register)在PWM信号输出中的作用是设置PWM波形的占空比。占空比是指PWM信号中高电平所占的时间比例,通常用百分比表示。CCR寄存器的值决定了PWM波形的占空比,具体计算公式为:

占空比 = (CCR值 / ARR值)* 100%

其中,ARR是自动重载寄存器的值,决定了PWM波形的周期。CCR的值可以通过软件编程或者硬件捕获来设置,从而实现不同的占空比。通过改变CCR的值,可以改变PWM信号的占空比,从而控制输出的电平。

  1. img

PWM的一个周期

  定时器从0开始向上计数
  当0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平
  t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平
  当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程
  至此一个PWM周期完成

每个定时器有四个通道,每一个通道都有一个捕获比较寄存器,

将寄存器值和计数器值比较,通过比较结果输出高低电平,便可以实现脉冲宽度调制模式(PWM信号)

TIMx_ARR寄存器确定PWM频率,周期是频率倒数,也可以说TIMx_ARR寄存器确定PWM信号周期

TIMx_CCRx寄存器确定占空比

因此想要得到PWM输出信号,只要一个TIMx的一个通道进行一些配置即可实现。简单来说,需要我们确定三个参数,第一个是用于计数的时钟源,随着时钟源波形信号的不断输出,TIMx_ARR寄存器的值不断增加(或减少,减少时为向下计数);第二个参数是TIMx_ARR寄存器的最大值,此参数控制着输出的PWM信号的频率;第三个参数是TIMx_CCRx寄存器的值,这个值就像一条分割线,高于此值时PWM信号输出高电平,低于此值的时候PWM输出低电平,以此来控制PWM信号的占空比。通过这三个参数,可以确定PWM信号的频率(周期也定了)、占空比。

3. PWM信号在STM32CubeMx中的配置

本小节我们讲解时以TIM1的Channel4这个PA11为例。当使用PWM信号控制小车调速时需要再加上一个PWM信号,在“6. 通过PWM信号实现小车调速”小节给出配置的页面。

选择TIM1的时钟源为“Internal Clock”,选择TIM1的Channel4为“PWM Generation CH4”,(TIM1的Channel4是引脚PA11的复用功能,对他操作就是对PA11操作)如下图:

image-20230609213225346

配置好PWM输出引脚后和时钟源后,还要设置STM32CubeMx中的三个参数来控制PWM信号的频率和占空比

在Parameter Settings中设置好Prescaler(预分频系数)、Counter Period(重装载值)、Pulse(脉冲时长)

PWM信号产生中的Prescaler(预分频系数)是指将输入时钟分频的系数,用于控制PWM信号的频率,分频的意思就是将时钟源的频率等分为多少份。

Counter Period(重装载值)是指计数器的最大值,当计数器计数达到该值时,计数器会自动清零并产生一个PWM周期,对应着上面讲到的TIMx_ARR寄存器的最大值。

Pulse(脉冲时长)是指PWM信号的高电平时间,也就是占空比的一部分,对应着上面讲到的的TIMx_CCRx寄存器的值。通过调整Prescaler、Counter Period和Pulse等参数,可以实现不同频率和占空比的PWM信号输出。

疑问解答:

  1. 什么是分频,为什么要分频?

    PWM信号产生中的分频是指将系统时钟或者其他高频信号分频后得到一个低频信号,用于控制PWM信号的频率。在PWM信号产生中,通常需要将高频信号分频后得到一个低频信号,然后再将低频信号与占空比控制信号进行比较,从而产生PWM信号。分频的大小决定了PWM信号的频率,一般情况下,分频系数越大,PWM信号的频率越低。

    PWM信号产生中的分频是指将输入的时钟信号分频后再用于PWM信号的产生。分频的目的是为了降低PWM信号的频率,以适应不同的应用场景。对于一些应用场景,需要较低的PWM频率,比如电机控制、LED调光等,而一些应用场景需要较高的PWM频率,比如DC-DC变换器、无线充电等。因此,通过分频可以将输入的时钟信号降低频率,以适应不同的应用场景。

  2. 电机控制为什么要较低的PWM频率?

    在电机控制中,较低的PWM频率可以减少电机的噪声和振动,同时也可以降低电机的损耗和温升。此外,较低的PWM频率还可以提高电机控制的精度和稳定性,使得电机的转速和转矩更加准确和可控。因此,较低的PWM频率在电机控制中是非常重要的。

STM32CubeMx中可以这样设置:psc=1440-1,arr=100-1,Pulse=50,这样设置的效果是PWM信号的频率为500Hz,周期为2ms。

image-20230611220206129

上面的设置参考这个视频:5-PWM输出和MDK如何仿真_哔哩哔哩_bilibili

4. 从公式的角度来理解PWM

符号说明:

符号 含义
Tout PWM周期。定时器溢出时间(单位为s)
Fpwm PWM频率。PWM周期的倒数(单位为Hz)
Tclk Tclk是定时器时钟源的时钟频率(单位为Hz)(未被分频的原始时钟频率)
arr 全拼:Counter Period (AutoReload Register),(重装载值)是指计数器的最大值,TIMx_ARR寄存器的最大值
psc 全拼:Prescaler,预分频系数
Tclk Tclk是定时器时钟源的时钟频率(单位为Hz)(未被分频的原始时钟频率)

有的人喜欢将PSC设置为主频-1(例如主频为72MHz),这样分频后频率为1MHz,一个周期刚好是1us,然后将ARR设置为1000-1 , 这样每个周期就是1ms,频率也就为1KHz。而Pulse设置为占空比,设置为500,刚好为1000的一半,则占空比为50%。(这句话相信看了下面的公式会很好理解)

计算公式:

PWM周期:Tout = ( (arr+1) * (psc+1) ) / Tclk (单位:s)

PWM频率:Fpwm = 1 / Tout = Tclk / ( (arr+1) * (psc+1) ) (单位:Hz)

比如 时钟源频率Tclk = 72Mhz ,arr=99 ,psc=1439 ,那么PWM频率就是72000000/100/1440= 500Hz,即Fpwm = 500Hz,Tout = 1 / 500 = 2ms。

占空比:

PWM信号的占空比是指在一个周期内,高电平所占的时间与周期时间的比值。通常用百分比表示,例如50%的占空比表示高电平持续时间占周期时间的50%。

模式 描述
PWM模式1 向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平 向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平
PWM模式2 向上计数:CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平 向下计数:CNT>CCR时,REF置有效电平,CNT≤CCR时,REF置无效电平
在STM32CubeMx中的参数说明:

Counter Mode 这个参数影响CNT的计数方式。
PWM Mode 这个参数影响比较CNT和Pulse的比较方式。mode=1时,当CNT < Pulse时,比较结果为1、反之为0,mode=2时差不多就是比较结果反一反;
CH Polarity 这个参数影响信号输出电平。设置为High时,当比较结果为1时输出高电平,结果为0时输出低电平;设置为Low时则输出电平反一反;

Counter Mode PWM Mode CH Polarity
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m2i7fuGi-1688999688888)(https://article.biliimg.com/bfs/article/233eafbd4383ad1a3b65c00a285e534c9184204b.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jjsHzy4M-1688999688888)(https://article.biliimg.com/bfs/article/2c6fe2a1ba91928b0c97bb934a71de9d9b434a4c.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0izZJ35Z-1688999688889)(https://article.biliimg.com/bfs/article/26e21d63a8ce958ec6515a4784f0976adf9678e9.png)]

表中图片均为默认设置。CH Polarity一般保持默认为High,无需改动。若在STM32CubeMx中不对“Counter Mode”、“PWM Mode”、“CH Polarity”三个参数进行改动,占空比计算公式默认为:占空比 = CCR / (ARR+1) (单位:%)

占空比计算公式:
  1. 占空比 = CCR / (ARR+1) (单位:%)(推荐使用)

    Counter Mode为向上计数(计数值不断增大),PWM Mode为PWM mode 1,CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平。如下图:

    image-20230612000113507

    例如:ARR=499,CCR=100 则pwm的占空比为20% 。

  2. 占空比 = ((ARR+1) - CCR) / (ARR+1) (单位:%)

    Counter Mode为向上计数(计数值不断增大),PWM Mode为PWM mode 2,CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平。如下图:

    img

    例如:ARR=499,CCR=100 则pwm的占空比为80% 。

改CCR可以修改占空比,修改ARR可以修改频率。


补充:

TIM1和TIM2的“Clock Source”有两种选择,“Internal Clock”和“ETR2”,如下图

image-20230609202808286

TIM3和TIM4的时钟源只有一种选择:“Internal Clock”,如下图

image-20230609202953837

13.3.4 时钟选择

image-20230609210950994

(123条消息) STM32的ETR引脚计数功能_DingUXiu的博客-CSDN博客


5. 通过PWM信号实现呼吸灯小实验

经过前面“3. PWM信号在STM32CubeMx中的配置”的讲解,跟着配置TIM1的Channel4即PA11,那节里所作的操作就是:

选择TIM1的时钟源为“Internal Clock”,

选择TIM1的Channel4为“PWM Generation CH4”,

Prescaler、Counter Period和Pulse等参数设置为:psc=1440-1,arr=100-1,Pulse=50。

这样PA11就会输出率为500Hz,周期为2ms的PWM信号。我们据通过这个PWM信号来完成呼吸灯的小实验。

在STM32CubeMx中配置好后,点击生成代码。

在完成以上设置之后,我们需要使能 TIM1 并且使能 TIM1_CH4输出。在 HAL 库中,函数 HAL_TIM_PWM_Start 可以用来实现这两个功能,函数声明如下:

  /* USER CODE BEGIN 2 */
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);	//开启定时器1的通道4的PWM输出
  /* USER CODE END 2 */

这个函数放在TIM1初始化函数之后就行,如下图:

image-20230612005613417

main.c中代码编写:
	/* USER CODE BEGIN WHILE */
	static int a=0;
	while(1)
	{
    
    
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);//板载绿色LED小灯引脚电平反转
		HAL_Delay(100);	
		while(a<99){
    
    
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,a++);//设置占空比
			HAL_Delay(10);
		}
		while(a){
    
    
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,a--);//设置占空比
			HAL_Delay(10);
		}		
	}
认识使用__HAL_TIM_SET_COMPARE()函数
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,a++);//设置占空比

代码里的这个函数的功能是设置CCR的值,以此来改变PWM信号占空比。我们在STM32CubeMx中设置使用默认的占空比计算公式:占空比 = CCR / (ARR+1) (单位:%),所以CCR的值越大,占空比越大,CCR最小为0,最大为ARR+1 。经过我的实验,发现当CCR大于ARR+1时,无论大多少,从电机转动的效果来看,都是100%的占空比输出。

image-20230612125139621

代码编写完成之后,点击编译,烧录,然后连接实物,将PA11接到LED小灯的正极,LED的负极接STM32F103C8T6的GND,最后就能看到渐亮渐灭的呼吸灯了。

video_20230611_22365 -small-original

6. keil中软件仿真查看PWM波形是输出

1. 首先设置好仿真环境

之前硬件调试时在“Debug”一栏的设置我们做一个备份,

Dialog DLL Parameter
DCM.DLL -pCM3

如下图:

image-20230613173127681

现在配置软件仿真的环境,参数设置如下:

Dialog DLL Parameter
DARMSTM.DLL -pSTM32F103C8

软件中配置如下图所示:

image-20230613174126247

2. 点击debug按钮,进入debug后按run或者F5

image-20230613174613296

再点击一下会回到代码编写的窗口。

3. VIEW->Analysis Windows->Logica Analyzer打开逻辑分析仪

image-20230613174814809

4. 添加要观察的PWM信号变量

image-20230613175859852

我们在代码中设置的两个PWM信号为PA6和PA11,在新建变量时输入“PORTA.6”后点击回车和输入“PORTA.11”后点击回车.如下图:

image-20230613175705486

5. 点击全速运行,观察示波器

image-20230613182428190

波形输出:

image-20230613182135747

我们在软件中设置的PA6和PA11的占空比一开始都是50%,然后通过While()循环,不断对占空比从0开始增大,到达最大值后再一点点减小,因此,我们在波形输出中可以看到一开始的波形的占空比为50%,接着占空比从0开始不断增大,然后不断减小,再不断增大,再。。。重复此过程。

7. 通过PWM信号实现小车调速

关于小车调速的PWM信号的频率设为多少让人犯难,网上众说纷纭,有的说要“大于1KHz,才能稳定地控制电机”,有的说“一般是10~20khz,如果电机电气时间常数小于0.1ms,要考虑用更高的频率”,有的说“据说在1khz之内就好,否则芯片会发热”,有的说[“频率越高驱动就越耗电,自然器件也就越热,频率高对主滤波储能电容的高频性能要求也越高,所以我觉得15K~25K就好”](用pwm控制直流电机速度,多大频率合适 (amobbs.com 阿莫电子论坛 - 东莞阿莫电子网站)),所以我打算自己实验一下,看看那种频率合适。

测试数据(占空比:50%):

psc,arr,Pulse设置 PWM频率(kHz) 效果 点击是否正常启动
psc=1440-1,arr=100-1,Pulse=50 0.5 良好
psc=72-1,arr=2000-1,Pulse=1000 0.5 良好
psc=72-1,arr=1000-1,Pulse=500 1 良好
psc=72-1,arr=666-1,Pulse=333 1.5 良好
psc=72-1,arr=500-1,Pulse=250 2 良好
psc=72-1,arr=200-1,Pulse=100 5 不适合
psc=72-1,arr=100-1,Pulse=50 10 不适合
psc=72-1,arr=66-1,Pulse=33 15 不适合
psc=72-1,arr=50-1,Pulse=25 20 不适合

说明:Pulse就是CCR,Tclk是72MHz,测试时占空比都为50%,Fpwm =Tclk / ( (arr+1) * (psc+1) ) ,改CCR可以修改占空比,修改ARR可以修改频率

效果动图如下所示:

22226月12日-PWM各频率电 -middle-original

经过上表的测试,控制电机的PWM信号频率可以控制在2kHz以内为好。后来又测试了10%占空比的数据,此时电机都无法正常转动,原因可能和电机有关,电机的设计存在缺陷,转动时需要克服不小的摩擦力后才开始转动,所以在占空比为10%时,电机原理上本应该转动的却没有转动。

测试数据(占空比:10%):

psc,arr,Pulse设置 PWM频率(kHz) 效果 点击是否正常启动
psc=1440-1,arr=100-1,Pulse=10 0.5
psc=72-1,arr=2000-1,Pulse=200 0.5
psc=72-1,arr=1000-1,Pulse=100 1
psc=72-1,arr=666-1,Pulse=66 1.5 不适合
psc=72-1,arr=500-1,Pulse=50 2 不适合

占空比为50%时,Fpwm=0.5、1、1.5、2时效果相差不大,都可以使用,我在代码中以psc=1440-1,arr=100-1,Pulse=50,Fpwm=0.5为例进行设计。

控制小车左右两侧的电机转动需要两个PWM信号,所以除PA11之外,我们再增加一个引脚:PA6(TIM3_CH1)

在STM32CubeMx中配置PA6:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uKny7e6o-1688999688889)(https://article.biliimg.com/bfs/article/675b1046743e82e63a008534513ff0a1888c3cb0.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-epYg6HE6-1688999688890)(https://article.biliimg.com/bfs/article/12914ea0bba6a8c4611df90ae1ef02a4579651bd.png)]

之后生成代码,在完成以上设置之后,我们需要在keil中使能 TIM1_CH4输出和TIM3_CH1输出。在 HAL 库中,函数 HAL_TIM_PWM_Start 可以用来实现这两个功能,函数声明如下:

  /* USER CODE BEGIN 2 */
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);	//开启定时器1的通道4的PWM输出
	HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);	//开启定时器3的通道1的PWM输出
  /* USER CODE END 2 */

这个函数放在TIM1初始化函数之后就行,如下图:

image-20230612212500421

main.c中代码编写:
	/* USER CODE BEGIN WHILE */
	static int a=0;
	//小车前进初始化
	Forward();
	while(1)
	{
    
    
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);//板载绿色LED小灯引脚电平反转
		HAL_Delay(100);
		while(a<99){
    
    
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,a++);//设置占空比
			__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,a++);//设置占空比
			HAL_Delay(10);
		}
		while(a){
    
    
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,a--);//设置占空比
			__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,a--);//设置占空比
			HAL_Delay(10);
		}		
	}

之后编译,烧录。L298N接线如下图所示:

image-20230613183256774

连接实物,通电运行。实物运转效果如下所示:

2222222222222222222 -middle-original

至此第五阶段的内容告一段落,准备下一阶段的学习。

第六阶段 变身蓝牙遥控小车

截至上一阶段,我们的项目已经可以正常全方位运动了,这一阶段主要讲如何给小车加上蓝牙模块,变身为蓝牙遥控小车,主要是HC-05蓝牙模块的学习。

1. 手机与电脑通过HC-05通信

在“一.3.6). HC-05 蓝牙模块”那里学习HC-05蓝牙模块的使用,跟着该模块“(1). 进入AT模式设置波特率”的内容修改HC-05蓝牙模块的波特率。

设置完通信的比特率为115200后,断开连接,重新上电,再次上电时不用长按按钮,不过使用pwlink连接时,每次都要配置pwlink的VDD引脚为5v。再次上电后,HC-05小灯一直快闪。

电脑端操作:

打开电脑端串口调试助手,进行连接。在电脑端串口调试助手中需要做如下设置:选择串口号、修改波特率为115200、停止位为1、数据位为8、校验位为None,然后点击“打开串口”,

手机端操作:

手机那头也打开蓝牙调试器“xnj.lazydog.btcontroller.apk”(在**资料链接**里下载),连接HC-05,之后就可以通信了。

关于蓝牙调试器“xnj.lazydog.btcontroller.apk”的更多操作请阅读:提高开发效率-蓝牙调试器 - 简书 (jianshu.com)

在手机端的APP的底部栏选项“设备连接”里连接HC-05,在“对话模式”里发送“t”,此时在电脑端的串口调试助手里可以看到手机发送的数据“t”。在电脑端的串口调试助手里填写字母“a”然后发送,此时在手机端也能收到电脑发送的信息。如此,完成了手机与电脑通过HC-05通信的小实验。数据发送如下图所示:

image-20230529200018760

2. 手机与STM32F103C8T6通过HC-05通信并控制小车运动

1). 原理说明

stm32f103c8t6接收HC-05的数据可以通过USART串口通信实现。下面是基于STM32F103C8T6的USART接收HC-05数据的步骤:

  1. 配置USART串口通信

首先需要配置USART串口通信,包括波特率、数据位、停止位、奇偶校验位等参数。可以使用STM32CubeMX工具进行配置,也可以手动编写代码进行配置。

  1. 使能USART接收中断

在USART初始化的代码中,需要使能USART接收中断。可以使用HAL库提供的函数HAL_UART_Receive_IT()来实现。

  1. 实现USART接收中断处理函数

当USART接收到数据时,会触发USART接收中断。此时需要在中断处理函数中读取接收到的数据。可以使用HAL库提供的函数HAL_UART_Receive_IT()来实现。

以下是一个简单的示例代码:

#include "stm32f1xx_hal.h"
UART_HandleTypeDef huart1;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
     
     
    if (huart == &huart1) {
     
     
        // 读取接收到的数据
        uint8_t data = huart1.Instance->DR;
        // 处理接收到的数据
        // ...
        // 继续使能USART接收中断
        HAL_UART_Receive_IT(&huart1, &data, 1);
    }
}
int main(void)
{
     
     
    // 初始化USART串口通信
    // ...
    // 使能USART接收中断
    HAL_UART_Receive_IT(&huart1, &data, 1);
    while (1) {
     
     
        // 主循环
        // ...
    }
}

在上面的代码中,HAL_UART_RxCpltCallback()函数是USART接收中断处理函数,当USART接收到数据时会自动调用该函数。在该函数中,可以读取接收到的数据并进行处理。最后,需要再次调用HAL_UART_Receive_IT()函数来继续使能USART接收中断。

此外,正点原子的“STM32F103 MINI开发指南V1.3.pdf”这个文件,在“第十七章 串口通信实验”,读者可以自行阅读,弥补一些欠缺的知识。在这里,我摘抄一些易理解且对项目有帮助的知识点,其他的知识能看懂越多越好,不理解影响也不大:

  1. 数据通信方式

    按数据通信方式分类,可分为串行通信和并行通信两种。串行和并行的对比如下图所示:

    image-20230613201936429
    串行通信的基本特征是数据逐位顺序依次传输,优点是传输线少、 布线成本低、 灵活度高等优点,一般用于近距离人机交互, 特殊处理后也可以用于远距离, 缺点就是传输速率低。而并行通信是数据各位可以通过多条线同时传输,优点是传输速率高,缺点就是布线成本高,抗干扰能力差因而适用于短距离、高速率的通信。

  2. 数据传输方向
    根据数据传输方向,通信又可分为全双工、半双工和单工通信。全双工、半双工和单工通信的比较如下图所示:

    image-20230613202209488

    单工是指数据传输仅能沿一个方向,不能实现反方向传输,如校园广播。半双工是指数据传输可以沿着两个方向,但是需要分时进行, 如对讲机。全双工是指数据可以同时进行双向传输,日常的打电话属于这种情形。
    这里注意全双工和半双工通信的区别:半双工通信是共用一条线路实现双向通信,而全双工是利用两条线路,一条用于发送数据,另一条用于接收数据。

  3. 数据同步方式
    根据数据同步方式,通信又可分为同步通信和异步通信。同步通信和异步通信比较如下图所示:

    image-20230613202506011

    同步通信要求通信双方共用同一时钟信号,在总线上保持统一的时序和周期完成信息传输。
    优点:可以实现高速率、大容量的数据传输,以及点对多点传输。
    缺点: 要求发送时钟和接收时钟保持严格同步,收发双方时钟允许的误差较小,同时硬件复杂。

    异步通信不需要时钟信号,而是在数据信号中加入开始位和停止位等一些同步信号,以便使接收端能够正确地将每一个字符接收下来,某些通信中还需要双方约定传输速率。
    优点:没有时钟信号硬件简单,双方时钟可允许一定误差。
    缺点: 通信速率较低,只适用点对点传输。

2). 在STM32CubeMx中配置串口

image-20230613203841988

序号1处

串口1(USART1)被标红了,显示为不可使用的状态,原因是USART1的USART1_TX(PA9)、USART1_RX(PA10)被占用了,在之前控制电机转动配置时,PA9作为IN2,PA10作为IN1,控制着左侧电机的转动方向。所以在这里无法使用串口1来与HC-05连接使用。串口2和串口3仍可以使用。

image-20230613204050671

序号2处

此处的配置为数据同步方式的配置,我们选择异步传输方式”Asynchronous“。

image-20230613204656737

Mode 描述 硬件引脚 支持外设
Asynchronous 异步模式 TXD、RXD USART、UART
Synchronous 同步模式 TXD、RXD、CK USART
Single Wire (Half-Duplex) 半双工单线模式 TXD USART、UART
Multiprocessor Communication 多处理器通讯模式 TXD、RXD USART、UART
IrDA 红外解码通信 TXD、RXD USART、UART
LIN 总线通信 TXD、RXD USART、UART
SmartCard 智能卡模式 TXD USART、UART
SmartCard with Card Clock 带时钟智能卡模式 TXD、CK USART

其中UART(Universal Asynchronous Receiver/Transmitter)为通用异步收发器

USART:(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步串行接收/发送器USART是一个全双工通用同步/异步串行收发模块,该接口是一个高度灵活的串行通信设备。

原文链接:https://blog.csdn.net/qq_45699195/article/details/119912517

序号3处

此处的配置为数据同步方式的配置,我们选择”Disable“。

image-20230613205406458

关于硬件流控制的相关知识相信看完下面这两篇文章便会有个大致的了解,读者在此处可以选择使用硬件流控制,让数据传输更可靠。

stm32串口USART 硬件流控 --学习笔记 - 简书 (jianshu.com)

(128条消息) UART串口流控制(Flow control)_uart流控_夏沫の浅雨的博客-CSDN博客

序号4处

此处为串口通信的参数设置,因为之前在“一.3.6).(1). 进入AT模式设置波特率”处讲解过蓝牙模块通信参数设置的原因就是为了与这里的默认设置保持一致,所以此处我们不做改动。

序号5处

一篇介绍NVIC的文章:(128条消息) STM32的NVIC和中断的总结_stm32g0中断分组_wuyuzun的博客-CSDN博客

image-20230613210215067

在这里我们需要使能串口2的全局中断,表示此串口采用中断的方式处理收发数据。

因为我们没使用DMA这种数据传输方式,所以”DMA Settings“选项无需设置。

“GPIO Settings”这栏保持默认就行。

至此在STM32CubeMx中配置串口的工作完成,随后点击生成代码,进入到Keil中编写代码。

3). 在Keil中编写代码

先来了解下HAL_UART_Init、HAL_UART_Receive_IT、HAL_UART_IRQHandler、 UART_Receive_IT、HAL_UART_RxCpltCallback

先来看看正点原子关于其中三个函数的说明:(130条消息) HAL_UART_Init、HAL_UART_Receive_IT、HAL_UART_IRQHandler说明_quxuexi的博客-CSDN博客

chatGPT回答:

  • HAL_UART_Init:用于初始化UART串口通信的相关参数,如波特率、数据位、停止位、校验位等。

  • HAL_UART_Receive_IT:用于开启UART串口接收中断,并启动接收数据。

  • HAL_UART_IRQHandler:用于处理UART串口接收中断,当有数据接收到时,会调用该函数进行处理。 -

  • UART_Receive_IT:是一个宏定义,用于调用HAL_UART_Receive_IT函数。 -

  • HAL_UART_RxCpltCallback:是一个回调函数,当UART串口接收完成时,会自动调用该函数进行处理。在该函数中,可以对接收到的数据进行处理,比如存储到缓冲区中。

在上一步生成的项目代码中均可以查到上述五个函数的定义,查看方法是:Ctrl+f调出查找窗口并按照图中指示查找即可:

image-20230614234443177

变量

uint8_t\uint_16_t\uint32_t\uint64_t

这些类型的来源:这些数据类型中都带有_t, _t 表示这些数据类型是通过typedef定义的,而不是新的数据类型。也就是说,它们其实是我们已知的类型的别名。

在C99标准中定义了这些数据类型,具体定义在:/usr/include/stdint.h ISO C99: 7.18 Integer types

typedef signed char             int8_t;   //  范围 -128~127     (1 Byte)
typedef short int               int16_t;  //  范围  -32768 ~  + 32767    (2 Bytes) 
typedef int                     int32_t;  //  范围 -32768  ~  + 32767    (4 Bytes)
typedef long int                int64_t;  //  范围   -9223372036854775808  ~   +9223372036854775807

typedef unsigned char           uint8_t;  //  范围0~255     (1 Byte)
typedef unsigned short int      uint16_t; //  范围0~65536   (2 Bytes)
typedef unsigned int            uint32_t; //  范围0~4294967295   (4 Bytes)
typedef unsigned long int       uint64_t; //  范围0~18446744073709551615   (8 Byte)
函数
HAL_UART_Init

image-20230614231915330

HAL_UART_Receive_IT

image-20230614231742765

//串口轮询模式发送,使用超时管理机制
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); 

//串口轮询模式发送,使用超时管理机制
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

//串口中断模式发送
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

//串口中断模式接收
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

//串口DMA模式发送
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

//串口DMA模式接收
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

/**
  * @param  huart Pointer to a UART_HandleTypeDef structure that contains
  *               the configuration information for the specified UART module.
  * @param  pData Pointer to data buffer (u8 or u16 data elements).
  * @param  Size  Amount of data elements (u8 or u16) to be received.
  * @param  Timeout Timeout duration
  * @retval HAL status
  */

HAL_UART_IRQHandler

image-20230614231847419

代码main.c中代码编写

先定义一个无符号字符型变量,用于接收串口收到的数据。

在串口中断模式接收函数中HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)第二个参数是uint8_t类型的指针,所以我们需要定义这样一个uint8_t类型的变量usart2ReceiveData来接收数据。

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
uint8_t usart2ReceiveData; //范围0~255
/* USER CODE END PD */

在前面我们为PWM信号设置了一些参数:psc=1440-1,arr=100-1,Pulse=50,在设置PWM信号占空比的函数__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,a)中第三个参数的值(即CRR的值)影响着占空比,CCR的值越大,占空比越大,CCR最小为0,最大为ARR+1 。经过我的实验,发现当CCR大于ARR+1时,无论大多少,从电机转动的效果来看,都是100%的占空比输出。结合PWM信号的参数(psc=1440-1,arr=100-1,Pulse=50),控制PWM信号占空比的CCR的值的范围在0~100之间。

当我们定义的变量usart2ReceiveData值为0~100时,表示收到串口发来的数据为 0~100,这时usart2ReceiveData的值应该表示PWM信号的占空比。当usart2ReceiveData的值大于100时,可以表示其他含义,其对应关系如下表所示:

usart2ReceiveData的值(十进制) usart2ReceiveData的值(十六进制) 含义
0~100 00~64 PWM信号占空比
101 65 小车停止
102 66 小车前进
103 67 小车后退
104 68 小车左转
105 69 小车右转

ASCALL码表对照表

image-20230616002328686

image-20230616002417056

再编写中断回调函数:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
    
    
	if(huart->Instance == USART2){
    
    	
		if(usart2ReceiveData == 101) 	Stop_run();//停止
		if(usart2ReceiveData == 102) 	Forward();//前进
		if(usart2ReceiveData == 103)	Backward();//后退
		if(usart2ReceiveData == 104)	Leftward();//左转
		if(usart2ReceiveData == 105)	Rightward();//右转
		if(0 <= usart2ReceiveData && usart2ReceiveData <= 100){
    
    
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_4,usart2ReceiveData);//设置占空比
			__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,usart2ReceiveData);//设置占空比
		}

		HAL_UART_Transmit(&huart2,&usart2ReceiveData,1,100);通过蓝牙向外发送数据,主要作为收到数据的反馈。
		HAL_UART_Receive_IT(&huart2,&usart2ReceiveData,1);
	}
}
/* USER CODE END 0 */

中断处理函数在“…\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c(2616)”处定义,定义为 : __weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart),函数前面有个__weak,weak 顾名思义是“弱”的意思,所以如果函数名称前面加上__weak 修饰符,我们一般称这个函数为“弱函数”。加上了__weak 修饰符的函数,用户可以在用户文件中重新定义一个 同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak 声明的函数,并且编译器不会报错。

我们在main.c的“/* USER CODE END 0 */”这行注释前重写中断处理函数。

再开启串口中断模式接收

 /* USER CODE BEGIN 2 */
	//串口中断模式接收
	HAL_UART_Receive_IT(&huart2,&usart2ReceiveData,1);//HAL_UART_Receive_IT(&huart2, (uint8_t *)rx_buf,1);这是接收1个字节到rx_buf中	
  /* USER CODE END 2 */

在while循环中不用再加控制小车运动的代码,因为我们将要通过手机蓝牙发送运动指令控制小车运动。while只保留控制板载绿色LED灯闪烁的代码即可:

while(1)
	{
    
    
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);//板载绿色LED小灯引脚电平反转
		HAL_Delay(100);	
	}

至此代码部分编写完成,然后编译,烧录。此阶段的main.c文件全部代码可以见:(133条消息) “三、从零开始,上手操作.第六阶段 变身蓝牙遥控小车. 3). 在Keil中编写代码. 代码main.c中代码编写“处参考main.c文件代码_quxuexi的博客-CSDN博客

4). 实物连接

实物连接示意图如下:

加上蓝牙_bb

实物连接图如下:

image-20230616211234013

5). 手机端蓝牙调试器的设置

在手机端蓝牙调试器APP中的“按钮控制界面”,如下图:

image-20230616212334832

第二行的“自动巡逻”、“手动”、“避障”是我们之后会设置的功能,目前暂时用不到,可以不用设置这三个按钮。

其他按钮设置如下:(全速也可以设为占空比100%)

慢速(占空比:43%) 中速(占空比:60%) 全速(占空比:90%) 前进
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qBi07jlp-1688999688891)(https://article.biliimg.com/bfs/article/20373387bbc891b06c38e639a57977b0431929b1.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MXnRGgU3-1688999688891)(https://article.biliimg.com/bfs/article/9e237c74fdddaa268f5ff409dacd2a39c84e16df.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wxukqtac-1688999688892)(https://article.biliimg.com/bfs/article/24926d5ae69fd52535cc63cc1aaa84aef8a25231.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yem0yXMn-1688999688892)(https://article.biliimg.com/bfs/article/8586b72d67c58318795d35b1b6cbea3bbe8627df.png)]
左转 停止 右转 后退
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i1xryuyP-1688999688892)(https://article.biliimg.com/bfs/article/fe0be1a33c4703061eef346f2c036a570fb26b85.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DCR3puMR-1688999688893)(https://article.biliimg.com/bfs/article/1812dec88e360847ca29f5f656d728a64e1e78e4.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dc7JDA7D-1688999688893)(https://article.biliimg.com/bfs/article/54d48ef213cc3e5c9fa5054688e0bc19c5b6b7bd.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tKFjuoHW-1688999688894)(https://article.biliimg.com/bfs/article/8c1d1aac33a53b511fe646e6daf7b62a4b14a250.png)]

像这样通过按钮控制速度无法做到精确的控制PWM占空比,我们也可以学习自己在APP里新建一个工程,专门来控制小车。

蓝牙调试器中新建工程的方法见:提高开发效率-蓝牙调试器 - 简书 (jianshu.com)

如果不想新建工程,却又想精确地控制PWM占空比,我们也可以在使用的过程中动态地修改其中一个按钮发送的数据,发送0~100之间的数都表示发送的是占空比的值。比如我们修改“慢速”按钮的值,经过实验,我买的零件只有当占空比大于2B(十六进制)时小车电机才能正常转动。如果我们想设置占空比为50%,我们就可以将“慢速”按钮的值改为32(我们输入的值都是16进制,进制之间的转换可以看上面的ASCALL码表对照表)。

至此,我们万事具备,只欠东风。跟着上面的步骤完成了代码编写,编译,烧录,实物连接,手机APP设置等,现在就可以通电,蓝牙连接,手机端点击按钮发送指令控制小车运动。

至此第六阶段“变身蓝牙遥控小车”的内容告一段落,准备下一阶段的学习。

第七阶段 乒乓球识别

上一阶段讲了如何变身蓝牙小车,这一阶段主要讲乒乓球识别模块。

1. K210模块的入手,环境搭建(建议看完再动手)

主要参考这个视频: K210入门_哔哩哔哩_bilibili

跟着这个视频学,先是打开K210文档:https://wiki.sipeed.com/soft/maixpy/zh/index.html

然后下载了MaixPy IDE,我用的芯片是maix dock,查看文档后发现我的CH340驱动还没装:Maix Dock USB 驱动安装 - Sipeed Wiki,然后在文档里点击下载了CH340驱动的安装程序,安装时显示驱动预安装成功,感觉不对劲,就查了查安装方法:(53条消息) win10下如何装CH340驱动_坤小白的博客-CSDN博客

预安装成功是什么?

如果你安装驱动的时候没有接硬件,驱动装上但不会立刻使用,提示你是预安装成功,等你插上硬件的时候,系统会自动安装驱动程序。但如果你插上硬件时再点击安装驱动,仍然是预安装成功,可能就有些问题了。

原来需要插上芯片才能解决驱动的问题,插上后果然自动安装了驱动,拔掉芯片后,驱动仍然存在。

image-20230616225724514

接着去更新固件,照着文档的操作,我下载的固件是最新的那版,

image-20230616225732859

如果此时又有了新的版本,也可以进到最新此时最新的那个目录里去下载固件。

点进去,下载下面这个:

image-20230618201403350


小插曲

可是为什么要下载这个固件呢?之前我下载的是另一个固件,如下图:

image-20230618201744225

这个固件的含义:

image-20230616230100726

突然一天早上看了一篇博客:(55条消息) K210快速上手教程(色块、人脸、声源识别等)_k210教程_Smalld_cat的博客-CSDN博客

复制他的“识别色块并且串口输出最大色块中心坐标”这块代码,运行时报错:

image-20230616230212851

后来查了原因:(55条消息) K210(1)解决一些新上手出现的问题_image’ object has no attribute 'cpu__-ARCHER-_的博客-CSDN博客

知道应该是固件版本不对,这篇博客给了一个建议:MaixPy IDE中的错误-有问必答-CSDN问答

“下载的固件的问题,它官网提供的一些固件是不支持外设和相关算法的,直接用出厂带的固件或者下载“maixpy_vx.y.z_x_xxx*.bin”这个固件就行”。

于是到固件下载的网址:下载站 - Sipeed

下载了这个版本的固件:

image-20230616230233621

果然,问题被解决了,好耶!!!


然后打开固件下载软件(绿色软件,无需安装),选择固件,芯片类型,端口就可以下载了

image-20230616230111539

下载完会提示成功。

image-20230616230122050

下面是maixPy IDE的使用:

“要使用 MaixPy IDE , 固件必须是 v0.3.1 版本以上, 否则MaixPyIDE 上会连接不上, 使用前尽量检查固件版本和 IDE 版本,都更新到最新版以保障能正常使用”

我下载的固件是v0.6.2版本的,符合使用要求:

image-20230618201403350

打开maixPy IDE,默认有一个测试程序,可以打开摄像头

image-20230616230158968

接下来解决识别乒乓球的问题,观看这个教学视频(15:00处)[k210] MaixPy 上手教程_哔哩哔哩_bilibili

讲解了如何设置色块阈值。

设置完白色和黄色球体的阈值后,再运行就可以识别乒乓球了。

2. K210模块代码编写

K210与单片机的连接

记录一下MaixPy IDE上的初始程序:

# Hello World Example
#
# Welcome to the MaixPy IDE!
# 1. Conenct board to computer
# 2. Select board at the top of MaixPy IDE: `tools->Select Board`
# 3. Click the connect buttion below to connect board
# 4. Click on the green run arrow button below to run the script!

import sensor, image, time, lcd

lcd.init(freq=15000000)
sensor.reset()                      # Reset and initialize the sensor. It will
                                    # run automatically, call sensor.run(0) to stop
sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.QVGA)   # Set frame size to QVGA (320x240)
sensor.skip_frames(time = 2000)     # Wait for settings take effect.
clock = time.clock()                # Create a clock object to track the FPS.

while(True):
    clock.tick()                    # Update the FPS clock.
    img = sensor.snapshot()         # Take a picture and return the image.
    lcd.display(img)                # Display on LCD
    print(clock.fps())              # Note: MaixPy's Cam runs about half as fast when connected
                                    # to the IDE. The FPS should increase once disconnected.

关于k210和maixPY的学习使用主要参考这两个官方中文文档:

MaixPy 文档简介 - Sipeed Wiki

序言 · OpenMV中文入门教程

首先需要了解我买的板子:M1W Dock,它属于Maix-I,W表示支持wifi功能

板子介绍:Sipeed M1/M1W - Sipeed Wiki

在这里找到了板子的一些文件资料:下载站 - Sipeed

K210的串口是任意映射的,所以我可以任意选择两个引脚作为输入和输出串口。

K210(Micro额外供电) STM32F103C8T6
GND GND
IO10(TXD) Rx(PB11)
IO9(RXD) Tx(PB10)

现在编写一下完整的将要保存到k210里的代码;主要实现的功能是:检测两种颜色的乒乓球,然后根据乒乓球在屏幕中的位置向单片机发送左转、右转、前进的命令。

在这里我放出来最后我使用的代码,中间过程及一开始的代码我放在一篇文章里:(134条消息) k210乒乓球识别模块乒乓球识别程序-初版_quxuexi的博客-CSDN博客

import sensor, image, time,lcd,utime
from machine import UART
from fpioa_manager import fm

fm.register(10, fm.fpioa.UART1_TX, force=True)#映射串口引脚
fm.register(9, fm.fpioa.UART1_RX, force=True)#映射串口引脚

uart = UART(UART.UART1, 115200, 8, 0, 0, timeout=1000, read_buf_len=4096)

clock = time.clock()
lcd.init() #显示屏初始化
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) #QQVGA: 160x120、QVGA: 320x240、
sensor.run(1)
sensor.skip_frames(20)#跳过刚启动开始的30帧照片
lcd.rotation(2)#LCD屏幕翻转,范围是0~3,上和下反转,左和右反转
sensor.set_hmirror(True)#摄像头镜像
sensor.set_auto_gain(False) # must be turned off for color tracking
#sensor.set_auto_whitebal(False) # must be turned off for color tracking,关闭白平衡

#sensor.set_brightness(3) #-3至+3,亮度越大,图片越亮
#sensor.set_saturation(2)#-3至+3,饱和度越大,色彩越鲜艳
#sensor.set_contrast(2)#-3至+3,对比度越大,颜色之间的反差越大

def find_max(blobs):
    max_size=0
    for blob in blobs:
        if blob[2]*blob[3] > max_size:
            max_blob=blob
            max_size = blob[2]*blob[3]
    return max_blob   

#存放不同的颜色阈值,依次为白色、黄色、绿色(白天光的上流:(82, 100, -3, 8, -3, 2))(晚上:(62, 100, -30, 4, -9, 31))
color = ((82, 100, -3, 8, -3, 2),(50, 96, -28, 18, 48, 90))
size_threshold = 4500 #若检测到的小球框的面积小于size_threshold表明小球距离小车太远,小车需要前进。这个参数的大小需要根据实际情况修改
target=()
flag = 0 #用于标记一个while循环中是否检测到小球,falg==1表示本轮发现了小球
count = 0
bug_open = False # True or False
previous_ball_location = 'r'
location_count=0 #用来防止误识别,保持识别结果的稳定性

def stable_output(location):
    global location_count,previous_ball_location
    if previous_ball_location != location:
        location_count = 1
        previous_ball_location = location
    else:
        location_count = location_count + 1
    if location_count >=10:
        uart.write(location) #通过串口向外发送数据,控制小车向location方向运动
        
clock.tick()#开始追踪运行时间。

while(True):
    sensor.set_auto_whitebal(False) # must be turned off for color tracking,检测黄球时,关闭白平衡,检测白球时开启白平衡
    img = sensor.snapshot().histeq(adaptive=True, clip_limit=3)
    img.lens_corr(1.8) #镜头畸变矫正(lens correction),lens_corr 为了去除畸变, 1.8 是默认参数,可以根据自己实际情况调整
    
    #专门检测黄色小球
    blobs = img.find_blobs([color[1]])
    if blobs:
        max_blob = find_max(blobs)
        x_error = max_blob[5]-img.width()/2#若x_error<0,则说明小球在左边,小车需要左转,若x_error>0,则说明小球在右边,小车需要右转
        h_error = max_blob[2]*max_blob[3]-size_threshold#若h_error<0,则小车距离小球还有距离,需要前进。
        img.draw_circle(max_blob.x()+int(max_blob.w()/2), max_blob.y()+int(max_blob.w()/2), int(max_blob.w()/2), color = (255, 255, 0),thickness=5)#识别到的白色圆形用白色的圆框出来
        #print("blob.density(): ", max_blob.density(),"blob.w(): ", max_blob.w())
        #给黄球标注框框
        #for b in blobs:
            #img.draw_circle(b.x()+int(b.w()/2), b.y()+int(b.w()/2), int(b.w()/2), color = (255, 255, 0),thickness=5)#识别到的白色圆形用白色的圆框出来
        if(x_error<-10 and max_blob.density()>0.7 and 70>max_blob.w()>8):#设为-5是留有一定的误差空间,因为不一定小球非要在正中间才能被收集
            #stable_output('l')
            uart.write('l')
            flag = 1 #标记本轮发现过目标
            count = 0 #发现目标,count置为0,从头开始计数
            lcd.draw_string(10, 10, "Left", lcd.RED, lcd.YELLOW)
            
            if bug_open == True:
                print("黄球,串口发送l,","blob.density(): ", max_blob.density(),"blob.w(): ", max_blob.w())

        if(x_error>10 and max_blob.density()>0.7 and 70>max_blob.w()>8):#设为-5是留有一定的误差空间,因为不一定小球非要在正中间才能被收集
            #stable_output('r')
            uart.write('r')
            flag = 1 #标记本轮发现过目标
            count = 0 #发现目标,count置为0,从头开始计数
            lcd.draw_string(10, 20, "Right", lcd.RED, lcd.WHITE)
            
            if bug_open == True:
                print("黄球,串口发送:r,","blob.density(): ", max_blob.density(),"blob.w(): ", max_blob.w())
            
        if(-10<x_error<10 and h_error<0 and max_blob.density()>0.7 and 70>max_blob.w()>8):
            #stable_output('h')
            uart.write('h')
            flag = 1 #标记本轮发现过目标
            count = 0 #发现目标,count置为0,从头开始计数
            lcd.draw_string(10, 30, "Head", lcd.RED, lcd.GREEN)
            
            if bug_open == True:
                print("黄球,串口发送:h,","blob.density(): ", max_blob.density(),"blob.w(): ", max_blob.w())
    else:
        stable_output('t')
        if bug_open == True:
            print("无黄,串口发送:t,")
        
        #检测白球时,开启白平衡效果会更好一点
        sensor.set_auto_whitebal(True) # must be turned off for color tracking,开启白平衡
        img = sensor.snapshot().histeq(adaptive=True, clip_limit=3)
        img.lens_corr(1.8) #镜头畸变矫正(lens correction),lens_corr 为了去除畸变, 1.8 是默认参数,可以根据自己实际情况调整
        #思想:先识别出圆形,再识别圆的颜色
        #img.find_circles:控制从霍夫变换中监测到的圆。
        for c in img.find_circles(threshold = 3500, x_margin = 10, y_margin = 10, r_margin = 10,
                r_min = 2, r_max = 100, r_step = 2):
            #area为识别到的圆的区域,即圆的外接矩形框
            area = (c.x()-c.r(), c.y()-c.r(), 2*c.r(), 2*c.r())    
            ##保存检测到的其中一个圆的一些参数,用于控制小车方向的计算
            #target = (c.x(), c.y(), c.r())          
            
            #像素颜色统计,roi 是感兴趣区域的矩形元组(x,y,w,h)。如果未指定,ROI即整个图像的图像矩形。操作范围仅限于 roi 区域内的像素。                
            statistics = img.get_statistics(roi=area)
            #l_mode(),a_mode(),b_mode()是L通道,A通道,B通道的众数。
            if color[0][0]<statistics.l_mode()<color[0][1] and color[0][2]<statistics.a_mode()<color[0][3] and color[0][4]<statistics.b_mode()<color[0][5]:#if the circle is red
                img.draw_circle(c.x(), c.y(), c.r(), color = (255, 255, 255),thickness=5)#识别到的白色圆形用白色的圆框出来
                #保存检测到的其中一个圆的一些参数,用于控制小车方向的计算
                target = (c.x(), c.y(), c.r())
            #elif color[1][0]<statistics.l_mode()<color[1][1] and color[1][2]<statistics.a_mode()<color[1][3] and color[1][4]<statistics.b_mode()<color[1][5]:#if the circle is red
                #img.draw_circle(c.x(), c.y(), c.r(), color = (255, 255, 0))#识别到的黄色圆形用黄色的圆框出来
                ##保存检测到的其中一个圆的一些参数,用于控制小车方向的计算
                #target = (c.x(), c.y(), c.r())
            else:
                img.draw_circle(c.x(), c.y(), c.r(), color = (0, 0, 0),thickness=5)#识别到的白色圆形用白色的圆框出来
                target = (c.x(), c.y(), c.r())#其实这里应该不加这一句,但为了演示效果更好,让小车也追一下圆形
                
        if target:
            flag = 1 #标记本轮发现过目标
            #一张图只保留一个小球的信息,只追一个小球
            x_error = target[0]-img.width()/2 #若x_error<0,则说明小球在左边,小车需要左转,若x_error>0,则说明小球在右边,小车需要右转
            h_error = 2*target[2]*2*target[2]-size_threshold #若h_error<0,则小车距离小球还有距离,需要前进。
            
            if(x_error<-10):#设为-5是留有一定的误差空间,因为不一定小球非要在正中间才能被收集
                #stable_output('l')
                uart.write('l')
                count = 0 #发现目标,count置为0,从头开始计数
                if bug_open == True:
                    print("白球,左转,发串口:l")
                lcd.draw_string(10, 10, "Left", lcd.RED, lcd.YELLOW)
            if(x_error>10):#设为-5是留有一定的误差空间,因为不一定小球非要在正中间才能被收集
                #stable_output('r')
                uart.write('r')
                count = 0 #发现目标,count置为0,从头开始计数
                if bug_open == True:
                    print("白球,右转,发串口:r")
                lcd.draw_string(10, 20, "Right", lcd.RED, lcd.WHITE)
            if(10>x_error>-10 and h_error<0):
                #stable_output('h')
                uart.write('h')
                count = 0 #发现目标,count置为0,从头开始计数
                if bug_open == True:
                    print("白球,前进,发串口:h")
                lcd.draw_string(10, 30, "Head", lcd.RED, lcd.GREEN)
        else:
            stable_output('t')          
            if bug_open == True:
                print("无白色球,发串口:t")
        target=()#清空target
        
    #控制视野内无球时,自动慢速右转
    if flag == 0:
        count = count+1
        if count%10 == 0:
            uart.write('s')
            utime.sleep_ms(10)
            uart.write('n') #通过串口向外发送数据,没有检测到黄色或白色小球
            
            if bug_open == True:
                print("视野无球,发串口:n")
            lcd.draw_string(250, 10, "FPS %f" % clock.fps(), lcd.BLACK, lcd.RED)
            count = 0
    flag = 0 #重置标记
    if bug_open == True:
        print("FPS %f" % clock.fps())#停止追踪运行时间,并返回当前FPS(每秒帧数)。在调用该函数前始终首先调用 tick 
        print("flag:",flag,"count:",count)
    lcd.display(img) #LCD 显示图片
    

如何提高小球检测成功率:

在最后检测的阶段,发现对于小球的检测存在不小的误差,经过实验,黄色小球直接使用色块查找比先找圆形在检验颜色的方法成功率高,所以黄色球直接颜色匹配。白色小球两种方法的效果都不大好,主要因为灯光和环境颜色的因素,导致白色小球和环境融合度高,不易被检测到,因此考虑能否调节亮度看看能不能改善一下效果。

查看了摄像头模块的库函数,可以设置对比度、亮度、饱和度、自动增益等,

(69条消息) 【K210】K210学习笔记一——sensor_k210摄像头模块_欠羽的博客-CSDN博客这篇文章探讨了自动增益,白平衡对图像呈现效果的影响。得出的结论是,颜色识别要关闭白平衡、自动增益要手动设置一个合适的值。

下面要上传脚本到开发板:参考上传脚本&模块到开发板 - Sipeed Wiki

image-20230618205017858

image-20230618205033858

运行这两行来检查是否保存成功:

import os 
os.listdir()

若运行之后并没有显示出boot.py文件,如下图:

image-20230618205134831

我都怀疑是出现问题了,小找了一下但没找到原因,后来自己试出来的方法:在显示完保存脚本成功后需要按一下板子的reset键,之后再上电,脚本就会直接运行了。所以其实脚本已经上传到开发板上了。

然后就是k210与stm32的连接了:

关于k210的供电问题:https://www.bilibili.com/video/BV1eS4y1h7r1/?spm_id_from=333.337.search-card.all.click&vd_source=ec7c0e8776ec5da069e2d080157bdbc2

这个视频的一条评论给出了答案(心酸)

image-20230618205226664

虽然理论上可以通过5V引脚给板子供电,一开始我这样做的,也确实能够正常工作,但做到后面,有时会出现k210的那块显示屏突然一闪然后不显示摄像头画面,板子上有电却无法正常工作。因为并没有找到是什么原因导致地这一现象,但后来我使用Micro口供电后这一问题便迎刃而解了。

K210(Micro额外供电) STM32F103C8T6
GND GND
IO10(TXD) Rx(PB11)
IO9(RXD) Tx(PB10)

3. 在Keil中main.c中编写代码

接下来,在单片机stm32上新创建一个用于收发的串口,之前用于蓝牙通信使用了串口2、这次我使用串口3,串口3的配置参照串口2的配置。

main.c中代码如下:

新定义一个变量用于接收串口三发送的数据,和控制串口2优先的标志(因为串口2直接与用户接触,优先级更高,串口2可以理解为手动模式控制,串口3为巡逻模式自动捡球,当处于手动模式时,禁止自动捡球)

uint8_t usart3ReceiveData;
int openUsart3Flag= 0;//openUsart3Flag为1表示开启巡逻模式自动捡球,为0表示不开启

image-20230617095740811

开启串口3中断

HAL_UART_Receive_IT(&huart3,&usart3ReceiveData,1);

image-20230617092710935

在中断回调函数中补充串口3的内容


小插曲

在编写中断回调函数的时候,我想加一个HAL_delay()函数,结果程序烧录后,小灯就不亮了,显然程序不知道卡在哪里了,搜索后找到解决办法:

(72条消息) STM32 中断中调用HAL_Delay卡死的原因及解决方法_delay中断优先级_BigProgrambug的博客-CSDN博客

 t=3127;  while(t--);  

大致相当于HAL_Delay(1);即延时一毫秒;


4). 手机端蓝牙调试器的设置

对“自动巡逻”、“手动”两个按钮进行设置

image-20230617103845038

编辑页面如下图:

自动巡逻 手动
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c8qnQlRy-1688999688895)(https://article.biliimg.com/bfs/article/9e03cd0da49d4540663cdb116d2cb7cb86a80d08.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zuNatUin-1688999688903)(https://article.biliimg.com/bfs/article/437f862e9fd22c28ae26a5b9fefa2a930bc0dac5.png)]

至此第七阶段的内容告一段落,准备下一阶段的学习。

第八阶段:学习原理图的绘制

到这里,本项目的大部分工作已经完成,只剩下一些小tesk。这一阶段主要讲如何给项目绘制它的原理图。

学习使用在线使用的嘉立创的EDA绘制原理图,网址:嘉立创EDA(标准版) - 免费、易用、强大的在线电路设计软件 (lceda.cn)

image-20230618210257547

在嘉立创EDA中导出的PNG图像在拉伸时容易模糊,这个视频的20:00介绍在Altium Designer Summer中导出不模糊的方法:(在文件里的打印预览里进行复制后粘贴,不过颜色是灰色)

https://www.bilibili.com/video/BV1PB4y1W7sc/?spm_id_from=333.337.search-card.all.click&vd_source=ec7c0e8776ec5da069e2d080157bdbc2

补充:想改为彩色可以右键预览图,点击Page Setup,有个color set,将其选中Color即可。

后来我发现一个方法:导出为svg格式的文件,然后直接将svg文件复制,粘贴到word中。

不过我还是觉得学习一下Altium Designer Summer软件的使用总没错,搜了一个学习教程:(83条消息) Altium Designer绘制stm32f103c8t6最小系统原理图_stm32f103c8t6原理图_牛奶yu茶的博客-CSDN博客

在将schlib中元件放到schdoc中时,元件老是跑到schdoc边框外面,导致无法选中,解决办法:ctrl+a全选,然后向下拖一点点。

参考:altium 画原理图添加的器件在边框外面挪不动进不了图框_百度知道 (baidu.com)

至此第八阶段的内容告一段落,准备下一阶段的学习。

第九阶段:亚克力板定制需要cad图纸

在淘宝上找人制作亚克力板时老板说必须要CAD图纸才能做,这一阶段主要讲如何绘制简单的CAD图。

AutoCAD安装教程:https://www.bilibili.com/video/BV1MY411J7ea/?spm_id_from=333.337.search-card.all.click&vd_source=ec7c0e8776ec5da069e2d080157bdbc2

安装包网盘地址:AutoCAD 2023 简体中文版_免费高速下载|百度网盘-分享无限制 (baidu.com)

网盘提取码:acad

照着视频安装完后打开软件,报错:

image-20230618210944012

我选择忽略这个错误,软件能用就行。

AutoCAD入门教程(我只看了p1、p2、p3、p4、p6):https://www.bilibili.com/video/BV1pR4y1C7AQ?p=1&vd_source=ec7c0e8776ec5da069e2d080157bdbc2

在标注尺寸时,需要额外设置,参考学习:CAD如何尺寸标注,标注样式怎样设置,大神教你快速标注秘诀!_哔哩哔哩_bilibili

学习笔记:

Dli:创建线性标注

Dal:斜着标注

Rec 空格 鼠标左键 d 空格 输入长度 空格 输入宽度 空格:创建矩形

C 空格 鼠标左键 d 空格 输入直径 空格:输入直径画圆

如何平分圆周,学习视频:https://www.bilibili.com/video/BV1YQ4y1Y7Z5/?spm_id_from=333.337.search-card.all.click&vd_source=ec7c0e8776ec5da069e2d080157bdbc2

画完结果:

image-20230618211713310

image-20230618211727470

上述图形的cad图文件在**其他资料**里可以找到

至此第九阶段的内容告一段落,准备下一阶段的学习。

第十阶段:红外避障模块的学习使用

这一阶段主要讲红外避障模块,之所以把它放在偏后面来说是因为我使用起来效果不大理想,传感器测距不精确,不好调节,而且在小车运动时产生震动,控制传感器测距的距离的螺丝容易松动,这导致可能上一秒刚调完只测范围30cm的障碍物,下一秒弹到测半米内的障碍物了,如果日后有机会可以尝试下超声波避障传感器的学习使用,这个用的挺多的。

一开始学习使用时,到网上搜索:“STM32 HAL库 红外避障”,找到一篇文章教学

(79条消息) 【STM32】标准库与HAL库对照学习教程外设篇–红外避障传感器_stm32红外避障传感器_修成真的博客-CSDN博客

我是照着这篇文章做的,但是里面的内容只是操作步骤,至于为什么没有讲解,就是没讲原理,但它提供了一个重要信息,GPIO_EXTI引脚的使用。

我查看红外避障原件的淘宝连接:红外壁障模块/避障小车避障传感器/黑白线识别 距离可调 光电开关-淘宝网 (taobao.com)

了解到:

连接方式:VCC-VCC;GND-GND;OUT-IO

当模块检测到前方障碍物信号时,电路板上绿色指示灯点亮电平,同时OUT端口持续输出低电平信号,反之,绿灯灭,引脚输出高电平,

红外避障元件就三个引脚,最值得注意的就是out引脚,这个引脚就要与stm32的GPIO_EXTI引脚来接收。

学习stm32的GPIO_EXTI引脚,看这篇文章:(79条消息) STM32CubeMX学习笔记(3)——EXTI(外部中断)接口使用_hal_gpio_exti_irqhandler_Leung_ManWah的博客-CSDN博客

在看到这里时:

image-20230618212540758

根据红外避障原件的特性:有障碍物发低电平,无障碍物发高电平。因此应该选择下降沿触发中断

但是硬件上已外部上拉这里我不清楚,

恶补下硬件知识:

硬件基础知识:上下拉电阻 - 知乎 (zhihu.com)

对于普通的单片机I/O,输入口具有上拉和下拉能力是什么意思啊?望高手解释下!_百度知道 (baidu.com)

查看了stm32f103系列的文档:

image-20230618212611346

image-20230618212624060

image-20230618212633277

这里的硬件上外部上拉是指有没有在单片机外面自己配置电阻,显然我没有电阻,所以应该选择内部上拉电阻。

image-20230618212655223

而且: 单个红外避障模块检测距离2~30cm,检测角度35°

我有三个元件,前面弄俩,后面弄一个。

照着这篇文档的操作步骤,我选择设置PA1、PA4、PA5为避障模块out的信号接收引脚PA1在前左、PA4在前中、PA5在前右

image-20230618212731058

然后生成代码。

在编写红外避障对应的回调函数时,有个问题,就是避障时应该关闭巡逻模式的串口数据传输,就是在躲避障碍物的时候,即使发现了小球,也应该优先去躲避障碍物,而不是避障的同时也执行着前去捡球的功能。

自然而然地想到了设置两个外部中断地优先级的方法来控制,(之前蓝牙串口和k210俩串口其实也可以这样来搞,但是当时没想到优先级,就设置了一个信号量来控制,这样也能实现)

但我觉得用优先级显得简单一点,逻辑更清晰一点。

恶补知识点:(79条消息) STM32 EXTI外部中断及NVIC的抢占优先级和响应优先级解释_一个旅者的博客-CSDN博客

设置如下:

image-20230618212751506

在main.c编写的避障模块回调函数:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    
    
	if(GPIO_Pin==out1_Pin)
	{
    
    
		infrared_signal1 = 'T';
		__HAL_GPIO_EXTI_CLEAR_IT(out1_Pin);  //清除中断标志
	}
	else if(GPIO_Pin==out2_Pin){
    
    
		infrared_signal2 = 'T';
		__HAL_GPIO_EXTI_CLEAR_IT(out2_Pin);  //清除中断标志
	}
	else if(GPIO_Pin==out3_Pin){
    
    
		infrared_signal3 = 'T';
		__HAL_GPIO_EXTI_CLEAR_IT(out3_Pin);  //清除中断标志
	}
}

编译后没有error,烧录到stm32上,连接引脚,上电运行。

一开始传感器绿灯一直亮,表示一直有障碍物,这时候可能是因为设置的检测距离太远,可以调节一下检测距离,调节方法:旋转传感器上的螺丝(旋钮),参考:(81条消息) E18-D80NK 红外避障传感器怎么调检测距离-其他-CSDN问答

至此第十阶段的内容告一段落,准备下一阶段的学习。

第十一阶段:给电源加上一个开关

为什么要加上一个开关呢?一是每次通电都要手动插上电源,有时候还插歪了,还有就是小车运动一段时间后,蓝牙和k210好几次都无故断电,不工作了,我怀疑可能是接线问题

于是搜相关问题,发现一篇文章讲了电源通电时注意不烧坏单片机的我觉得挺有道理的。就是“一定要先接通负极再接正极。“

参考链接:(94条消息) STM32接电机驱动,杜邦线供电,然后反烧问题_stm32供电最大电流_我与nano的博客-CSDN博客

于是后来给能源加上一个开关,的使用方法:

船型开关也叫翘板开关它的接线脚有两个接线柱和三个接线柱的,下面华琴小编带你了解船型开关、跷板开两脚和三脚的差异:

1、两脚船型开关、翘板开关

船型开关和通常的开关一样,起个断开和接通电路的效果。绝不允许将他的两个接线柱一个接正极一个接负极,那样会短路的。

准确的接法是,电源的正极进入船型开关的任意一接线柱都可以,然后它的另一接线柱引出接入负载后再回到电源负极。

2、三脚船型开关、翘板开关

三个接线柱的应当不会有指示灯,而是带常开常闭点的,通常中心的是公共点,两头的是常开或常闭(即是不同方位的开关)

做转换开关时,中心的是动触点,两头的是定触点;做单个开关时,可以只接中心柱和边上任意一柱。

参考链接:电源插座,船形开关,8字插座,品字插座,AC插座厂家,梅花插座,八字插座,东莞市华琴电子有限公司 (huaconn.com.cn)

至此第十一阶段的内容告一段落。

第十二阶段:STM32F103C8T6的一个引脚烧坏了怎么办?

新手学习单片机有可能会遇到将某个GPIO口烧坏的情况,此时不必惊慌,只需要用另一个具有同样功能的引脚代替,然后将keil中与之相关的代码也换成另一个引脚即可。这一阶段主要讲如何更换烧坏的引脚。

LED3中的PB5引脚烧坏,使用PB8替换这个引脚为LED4工程

做修改引脚的工作时,我先将LED3复制一份并命名为LED4,打开LED4的ioc文件,在cubeMAX中编辑引脚。我将无法使用的引脚(PB5)设为Reset_State状态,

image-20230618213545290

然后查看的STM32F103c8t6的引脚,再找一个GPIO口,我选择PB8这个引脚

image-20230618213708915

将PB8设为GPIO口,标签改为IN3

image-20230618213722441

其他的都不改,直接点击GENERATE CODE,生成代码,再选择open project

image-20230618213734537

来到keil编辑器中,使用快捷键Ctrl+f,查找所有的PB5,就搜“GPIO_PIN_5 “就行,

image-20230618213749601

得到结果:

image-20230618213801148

所以我们只需要修改thread_run.c和main.c中的代码即可,将PB5都改为PB8.

比如说这一个,我们只要将数字5改成8即可:

image-20230618213812594

改为:

image-20230618213826195

全部修改完之后,先编译一下,没毛病:

image-20230618213836963

然后就是烧录到单片机上运行看看,烧录时一定记得将锂电池的供电关闭(否则引脚又烧了别怪别人)

image-20230618213846250

烧录完就更改接线,将L298N的IN3接到PB8即可。

然后就是给小车通电。到此更换引脚的工作结束。全部修改完之后,编译,烧录,小车上电测试

至此第十二阶段的内容告一段落。

补充

1. 误把SWD调试接口禁用,导致无法烧录

image-20230616224059570

烧录时弹出的窗口,打开魔法棒发现设备通信失败:

image-20230616224313132

我怀疑的问题就出现在,有一次我新建了一个项目用来测试串口通信的,结果在sys设置那里没有设置Serial Wire,然后就稀里糊涂生成了代码,然后烧录,我也不记得有没有烧录成功,但后来就无法烧录了,使用之前可以烧录的项目进行烧录也无法烧录,我一度怀疑是不是板子或烧录器被我玩坏了。

image-20230616224351718

后来上网搜了问题的解决办法,发现应该是我把SWD调试接口禁用了,详情见文章:在MDK调试STM32出现“could not stop cortex-m device”解决办法 - 简书 (jianshu.com)

然后找了解决办法:

1.板子上电之前将BOOT0引脚接到3.3V高电平
2.板子上电
3.重新烧录程序
4.BOOT0置地电平

和原文档中说法有点不一样,我的情况和评论里一位大佬一样:

image-20230616224421779

(65条消息) keil提示仿真器SWD/JTAG Communication Failure的问题解决_y511374875的博客-CSDN博客

总之有惊无险地解决了问题,又可以烧录了。

这样设置一次烧录成功后,之后把boot0再次接到0v,也可以像往常一样烧录了。回归了正常。

附件

一、官网

keil官网:Keil Embedded Development Tools for Arm, Cortex-M, Cortex-R4, 8051, C166, and 251 processor families.

Openmv官方网站:追小球的小车 · OpenMV中文入门教程

Openmv函数资料:MicroPython 函数库 — MicroPython 1.9.2 文档 (singtown.com)

MaixPy 文档简介:MaixPy 文档简介 - Sipeed Wiki

二、B站视频

一、 去b战找视频做了。

库函数开发项目视频教学:[stm32入门教程][STM32实战项目]STM32智能小车教程-循迹-避障-蓝牙遥控-跟随-stm32f103c8t6-stm32最小系统-手把手入门教程_哔哩哔哩_bilibili

HAL库开发项目视频教学:STM32智能小车V3-STM32入门教程-STM32项目-STM32循迹小车 避障 蓝牙遥控 课设 毕设 电赛 嵌入式学习 PID控制算法 编码器电机 跟随_哔哩哔哩_bilibili

MaixPy 上手教程:[k210] MaixPy 上手教程_哔哩哔哩_bilibili

三、感兴趣的文档

(57条消息) K210快速上手教程(色块、人脸、声源识别等)_k210教程_Smalld_cat的博客-CSDN博客

找圆算法:

opencv —— HoughCircles 霍夫圆变换原理及圆检测

找圆算法((HoughCircles)总结与优化_我不是校长的博客-CSDN博客

色块识别的改善:(88条消息) openmv学习之旅②之色块追踪算法的改善_openmv不同颜色的一般阈值__杰杰_的博客-CSDN博客

这个连接也是做捡球小车的,他的小车的外貌,组装和捡球思路可以给我提供改进的思路。

捡球机器人 - DF创客社区 - 分享创造的喜悦 (dfrobot.com.cn)

image-20230618220635253

额外准备的小问题(部分)

一、STM32单片机的供电方式?

有两种方法:

第一,通过Micro USB接口供电;第二,通过5V或3.3V的引脚给单片机供电,5V供电时,单片机内部有调压器将5V调为3.3V。

关于电源的一些符号说明:(106条消息) STM32F103电源引脚分析对比_stm32f103供电架构_王小琪0712的博客-CSDN博客

二、STM32单片机上的跳帽如何处理?

boot0和boot1,boot0主要和烧录的方式有关

三、常识

tt直流电机的工作电压:3V~6V

滤波电容作用是让电平更加平稳

使用一个晶体/陶瓷谐振器产生的高速外部时钟,高速外部时钟(HSE)可以使用一个4~16MHz的晶体/陶瓷谐振器构成的振荡器产生。

64K字节的内置闪存存储器,用于存放程序和数据 ,20K字节的内置SRAM

image-20230529160943072

外部中断/事件控制器(EXTI)
外部中断/事件控制器包含19个边沿检测器,用于产生中断/事件请求。每个中断线都可以独立地配置它的触发事件(上升沿或下降沿或双边沿),并能够单独地被屏蔽;有一个挂起寄存器维持所有中断请求的状态。

RTC(实时时钟) 、通用同步/异步收发器(USART)

STM32F103xx增强型系列产品包含1个高级控制定时器、 3个普通定时器,

image-20230529161811170

通用输入输出接口(GPIO)
每个GPIO引脚都可以由软件配置成输出(推挽或开漏)、输入(带或不带上拉或下拉)或复用的外设功能端口。多数GPIO引脚都与数字或模拟的复用外设共用。除了具有模拟输入功能的端口,所有的GPIO引脚都有大电流通过能力。

四、原理图讲解:

STM32入门实战:单片机最小系统板电路分析,看完你也能设计-教育视频-搜狐视频 (sohu.com)

STM32第二次培训(原理图讲解、焊接的注意事项)_哔哩哔哩_bilibili

猜你喜欢

转载自blog.csdn.net/quxuexi/article/details/131649565