(STM32)全局变量的初始值怎么实现的?

单片机如何从上电复位执行到main函数?系统上电后CPU执行的第一条是Reset_Handler函数的第一条语句。51单片机最小系统:单片机、复位电路、晶振(时钟)电路、电源最小系统用到的引脚此时,按下电源开关给单片机上电,下载软件会识别出单片机,然后自动下载程序。

(STM32)全局变量的初始值怎么实现的?

\插曲:文末有惊喜~///

从事嵌入式开发的伙伴可能思考过一个问题。 我们通常使用芯片厂家提供的驱动库和初始化文件,直接从main函数中编写程序。 那么系统上电后,程序是如何引导到main函数中执行的呢? 呢绒? 另外,系统上电后RAM中的数据是随机的,那么定义的全局变量的初始值是如何实现的呢?

接下来我就带着这两个问题,以Cortex-M架构为例,使用IAR EWARM作为编译工具链,从系统上电后执行的第一条代码开始,梳理一下系统的启动流程,并了解编译器在此期间所做的工作。 其他工具链,例如Keil和GCC,在系统初始化过程中执行类似的工作,但具体实现有所不同。

1.启动文件

芯片厂家提供的启动文件一般都是用汇编语言编写的,也有少数使用C语言。 一般来说,启动文件中至少有以下两部分内容:

1.向量表

2. 默认中断和异常处理程序

向量表实际上是一个数组,放置在内存的零地址处,每个元素存储每个中断或异常处理程序的入口地址。 以基于IAR工具的STM32F107芯片的启动文件为例:

在文件的开头定义了一个名为 __vector_table 的全局符号。 “DATA”的作用是在代码段中定义一个数据区,用作向量表。 数据区的内容是使用DCD指令定义的32位宽度常数。 除了第一个sfe(CSTACK)比较特殊外,其他常量都是异常和中断服务程序的地址(函数名在编译时会被替换为函数入口地址)。 sfe(CSTACK)是IAR汇编器段操作,用于获取段的完成地址。 这里的目的是什么?

其实这就是获取栈基地址的操作。 IAR 在链接描述文件 (*.icf) 文件中定义堆栈。 它实际上定义了一个名为“CSTACK”的空闲块(block),如下图脚本命令所示。 所谓块,就是预留一块不间断的地址空间,作为栈或者堆使用。 当然,块也可以用于内容,例如可以用于管理段,但这超出了今天讨论的范围。

我们知道Cortex-M架构的堆栈模型是全递减堆栈。 栈是从高地址向低地址增长的,所以栈的基地址就是CSTACK的完成地址。

向量表的第一个元素是由 Cortex-M 架构定义的堆栈基地址。 系统上电后,硬件自动从向量表中获取并设置主堆栈指针MSP,不像其他ARM架构需要通过软件设置堆栈指针。

向量表中的第二个元素是复位异常(Reset_Handler)的入口地址。 系统上电后,硬件自动从__vector_table+4的位置读取,并从读取的地址开始执行。 系统上电后CPU执行的第一条语句是Reset_Handler函数的第一条语句。

上述THUMB命令表示后面的代码采用THUMB模式(Cortex-M仅支持Thumb-2指令集); SECTION用于定义一个段,段名称为“.ResetHandler”,段类型为代码(CODE); REODER 指示链接器以给定名称打开一个新节; ROOT 指示链接器,当节中的符号未被引用时,链接器不能丢弃该节。

PUBWEAK 是一个弱定义。 如果用户在别处写了中断处理函数,那么在连接的时候实际上是链接了用户写的服务函数。 启动文件中用汇编语言编写的服务函数将被忽略。 之所以所有的异常和中断服务函数都必须以弱定义的方式写在启动文件中,是为了防止用户在不写服务函数的情况下开启并触发中断,造成系统的不确定性。

2.系统初始化流程

在EWARM的项目Options>Debugger>Setup中,取消勾选“Run to”,这样进入调试后就会停在最先执行的代码位置:

进入调试后,会停在启动文件中Reset_Handler函数的第一条汇编指令处:

此时通过寄存器观察窗口看到的SP值为0x20009820。 通过链接时生成的map文件查看CSTACK的地址范围。 0x20009820正是CSTACK的结束地址。 有了MSP,C代码就可以运行了。

systemInit函数是芯片制造商基于ARM的CMSIS标准提供的基本系统配置函数,用于配置基本时钟系统和向量表重定位。 这里的LDR是一条伪指令,它将SystemInit函数的地址加载到寄存器R0中。 它实际上是通过PC偏移寻址来获取SystemInit的地址的。

从上图可以发现一个问题。 在反汇编窗口中可以观察到SystemInit的地址是0x20000150,但是加载到R0寄存器后是0x20000151。 这是因为当使用跳转指令更新PC时,需要将PC的LSB设置为1以指示THUMB模式。 由于 Cortex-M 不支持 ARM 模式,因此 LSB 始终为 1。

执行完芯片厂家提供的SystemInit函数后,跳转到__iar_program_start,这是IAR编译器提供的初始化代码的入口。

