前言
很多单片机开发工程师都能熟练的使用单片机的各种外设,但是对单片机的系统构架却了解的很少,主要是那一张系统构架图看不明白,各种专业的缩写词不理解。这种知其然不知其所以然的情况居然丝毫不影响使用单片机,其实这也很正常,就像你不了解手机各模块的原理,但是可以熟练的使用手机看视频、发消息。作为一名工程师,最好还是掌握单片机的系统框架,以进一步提升自己的天花板。
代码在MCU中怎么存储
可以先看一段简单的代码,里面有全局变量、局部变量、常量,还有函数代码。代码经过编译之后,编译器会将不同的东西分类,然后存在MCU的不同区域
uint8_t a =0; //全局变量,已经初始化,放在已初始化全局变量和静态变量区,.data段
static uint8_t b = 1; //静态变量,已经初始化,放在已初始化全局变量和静态变量区,.data段
char *p1; //全局变量,未初始化,放在全局位初始化区, .bss段
const uint8_t c = 2; //const 修饰的变量,放在.rodata段
volatile const uint8_t d = 3; //.data段
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t e =0; //局部变量,放在栈中
static uint8_t f = 1; //静态变量,已经初始化,放在已初始化全局变量和静态变量区,.data段
uint8_t *p2; //局部变量,放在栈中
char *p3 = "123456";//"123456" == 123456\0 放在常量区,p3放在栈
strcpy(p1,"1234567");
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
while (1)
{
}
}
不同的内容分区表
单片机的内存是包含两部分的:SRAM和FLASH。
SARM相当于电脑的内存,断电之后里面的数据都没有了;
FLASH相当于电脑的硬盘,断电之后里面的数据还在。
栈(stack):函数的形参和局部变量都存在这个地方
堆(heap):程序员使用malloc函数申请的一段内存区,MCU上用的不多
数据区:存放全局变量、静态变量、常量,数据区有(SRAM数据区和FLASH数据区)
程序代码(code):存放函数体的二级制代码,存放在FLASH
从这个表格可以看出,代码是存放在FLASH里面的,因为掉电不丢失,所以每次上电MCU可以重新运行。只读的数据,就是那些常量,也是存放在FLASH里面的。静态变量,全局变量,局部变量都是存在SRAM中。数据分区的这些工作都是编译器来完成的,感兴趣的可以去研究一下。
前面的一段代码用Keil编译器编译之后,在编译结果中有显示Program Size这么一行。
Code = 4172表示程序代码的大小
RO-data = 360表示常量区的大小
RW-data = 20表示栈区、堆区、全局与静态变量区的大小
ZI-data = 1092表示未初始化的全局变量区大小
STM32F103单片机系统构架图
单片机的数据是如何在内存与外设之间传输的
还是通过一个简单的代码来看看,通过USART1往外面发送5个数据,
1、先定一个全局变量数据 uint8_t Tx_Buffer[] ={0xAA, 0x11, 0x22, 0x33, 0xBB};
2、调用HAL_UART_Transmit(&huart1, Tx_Buffer, sizeof(Tx_Buffer), 10)函数将定义的数据发出去
uint8_t Tx_Buffer[] ={0xAA, 0x11, 0x22, 0x33, 0xBB}; //定义一个全局变量
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
while (1)
{
//通过USART1将数据发出去
HAL_UART_Transmit(&huart1, Tx_Buffer, sizeof(Tx_Buffer), 10);
HAL_Delay(1000);
}
}
这个简单的串口发送数据,因为要发送的数据是个全局变量,数据存在SRAM的全局变量区。所以数据流是这么进行的:
第一步:CPU从SRAM中取数据(SARM的数据经过总线矩阵,DCode总线到CPU);
第二步:CPU将数据送到USART外设的发送缓冲区(CPU的数据经过DCode总线、总线矩阵、AHB系统总线、桥接1到USART1)
串口接收数据就是上面的逆过程。其他外设ADC、USB、SPI、IIC的数据流向也基本是这样。
常量是存在Flash里面的,CPU调用常量的路径如下,Flash里面的常量数据经过Flash接口,再经过总线矩阵、DCode总线,到达CPU。
代码也是存在Flash里面,程序的运行,也是从Flash中去指令,路径是指令从Flash、到Flash接口,再经过ICode总线到达CPU。
MCU的DMA怎么传输数据
MCU的架构图中有很大的一部分是DMA(直接存储器访问),有直接存储器访问,就有间接存储器访问,什么是间接存储器访问?前面介绍的,数据从SRAM到CPU,在从CPU到外设这个过程就叫间接存储器访问,简单点理解就是,只要数据经过了CPU就是间接的。就像你租房子的时候,从房东手上租房子就是直接租,从中介那边再经过房东就是间接租,显然从房东那边直接租更划算。MCU的数据传输也是一样,为什么数据都要经过CPU转下手,从内存直接到内存可不可以?从内存直接到外设可不可以?从外设直接到外设可不可以?答案是肯定的,肯定可以,那就要用到DMA总线,正好Cortex-M 3系列单片机,很多都有DMA总线,基本是标配。
内存到内存的DMA传输路径
DMA1和DMA2的功能是差不多,就看单片机是怎么分配的,以DMA1为例,在SRAM中建立两个缓冲区(也就是建两个变量)A和B,将A里面的数据给B,用DMA1来实现:就是A中的数据经过总线矩阵、DMA总线,DMA1的某个通道(比如通道1)、DMA总线、总线矩阵、到达B;数据不经过CPU,CPU就轻松多了。
内存到外设(外设到内存)的数据路径
比如将SRAM中的数据经过USART3外设发出去,
数据从SRAM,经过总线矩阵、DMA总线、DMA中的某个通道、DMA总线、总线矩阵、AHB系统总线、桥接2、APB1总线、USART3外设的寄存器。
外设到内存就是一个相反的过程,比如串口接收数据。
外设到外设的数据路径
同理,只经过DMA总线,不经过CPU,但是工程上外设到外设用的不多,以后用到了再展开。
虽然DMA数据传输不仅过CPU,但是DMA也算是一个工具,是要接收CPU的控制的,DMA的通道就这么多,谁先用,谁后用,怎么协调资源还是要CPU来决定的,CPU就是通过system总线来管理总线矩阵的
FSMC的作用
FSMC == Flexible Static Memory Controller == 灵活的静态存储器控制器
这个就相当于你电脑的内存扩展口,你的64位电脑可以使用16G的内存,但是有的电脑只配了一个8G的内存条,你可以自己再插一张8G内存条进去。单片机安的FSMC就差不多这个意思,单片机都有个内=内置的SRAM,有的大有的小,一般是够用的。但是如果你要跑一些炫丽的界面图像,那内存小了就会比较卡,需要扩展内存,就需要用到FSMC了,这个接口可以接SRAM、NOR Flash、NAND Flash,但是不能接SDRAM。
总结
其实单片机就这么点内容CPU、内存、外设,其实各种处理器也都是这样的,知道他们之间的数据是怎么流通的,命令怎么调用,基本就掌握了,其他的只是去熟悉各种外设怎么使用而已。