stm32填坑之旅 - stm32f103c8t6点亮板载贴片蓝色LED
转载请注明:https://www.cnblogs.com/rockyf/p/11691622.html

开篇
没有时间只是自己找的借口罢了!
开篇一定要精彩,不然路人不理睬!下述是笔者作为arm小白的填坑之旅
没错,这个之前一直从事软件开发的笔者,开始搞硬件了,当然仅仅是数电!模电需要有很扎实的电路基础,而笔者有的只有“扎实”的逻辑基础。
那为什么笔者要开始搞硬件呢?
其实早在大学期间,笔者所在专业(计算机科学与技术)中就有一门课就专门讲了硬件-软件的连接以及实现,只怪当初没有好好学,只是心中有那么个印象,就是时钟驱动逻辑电路去处理每一个指令然后完成整个逻辑(当然,这个印象很重要,在arm中,时钟就是它的心脏!)。
毕业后若干年,物联网行业开始兴起,于是手痒痒了,仅凭这一印象,开始入手了人生中的第一块板子——树莓派3B,用来做了一些小玩意儿,但那都是在linux的基础上做的,和软件开发没什么区别,于是乎,这块树莓派至今都在吃灰。
第二块板子便是arduino,比树莓派稍微有点难度了,没有OS,且ram也只有几百KB,做了几个demo后,发现太依赖arduino的环境了,也不是C开发,并没有真正接触底层,于是这块arduino跟树莓派正在一起吃灰中。
笔者的主开发语言是js,出于对脚本语言的熟练,我偶然间发现了NodeMCU这个东西,发现是块可以用lua脚本写逻辑的板子,甚是欢喜,后来还烧录了espruino固件和micropython固件,把玩了许久后终于还是去吃灰了!
看来IoT行业并没有那么简单,于是收收心搞主业了!直到上个月手头没啥业务了,又开始手痒痒,查阅了avr和arm的利弊后,最终选择了arm,毕竟大佬的意见是想挑战就选arm(其实arduino板就是使用了avr架构的atmega芯片)!于是开始某宝之路。
选材#1 STM32f103c8t6
笔者作为arm初学者,不能上来就搞大货(比如xx开发套件,xx集成开发板),一是贵,二是没必要。再三某宝后,最终选定了stm32最便宜的板子STM32f103c8t6,是国产的板子,应该是st授权过的板子,然后各种仿制。
笔者入的是块黑色板子,如下图:

这块板子对于初学者来说太实惠了,RMB11,65536b(64kb)的flash和20480b(20kb)的sram,完全够用了,还有一个microUSB口,舒服!
当然,某宝上还有其他各种颜色的板子,电路排布略有不同,但功能都不尽相同。
踩坑#1 烧录
兴致勃勃地拿了快递,兴致勃勃地拆了快递,兴致勃勃地拿USB线连接到了电脑,尴尬的是毫无反应,USB信息里也没有任何st字样的项,于是开始查阅各种资料才发现,stm32f103x的microUSB口是用作电源和DFU烧录用的,于是又查了DFU的资料,发现stm32f103x并没有烧录dfu的支持固件,所以不能用DFU烧录,所以还是要其他烧录方式!
选材#2 st-link v2
在采坑#1后,我查到了stm32的另外两种烧录方式:JTag和st-link,JTag在某宝上的价格要几十块,而st-link则是10块上下,但是JTag比st-link要好用,于是果断选了st-link,便宜和爱折腾才是王道(一位图拉丁人说)。
于是在某宝上又入了一个st-link v2,RMB10.5。
踩坑#2 跑起来了
拿到st-link后,才意识到stm板子上的引脚没有焊接,于是就把swd引脚和跳线引脚给焊接上了。
然后照着板子上的swd的引脚说明,连接到st-link对应的引脚!

完美,一插上,板子上的贴片蓝色LED就开始闪烁起来了(据说蓝灯闪烁是出场时候烧录的测试程序,说明板子是正常工作的)。
踩坑#3 开发环境搭建
在查阅资料的时候,发现大大多数开发者用的操作系统要么是Windows要么就是Linux的,而笔者用的macOS,又一个大坑渐渐浮现,我直接填一下吧。
需要材料:
- 安装STM32CubeMX
- 安装homebrew
- 安装stlink命令行工具:brew install stlink
- 安装open-ocd命令行工具:brew install openocd
- 安装Clion2019,笔者比较喜欢jetbrains系列的IDE。记住,一定要安装新版本,老板没有适配和安装Embedded MCU Development plugin,这个插件能简化很多操作!
然后就可以愉快地玩耍了!
打开clion,新建一个项目,选嵌入式stm32的那个

创建项目后,会自动打开STM32CubeMX,或者手动打开项目中的ioc文件,在编辑区会有一个链接能打开STM32CubeMX。

它默认创建的是STM32f030f4px的芯片,在下面的操作中修改芯片

然后在project manager中修改

路径修改了一次就不能修改了哦!最后点击右上角的generate code。
返回clion后,就会同步文件,发现代码都生成了,点击编译,居然毫不费力地成功了,甚是欢喜!

然后烧录,点击运行,clion居然报错了

