zoukankan      html  css  js  c++  java
  • 嵌入式C语言进行曲之要诀

    一. 良好的编程风格

         1.排版:a. 代码缩进空格数为4 个。若是可能,尽量用空格来代替Tab键,因为有些编译器不支持Tab键(我自己至今未见过,但确实有这个风险),这给程序的移植带来了问题。

          b. 较长的语句要分2行来书写,并用‘\’符号隔开。

          c. 函数代码的参数过长,分多行来书写。void UARTSendAndRecv(UINT8 *ucSendBuf,
                                         UINT8 ucSendLength, 
                                           UINT8 *ucRecvBuf, 
                                         UINT8 ucRecvLength) 

          d. if、do、while 、switch、for、case、default 等关键字,必须加上大括号{}。

          c. 函数头应该进行注释,例如函数名称、输入参数、返回值、功能说明。

          e. 复杂的宏定义同样要加上注释。

          2.模块化程序设计应该理解以下概述:

         (1) 模块即是一个.c 文件和一个.h 文件的结合,头文件(.h)中是对于该模块接口的声明;

              一个嵌入式系统通常包括两类(注意是两类,不是两个)模块: 
                          (1)硬件驱动模块,一种特定硬件对应一个模块; 
                          (2)软件功能模块,其模块的划分应满足低偶合、高内聚的要求。

          下面以 keil C  编译器为例,讲一下模块化编程的步骤。下面这个程序分为三层,共 7 个模块,共同为主程序服务(它们之间也会相互调用)。

          

    程序主要模块和功能简介:
    一. 底层驱动
      1.  红外键盘:程序通过红外键盘进行操作。红外键盘独占定时器0 和外部中断 0 ,以实现红外解码和键盘键值的识别。红外键盘定义了五个按键,分别为上翻、下翻、左翻、右翻和确认键。 
      2. LCD 液晶显示:程序主要通过 LCD 显示信息,LCD 液晶显示驱动提供显示汉字、图形和 ASCII码的函数接口。可以全屏、单行显示汉字,任意位置显示ASCII码,还可以全屏、半屏显示图形。

    二.  功能模块
      1. LCD 菜单程序:菜单程序可以使人机交互更加方便、容易。本菜单程序的菜单级别深度受 RAM 大小的限制,每增加一级菜单将多消耗 4 字节的 RAM 。菜单程序主要完成菜单功能函数的调度,LCD 显示刷新。
      2.  计算器程序:实现 65536 以内的加、减、乘、除,超出范围会出现溢出,溢出发生时,LCD 显示“错误:出现溢出”的错误提示,同时本次运算被忽略。对于负数会显示“-”号,除数为零时 LCD 显示“错误:除数为零”的错误提示。

      3.  开机次数记忆程序:主要对基于 IIC 总线的 EEPROM 进行读写,单片机每次上电后,将开机次数写入 EEPROM. 
      4.  串口测试程序: 进入该程序后,单片机向电脑发送字符串“Hello Word!”,发送数字24(以字符的形式显示)。编写此程序的目的是为了能够方便的向电脑发送字符串和变量,便于程序的调试。串口占用串口资源,与频率测量程序共享定时器 1
      5.  频率测量:复用定时器 1,占用外部中断 1,实现 5~20KHZ 频率的测量.

    三.  主程序
         主程序主要完成程序的初始化,LCD 菜单显示,监视键盘程序并根据键值更新菜单。

                         定义  红外键盘模块:key.c 与key.h
                                 菜单模块:menu.c与menu.h
                                 串口通信模块:uart_.c 与uart.h
                                 计算器模块:counter.c 与counter.h 
                                 频率测量模块:mea_fre.c 与mea_fre.h
                                开机次数记忆模块:eepram.c 与eepram.h 

    1.static 关键字:在嵌入式C语言当中,它有三个作用:
           作用一:在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

           作用说明了局部静态变量的特性:在函数体(子),一个被声明为静态的变量(也就是局部静态变量)在这一函数被调用过程中维持其值不变(子,局部会释放为0)。声明函数的一个局部变量,并设为static 类型,作为一个计数器,这样函数每次被调用的时候就可以进行计数。  

            作用二:在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。(一个C项目可以分为多个模块C文件,一个C文件可以包含多个函数体)。(相同名字的变量,不会发生冲突)

            作用三:在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用(静态函数)。(相同名字的函数,不会发生冲突;)

    最后说一下存储说明符,在标准C语言中,存储说明符有以下几类:
         auto、register 、extern 和static  对应两种存储期:自动存储期和静态存储期。
         auto和register 对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。
         关键字extern 和static 用来说明具有静态存储期的变量和函数。用static 声明的局部变量具有静态存储持续期(static storage duration),或静态范围(static extent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。

    2.  const 关键字

                     a. const关键字修饰的变量可以认为有只读属性,但它绝不与常量划等号。const int i=5;
                                               int j=0;

                  i= j;     // 非法,导致编译错误,因为只能被读 
                         j=i;     // 合法

          b. const关键字修饰的变量在声明时必须进行初始化。如下代码:
                                        const int i=5;     // 合法 
                                             const int j;       // 非法,导致编译错误

          c. 用const声明的变量虽然增加了分配空间,但是可以保证类型安全。

          d. C 标准中,const定义的常量是全局的。

          e. 必须明白下面语句的含义,方法是:若是想定义一个只读属性的指针,那么关键字const要放到‘*  ’后面。
                 char *const cp; //指针不可改变,但指向的内容可以改变
               char const *pc1; // 指针可以改变,但指向的内容不能改变
               const char *pc2; // 同上(后两个声明是等同的)

            f.  将函数传入参数声明为const,以指明使用这种参数仅仅是为了效率的原因,而不是想让调用函数能够修改对象的值。 
            参数const通常用于参数为指针或引用的情况,且只能修饰输入参数;若输入参数采用“值传递”方式,由于函数将自动产生临时变量用于复制该参数,该参数本就不需要保护,所以不用const修饰。例子:
            void fun0(const    int  * a );  
            void fun1(const    int  & a);
           调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const  int  * a,则不能对传递进来的指针所指向的内容进行改变,保护了原指针所指向的内容;如形参为const  int  & a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。 
            g. 修饰函数返回值,可以阻止用户修改返回值。(在嵌入式C 中一般不用,主要用于C++ ) 
            h. const消除了预处理器的值替代的不良影响,并且提供了良好的类型检查形式和安全性,在可能的地方尽可能的使用const对我们的编程有很大的帮助,前提是:你对const有了足够的理解。
      最后,举两个常用的标准C 库函数声明,它们都是使用const的典范。
      1. 字符串拷贝函数:char *strcpy(char *strDest,const char *strSrc );
      2. 返回字符串长度函数:int strlen (const char *str);

  • 相关阅读:
    Mysql有什么办法批量去掉某个字段字符中的空格
    Mysql order by 排序 varchar 类型数据
    JS将人民币小写金额转换为大写
    禁止表单输入中文(禁止粘贴)
    abp vnext 开发快速入门 3 实现权限控制
    abp vnext 开发快速入门 2 实现基本增删改查
    abp vnext 开发快速入门 1 认识框架
    从零开始一起学Blazor WebAssembly 开发(4)
    发布一个自己做的图片转Base64的软件,Markdown写文章时能用到
    一起学Blazor WebAssembly 开发(3)
  • 原文地址:https://www.cnblogs.com/wangh0802PositiveANDupward/p/2624290.html
Copyright © 2011-2022 走看看