原来MCU初始化大有讲究!

嵌入式ARM 2023-01-16 12:00

一、初始化做些啥? 

大家平时进行MCU软件开发时,基本上都会有一个初始化过程(如果没有的话,就不知道该说什么好了)。我们的硬件寄存器、模块的配置、软件数据结构、系统初始状态等,都是需要进行初始化设置的,以便于把控系统的初始运行状态。那么,初始化过程中一般会进行哪些工作呢?

1、初始化延时一段时间

在较多工程代码初始化阶段都会看到一个Delay_ms(XXX);的语句,有些小伙伴可能没怎么在意,延时就延时呗,有什么大惊小怪的。
有些小伙伴认为是防止MCU跑飞等等之类的原因,其实这个语句也是需要根据具体情况来进行编写的,比如之前就有一个项目需要快速启动,那么初始化延时就是不可取的。
 1//伪代码 
2#define SYS_INITIAL_DELY (200)
3void SystemInitial(void)
4{
5    Delay_ms(SYS_INITIAL_DELY);  //系统延时 
6    sLowInitial();               //底层初始化 
7    sFucInitial();               //功能初始化 
8    //...... 
9}
10void main(void) {
11
12    SystemInitial(); //系统初始化
13    //...... 
14}
Delay一下的原因:
  • 首先聊聊对于"等待MCU电源稳定防止跑飞"这个原因,多少有点牵强,因为Delay函数也是一种正常程序运行,如果MCU跑飞Delay函数也是无法缓解的。

  • 如果是为了防止外设初始化失败可能还说得过去,毕竟对于MCU内部外设功能的初始化有时候需要一个稳定的电源,否则容易产生初始化不成功等等异常。

  • 不过根据之前开发MCU的经验来看,主要是MCU与其他模块对接时候的上电运行门限存在差异,都知道大部分芯片都会有一个最低上电启动电压,电压太低芯片无法启动,电压如果在最低电压附近波动容易造成系统不稳定,如果外部芯片与MCU共用同一个电源,MCU上电运行电压门限低,而外部芯片门限高,当MCU已经开始进行配置外部芯片操作,而外部芯片才刚刚开始进入运行初始化,这样会导致MCU对外部芯片配置不成功等问题。

2、比较传统的初始化结构图

大家别小看一个简单的初始化工作,一个结构清晰,层次分明的初始化函数封装能够为你在以后的大工程项目中省下不少时间,还记得刚写代码的时候,那变量初始化一个乱字都形容不过来,往往前面刚赋值接下来又被清零了。
下面为大家提供一个简单传统的MCU初始化层次结构图,大家也可以结合自身项目进行设计:

解释一下:
  • 上面的结构图采用自底向上的初始化层次,先进行最基础的系统时钟和总线时钟的配置,以及一些CPU相关的底层初始化;对于MCU次底层的是各个外设的初始化比如UART、USB、SDIO等等;然后对于数据结构和模型初始化可以根据具体功能模块进行划分,最后是对EEPROM、FLASH等存储信息进行读取以恢复系统之前的默认参数和状态。

  • 可以根据自身项目具体情况进行设计,比如含有RTOS、GUI等等组件初始化也是需要进行划分与归类的,这里仅仅提供一些思路。

二、让MCU告诉我更多信息 

其实进行MCU软件开发的时候对本身并不是特别的熟悉,而且确实现在很多MCU都封装得特别好,比如MCU具体如何进行运算,在哪里取数据,又把数据送去哪里,一段代码会运算多长时间等等
导致一些朋友遇到一些bug就难以解决,所以如果能够更清楚的了解一款MCU那么就多一分对bug的把控能力,一定玩玩MCU,而不要被MCU耍了
好了,为了能够更好的把控MCU,我们得在今天的初始化主题这里干点事。

1、直接初始化输出基础类型大小

 1void PrintTypeSize(void)
2{
3    printf("Type Size:\n");
4    printf("char      : %u\n", sizeof(char));
5    printf("short     : %u\n", sizeof(short));
6    printf("int       : %u\n", sizeof(int));
7    printf("long      : %u\n", sizeof(long));
8    printf("long long : %u\n", sizeof(long long));
9    printf("void*     : %u\n", sizeof(void *));
10    printf("float     : %u\n", sizeof(float));
11    printf("double    : %u\n", sizeof(double));
12    //......Add your printf of your think
13}
解释一下:

这一段代码很简单吧,估计有很多朋友都没有真正在自己所用的平台上打印过,在学习C语言的过程中应该都知道这中间有些数据类型是与平台相关的,如果没有对这些基础类型的长度把控好,估计bug就来找你了.

同时大家在平时的编程过程中也一定要注意数据类型的范围,引起的后果可大可小哦,同时对于数据类型的深入学习可以参考往期文章。

2、字节对齐与顺序

这一部分算是开了几篇文章好好谈过的话题了,也是非常重要的内容,这里不做过多的解释,相关的检测算法也在其中为大家展示了,比较简单,所以大家如果不想查看MCU手册的时候直接可以使用对应的函数输出对应的结构体默认的对齐方式,字节序(也就是我们带小端)等等属性,所以这里建议大家在研发前期初始化过程中打印相关内容。
一些人遇到一些小问题就会到处查资料,其实有些答案可以通过编程让MCU自己告诉我们,这也是快速开发一款新的MCU开发的基础。
3、运算时间的把控
同样也是本文非常重要的一部分内容,也是非常想推荐给大家的一种评估和熟悉MCU性能方法,非常经典的宏定义,下面是在Windows下面模拟的程序,大家可以改造到自己的MCU上运行测试:
 1#include 