原来是编辑器板子的配置文件没有选定,需要再run/debug configuration中配置


这时,笔者找遍了整个列表都没找到stm32f103字样的项,于是去各种查阅,网上说并没有stm32f1discovery的项,这个low-level的板子太杂了,需要用board/st_nucleo_f103rb.cfg才行。
然后再点击运行,嘿,居然一堆红色的文子,看得头皮发麻

然后又是各种查阅,原来要修改board/st_nucleo_f103rb.cfg的配置
- 把接口改成stlink-v2,原来是stlink-v2-1,笔者买的是stlink-v2,如果你买的是v2-1,那这个不用修改
- 把最后一行注释掉 #reset_config srst_only
再运行,嘿,蓝灯居然不闪了,估计是烧录成功了,因为红色文子里没有什么错误信息了。
然后开始看项目结构,根据笔者的经验,用户逻辑的入口肯定是类似src,main之类字样的文件中的,果然,在Src/main.c中找到了入口。
里面有很多注释,主要是用于STM32CubeMX生成代码所标记的,不要乱改这些注释,否则会对代码生成产生影响的,你需要修改的就USER CODE字样注释范围内。
果然找到了蓝灯不闪烁的原因了,原来是main方法里的while里是空的,导致没有对蓝灯没有做任何处理,蓝灯默认是灭的。
于是开始查阅stm32有关GPIO的文档,可以使用hal库来操作
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_12);
HAL_Delay(100);
}
HAL_GPIO_TogglePin方法是切换io口的状态,第一个参数是io口的集合,第二个参数是具体集合中那个口。那为什么是GPIOB和GPIO_PIN_12呢?
采坑#4 GPIO
STM32f103c8t6板载的蓝色LED肯定是能修改的,或者是有其他用途的。经仔细查阅某宝的那个详情后,找到了它的电路图

在图中,找到了两个LED灯,一个是红色LED,是接地的,常亮状态,指示通电状态。蓝色LED则是接入到了PB12,意思就是可以通过PB12的口来控制这个蓝灯,于是,推断一下就是GPIOB和GPIO_PIN_12这两个参数了(其实是通过多次敲代码,在只能提示候选列表中找到的)。
HAL_Delay自然就是延时等待多少毫秒的作用了!
代码修改好了,再运行,吧唧,没反应,蓝灯没有闪也没有亮,咋回事?预期应该是狂闪的呀!
采坑#5 hal库和rcc库
为什么操作GPIO没有反应呢?依旧是查阅资料,网上说需要配置GPIO,不然用不了,然后给出了很多代码,粘贴进来后,都是语法错误,什么RCC没有找到之类的错误,应该是库没有引入进来导致的,想include rcc库,结果在项目中找不到rcc库,于是又是一番查阅。
笔者这个时候就在想,我用的hal库,会不会rcc也是类似hal的库呢,果然不是!hal中也有rcc的部分实现,所以只是用hal库应该没什么问题。
然后就搁置了一段时间!
采坑#6 调试
我想想看,能不能用调试功能,因为st-link仿真器是有调试功能,于是又开始捣腾!
奈何怎么调试没用,GDB调试器始终无法连接st-link:Error: init mode failed (unable to connect to the target)。但是在HAL_Init()上的断点就能断到,每次都是HAL_Init()过不去,然后一步一步跟踪进去调试,发现在__HAL_AFIO_REMAP_SWJ_NOJTAG这个方法过不去了,再升入就不行了,于是按照__HAL_AFIO_REMAP_SWJ_NOJTAG关键词阅资料发现,stm的调试是需要在STM32CubeMX中配置的,配置点在:SYS>Debug中

默认是No Debug,选择Serial Wire后generate code一次再编译就能开启调试了!简直完美!
采坑#7 引脚配置
但是调试发现,代码很完美啊(其实心里也没有底,还是查了其他文档,怀疑板载的蓝色LED并不是PB12)。
偶然间想起来,在STM32CubeMX中配置调试的时候,好像在右侧的芯片引脚图看到了PB这个口子,果然,在芯片引脚图上找到了PB12,甚是欢喜啊!

然后把PB12的引脚设置成GPIO_OUTPUT,然后generate code,再运行,终于,蓝灯开始闪烁啦,舒服!
仔细查阅main.c,会发现,其实在配置引脚后,生成的代码的MX_GPIO_Init中多了一些代码,这些代码就是配置引脚用的!
完结
至此,板载蓝色LED终于闪烁了,达成了目标!
其实,在整个填坑过程中,不止上述的那些步骤,还有其他很多坑,比如:
- stlink命令行工具怎么都打印不出stm板子的信息,甚至把stlink的源码clone下来,调试看了log,果然不是stlink的问题!最后在其issue中找到了答案,原来通过swd连接st-link的时候,需要将boot0置1,就是要把boot0的跳线帽连接右侧,boot1随意

