转载请注明: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,又一个大坑渐渐浮现,我直接填一下吧。

需要材料:

  1. 安装STM32CubeMX
  2. 安装homebrew
  3. 安装stlink命令行工具:brew install stlink
  4. 安装open-ocd命令行工具:brew install openocd
  5. 安装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的更多相关文章

  1. Cubieboard2裸机开发之(一)点亮板载LED

    前言 CUbieboard2板载两个LED,一个绿色的,一个蓝色的,其中绿色LED通过三极管与PH20管脚连接,蓝色LED通过三极管与PH21管脚连接,这里只以蓝色LED为例,电路原理图如图1和图2所 ...

  2. bootstrap-table填坑之旅<一>认识bootstrap-table

    应公司需求,改版公司ERP的数据显示样式.由于前期开发的样式是bootstrap,所以选bootstrap-table理所当然(也是因为看了bootstrap-table官网的example功能强大, ...

  3. React Native填坑之旅--与Native通信之iOS篇

    终于开始新一篇的填坑之旅了.RN厉害的一个地方就是RN可以和Native组件通信.这个Native组件包括native的库和自定义视图,我们今天主要设计的内容是native库方面的只是.自定义视图的使 ...

  4. React Native填坑之旅--Flow篇(番外)

    flow不是React Native必会的技能,但是作为正式的产品开发优势很有必要掌握的技能之一.所以,算是RN填坑之旅系列的番外篇. Flow是一个静态的检查类型检查工具,设计之初的目的就是为了可以 ...

  5. React Native填坑之旅--布局篇

    代码在这里: https://github.com/future-challenger/petshop/tree/master/client/petshop/src/controller 回头看看RN ...

  6. 使用vue开发微信公众号下SPA站点的填坑之旅

    原文发表于本人博客,点击进入使用vue开发微信公众号下SPA站点的填坑之旅 本文为我创业过程中,开发项目的填坑之旅.作为一个技术宅男,我的项目是做一个微信公众号,前后端全部自己搞定,不浪费国家一分钱^ ...

  7. https填坑之旅

    Boss说,我们买了个权威证书,不如做全站式的https吧,让用户打开主页就能看到受信任的绿标.于是我们就开始了填坑之旅. [只上主域好不好?] 不好...console会报出一大堆warning因为 ...

  8. webpack入坑之旅(五)加载vue单文件组件

    这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...

  9. React Native填坑之旅--Stateless组件

    Stateless component也叫无状态组件.有三种方法可以创建无状态组件. 坑 一般一个组件是怎么定义的: 很久以前的方法: const Heading = createClass({ re ...

随机推荐

  1. 实现一个基于码云的Storage

    实现一个简单的基于码云(Gitee) 的 Storage Intro 上次在 asp.net core 从单机到集群 一文中提到存储还不支持分布式,并立了一个 flag 基于 github 或者 开源 ...

  2. this指哪儿

    this的指向问题 一.this初识 this是javascript中最复杂的机制之一.它尤为特殊,被自动定义在所有函数的作用域中.这篇文章将浅析this与函数的关系. 二.了解this 学习this ...

  3. 007 Python程序语法元素分析

    目录 一.概述 二.程序的格式框架 2.1 代码高亮 2.2 缩进 2.3 注释 2.4 缩进.注释 三.命名与保留字 3.1 变量 3.2 命名 3.3 保留字 3.4 变量.命名.保留字 四.数据 ...

  4. 使用VUE实现在table中文字信息超过5个隐藏,鼠标移到时弹窗显示全部

    使用VUE实现在table中文字信息超过5个隐藏,鼠标移到时弹窗显示全部 <template> <div> <table> <tr v-for="i ...

  5. C# 表达式树分页扩展(三)

    一.前言 前面我们知道了表达树的基本知识,也明白了怎么遍历和修改一个表达式,这里我们就一个实际的场景来进行功能开发. 表达式系列目录 C# 表达式树讲解(一) C# 表达式树遍历(二) C# 表达式树 ...

  6. WAP自助建站平台娃派宣布关闭 感谢建站之路有你的启蒙

    如题所示的这篇文章是我心血来潮在网上搜索到的,写的挺让我感同身受的,不妨先看一下原文吧. 原文 不知是偶然还是"冥冥定数",最后一次访问娃派建站(wap.ai)已有数十月之久了,突 ...

  7. Java面试-如何获取客户端真实IP

    在进行一些小游戏开发时,我们经常比较关注的一个功能便是分享.针对分享,我们希望能根据各个城市或者地区,能有不同的分享文案,辨识地区的功能如果由服务器来完成的话,我们就需要知道客户端的真实IP.今天我们 ...

  8. nfs 存储服务

    今日内容: NFS 1.什么是nfs? network file system 网络文件系统 nfs共享存储 2.nfs能干什么? nfs 能为 不同主机系统之间 实现 文件的共享 3.为什么要使用n ...

  9. Day 2 总结

  10. ES6中的迭代器、Generator函数以及Generator函数的异步操作

    最近在写RN相关的东西,其中涉及到了redux-saga ,saga的实现原理就是ES6中的Generator函数,而Generator函数又和迭代器有着密不可分的关系.所以本篇博客先学习总结了ite ...