关注公众号,回复“入门资料”获取单片机入门到高级开挂教程
开发板带你入门,我们带你飞
文 | 无际(微信:2777492857)
全文约3959字,阅读大约需要 10 分钟
很多单片机开发者,即使有一定经验,也可能对芯片内部的运作机制不甚了了。
你写的代码,烧录进去,灯亮了,串口通了,电机转了,感觉挺神奇,但具体是芯片内部哪个小零件在干活,它们之间又是怎么协同工作、传递信息的,是不是有点模糊?
或者,你想优化程序性能,减少功耗,但因为不清楚硬件的工作机制,不知道从哪里下手,只能凭感觉调整,效果嘛…随缘?
遇到奇奇怪怪的 Bug,比如某个外设突然不听使唤,或者程序莫名其妙跑飞,调试起来像是在猜谜,只能一遍遍试错,心里默念“玄学,这绝对是玄学”?
翻开厚厚的数据手册(Datasheet),看到密密麻麻的寄存器地址、总线架构图、时钟树,是不是感觉像在读天书,恨不得直接跳到代码示例那一页?
以上,都是我以前学单片机经历过的问题。
这种“知其然不知其所以然”的状态,短期内似乎不影响你完成基本功能开发,但长远来看,它会成为你技术成长的隐形天花板。
你会发现,当问题超越了简单的逻辑错误,涉及到硬件时序、资源冲突、中断优先级等底层问题时,缺乏内部结构知识会让你束手无策,大大延长调试时间。
不懂CPU如何取指执行,不了解内存访问速度差异,不清楚外设与CPU的交互方式(轮询、中断、DMA),你就很难写出真正高效、低耗的代码。
无法根据具体应用场景,合理选择芯片资源,有效规划内存使用,设计健壮可靠的系统架构。比如,在多任务环境下,不理解中断和上下文切换,就容易写出有潜在风险的代码。
像实时操作系统(RTOS)的移植与应用、复杂驱动程序的开发、底层协议栈的理解等进阶内容,都建立在对单片机硬件结构深刻理解的基础上。
放心,我们不搞纯理论轰炸。这篇文章会用大白话,为你梳理单片机最核心的三个组成部分:CPU、内存、外设,并讲清楚它们之间是如何通过总线系统协同工作的。
读完后,你将:
?在脑海中建立一个清晰的单片机内部宏观模型。
?理解代码是如何被执行,数据是如何被存储和访问的。
?明白外设是如何被控制,以及它们如何与CPU互动的。
?更有信心地阅读数据手册,理解那些看似复杂的术语和图表。
?为后续学习更高级的主题(如中断、DMA、RTOS)打下坚实的基础。
一个单片机(Microcontroller Unit, MCU)就像一个微型的计算机系统,被集成到了一块芯片上。它虽小,五脏俱全,主要包含以下几个关键部分:
1. 中央处理器 (CPU):不知疲倦的大脑
CPU是单片机的核心,是真正干活的那个“老大哥”。它的主要职责是:
wulrii5qdsp64029957729.png
?取指令: 从存储器(通常是Flash)中,按照程序计数器(PC)的指示,读取下一条要执行的指令。
?译码: 分析这条指令,搞明白要做什么操作(比如加法、数据搬运、跳转等)。
?执行: 调用相应的运算单元(如ALU算术逻辑单元)或控制单元,完成指令要求的工作。这可能涉及到读写内存数据、操作外设寄存器等。
市面上常见的单片机CPU核有多种,比如经典的8051,或者现在更主流的ARM Cortex-M系列(M0, M3, M4, M7等)。不同的核,其指令集、运算能力、功耗特性有所不同,但其基本工作原理——取指、译码、执行——是相通的。
简单来说,CPU就是那个严格按照你的代码(编译后的机器指令)一步步执行,完成各种计算、判断和控制任务的“执行者”。它很忙,一直在不停地奔跑。
2. 内存 (Memory)
程序代码和运行时产生的数据总得有地方放吧?这就是内存的任务。单片机中的内存主要分为两大类:
?程序存储器 (Program Memory):通常是 Flash Memory
?特点:非易失性(掉电后数据不丢失)。
?用途:存放你编写、编译后的程序代码(机器指令)。CPU就是从这里读取指令来执行的。通常容量较大(几十KB到几MB不等)。它一般是只读的(在程序运行时),需要特殊的编程操作才能写入。
?数据存储器 (Data Memory):通常是 SRAM (Static RAM)
?特点:易失性(掉电后数据丢失)。读写速度非常快。
?用途:存放程序运行时产生的临时数据、变量、函数调用的栈信息、动态分配的堆空间等。CPU进行计算时,需要频繁读写SRAM。容量相对Flash较小(几KB到几百KB不等)。
内存映射 (Memory Map):
这是一个至关重要的概念!在单片机内部,无论是Flash、SRAM,还是后面要讲的外设寄存器,它们都被统一安排在一个地址空间内。就像城市地图,每个存储单元或寄存器都有一个唯一的地址编号。CPU想要访问某个位置(读数据、写数据、取指令),就通过这个地址去定位。
fl5hzv5nvuf64029957829.png
数据手册里通常会有一张内存映射图,告诉你哪个地址范围对应Flash,哪个范围对应SRAM,哪个范围又分配给了哪个外设。看懂这张图,你就知道该如何通过地址去访问特定的硬件资源了。
3. 外设 (Peripherals)
要与外部世界互动,就需要各种各样的外设。外设是单片机感知外部信号、控制外部器件的接口。常见的外设包括:
?GPIO (General Purpose Input/Output): 通用输入输出口。可以配置为输入(检测外部高低电平)或输出(控制LED亮灭、驱动继电器等)。这是最基本、最常用的外设。
?UART (Universal Asynchronous Receiver/Transmitter): 异步串口。用于与其他设备(如电脑、传感器模块)进行串行通信。
?SPI (Serial Peripheral Interface) / I2C (Inter-Integrated Circuit): 串行通信接口。常用于连接其他芯片,如传感器、存储器、显示屏等。
?Timers/Counters: 定时器/计数器。可以用来产生精确的延时、测量时间间隔、生成PWM波(控制电机转速、呼吸灯效果)等。
?ADC (Analog-to-Digital Converter): 模数转换器。将外部的模拟信号(如传感器电压)转换为数字值,供CPU处理。
?DAC (Digital-to-Analog Converter): 数模转换器。将CPU处理后的数字值转换为模拟信号输出。
?...还有看门狗(Watchdog)、DMA控制器、USB接口、CAN控制器等等,根据芯片型号不同而异。
外设是如何被CPU控制的?
答案是:通过寄存器 (Registers)。
每个外设内部都有一组寄存器,它们就像这个外设的控制面板和状态显示屏。这些寄存器也被映射到了内存地址空间中(就是前面说的内存映射)。
CPU通过向这些特定地址写入不同的值,来配置外设的工作模式(比如设置GPIO是输入还是输出,配置UART的波特率),启动或停止外设工作,发送数据等。同时,CPU也可以通过读取这些寄存器,来获取外设的状态(比如串口是否接收到数据,ADC转换是否完成)或接收到的数据。
所以,我们平时在代码里包含的那些stm32f10x.h或类似的头文件,里面定义的大量宏,很多就是这些外设寄存器的地址和位的含义。我们调用库函数配置外设,其底层本质就是在读写这些特定地址的寄存器。
4. 总线 (Bus)
CPU、内存、外设,这三大块不是孤立存在的。它们需要一种方式来互相传递信息(地址、数据、控制信号)。这个信息通道就是总线。
你可以把总线想象成单片机内部的高速公路系统:
2hntqt0oavr64029957929.png
?地址总线 (Address Bus): 单向,由CPU发出。CPU想访问某个内存单元或外设寄存器时,就把它的地址放到地址总线上。地址总线的宽度决定了CPU能访问的最大内存空间(例如32位地址总线可以访问2^32=4GB地址空间)。
?数据总线 (Data Bus): 双向。用于在CPU、内存、外设之间传输实际的数据。数据总线的宽度决定了一次能传输多少位数据(如8位、16位、32位)。
?控制总线 (Control Bus): 传输控制信号。比如CPU发出的读信号或写信号,内存或外设发出的就绪信号、中断请求信号等。它负责协调整个数据传输过程。
当CPU要从SRAM读取一个变量时,大致过程是:
1.CPU将该变量的地址放到地址总线上。
2.CPU在控制总线上发出“读”信号。
3.SRAM接收到地址和读信号,找到对应的数据。
4.SRAM将数据放到数据总线上。
5.CPU从数据总线上取走数据。
当CPU要向GPIO端口写入数据以点亮LED时,过程类似:
1.CPU将GPIO端口数据寄存器的地址放到地址总线上。
2.CPU将要写入的数据(比如0xFF)放到数据总线上。
3.CPU在控制总线上发出“写”信号。
4.GPIO外设接收到地址、数据和写信号,将数据锁存到其内部的数据寄存器中,从而改变引脚电平。
总线架构的学问:
在一些性能较高的单片机(如ARM Cortex-M3/M4/M7)中,通常不止一条总线。
可能会有高速总线(如AHB, Advanced High-performance Bus)连接CPU、Flash、SRAM等需要快速访问的部件,以及低速总线(如APB, Advanced Peripheral Bus)连接大部分外设。这样做是为了平衡性能和功耗,避免慢速外设拖慢高速部件的访问。
cjdaejtqmu064029958029.png
数据手册中的总线架构图就是描绘这种连接关系的。
中断与DMA
除了CPU主动读写,外设也能主动“打扰”CPU。
当外设完成某个任务(如串口收到数据、ADC转换完毕、定时器溢出)时,它可以向CPU发送一个 中断请求 。CPU收到中断请求后,如果允许该中断,就会暂停当前正在执行的主程序,转而去执行一个预先设定好的 中断服务函数 (Interrupt Service Routine, ISR),处理这个外设事件,处理完毕后再返回主程序断点处继续执行。中断机制极大地提高了CPU效率,避免了CPU需要不断轮询检查外设状态的低效做法。
DMA (Direct Memory Access) 则更进一步。对于大量数据的传输(比如从ADC连续采集数据存入内存,或者将内存中的图像数据发送到显示屏),如果让CPU一个字节一个字节地搬运,会非常占用CPU资源。
DMA控制器就像一个“搬运工”,CPU可以配置好DMA,告诉它源地址、目标地址、传输数量,然后DMA就可以在不需要CPU干预的情况下,直接在外设和内存之间,或者内存与内存之间高速传输数据,传输完成后再通过中断通知CPU。这极大地解放了CPU,让它可以去做更重要的计算任务。
理解中断和DMA的工作原理,同样离不开对CPU、内存、外设以及它们之间总线连接关系的认识。
单片机虽小,其内部却是一个组织严密、分工明确、协作高效的微型世界。理解了CPU的统领、内存的支撑、外设的感知与执行,以及总线的连接,你就掌握了解读数据手册、高效调试、优化性能、设计稳健系统的“金钥匙”。不再隔“芯”看物,方能随“芯”所欲。
end
e5xiyu4slzi64029958129.jpg
下面是更多无际原创的个人成长经历、行业经验、技术干货。
1.电子工程师是怎样的成长之路?10年5000字总结
2.如何快速看懂别人的代码和思维
3.单片机开发项目全局变量太多怎么管理?
4.C语言开发单片机为什么大多数都采用全局变量的形式?
5.单片机怎么实现模块化编程?实用程度让人发指!
6.c语言回调函数的使用及实际作用详解
7.手把手教你c语言队列实现代码,通俗易懂超详细!
8.c语言指针用法详解,通俗易懂超详细! |