包括烧录程序,首次连接都需要上图的连接,否则会报初始化失败的错误! - clion无法调试c的项目,查找后原来是笔者升级了macOS catalina 10.15版本,导致GDB调试器出错无法调试,升级到最新版本即可!
- 为什么要把#reset_config srst_only这行注释掉呢,因为对于STM32f103这样的的low-level的板子,并不支持reset,所以怎么都不能重置板子,在烧录成功,st-link会自动重置板子,所以依旧能达到重置板子的效果!
- ……想不起来了
心得
写博怎么不写心得呢!
世上本来并没有坑,只是完成教程太少,便有了坑!
其实在整个填坑过程中,最多的是查阅资料和尝试,身边没有朋友学过或正在从事相关的工作。
- 查阅资料就是baidu+google,双剑合璧,baidu查中文,google查英文,几乎都能找到!
- STM32f103c8t6这块板子的flash据说有10w次的擦写寿命,所以几乎完全用不完,多尝试,多失败,才能达到最终的成功!
以上
stm32填坑之旅 - stm32f103c8t6点亮板载贴片蓝色LED的更多相关文章
- Cubieboard2裸机开发之(一)点亮板载LED
前言 CUbieboard2板载两个LED,一个绿色的,一个蓝色的,其中绿色LED通过三极管与PH20管脚连接,蓝色LED通过三极管与PH21管脚连接,这里只以蓝色LED为例,电路原理图如图1和图2所 ...
- bootstrap-table填坑之旅<一>认识bootstrap-table
应公司需求,改版公司ERP的数据显示样式.由于前期开发的样式是bootstrap,所以选bootstrap-table理所当然(也是因为看了bootstrap-table官网的example功能强大, ...
- React Native填坑之旅--与Native通信之iOS篇
终于开始新一篇的填坑之旅了.RN厉害的一个地方就是RN可以和Native组件通信.这个Native组件包括native的库和自定义视图,我们今天主要设计的内容是native库方面的只是.自定义视图的使 ...
- React Native填坑之旅--Flow篇(番外)
flow不是React Native必会的技能,但是作为正式的产品开发优势很有必要掌握的技能之一.所以,算是RN填坑之旅系列的番外篇. Flow是一个静态的检查类型检查工具,设计之初的目的就是为了可以 ...
- React Native填坑之旅--布局篇
代码在这里: https://github.com/future-challenger/petshop/tree/master/client/petshop/src/controller 回头看看RN ...
- 使用vue开发微信公众号下SPA站点的填坑之旅
原文发表于本人博客,点击进入使用vue开发微信公众号下SPA站点的填坑之旅 本文为我创业过程中,开发项目的填坑之旅.作为一个技术宅男,我的项目是做一个微信公众号,前后端全部自己搞定,不浪费国家一分钱^ ...
- https填坑之旅
Boss说,我们买了个权威证书,不如做全站式的https吧,让用户打开主页就能看到受信任的绿标.于是我们就开始了填坑之旅. [只上主域好不好?] 不好...console会报出一大堆warning因为 ...
- webpack入坑之旅(五)加载vue单文件组件
这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...
- React Native填坑之旅--Stateless组件
Stateless component也叫无状态组件.有三种方法可以创建无状态组件. 坑 一般一个组件是怎么定义的: 很久以前的方法: const Heading = createClass({ re ...
随机推荐
- Matlab2016b破解安装教程——超详细
一.MATLAB是什么 MATLAB :是美国MathWorks公司出品的商业数学软件,用于算法开发.数据可视化.数据分析以及数值计算的高级技术计算语言和交互式环境,主要包括MATLAB和Simuli ...
- oracle用imp导入dmp文件
oracle命令行登录 sqlplus 用户名/密码 创建用户 create user 用户 identified by 密码 ; 创建表空间 create tablespace 表空间名 dataf ...
- .Net基础篇_学习笔记_第五天_流程控制while循环
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- Eclipse中maven项目报错:org.springframework.web.filter.CharacterEncodingFilter
写了一个demo,发现在tomcat中部署完项目,启动时报错. 1,问题描述 2,解决办法 1)程序在部署完成后报错,说明是程序是编译通过的,即编译编译路径Java Build Path没问题.2)此 ...
- thinkphp6 常用方法文档
请求变量 use think\facade\Request; Request::param('name'); Request::param();全部请求变量 返回数组 Request::param([ ...
- Redis 的底层数据结构(字典)
字典相对于数组,链表来说,是一种较高层次的数据结构,像我们的汉语字典一样,可以通过拼音或偏旁唯一确定一个汉字,在程序里我们管每一个映射关系叫做一个键值对,很多个键值对放在一起就构成了我们的字典结构. ...
- Vue学习之todolist功能开发
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 浅谈@RestController和@Controller的区别
在做Spring MVC开发时,如果对@RestController或者@Controller这两个注解理解不够清晰的话,就难免会出现用混的情况.而混用的结果往往是无法实现期望的跳转结果或者是直接将跳 ...
- C++ 变量判定的螺旋法则
C++ 中一个标识符配合着各种修饰界定符,使得标识符的本意不那么直观一眼就能看出,甚至需要仔细分析,才能知道该标识符的具体你含义. 比如: void (*signal(int, void (*fp)( ...
- JAVA设计模式-动态代理(Proxy)源码分析
在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现. 一,Proxy.newProxyInstance方法 @Cal ...