历史上的今天
返回首页

历史上的今天

今天是:2024年12月29日(星期日)

2021年12月29日 | 如何通过map文件优化代码

2021-12-29 来源:eefocus

  在平时写代码的时候,特别是嵌入式相关的代码时,能想到的优化方法一般就是通过设置编译器的优化等级。或者是在定义变量的时候考虑变量的使用范围,然后根据数据范围选择比较适合的数据类型。但是这种优化方式操作起来都比较模糊,没有一个直观的感受。为了让代码的优化有个直观的感受,今天就借助map文件来优化代码。


  首先看一段简单的示例。

在这里插入图片描述

  这是一段很简单的测试代码,就是在主程序里面让LED灯闪烁,同时给x变量每次加0.1。这个代码还需要优化吗?别着急,先打开工程中生成的map文件看看。

在这里插入图片描述

  map文件在工程目录debug文件夹里面的List文件夹中,使用记事本打开这个文件。

在这里插入图片描述

  在文件中间有一部分是各个目标文件所占用的空间大小,依次往下找,找几个占用空间比较大的位置。

在这里插入图片描述

  可以发现float.o这个目标文件占用的空间相对于其他文件来说很大了。那么这个float.o文件是哪里来的呢?看到float大概可以猜测到这是浮点相关的文件。在程序中只有一个地方用到了浮点运算。

在这里插入图片描述

  难道这一行代码能占用那么多的空间吗?那么把浮点运算改为整形运算试试。

在这里插入图片描述

  将x扩大10倍,然后每次加1,编译代码后重新打开map文件查看。

在这里插入图片描述

  这时就会发现在long.o前面的float.o文件消失了。由此可见,刚才那个float.o文件就是代码中的那一行浮点运算生成的。通过map文件的观察可以得出一个结论,浮点运算在单片机中占用的空间很大,所以尽量把浮点运算换算成整形运算。否则如果浮点运算的运算量比较大时,单片机的空间很快就会被占满了。


  接下来在通过串口将变量的值打印出来。

在这里插入图片描述

  通过串口助手观察打印的值

在这里插入图片描述

  串口打印的值也正常,接下来继续查看map文件。

在这里插入图片描述

  在map文件中可以看到在long.o文件的前面和后面多了好几个文件。而且占用空间非常大。


  那为什么又出现了一个非常大的 float.o 文件?这是因为printf函数支持浮点数打印,在函数里面有浮点数,所以就会产生一个float.o文件。xprintffull_nomb.o也是在调用printf函数时生成的。


  由此可见,printf函数占用的空间相当大的,在程序中尽可能的避免使用printf函数。那么要打印数据的时候怎么办呢?可以通过单片机串口默认输出功能打印字符,但是又有一个新问题,串口输出都是字符格式,而现在要打印整数,如何将整数转换为字符格式呢?可以通过自定义的函数,先将数字转换为字符串,然后在通过串口输出字符串。


  首先编写一段整数转字符串的函数。


void int2str(int n, char *str)

{

    char buf[10] = "";

    int i = 0;

    int len = 0;

    int temp = n < 0 ? -n: n;  // temp为n的绝对值


    if (str == NULL)

    {

        return;

    }

    while(temp)

    {

        buf[i++] = (temp % 10) + '0';  //把temp的每一位上的数存入buf

        temp = temp / 10;

    }


    len = n < 0 ? ++i: i;  //如果n是负数,则多需要一位来存储负号

    str[i] = 0;            //末尾是结束符0

    while(1)

    {

        i--;

        if (buf[len-i-1] ==0)

        {

            break;

        }

        str[i] = buf[len-i-1];  //把buf数组里的字符拷到字符串

    }

    if (i == 0 )

    {

        str[i] = '-';          //如果是负数,添加一个负号

    }

}


  接下来编写串口相关函数。


//发送单个字符

void SendChar( unsigned char dat )

{

    while( ( UART1_SR & 0x80 ) == 0x00 );       //发送数据寄存器空

    UART1_DR = dat;

}

//发送字符串

void SendString( unsigned char* s )

{

    while( 0 != *s )

    {

        SendChar( *s );

        s++;

    }

}


  下面修改主函数代码。


void main( void )

{

    int  x = 10;

    char str[100] = {0};

        

    __asm( "sim" );                             //禁止中断

    SysClkInit();

    delay_init( 16 );

    LED_GPIO_Init();

    Uart1_IO_Init();

    Uart1_Init( 9600 );

    __asm( "rim" );                             //开启中断


    while( 1 )

    {

        LED = ~LED;


        x += 1;    

        int2str(x,str);

        SendString(str);

        SendString("rn");

        delay_ms( 1000 );

    }

}


  首先通过int2str函数将变量x转换为字符串,然后在通过SendString函数将字符串打印出来,最后在调用一次SendString打印回车换行字符。打印效果如下:

在这里插入图片描述

  接下来再看一下map文件中占用的空间大小。

在这里插入图片描述

  通过map文件可以看到,相对于直接使用printf函数来说,自定义函数实现打印功能要节省不少空间。这样通过观察map文件中的目标文件大小,在优化程序的过程中就可以直观的看到优化后的代码与优化前的代码具体差距在哪里。这样在调试代码的过程中就会胸有成竹,不会像无头苍蝇一样到处乱撞。