__iar_program_start首先会执行两个函数:__iar_init_core和__iar_init_vfp,可以完成一些与CPU和FPU相关的初始化操作。 在一些ARM架构封装的运行库中,将会提供这两个函数,用户也可以重写这两个函数来自行实现一些相关操作。

之后跳转到__cmain函数执行。 在 __cmain 中调用 __low_level_init 函数。 该函数专门用于为用户提供初步的初始化操作。 它在全局变量初始化之前执行。 例如,可以在__low_level_init中初始化SDRAM,这样就可以将全局变量定义到SDRAM中使用。

__low_level_init 可以写入任何 C 文件中。 注意它的返回值。 如果返回0,则跳过后续的变量初始化操作。 一般情况下返回1。

3、全局变量的初始化

之后,进入__iar_data_init3函数,这里将完成所有带初始值的全局/静态变量的赋值,以及零初始化的全局/静态变量的清除操作。 会分别调用__iar_copy_init3和__iar_zero_init3,将链接保存在ROM区中的编译器生成的变量的初始值复制到该变量的地址。 注意,新EWARM版本默认的变量初始化操作可能会使用压缩算法,实际变量初始化调用的函数可能会有所不同。

在全局变量初始化之前,通过watch窗口可以看到变量的值都是随机数。

__iar_data_init3执行完成后,所有变量的初始值赋值已经完成。

在__cmain函数的最后,跳转到用户的main函数,最后初始化用户的代码执行。

了解了编译器提供的初始化流程和处理器架构,我们就可以根据自己的需求定制系统的初始化。

例如,在进入__iar_program_start之前,可以进行必要的硬件初始化操作,可以用汇编或C编写。也可以手动控制变量的初始化操作,自己实现变量的初始化。 甚至,可以自己从复位序列启动到主函数,而不需要使用IAR编译器提供的初始化操作。

硬件开发工具:

Altium 设计师 17.1

编程开发工具:

凯尔4

程序下载工具:

STC-ISP

串口驱动:

CH341SER

单片机最小系统介绍

微控制器是一种集成电路芯片,采用超大规模集成电路技术,将具有数据处理能力的中央处理器(CPU)、随机存取存储器(RAM)、只读存储器(ROM)、各种I/O端口、中断系统和计时器。 /计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路复用器、A/D转换器等电路)集成到一块硅芯片上,形成一个小而完整的微计算机系统。 广泛应用于控制领域。 从20世纪80年代开始,从当时的4位、8位单片机发展到现在的300M高速单片机。 本文中的单片机特指51单片机,具体芯片型号为STC89C52RC。 需要说明的是,STC89C51、STC89C52、AT89C51、AT89C52都是51单片机的具体芯片型号。

最小系统组件:

51单片机最小系统:单片机、复位电路、晶振(时钟)电路、电源

使用的最少系统引脚

1. 主电源引脚(2针)

VCC:电源输入和写入,接+5V电源

GND:地线

2. 外部晶振引脚(2)

XTAL1:片内振荡电路输入写入端

XTAL2:片内振荡电路输出端

3. 控制引脚(4)

RST/VPP:复位引脚

电源

设计中采用的电源接口为DC 5V。 USB座可以检测手机的充电端口并从电脑的USB端口获取电力。 连接好线路后,按下电源开关,单片机就开始工作。

输入电源和启动按钮

直流5V连接线

复位电路

复位电路

电路图中,电容尺寸为10uf,电阻尺寸为10k。

在5V正常工作的51单片机中,小于1.5V的电压信号为低电平信号,大于1.5V的电压信号为高电平信号。 可以计算出,将电容充电到0.7倍电源电压,即电容两端电压为3.5V,电阻两端电压为1.5V时,所需时间约为T=RC=10K* 10UF=0.1S。

也就是说,单片机上电启动的0.1S内,电容两端的电压从0-3.5V持续升高。 此时10K电阻两端的电压继续从5-1.5V下降(串联电路两端电压之和即为总电压),所以RST引脚收到的电压是5V-1.5V的过程,即从高电平到低电平的过程。

单片机的RST引脚高电平有效,即复位; 低电平无效,即单片机正常工作。 因此,在开机后0.1S内,单片机系统的RST引脚收到持续约0.1S的高电平信号,从而实现自动复位。

单片机启动0.1S后,电容C两端电压继续充电至5V。 此时10K电阻两端电压接近0V,RST为低电平,系统正常工作。 当按下按钮时,开关打开。 此时电容器两端形成回路,电容器短路。 因此,在按下按钮的过程中,电容器首先释放先前充电的电力。 随着时间的推移,电容电压在0.1S内从5V释放到1.5V甚至更低。 根据串联电路各部分的电压之和,此时10K电阻两端的电压为3.5V,甚至更大,因此RST引脚再次恢复为高电平。 微控制器系统自动复位。

晶体振荡器电路

晶体振荡器电路

