嵌入式 C 语言编程总结

目录:

  1. 全局变量

1.全局变量

在纯 C 语言(Pure C)开发的嵌入式程序中,需要在多处用到同一个变量,需要注意几点:

  • 不要在头文件中对变量进行定义
  • 头文件中变量的声明添加关键字 extern
  • 在相应的 .c 文件中对变量进行定义

这样,其它地方需要用到该全局变量时,仅需要包含 .h 头文件即可,不必再用 extern 声明变量。

example 1.1

在 .h 头文件中定义全局变量 value:

  1. // filename: var.h
  2. #ifndef VAR_H
  3. #define VAR_H
  4. extern const double value;
  5. extern double varValue;
  6. #endif

在 .c 文件中对 value 进行赋值(定义):

  1. // filename: var.c
  2. #include "var.h"
  3. const double value = 1.0;
  4. double varValue = 1.0;

在 main.c 中对使用 value 的值:

  1. #include "var.h"
  2. #include "stdio.h"
  3. int main( int argc, char ** argv ) {
  4. double v = 0.0;
  5. v = value;
  6. printf( "value is %.2f\n", v );
  7. varValue = 2.0;
  8. printf("varValue is %.2f\n", varValue);
  9. return 0;
  10. }

可以在控制台中看到输出

  1. value is 1.00
  2. varValue is 1.00

注意: 该例中定义的变量 value 为 const 类型,以防止在其它文件中对值进行修改,若需要其它文件能够修改值,则取消 const 关键字修饰(如 varValue)。

2.程序接口

在嵌入式开发中,经常需要选择与上位机进行通讯的协议(如 Uart,SPI 通讯协议),由于 C 语言里面并没有 CPP 中命名空间以及接口(纯虚函数)等的概念,

所以通常编写特定协议的代码时需要对不同协议中定义的函数接口进行区分,但在函数使用时,就需要用到特定协议的头文件中所声明的接口。

example 2.1

以串口初始化为例,可能就有这样的两个接口:

  1. // uart initialization
  2. void uartInit();
  3. // spi initializaiton
  4. void spiInit();

而后在主程序中需要调用串口初始化函数(这里假设这两种串口协议不会同时使用,否则的话情况就比较复杂):

  1. #include "uart.h"
  2. #include "spi.h"
  3. int main( int argc, char ** argv ) {
  4. uartInit();
  5. // spiInit();
  6. // do something else
  7. }

在实际使用中,肯定会对串口通讯进行封装,提供许多 API,那么在使用 UART 协议的时候就需要把之前所有用到与 SPI 协议相关的

函数全部替换成 UART 相关的函数。为了简化函数的使用,可以利用 宏定义,向主程序提供一个统一的接口。

为了定义统一的接口,引入新的头文件 com.h:

  1. #ifndef COM_H
  2. #define COM_H
  3. #define COM_UART
  4. // #define COM_SPI
  5. #if defined (COM_UART)
  6. #include "uart.h"
  7. #define comInit() uartInit()
  8. // end of COM_UART
  9. #elif defined (COM_SPI)
  10. #include "spi.h"
  11. #define comInit() spiInit()
  12. // end of COM_SPI
  13. #endif
  14. #endif

这里我们认为 UART 的优先级最高,在定义了 COM_UART 之后就会使用 uart 通讯协议,不论是否定义过 COM_SPI 。

在主程序 main.c 中,我们可以调用 comInit() 对串口进行初始化:

  1. #include "com.h"
  2. int main( int argc, char** argv ) {
  3. comInit();
  4. return 0;
  5. }

分别在 uart 和 spi 的实现文件里的初始化函数中加入打印字符串的功能:

  1. // uart.c
  2. #include "uart.h"
  3. #include <stdio.h>
  4. void uartInit() {
  5. printf("UART Init\n");
  6. }
  7. // spi.c
  8. #include "spi.h"
  9. #include <stdio.h>
  10. void spiInit() {
  11. printf("SPI Init\n");
  12. }

运行程序,可以在控制台中得到以下信息:

  1. UART Init

注释掉 com.h 中对 COM_UART 的定义,取消 COM_SPI 的注释,再运行程序,可以看到:

  1. SPI Init

通过宏定义,就可以为整个项目提供统一的串口函数接口。

程序接口的优缺点

优点:

  1. 统一了函数接口,方便程序迭代。
  2. 便于项目管理。

缺点:

  1. 尽管通过宏定义,可以方便的对外提供统一的函数接口,但是每当添加一个新的协议时,都需要在

    com.h 头文件中添加新的条件分支和额外的宏定义。

  2. 当串口协议出现了特殊的函数接口时,进行宏定义时需要考虑到这些特殊的情况

  3. 上述代码是假设 UART 协议和 SPI 协议是不会同时使用的(要么使用 UART 协议,要么使用 SPI 协议,考虑的情况较为简单)条件判断的复杂程度为 O(n);而实际上有些程序的接口中可能需要同时使用 A 实现,又要使用 B 实现,那么复杂程度将会变为 O(n^2)。

