如果你只有C语言基础就马上学习STM32,你一定会有这些疑惑:

为什么有这么多没见过的API函数?没见过的变量(寄存器)名称?

为什么工程除了main.c,还有这么多其它没见过的文件?它们有什么用?

什么是Flash?什么是RAM?什么是ROM?

什么是寄存器?什么是时钟?什么是中断?什么是定时器?什么是DMA?

什么是端口复用与重映射?什么是ADC?什么是PWM?什么是UART?什么是IIC?什么是SPI?

什么是原理图?什么是PCB?什么是晶振?什么是复位?什么是电平?什么是上拉下拉浮空?

为什么我的helloworld c语言程序不能下载到STM32中运行?为什么下载的固是.hex文件?.hex .bin .exe文件有什么区别?

为什么有寄存器编程?还有标准/HAL库编程?甚至网上查的教程还有STM32CubeMX可视化配置编程?应该学哪种?用哪种?

如果你只有C语言基础,你有上面这些疑惑,是非常非常正常的。因为C语言只是一门编程语言,在单片机上,你可以用汇编编程、C语言编程,甚至很多极客板卡上,你可以用Python,JavaScript编程。为什么现在单片机编程都以C语言为主?因为各大芯片厂商,提供的BSP包都是以C为主,权衡性能效率和可维护性来说,C语言可以说是当前最优解。

所以你和STM32之间,差的就是这部分的知识点,或者换个角度说,你和单片机之间,差的就是这部分的知识点,因为对于所有的单片机,这部分的知识都是通用的。

前置:开发板的选择

我个人是比较建议买最小系统板的,一是价格低,二是学习的时候你更容易理清每个模块的关系,三是可以根据自己设计需要购买不同的外设模块进行调试。

一款系统板,一个Jlink,一个串口模块你就可以学习工程搭建,时钟配置,定时器,GPIO,UART,USB甚至RTOS这些内容,在买个SPI小屏幕、IIC传感器啥的,百元内完全覆盖。

STM32F103最小系统板

一、单片机基础知识点

关于这部分的知识点,可以参考这本书籍,通读一遍,对这些关键词有概念即可。

打开网易新闻 查看更多图片

书籍可在公众号下载:嵌入式思维导图,回复“单片机”

二、单片机启动过程

有基本的了解后,了解下单片机的启动过程,无论那款单片机,都会有一个启动文件,这个文件由原厂提供,通过了解启动文件,我们可以了解到处理器的架构、指令集、中断向量安排等内容。

启动代码通常都烧写在flash中,它是系统一上电就执行的一段程序,它运行在任何用户c代码之前。上电后,arm处理器处于arm态,运行于管理模式,同时系统所有中断被禁止,pc到地址0处取指令执行。一个可执行映像文件必须有个入口点,而能放在rom起始处的映像文件的入口地址也必须设置为0.在汇编语言中,我们已经说过怎样定义一个程序的入口点,当工程中有多个入口点时,需要在连接器中使用-entry指出程序的入口点。如果用户创建的程序中,包含了main函数,则与c库初始化代码对应的也会有个入口点。
总的来说,启动代码主要完成两方面的工作,一是初始化执行环境,例如中断向量表、堆栈、i/o等;二是初始化c库和用户应用程序。

这段文字看不懂怎么办?没关系,入门时,我们只需要知道有这个东西即可。

而STM32整个启动过程是指从上电开始,一直到运行到main函数之间的这段过程,步骤为:

①上电后硬件设置SP、PC

PC:Program Counter,通用寄存器,控制程序执行,用来指向当前运行指令的下一条指令。

SP:Stack Pointer,通用寄存器,堆栈指针,用于入栈和出栈操作。

ARM微处理器共有37个32位寄存器,其中31个为通用寄存器,6个位状态寄存器。

但是这些寄存器不能被同时访问,具体哪些寄存器是可以访问的,取决ARM处理器的工作状态及具体的运行模式。

但在任何时候,通用寄存器R14~R0、程序计数器PC(即R15)、一个状态寄存器都是可访问的。

②设置系统时钟

③软件设置SP

④加载.data、.bss,并初始化栈区

⑤跳转到C文件的main函数

打开网易新闻 查看更多图片

STM32启动过程

到这里,终于到了我们学C语言的入口部分main,是不是熟悉多了?

所以总结来说,相比于我们之前写C语言程序,单片机工程里面有一部分的文件和代码都是为上面这个启动过程服务的,所以看不懂工程里面的这些文件也就很正常,就入门来说,我们直接使用官方工程配置的文件即可。

三、单片机工程如何搭建

那STM32的工程是如何生成呢?传统的视频教程,都会教我们一个个文件新建、复制,教程的老师为什么知道需要使用什么文件?因为那是芯片原厂提供的,我们当然可以直接下载芯片原厂的示例库,然后直接用上面的工程,修改main函数后的内容进行开发。

原厂资料下载看这里:ST官网,这里你可以找到的使用手册、源码、软件工具,比任何教程资料都要完整。

这里顺便再提及一个点,我们学C语言的时候IDE用Visual C++,Visual Studio,然后学单片机的时候为什么需要用KEIL、IAR呢?这里就有一个交叉编译的概念。

我们之前常见的软件开发,都是属于本地编译:

在当前的PC下,x86的CPU下,直接编译出来程序,可以运行的程序(或者库文件),其可以直接在当前的环境,此时的

编译,可以叫做本地编译。

交叉编译,是一个和,本地编译,相对应的概念。

