1.STM32的上电启动过程
启动文件
我们正常在操作一款单片机的时候,都是从main函数开始进行编程的,但是单片机上电是从main函数开始执行的吗?答案当然是否定的,在main函数之前单片机最先执行的是硬件设置SP、PC然后是“启动文件”,一般主要是项目文件里面的startup_xxxxx.s文件。其实这个就是我们常说的Bootloader。
其实不光STM32系列单片机是这样,我们接触的NXP的微控制器、TI的MSP430以及51单片机等等其实都是有上述的启动文件的。启动文件负责的就是从单片机复位开始到main函数之前这段时间所需要进行的工作。我们一般很少接触启动文件的主要原因是开发环境往往给开发者自动的提供了这个启动文件,不需要我们再去操心,直接从main函数开始进行设计就可以了。
STM32三种启动方式
接触过STM32系列单片机的朋友应该知道STM32有三种启动模式,用户可以通过设置BOOT0和BOOT1的引脚电平状态,来选择复位后的启动模式。
需要注意的是STM32上电复位以后,代码区都是从0x00000000开始的,三种启动模式只是将各自存储空间的地址映射到0x00000000中。
2.STM32上电到main函数之前做了什么事?
具体看一下从用户的Flash启动STM32,从上电到main函数之间的这段时间都做了什么。
第一步是硬件设置SP、PC
我们参考《Cortex-M3权威指南》向量表章节表7.6,如下图所示:
前两段地址主要是用来指定SP和PC的初值,上一节我们已经知道了映射关系,所以这时已自动从0x08000000位置处读取数据赋值给了栈指针SP,从0x08000004位置处读取数据赋值给了PC。需要注意的是这个复位向量初始值并不是固定的,可以通过一个叫“向量表偏移量寄存器”来修改定位。
下图是我们那个开源OLED时钟项目的HEX文件,用J-Flash打开就可以看到设置完的SP=0x20005B88,PC=0x0800282D。
第二步是设置系统时钟
我们接着来追踪系统的运行轨迹,上面我们已经知道了PC的地址为0x0800282D,但是这没有遵循4字节对齐,我们将其对齐为0x0800282C,这时我们打开项目文件里面的.map文件,找到这个地址,如下图示:
我们发现来到了第一节说的startup_xxxxx.s文件,我们打开startup文件找到:
我们发现运行到了SystemInit,C的世界我们就不陌生了,在项目文件的system_stm32f10x.c里面可以找到SystemInit函数,也就是初始化系统时钟了。
第三步是___main
到这里大家可能会以为已经到了main函数了,其实不是这样的。___main和main是不一样的,我们寻找这个___main会发现找不到,startup文件里面没有,map文件里面也没有。其实它是在MDK自带的库里面了,主要的功能是软件设置SP、加载.data.bss并初始化栈区。由于需要在线跟踪才能看到,我在这里就不给大家列出来了,感兴趣的朋友可以深入研究一下。
最后来到C的世界
在执行到___main的最后就跳转到了C文件的main函数了。
最后用一张图来整体看一下流程:
总 结
到这里STM32的存储器以及上电启动过程就完整的总结完了,希望对大家有所帮助,大家如果感兴趣可以在调试STM32的时候一步一步的来跟踪一下看看,每一款单片机的启动文件其实都是很值得玩味的,对我们系统的来体会控制器的架构、指令集、中断向量等内容是很有帮助的。大家如果将启动过程了解清楚了对我们后面来进行IAP等有意思的操作是很有帮助的。
3.IIC总线通讯
iic通讯一般采用一主多从的方式.同一时间要么在发送信息,要么在读取信息(半双工通讯)
标准的写数据帧(主机向从机写数据)
解释以上的写数据帧
- S:起始信号(在SCL高电平期间,SDA由高跳低),此时主机发送起始信号
逻辑1 (时钟线为高电平时,数据线上的数据必修保持稳定) 时钟线为高电平,数据线为高电平表示逻辑1
逻辑0 (时钟线为高电平时,数据线上的数据必修保持稳定) 时钟线为高电平,数据线为低电平表示逻辑0 - 主机发送从机设备地址((从机的设备地址 7位,从设备的地址码唯一),设备的地址码一般是硬件写死的,有的有跳线可以改.)
-
读/写位. 主机发送写位(0). 置为0位写数据,置为1位读数据.
- 从机发送应答信号,这个信号是由从机发给主机的.收到信息回复0,未收到或者主机读取接受完毕回复1.
- 主机发送从机的寄存器地址(8位)
- 从机返回应答信号.收到信息回复0.未收到回复1.
- 主机发送数据(要给寄存器写入的数据)
- 从机发送应答信号. 0表示写入数据成功.1表示失败.
- 写入停止位(结束信号) 时钟信号为高时,数据信号由低到高跳变(和起始信号相反)
读数据帧
解释以上的读数据帧
主机发送起始信号
主机发送从机设备地址
主机发送写位(0)
从机发送应答信号
主机发送从机寄存器的地址
从机发送应答信号
主机再次发送起始信号
主机再次发送设备地址
主机发送读数据位(1)
从机把寄存器里的数据发送给主机
主机发送应答信号,此时位1表示读取从机寄存器数据完毕.这里需要注意是主机发送应答信号表示读数据完毕.
在写数据帧中主机发送数据,从机负责应答,每次主机连续发超过8位都需要从机应答.
在读数据帧中主机每次连续发超过8位也需要从机应答.在读数据帧发送了两次起始信号,且在第二次起始信号中,主机发设备地址+读数据位(共8位),从机发8位数据.此处并没有主机连续发送数据的情况,所有没有要从机应答,最后是主机发送应答信号,表示已经接受到数据(读取数据完毕).
4.spi通讯
5.USART通信协议
6.RS485、RS232、RS422通信协议
一、RS232
硬件特性:
全双工串行,速率1Mbps,其传输波特率为19200bund/s,距离15m,容易产生共模干扰
且只能一对一通信
电平特性:
当输出电平为-5V到-15V时代表逻辑”1“
当输出电平为-5V到+15V时代表逻辑”0”
常用转换IC收发器:
MAX3232
总结:通信距离太短,通信速度较慢,现在工业上已经用得比较少了
二、RS485:
硬件特性:
半双工串行通信,距离1500m,速率:10Mbps,可实现多设备组网:根据所用的RS485转换芯片的不同,组网设备数量的上限为64,128,256个不等。
两条差分线:A和B,双绞线,抗干扰性强
特别注意:附近的电焊或者雷电最容易形成干扰
对于发送端:
当2V<A-B<6V时候, RS485被认为发送高电平(逻辑1)
当-6V<A-B<-2V时候,RS485被认为发送低电平(逻辑0)
对于接收端:
当A-B>0.2V时候, RS485被认为收到高电平(逻辑1)
当A-B<-0.2V时候,RS485被认为收到低电平(逻辑0)
常用转换IC收发器:SSP485
电路设计方面:
A信号加上拉电阻
B信号加下拉电阻
A、B之间加一个120Ω的电阻,用于抵消RS485的信号反射
进行多设备通信的时候,从设备的距离离主线设备越近越好
RS485收发器的速度越快线长就越短
这是大佬根据经验得出来的公式(很重要):
传输线缆损耗经验公式:传输距离(m)*数据速率(bps)<10^7
总结:通信距离长,通信速度较快,抗干扰能力强,且能够多设备组网,现在工业上主要用于单片机和PLC进行远距离的通信。
三、RS422(相当于全双工的RS485)
硬件特性:
全双工串行通信,距离1500m,速率:10Mbps,最多能实现一主十从
四条通信线,分别是用于接收和发送的两对差分线:双绞线,抗干扰性强
特别注意:附近的电焊或者雷电最容易形成干扰
对于发送端:
当2V<A-B<6V时候, RS422被认为发送高电平(逻辑1)
当-6V<A-B<-2V时候,RS422被认为发送低电平(逻辑0)
对于接收端:
当A-B>0.2V时候, RS422被认为收到高电平(逻辑1)
当A-B<-0.2V时候,RS422被认为收到低电平(逻辑0)
常用转换IC收发器: SSP485
电路设计方面:
A信号加上拉电阻
B信号加下拉电阻
A、B之间加一个100Ω的电阻,用于抵消RS422的信号反射
进行多设备通信的时候,从设备的距离离主线设备越近越好