晶体振荡器的基本概念。 晶振的全称是晶振。 每个单片机系统中都存在一个晶体振荡器。 晶振是由石英晶体加工而成,并镀有电极。 其主要特点是通电后会产生机械振荡,可以给单片机提供稳定的时钟源。 晶体振荡器提供的时钟频率越高,微控制器的运行速度就越快。 晶振是利用能够将电能和机械能相互转换的晶体工作在谐振状态,提供稳定、准确的单频振荡。

晶振开始振荡后,产生的振动信号将经过XTAL1引脚,依次经过振荡器和时钟发生器处理,得到机器周期信号,作为指令运行的依据。 51单片机常用晶振有12M和11.0592M

零部件清单和原型焊接

零件清单

注释描述设计器足迹库参考数量

30P陶瓷电容C2、C3CAP-2.54Cap2

10uF/16V 直插电解电容 CE1CAP 1.5*4*8CE1

CON9 直插电阻 10KJ0R SIP9-2.54CON91

CON22 排针 J4HDR2.54-LI-2PCON21

接头 44 针 JP3、P6HDR2.54-LI-4PHEADER 42

红色插件5mm LEDLED1、LED2LED 5MM-RLED-5MM2

CON84 排针 P0、P1、P2、P3HDR2.54-LI-8PCON84

KEY自锁按钮 POWER_BUTTONSW-8X8X8HEADER 3X21

DC 5V电源 DC 5V插座 PW_5VDC05HEADER 31

10K电阻R1AXIAL0.3RES21

2K电阻R2、R3AXIAL0.3RES22

SW-PB触摸按钮S1SW-0606SW-PB1

具有 4K 闪存 ROMU1DIP40AT89C511 的 STC89C52RC8 位微控制器

11.0592M晶体振荡器Y1OSC HC-49SCRYSTAL1

如果不想将芯片直接焊接到板上,可以购买如下图的黑色锁紧座。 规格选择DIP40

PCB板生产

方法一:学校实验室常用的DIY腐蚀电路板制作(略)

方法二:外包给专业的PCB厂。 推荐嘉里创#

可代发货,需要的请私信。

空板正反面:

空板

焊接注意事项

直插式电解电容和LED灯都有正负极之分。

区分电解电容的正负极:

1、看实际外壳

2、看引脚长度:

电解电容的正极引线比较长,负极引线稍短。

LED灯正负极性区分:

1. 还可以看到引脚的长度。 发光二极管的正极和负极分别是长引脚和短引脚。

2. 将万用表拨至二极管档位,分别短接 LED 灯引脚。 如果亮起,则红色测试线连接到正极。

最终对象:

实际焊接的物体如图所示

程序烧录和测试

测试所用的51单片机型号为STC89C52RC,是国产品牌宏晶科技STC量产的8051单片机。

测试代码

#包括

#包括

//数据类型定义

typedef 无符号字符 uchar;

typedef 无符号整型 uint;

uchar 标志1s = 0;

uint one_sec_flag = 0;

sbit TEST_LED=P1^0;

无效主()

EA=1;//使能总中断

TMOD=0X01; //T0的工作模式为模式1

TH0=0X4C;

TL0=0X00;//11.0592M晶振50ms定时初始值

ET0=1; //允许定时器1中断

TR0=1;//启动定时器0

同时(1)

if(flag1s)//每秒刷新一次

测试 LED = 0;

}别的{

测试 LED = 1;

void Timer0() 中断 1

TH0=0XBB;

TL0=0X00;

if(++one_sec_flag

return;//提前完成函数

如果(标志1)

标志1s = 0;

}别的{

标志1s = 1;

one_sec_flag=0;

编译后生成test.hex烧录文件。

下载器和下载驱动程序

STC89C52单片机下载器实际上是USB转TTL串口,如下图

某宝上的下载器

驱动程序:压缩包中的CH341SER.EXE

必须先安装驱动程序,然后才能将代码下载到微​​控制器。

程序下载

硬件准备:

下载器的RXD连接到芯片的TXD(P30),下载器的TXD连接到芯片的RXD(P31)。 这样的设计引出了芯片的RXD和TXD,可以如上图所示连接。

软件准备:

双击STC-ISP.exe打开并下载步骤

1选择单片机型号

2.选择下载器的串口

3.打开编译生成的HEX文件

4.点击下载

下载界面

等待

此时按下电源开关即可给单片机上电。 下载软件会识别单片机,然后自动下载程序。 下载成功后会有提醒。

编程成功

测试效果:测试LED灯每隔一秒闪烁一次。

新一代编程工具-STM32CubeProgrammer

STM32CubeProgrammer(STM32CubeProg)是STM32微控制器的专用编程工具。 STM32用户都知道,在完成程序调试时,需要对芯片进行烧录和编程。 一般有三种选择:通过调试接口[JTAG/SWD]?

单片机

STM32单片机+LCD1602液晶显示模块的部分引脚错误

2024-2-5 11:02:47

单片机

从别的地方挖来了他们三巨头,CFA、FRM双料持证人

2024-2-5 12:05:11

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索