精华内容
下载资源
问答
  • SYD8801是一款低功耗高性能蓝牙低功耗SOC,集成了高性能2.4GHz射频收发机、32位ARM Cortex-M0处理器、128kB Flash存储器、以及丰富的数字接口。...单片机编译器中局部变量和全局变量的深入解析   ...

    SYD8801是一款低功耗高性能蓝牙低功耗SOC,集成了高性能2.4GHz射频收发机、32位ARM Cortex-M0处理器、128kB Flash存储器、以及丰富的数字接口。SYD8801片上集成了Balun无需阻抗匹配网络、高效率DCDC降压转换器,适合用于可穿戴、物联网设备等。具体可咨询:http://www.sydtek.com/

     

    单片机编译器中局部变量和全局变量的深入解析

     

    本节博客摘录于:http://blog.sina.com.cn/s/blog_4c2e13ff0101e3gr.html

    通常我们都是学了标准c语言教程后从事单片机c语言的编写的, 那就先要明白一点,标准c语言实际上是起源于pc平台上的一种语言, 标准c语言肯定是不会照顾到单片机的特殊性的.因此单片机c编译器中的c语言是一种基于标准c,但是又有相应修改扩充的扩展c语言. 

         在标准c里,局部变量是函数在调用的时候才临时分配存储空间的,全局变量是程序整个生命周期都一直存在的. 不过要知道,临时分配存储空间是需要操作系统内存管理程序支持的,单片机中通常都没有操作系统,也就不能实现像pc平台中那样的局部变量的空间分配. 这里就需要深入了解一下单片机的c编译器究竟是如何处理局部变量的,如果对此没有概念,碰到调试过程中的一些奇异现象恐怕只能觉匪夷所思了.

         另外需要知道的一点是, 不同的编译器对于局部变量的处理方法也不一样, 不能学了一个就到处照搬. 这里拿KEIL C ,IARAVR,ICCAVR这个三个编译器做分析比较.

     

         

          首先说 Keil C51 , 它的局部变量并不是在堆栈中, C51 为了提高代码的效率, 根据 51处理器的特性. 编译器对函数局部变量的安排进行了处理.局部变量如果不能分配到 寄存器里, 就放在 RAM 中了.编译器通过覆盖分析,可以共享局部变量的地址空间.。 最终的DATA使用量取决于调用链中那个使用DATA最多的链。所以,在程序中增加一个局部变量,如果不是位于那个使用DATA最多的链中,需要的DATA数量是有可能不会增加的。

         如:main()->f11()->f12()->f13().... // 链1
                 |----->f21()->f22()->f23().... // 链2

         因为f11(),f21()不在同一个调用链上,显然,f11()中使用的局部变量,可以和f21()中的局部变量,使用同一个存储单元。因为它们中的任何一个处在生命期内的话,另一个必然已经离开它的生命周期,同时它的局部变量也离开了它的生命周期,这些局部变量所占用的存储单元当然可以另做它用了。
         假设链1目前的局部变量需要50个存储单元,链2需要40个存储单元。那么你在链2中加入不多于10个单元的局部变量的话,程序最终需要的存储单元数量是不会增加的。

     

     

          再说ICCAVR ,  它把局部变量存放在软件堆栈空间中. ICCAVR使用两个堆栈:一个用于子程序调用和中断操作的硬件堆栈,一个用于传递参数、临时变量和局部变量的软件堆栈。硬件堆栈是从数据内存的顶部开始分配的,在硬件堆栈下面再分配一定数量的字节作为软件堆栈。

          IARAVR对于局部变量的处理方法与ICCAVR一样. 它也有两个堆栈,一个是data stack ,一个是returnaddress stack.  分别用于存放临时变量,局部变量,传递参数, 和函数返回地址.

          这里需要注意的是, 局部变量存放在堆栈中的处理方式一定要保证堆栈足够大,特别是定义了局部数组变量的情况下,一旦数组过大,超过了堆栈大小就会发生堆栈溢出, 如果只是读取数据还好, 一旦写入数据,就会破坏堆栈空间以外的数据, 导致程序时常.

    所以在单片机c编译器里写程序时一定要了解单片机编译器扩展c语言的不同之处, 绝不能死板地照搬标准c.

     

     

    另外对于编译而言有这些规则:(摘录于:https://blog.csdn.net/chengdong1314/article/details/78663785

    r0-r3    用作传入函数参数,传出函数返回值。在子程序调用之间,可以将 r0-r3 用于任何用途。

                被调用函数在返回之前不必恢复 r0-r3。如果调用函数需要再次使用 r0-r3 的内容,则它必须保留这些内容。

    r4-r11 被用来存放函数的局部变量。如果被调用函数使用了这些寄存器,它在返回之前必须恢复这些寄存器的值。

    r12        是内部调用暂时寄存器 ip。它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。
                 

    在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 r12。

    13        是栈指针 sp。它不能用于任何其它用途。sp 中存放的值在退出被调用函数时必须与进入时的值相同。

    r14        是链接寄存器 lr。如果您保存了返回地址,则可以在调用之间将 r14 用于其它用途,程序返回时要恢复

    r15        是程序计数器 PC。它不能用于任何其它用途。
         

    注意:在中断程序中,所有的寄存器都必须保护,编译器会自动保护R4~R11

     

    展开全文
  • 单片机全局变量 局部变量 堆与栈

    千次阅读 2017-01-06 12:50:11
    局部变量,全局变量

    局部变量空间,就是堆栈空间,也就是栈空间。

    从局部变量声明的时候,它就在堆栈空间了,而不是调用函数的时候,才让它入栈的。

    定义一个局部变量a,编译器会将a的地址分配到寄存器组R0~R7中去。由于它是局部变量,所以编译器将使用立即数赋值语句为代表a的寄存器Rn赋值,最后计算的结果也将存在寄存器组中,位置由编译器任意指定。

    定义一个全局变量a,编译器将在RAM中为变量a指定一个专用地址,在C程序中给a赋的值将存入这个专用地址中。程序操作变量a时,首先从专用地址中取出存放的值,然后再进行计算。

    结论:

    局部变量由于用寄存器直接操作,存取速度和计算速度都很快;由于寄存器数量有限,如果局部变量过多,将使代码由于频繁分配寄存器而变得冗长。

    全局变量被定义在内存中的专门地址上,存取位置固定。对于频繁存取的重要变量可以采用全局变量以减少代码的长度;由于全局变量总是占用内存,如果过多,或者把程序处理和计算中的一些中间变量也定义成全局变量,将大量消耗内存空间,处理速度会减慢,同时数据安全性也会降低。

    接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据。那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?下面就会对此进行深入的讨论。下文中的C语言代码如没有特别声明,默认都使用VC编译的release版。

    首先,来了解一下 C 语言的变量是如何在内存分部的。C 语言有全局变量(Global)、本地变量(Local),静态变量(Static)、寄存器变量(Regeister)。每种变量都有不同的分配方式。先来看下面这段代码:

    include

    int g1=0, g2=0, g3=0;

    int main()

    {

    static int s1=0, s2=0, s3=0;

    int v1=0, v2=0, v3=0;

    //打印出各个变量的内存地址

    printf(“0xx\n”,&v1); //打印各本地变量的内存地址

    printf(“0xx\n”,&v2);

    printf(“0xx\n\n”,&v3);

    printf(“0xx\n”,&g1); //打印各全局变量的内存地址

    printf(“0xx\n”,&g2);

    printf(“0xx\n\n”,&g3);

    printf(“0xx\n”,&s1); //打印各静态变量的内存地址

    printf(“0xx\n”,&s2);

    printf(“0xx\n\n”,&s3);

    return 0;

    }

    编译后的执行结果是:

    0x0012ff78

    0x0012ff7c

    0x0012ff80

    0x004068d0

    0x004068d4

    0x004068d8

    0x004068dc

    0x004068e0

    0x004068e4

    输 出的结果就是变量的内存地址。其中v1,v2,v3是本地变量,g1,g2,g3是全局变量,s1,s2,s3是静态变量。你可以看到这些变量在内存是连 续分布的,但是本地变量和全局变量分配的内存地址差了十万八千里,而全局变量和静态变量分配的内存是连续的。这是因为本地变量和全局/静态变量是分配在不 同类型的内存区域中的结果。对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈 (stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”,所以每个线程虽然 代码一样,但本地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数 据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。

    补充:怎么让程序的全局变量不会漫天飞

    1.使用结构体分类
    2.把全局变量放在一个.c里面
    3.如果外部函数要调用的话,就使用相应API(如cmSet_xxxxx() cmGet_xxxxx())

    展开全文
  • 单片机全局变量 局部变量

    千次阅读 2018-04-16 20:34:07
    若在C51中定义一个全局变量,编译器将...C51中定义一个的局部变量可以和全局变量同名,但在这种情况下,局部变量的优先级较高,而同名的全局变量在该功能模块内暂时被屏蔽。若在C51中定义一个局部变量,编译器会将该...


    若在C51中定义一个全局变量,编译器将在RAM中为该变量指定一个专用地址,在C程序中给变量赋的值将存入这个专用地址中,程序操作该变量是,首先从专用地址中取出存放的值,然后再进行计算。全局变量被定义在内存中的专门地址上,存储位置固定。

    C51中定义一个的局部变量可以和全局变量同名,但在这种情况下,局部变量的优先级较高,而同名的全局变量在该功能模块内暂时被屏蔽。


    若在C51中定义一个局部变量,编译器会将该变量的地址分配到寄存器组R0~R7中。由于他是局部变量,所以编译器将使用立即数赋值语句为代表该变量的寄存器Rn赋值,最后的计算结果也将存在寄存器组中,位置有编译器任意指定。局部变量由于用寄存器直接操作,存取速度和计算机速度都很快;由于寄存器数量有限,若局部变量过多,将会使代码由于频繁分配寄存器而变得冗长。


    局部变量空间,就是堆栈空间,也就是栈空间。

    从局部变量声明的时候,它就在堆栈空间了,而不是调用函数的时候,才让它入栈的。

    定义一个局部变量a,编译器会将a的地址分配到寄存器组R0~R7中去。由于它是局部变量,所以编译器将使用立即数赋值语句为代表a的寄存器Rn赋值,最后计算的结果也将存在寄存器组中,位置由编译器任意指定。

    定义一个全局变量a,编译器将在RAM中为变量a指定一个专用地址,在C程序中给a赋的值将存入这个专用地址中。程序操作变量a时,首先从专用地址中取出存放的值,然后再进行计算。

    程序的局部变量存在于(堆栈)中,全局变量存在于(静态区 )中,动态申请数据存在于( 堆)中。


    假如说在keil中定义了一个全局变量int i = 0x1234;这个i的初始化肯定是在上电之后,main函数之前。编译完之后debug,从地址0开始执行,怎么没看见对i的初始化呢?有的说是在init.a51文件之中。但是一直没有找到明确的解释。

    代码都是烧写在ROM中的,而全局之类的变量都是在RAM中,所以上电的时候肯定要初始化的。我知道编译器肯定要在main之前加入初始化代码的,但是我不知道加在哪儿了?在keil 中debug后的汇编后的汇编中似乎看不见呢。

    一般来说,全局变量如果有初始值,它们会被存放在ROM的某个区域,上电后会执行一段从ROM到RAM复制的过程.....这就是全局变量的初始化.

    你还记得用keil建工程的时候,有个提示:Copy Standard 8051 Startup Code to project folder and add file to project ?" 

    这个提示就是说,是否添加Startup code 到工程 ,Startup code 是cpu复位或上电启动后立即运行的一段启动代码。
    c编程的时候cpu先找到Startup code 代码,在跳到main函数入口  所以不是从rom 0地址开始的

    而Startup code 代码的作用是:

    1:清除片内外RAM PDATA  堆栈和指针

    2:如果有全局变量,则初始化,如果无全局变量,则直接进入main函数







    展开全文
  • 通常我们都是学了标准c语言教程后从事单片机c语言的编写的, 那就先要明白一点, 标准c语言实际上是起源于pc平台上的一种语言, 标准c语言肯定是不会照顾到单片机的特殊性的.... 在标准c里, 局部变量是函
    通常我们都是学了标准c语言教程后从事单片机c语言的编写的, 那就先要明白一点, 标准c语言实际上是起源于pc平台上的一种语言, 标准c语言肯定是不会照顾到单片机的特殊性的. 因此单片机c编译器中的c语言是一种基于标准c,但是又有相应修改扩充的扩展c语言.  所以在单片机c编译器里写程序时一定要了解单片机编译器扩展c语言的不同之处, 绝不能死板地照搬标准c. 
    

          在标准c里, 局部变量是函数在调用的时候才临时分配存储空间的,全局变量是程序整个生命周期都一直存在的.  不过要知道,临时分配存储空间是需要操作系统内存管理程序支持的, 单片机中通常都没有操作系统,也就不能实现像pc平台中那样的局部变量的空间分配.  这里就需要深入了解一下单片机的c编译器究竟是如何处理局部变量的,如果对此没有概念,碰到调试过程中的一些奇异现象恐怕只能觉匪夷所思了.

          另外需要知道的一点是, 不同的编译器对于局部变量的处理方法也不一样, 不能学了一个就到处照搬. 这里拿KEIL C ,IARAVR, ICCAVR这个三个编译器做分析比较.

     

         

           首先说 Keil C51 , 它的局部变量并不是在堆栈中, C51 为了提高代码的效率, 根据 51 处理器的特性. 编译器对函数局部变量的安排进行了处理.局部变量如果不能分配到 寄存器里, 就放在 RAM 中了.编译器通过覆盖分析, 可以共享局部变量的地址空间.。 最终的DATA使用量取决于调用链中那个使用DATA最多的链。所以,在程序中增加一个局部变量,如果不是位于那个使用DATA最多的链中,需要的DATA数量是有可能不会增加的。

          如:main()->f11()->f12()->f13().... // 链1
                  |----->f21()->f22()->f23().... // 链2

          因为f11(),f21()不在同一个调用链上,显然,f11()中使用的局部变量,可以和f21()中的局部变量,使用同一个存储单元。因为它们中的任何一个处在生命期内的话,另一个必然已经离开它的生命周期,同时它的局部变量也离开了它的生命周期,这些局部变量所占用的存储单元当然可以另做它用了。
          假设链1目前的局部变量需要50个存储单元,链2需要40个存储单元。那么你在链2中加入不多于10个单元的局部变量的话,程序最终需要的存储单元数量是不会增加的。

     

     

           再说ICCAVR ,  它把局部变量存放在软件堆栈空间中.  ICCAVR使用两个堆栈:一个用于子程序调用和中断操作的硬件堆栈,一个用于传递参数、临时变量和局部变量的软件堆栈。硬件堆栈是从数据内存的顶部开始分配的,在硬件堆栈下面再分配一定数量的字节作为软件堆栈。

           IARAVR对于局部变量的处理方法与ICCAVR一样. 它也有两个堆栈,一个是data stack ,一个是return address stack.  分别用于存放临时变量,局部变量,传递参数, 和函数返回地址.

           这里需要注意的是, 局部变量存放在堆栈中的处理方式一定要保证堆栈足够大, 特别是定义了局部数组变量的情况下,一旦数组过大,超过了堆栈大小就会发生堆栈溢出,  如果只是读取数据还好, 一旦写入数据,就会破坏堆栈空间以外的数据, 导致程序时常.

    展开全文
  • 单片机全局变量和局部变量的使用

    千次阅读 2013-07-26 10:11:39
    全局变量是存在RAM中的,而局部变量是存在堆栈中的   全局变量是从低地址往高地址存,局部变量是从RAM的高地址往低地址存,如果你定义的变量太多就有可能是溢出了。 在MSP430中,局部变量如果不多,就会分配r4...
  • 单片机全局变量和局部变量的使用 .

    千次阅读 2013-07-25 17:04:43
    全局变量是存在RAM中的,而局部变量是存在堆栈中的 全局变量是从低地址往高地址存,局部变量是从RAM的高地址往低地址存,如果你定义的变量太多就有可能是溢出了。在MSP430中,局部变量如果不多,就会分配r4-r15的...
  • 在代码编译过程中,编译器会根据配置代码进行空间分配,包括...*如果多级函数调用或者中断产生的实际临时变量(局部变量)的大小超过预设的栈区空间大小,会造成局部变量覆盖全局变量的情况,造成程序异常。 分配...
  • MSP430单片机全局变量局部变量

    千次阅读 2014-01-14 17:18:37
    全局变量是存在RAM中的,而局部变量是存在堆栈中的   全局变量是从低地址往高地址存,局部变量是从RAM的高地址往低地址存,如果你定义的变量太多就有可能是溢出了。 在MSP430中,局部变量如果不多,就会分配r4...
  • 单片机全局变量 局部变量 堆与栈 的区别 局部变量空间,就是堆栈空间,也就是栈空间。 从局部变量声明的时候,它就在堆栈空间了,而不是调用函数的时候,才让它入栈的。 定义一个局部变量a,编译器会将a...
  • STM32 keilC 局部变量和全局变量

    千次阅读 2013-05-15 22:48:05
    keil C中的局部变量是放在栈中,而栈大小在启动文件中设置好了的,所以在写函数的局部变量的时候不应该定义大的数组,不然栈不够装,就会就会导致局部变量的地址和全局变量的地址重叠。
  •  按存储区域分,全局变量、静态全局变量和静态局部变量都存放在内存的静态 存储区域,局部变量存放在内存的栈区。 按作用域分,全局变量在整个工程文件内都有效;静态全局变量只在定义它的 文件内有效;静态局部...
  • < 博客宗旨:文章短,时间短,不考验耐力 &...全局变量:就是在整个工程都可以使用的(概括说,当然需要引用extern 等关键字)。 局部变量:是在函数内有效。或者说是在 { } 域内有效的变量。 ...
  • 静态存储方式:是指在程序运行期间分配固定的存储空间的方式。 动态存储方式:是在程序...全局变量全部存放在静态存储区,在程序开始执行时给全局变量分配存储区,程序行完毕就释放。在程序执行过程中它们占据固定的
  • 文章目录1、成员变量2、全局变量3、局部变量:补充:参考 1、成员变量 成员变量是存在类中声明的。 依类而生,离开类之后就不是成员变量。 成员变量只能通过对象访问。 存储 :栈中 注:成员变量不能在定义的同时不能...
  • 定义全局变量时,默认初值全是0,原因是全局变量放在堆区,这里由编译器统一初始化,即编译时候编译器统一把它们弄为0 定义局部变量时,默认初始是随机的,因为局部变量的定义是在栈区,这个是程序运行起来后,动态...
  • 局部变量:是在函数内部定义的变量,只在定义它的函数内部有效,仅在使用它时,才为它分配内存单元。全局变量:又称外部变量,是在函数外部定义的变量,可以为多个函数共同使用,其有效作用范围是从它定义的位置开始...
  • C语言全局/局部变量

    2018-08-20 23:14:50
    这个工程里面的描述很简单。就是陈列了一个全局变量和一个局部变量。适合人群:刚开始C语言单片机编程的开发人员。对函数之间数据交互不太清楚的人。
  • 最近keil中调试STM32程序时,出现的问题是局部变量冲掉了全局变量的数据。 查资料,原因是局部变量定义在栈中,栈在RAM区,由系统自动管理,查看map文件可以看到栈区空间位于在系统计算的实际需要的RAM大小的最后...
  • C语言中全局变量和局部变量的区别

    万次阅读 2018-11-27 09:19:10
    1.局部变量也称为内部变量。局部变量是在函数内作定义说明的。其作用域仅限于函数内, 离开该函数后再使用这种变量是非法的。 2.a.全局变量是没有定义存储类型的外部变量,其作用域是从定义点到程序结束.省略了存储...
  • 从不上系统角度,如果中断函数中没有调用延时函数,就都可以;但是如果中断函数中有用到延时函数,就用 局部变量。因此,全部使用局部变量最好。...
  • 变量分为局部与全局,局部变量又可称之为内部变量。由某对象或某个函数所创建的变量通常都是局部变量,只能被内部引用,而无法被其它对象或函数引用。全局变量既可以是某对象函数创建,也可以是在本程序任何地方创建...
  • 全局变量、静态变量、局部变量的生存周期与作用域 1、生存周期作用域的定义1 生存周期: 变量从定义到销毁的时间范围。存放在全局数据区的变量的生存周期存在于整个程序运行期间,而存放在栈中的数据则随着函数等的...
  • 那么问题来了,我有必要将全局变量变成局部变量或者static变量吗?(如果可以),有必要将某些函数变成static函数吗?(有些驱动只有本文件有用)。 如果这么变了,对程序编译后的影响有多大?是变大还是变小?值不...
  • 1、栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与...
  • 根据作用域可分为全局变量和局部变量。 根据生存周期可分为静态存储方式和动态存储方式,具体地又分为自动的(auto)、静态的(static)、寄存器的(register)、外部的(extern)。 静态存储方式是指在程序运行...
  • extern auto static register extern ...如果同一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量被“屏蔽”,即它不起作用。 3.如果写在文件的开头,可以省略extern。 ...
  • 最近准备在一个函数里传输几百个数据给其他芯片,只执行一次 第一个思路是分组传送,利用一个结构体里的数组,20个char,也就是需要重复很多次发送,无需...局部变量在函数执行完以后,自动释放,所以定义指针...
  • 局部变量空间,就是堆栈空间,也就是栈空间。 从局部变量声明的时候,它就在堆栈空间了,而不是调用函数的时候,才让它入栈的。...定义一个全局变量a,编译器将在RAM中为变量a指定一个专用地址,在C程序...
  • 在用VB开发软件时,经常需要在不同的窗体间共享数据,但在过多的使用全局变量时不便于软件的调试修改。通常有两种解决方法。第一种方法:定义全局变量,然后在各个窗体中直接使用,例如Public strCustomerID As ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,592
精华内容 1,436
关键字:

单片机局部变量和全局变量