而所谓的,交叉编译,就是在一种平台上编译,编译出来的程序,是放到别的平台上运行即编译的环境,和运行的环境

不一样,属于交叉的,此所谓cross。

而KEIL MDK、IAR就是一套集合了交叉编译工具链、仿真、下载工具的一个更方便开发的软件而已。所以企业里面使用破解KEIL的时候收到律师函就很正常了,别人做一个这么好用的工具是要收费的。但如果你喜欢,你其实是可以在Linux上搭建自己的STM32交叉编译工具链(gcc-arm-none-eabi)环境的,然后用gdb进行仿真调试,完全脱离KEIL。

然后我们回到STM32学习这个问题上,之前说了,STM32编程有三种方式:

.寄存器编程

.标准/HAL库编程

.STM32CubeMX可视化编程

它们出现的时间是1>2>3,寄存器是最早也是最原始的,所以,我更建议的入门方法是,STM32CubeMX可视化编程的方式,这也是ST主推的一种方式,对于我们而已,这也是最容易上手的一种学习方式。

关于是否有必要从寄存器编程开始学?入门我是不建议的,学习效率太低,一种功能需要修改的数据、控制、状态多个寄存器,各种与或非移位操作,一旦看错一个位,排查困难,而且代码维护也非常困难,必须对着几百几千页的芯片手册,一个一个看。也正是因为寄存器开发效率太低,所以ST才封装了标准库和HAL库,而STM32CubeMX可视化编程的出现,则是因为HAL库的配置不直观,就像你配置一个外设时钟,你得各种计算,而CubeMX,一张图即可非常清晰明了。

所以你完全可以先快速入门,然后有需要再去理解寄存器编程,寄存器编程无非就是按照芯片手册修改对应的数据、控制、状态寄存器而已,并不是一个有技术门槛的东西。

STM32官网教程 && 微雪CubeMX教程,不得不说,官方的就是最好的。

打开网易新闻 查看更多图片

文档也可在公众号下载:嵌入式思维导图

四、单片机上的helloworld

到这里,你就可以按教程配置好自己的工程,写出STM32的helloworld啦。

除了helloworld外,你还可以实现各种加减乘除,栈、队列、链表、树等各类数据结构,甚至各类排序查询算法,这是不是和c语言学习的内容完全一致呢?

当然,你会发现,我在单片机上面跑的程序,怎么像Visual C++把结果打印出来在电脑看呢?因为单片机还没驱动屏幕来着?

五、单片机的时钟、外设

时钟比较好理解,时钟是单片机的脉搏,时钟频率决定了单片机运行一个指令周期的时。。就好像我们做广播体操的时候广播上喊的节拍1234 2234 3234。。。。然后我们全部的同学就按照这个节奏进行一个个动作。节拍越快我们动作越快。节拍越慢我们动作的越慢。

在CubeMX生成的所有工程,都需要配置好时钟,这样程序烧录到单片机才能按设置的主频跑起来,具体如何设置,就需要学习时钟配置章节了。

而单片机外设模块,就和我们需要实现的业务功能息息相关了,常见的外设子模块如下:GPIO、定时器、串口、SPI、I2C、USB等等。

·你要使用串口打印日志到电脑,你就学习UART模块。

·你要定时打印时间,你就学习UART、定时器模块。

·你要读取按键状态,你就学习GPIO、外部中断。

·你要控制LED开关,你就学习GPIO,你要花式点灯,你就学习定时器、PWM、GPIO模块。

·你要驱动IIC接口温湿度传感器,你就学习I2C模块。

·你要驱动SPI屏幕,你就学习SPI模块。

·你要驱动电机,你就学习PWM、定时器、计数器模块。

·你要驱动串口舵机,你就学习UART模块,根据协议发送16进制数据即可。

六、单片机的业务逻辑

到这里,你把常用的外设模块驱动起来了,那怎么用这些模块去做出一个产品呢?

例如下面就是一个智能手环的框图,无非就是GPIO驱动震动器、I2C驱动心率传感器、SPI驱动屏幕、I2C驱动NFC而已。

至于什么时候点亮屏幕?多久读一次的心率传感器数据?什么时候震动?用C语言的语法就可以实现啦。比如说定时器定时10s读取一次心率数据,然后同步更新到屏幕,正常心率显示绿色图标,当读取的数据大于多少时,显示为红色。这些都是常见的if switch while基础的语法可以实现的逻辑。

七、高级的单片机编程

在实现了基本的外设驱动、基本的业务逻辑后,你在想,入门工程师和中高级的单片机开发工程师区别在哪里?

·懂不懂程序模块化?

·懂不懂底层与业务解耦?

·懂不懂设计模式?

·懂不懂代码执行效率优化?

这时候就需要你有各类关键词extern ifndef const volatile、预处理、结构体、指针等稍微深入的C语言使用技巧,学习数据结构、设计模式,看各类开源源码等等方法,提升自己的综合能力了。

智能音箱的软件模块设计框图

八、建议

不已解决实际问题为由的学习都是耍流氓。

不已抄代码开始的学习都是闭门造车。

不要刻意去背芯片手册、各类寄存器、各类API,学会看手册、学会搜索、学会提问即可。

思考底层逻辑,技术的出现是因为有场景需要,而不是技术本身,单片机所有的功能点都是为解决某个问题的。

最后,分享初级嵌入开发工程师技术栈供您参考,更多资源获取可以关注“嵌入式思维导图”:

打开网易新闻 查看更多图片

说了这么多,大家记得留意下方评论第一条(或者私信我)有干货~