推荐阅读

史海拾趣

APLUS Products公司的发展小趣事

在发展过程中,APLUS Products公司注重与上下游企业的合作与共赢。公司积极与供应商建立良好的合作关系,确保原材料的质量和供应的稳定性;同时,也与多家知名企业建立了战略合作关系,共同开拓市场、分享资源。这些合作不仅提高了公司的运营效率,也增强了其市场竞争力。

CYAN公司的发展小趣事

随着公司的发展,CYAN开始寻求与大型企业的合作。2009年,CYAN与沃尔沃汽车达成战略合作,为其提供了先进的网络解决方案,并成功将技术应用于沃尔沃的量产车型中。这次合作不仅提升了CYAN的品牌知名度,也为其带来了更多的商业机会。

Eurotech公司的发展小趣事

Eurofarad公司深知品质是企业生存和发展的根本。因此,公司一直注重品质管理,建立了严格的质量控制体系。同时,公司还不断提升服务水平,为客户提供全方位的售前咨询和售后服务。这些措施不仅提高了客户的满意度和忠诚度,还为公司的口碑和品牌形象增添了光彩。

Electronic公司的发展小趣事

AMD,曾经一度陷入困境的半导体公司,近年来实现了逆袭。AMD通过持续的技术创新和市场竞争策略的调整,成功在处理器和显卡市场取得了重要份额。AMD的产品性能不断提升,价格也更加亲民,赢得了消费者的广泛认可。同时,AMD还积极与游戏厂商和硬件厂商合作,推出了多款定制化的产品和解决方案。这些努力使得AMD在激烈的市场竞争中逐渐崭露头角。

Alliance Memory公司的发展小趣事

AMD,曾经一度陷入困境的半导体公司,近年来实现了逆袭。AMD通过持续的技术创新和市场竞争策略的调整,成功在处理器和显卡市场取得了重要份额。AMD的产品性能不断提升,价格也更加亲民,赢得了消费者的广泛认可。同时,AMD还积极与游戏厂商和硬件厂商合作,推出了多款定制化的产品和解决方案。这些努力使得AMD在激烈的市场竞争中逐渐崭露头角。

GC Electronics公司的发展小趣事
如温度、湿度等环境因素的变化,有时也可能对传感器的工作产生影响,导致误报。

问答坊 | AI 解惑

走出防电脑辐射的种种误区

很长一段时间以来,由射线防护品生产厂商们炒作的电磁辐射危害人类生存的浪潮愈演愈烈,引诱了很多日用品的生产者跟风,向消费者不断推销号称“世界领先科技”的防护用品,如:防电脑辐射的眼镜、手套、面罩、上衣、裤子、甚至孕妇专用的套装等等千 ...…

查看全部问答>

什么是汽车电子?

汽车电子简而言之就是半导体和汽车的结合,主要分为两类:一类是汽车电子控制装置,要和机械系统配合使用,例如电子燃油喷射系统、制动防抱死控制、防滑控制、悬架控制、动力转向等。另一类是车载汽车电子装置,是在汽车环境下能够独立使用的电子装 ...…

查看全部问答>

【藏书阁】电子线路与电子技术 /电器修理技术丛书

目录: 第1章 基础知识 第1节 基本概念 第2节 电子元器件主要特性和典型应用电路故障分析 第2章 音频放大器电路 第1节 晶体管单级放大器电路和电路故障分析 第2节 多级放大器电路及电路故障分析 第3节 放大器性能参数 第4节 音频功率放大 ...…

查看全部问答>

【藏书阁】微型计算机原理与汇编语言程序设计

第01章 微型计算机概述 38页.ppt 第02章 计算机中的数据表示 26页.ppt 第03章 80X86微处理器及其体系结构 33页.ppt 第04章 指令系统 134页.ppt 第05章 汇编语言的基本表达及其运行 28页.ppt 第06章 汇编语言程序设计 78页.ppt 第07章 中断调 ...…

查看全部问答>

求硬件开发的人才

高薪求人才! 职位描述及要求: 1. 生物医学工程、精密仪器、检测电子、电子信息工程等相关专业毕业 2、医疗工程系毕业的硕士优先考虑 2. 精通FPGA,单片机等硬件编程芯片的程序设计者优先考虑 3. 熟悉模拟电路、数字电路等sch设计及pcb设计 ...…

查看全部问答>

请教关于HALT模式

本人使用的不是低功耗的ST8芯片,在进入HALT后,用470uF的电容只能够记忆10S左右,但是我看说明书说进入HALT的电流是6ua,我把定时器,看门狗,内外部时钟都关掉,IO口置为输入,请问我是否有其他用电器需要关掉,谢谢.…

查看全部问答>

关于FLASH读写

                                 我现在FLASH能读,但是写不进去,也擦不了。对寄存器也是正确操作。…

查看全部问答>

关于P2IN

给P2.5输入0,程序如下 P2SEL &=~BIT5; P2IN    &=~BIT5; 结果编译出错,改成P2OUT &=~BIT5,没问题,但我一直理解的是P2OUT为输出的值,P2IN为输入的值,不知道这样理解对不对…

查看全部问答>

独立按键接法

小弟是刚开始学习的,按键触发不是有高低电平吗,我想知道独立按键的高电平触发电路接法和低电平触发电路接法.…

查看全部问答>