总而言之,具体项目需要具体分析,这里仅是给出一种简化代码使用的思路。

嵌入式 C 语言编程总结的更多相关文章

  1. 17条嵌入式C语言编程小知识总结

    流水线被指令填满时才能发挥最大效能,即每时钟周期完成一条指令的执行(仅指单周期指令). 如果程序发生跳转,流水线会被清空,这将需要几个时钟才能使流水线再次填满.因此,尽量少的使用跳转指令可以提高程序执 ...

  2. 【转】 嵌入式C语言编程中Inline函数的应用

    源地址:https://blog.csdn.net/vigour1000/article/details/9622037 有一段儿时间没写写经验笔记了,哎,也是自己这一段时间以来(其实最近一直是这个状 ...

  3. 【嵌入式】C语言高级编程▁▁▁嵌入式C语言入门编程学习!

    ✍  1.C 语言标准 什么是 C 语言标准呢? 我们生活的现实世界,就是由各种标准构成的,正是这些标准,我们的社会才会有条不紊的运行. 比如我们过马路,遵循的交通规则就是一个标准:红灯停,绿灯行,黄 ...

  4. LINUX下C语言编程基础

    实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用 ...

  5. 第二章 C语言编程实践

    上章回顾 宏定义特点和注意细节 条件编译特点和主要用处 文件包含的路径查询规则 C语言扩展宏定义的用法 第二章 第二章 C语言编程实践 C语言编程实践 预习检查 异或的运算符是什么 宏定义最主要的特点 ...

  6. 华为C语言编程规范

    DKBA华为技术有限公司内部技术规范DKBA 2826-2011.5C语言编程规范2011年5月9日发布 2011年5月9日实施华为技术有限公司Huawei Technologies Co., Ltd ...

  7. 嵌入式C语言不可不用的关键字

    1.static关键字 这个关键字前面也有提到,它的作用是强大的. 要对static关键字深入了解,首先需要掌握标准C程序的组成. 标准C程序一直由下列部分组成: 1)正文段——CPU执行的机器指令部 ...

  8. 嵌入式C语言优化小技巧

    嵌入式C语言优化小技巧 1 概述 嵌入式系统是指完成一种或几种特定功能的计算机系统,具有自动化程度高,响应速度快等优点,目前已广泛应用于消费电子,工业控制等领域.嵌入式系统受其使用的硬件以及运行环境的 ...

  9. 嵌入式系统C编程之堆栈回溯【转】

    转自:https://www.cnblogs.com/clover-toeic/p/3949896.html 前言 在嵌入式系统C语言开发调试过程中,常会遇到各类异常情况.一般可按需添加打印信息,以便 ...

随机推荐

  1. 浏览器显示XML文档

    在网站后台管理介面上,有一个预览铵钮,管理员能点一点,把XML的文档显示于浏览器上.这个XML文档如下: HTML Markup: 去.aspx.cs写ButtonPreview_Click事件: 运 ...

  2. Hibernate常见异常总结

    系统配置 1.没有查找到src目录下的hibernate.cfg.xml Exception in thread "main" org.hibernate.HibernateExc ...

  3. Django之文件下载

    到目前为止,我们的注意力都在HTML网页上,但是实际上,在网站上除了HTML外还有图片,文件,PDF等等. 首先来看下返回一张图片为例,读取本地磁盘上的一张图片并返回到网页上显示. def test1 ...

  4. Task4

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. Java Web之数据库连接池

    数据库连接池 一.数据库连接池 1. 数据库连接池就是存放数据库连接(Connection)的集合 2. 我们获取一个数据库连接是一个相对很麻烦的过程,如果我们获取一个数据库连接,使用一次以后就给它关 ...

  6. [USACO08FEB]酒店Hotel 线段树 BZOJ 1593

    题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...

  7. Git 的简单测试

    Git 简介 Git(读音为/gɪt/.)是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开 ...

  8. Bootstrap FileInput 上传 中文 API 整理

    Bootstrap FileInput 上传  中文 API 整理 上传插件有很多 但是公司用的就是 Bootstrap FileInput 自己就看了看  会用就行 自己都不知道每个值是干嘛用的就问 ...

  9. kubernetes相关命令

    关闭防火墙 [关闭swap] 执行swapoff -a可临时关闭,但系统重启后恢复 编辑/etc/fstab,注释掉包含swap的那一行即可永久关闭 [关闭SeLinux] sed -i 's/SEL ...

  10. js 点击页面出现烟花 心形

    css :1 body{width:1000px; height:500px;} input{ margin:100px; width:250px; height: 50px } 3 .Firewor ...