2#include 
3#include 
4#include 
5/***************************************************
6 * Fuction: 10次运行Operation 
7 * Author :(公众号:最后一个bug) 
8 ***************************************************/
 
9#define TEN_OPERATE_TIMES(x) do { x; x; x; x; x; x; x; x; x; x; } while (0)
10/***************************************************
11 * Fuction: 50次运行Operation 
12 * Author :(公众号:最后一个bug) 
13 ***************************************************/
 
14#define FIFTY_OPERATE_TIMES(x) do {\
15                                    TEN_OPERATE_TIMES(x); \
16                                    TEN_OPERATE_TIMES(x); \
17                                    TEN_OPERATE_TIMES(x); \
18                                    TEN_OPERATE_TIMES(x); \
19                                    TEN_OPERATE_TIMES(x); \
20                                } while (0)
21/***************************************************
22 * Fuction: 答应对应运算op所需时间 
23 * Author :(公众号:最后一个bug) 
24 ***************************************************/
 
25#define PRINT_TIME(name, operate, count) do { \
26                                    unsigned char i = 0;\
27                                    LARGE_INTEGER StartTime;\
28                                    LARGE_INTEGER EndTime;\
29                                    LARGE_INTEGER Freq;\
30                                    QueryPerformanceFrequency (&Freq);\
31                                    QueryPerformanceCounter(&StartTime);\
32                                    for (i = 0; i < count; i++) { \
33                                        FIFTY_OPERATE_TIMES(operate); \
34                                    } \
35                                    QueryPerformanceCounter(&EndTime);\ 
36                                    printf("%-8s  %7.8f ms\n", name, (EndTime.QuadPart -StartTime.QuadPart )*1000.0f*1000.0f/Freq.QuadPart/ (double)(count * 50.0));\
37                                } while (0)
38
39
40/***************************************************
41 * Fuction: 变量定义区域 
42 * Author :(公众号:最后一个bug) 
43 ***************************************************/
 
44volatile float fv = 1.0;
45volatile float fv_out = 0.8;
46/***************************************************
47 * Fuction: 测试main函数 
48 * Author :(公众号:最后一个bug) 
49 ***************************************************/
 
50int main(int argc, char *argv[]) {
51
52    PRINT_TIME("Mul   :", fv_out *= fv, 200);
53    PRINT_TIME("Div   :", fv_out /= fv, 200);
54    PRINT_TIME("sin(x):", fv_out = sinf(fv), 100);
55    PRINT_TIME("cos(x):", fv_out = cosf(fv), 100);
56    printf("\n欢迎关注公众号:最后一个bug\n");
57    return 0;
58}
运行结果看一看:

解析一下:
  • 首先这里主要是宏定义和do{}while(0);的结合使用案例,大家可以学习一下这种定义方式。

  • 设计亮点 : 前面两个宏定义的设计大家应该会有疑问为什么不在for循环里面直接cnt累计时间,最后累计好足够的时间不就可以计算每次运算的时间了吗 ?

  • 大家需要注意的是for循环也是由几条汇编语句构成的,如果所测试的运算操作时间非常短,测试的最小时间也不会小于for运算的时间,这样测量误差较大,所以这里构造了多次运算,从而与for语句运算时间不在一个运行时间等级上便可以提高精度。

  • 如果很多小伙伴听得迷迷糊糊,上图!!!!

END

来源:最后一个bug

版权归原作者所有,如有侵权,请联系删除。

推荐阅读
曾经对程序员最好的公司,倒下了…
一款活跃了17年的开发工具,好用到起飞~
单片机只会调库和复制别人的代码是什么水平?

→点关注,不迷路←

嵌入式ARM 关注这个时代最火的嵌入式ARM,你想知道的都在这里。
评论
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 204浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 124浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 144浏览
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 108浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 126浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 167浏览
  • 「他明明跟我同梯进来,为什么就是升得比我快?」许多人都有这样的疑问:明明就战绩也不比隔壁同事差,升迁之路却比别人苦。其实,之间的差异就在于「领导力」。並非必须当管理者才需要「领导力」,而是散发领导力特质的人,才更容易被晓明。许多领导力和特质,都可以通过努力和学习获得,因此就算不是天生的领导者,也能成为一个具备领导魅力的人,进而被老板看见,向你伸出升迁的橘子枝。领导力是什么?领导力是一种能力或特质,甚至可以说是一种「影响力」。好的领导者通常具备影响和鼓励他人的能力,并导引他们朝着共同的目标和愿景前
    优思学院 2025-01-08 14:54 66浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 70浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 223浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 96浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 158浏览
  • 大模型的赋能是指利用大型机器学习模型(如深度学习模型)来增强或改进各种应用和服务。这种技术在许多领域都显示出了巨大的潜力,包括但不限于以下几个方面: 1. 企业服务:大模型可以用于构建智能客服系统、知识库问答系统等,提升企业的服务质量和运营效率。 2. 教育服务:在教育领域,大模型被应用于个性化学习、智能辅导、作业批改等,帮助教师减轻工作负担,提高教学质量。 3. 工业智能化:大模型有助于解决工业领域的复杂性和不确定性问题,尽管在认知能力方面尚未完全具备专家级的复杂决策能力。 4. 消费
    丙丁先生 2025-01-07 09:25 117浏览
  • 本文介绍编译Android13 ROOT权限固件的方法,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。关闭selinux修改此文件("+"号为修改内容)device/rockchip/common/BoardConfig.mkBOARD_BOOT_HEADER_VERSION ?= 2BOARD_MKBOOTIMG_ARGS :=BOARD_PREBUILT_DTB
    Industio_触觉智能 2025-01-08 00:06 92浏览
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 61浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