![](https://csdnimg.cn/release/download_crawler_static/86569292/bg1.jpg)
C 语言嵌入式系统编程修炼之道
1
C 语言嵌入式系统编程
修炼之道
整理 Cysoft /摘自 Internet
![](https://csdnimg.cn/release/download_crawler_static/86569292/bg2.jpg)
C 语言嵌入式系统编程修炼之道
2
目录
1.背景 ......................................................................................... 3
2. 软件架构篇 ........................................................................... 5
2.1 模块划分............................................................................................................................5
2.2 多任务还是单任务............................................................................................................6
2.3 单任务程序典型架构........................................................................................................6
2.4 中断服务程序....................................................................................................................7
2.5 硬件驱动模块....................................................................................................................9
2.6 C 的面向对象化.................................................................................................................9
2.7 总结..................................................................................................................................10
3 内存操作 .............................................................................. 10
3.1 数据指针..........................................................................................................................10
3.2 函数指针..........................................................................................................................11
3.3 数组 vs.动态申请 ............................................................................................................11
3.4 关键字 const ....................................................................................................................12
3.5 关键字 volatile.................................................................................................................13
3.6 CPU 字长与存储器位宽不一致处理 ..............................................................................13
3.7 总结..................................................................................................................................15
4 屏幕操作 .............................................................................. 15
4.1 汉字处理..........................................................................................................................15
4.2 系统时间显示..................................................................................................................17
4.3 菜单操作..........................................................................................................................19
4.4 模拟 Message Box 函数 ..................................................................................................21
4.5 总结..................................................................................................................................22
5 键盘操作 .............................................................................. 22
5.1 处理功能键......................................................................................................................22
5.2 处理数字键......................................................................................................................24
5.3 整理用户输入..................................................................................................................25
5.4 总结..................................................................................................................................26
6 性能优化 .............................................................................. 26
6.1 使用宏定义......................................................................................................................26
6.2 使用寄存器变量..............................................................................................................27
6.3 内嵌汇编..........................................................................................................................27
6.4 利用硬件特性..................................................................................................................28
6.5 活用位操作......................................................................................................................28
6.6 总结..................................................................................................................................29
![](https://csdnimg.cn/release/download_crawler_static/86569292/bg3.jpg)
C 语言嵌入式系统编程修炼之道
3
1.背景
不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编
程语言具备较强的硬件直接操作能力。无疑,汇编语言
具备这样的特质。但是,归因于汇编
语言开发过程的复杂性,它并不是嵌入式系统开发
的一般选择。而与之相比,C 语言--一种
"高级的低级"语言,则成为嵌入式系统开发的最佳选择。笔者在嵌入式系统项目的开发过程
中,一次又一次感受到 C 语言
的精妙,沉醉于 C 语言给嵌入式开发带来的便利。
图 1 给出了本文的讨论所基于的硬件平台,实际上,这也是大多数嵌入式系统的硬件平
台。它包括两部分:
(1) 以通用处理器为中心的协议处理模块,用于网络控制协议的处理;
(2) 以数字信号处理器(DSP)为中心的信号处理模块,用于调制、解调和数/模信
号转换。
本文的讨论主要围绕以通用处理器为中心的协议处理模块进行,因为它更多地牵涉到具
体的 C 语言编程技巧。而 DSP 编程则重点关注具体的数字信号处理算法,主要涉及通信领
域的知识,不是本文的讨论重点。
着眼于讨论普遍的嵌入式系统 C 编程技巧,系统的协议处理模块没有选择特别的 CPU,
而是选择了众所周知的 CPU 芯片--80186,每一位学习过《微机原理》的读者都应该对此芯
片有一个基本的认识,且对其指令集比较熟悉。80186 的字长是 16 位,可以寻址到的内存
空间为 1MB,只有实地址模式。C 语言编译生成的指针为 32 位(双字),高 16 位为段地址,
低 16 位为段内编译,一段最多 64KB。
图 1 系统硬件架构
协议处理模块中的 FLASH
和 RAM 几乎是每个嵌入式系统的必备设备,前者用于存储
![](https://csdnimg.cn/release/download_crawler_static/86569292/bg4.jpg)
C 语言嵌入式系统编程修炼之道
4
程序,后者则是程序运行时指令及数据的存放位置。系统所选择的 FLASH 和 RAM 的位宽
都为 16 位,与 CPU 一致。
实时钟芯片可以为系统定时,给出当前的年、月、日及具体时间(小时、分、秒及毫秒),
可以设定其经过一段时间即向 CPU 提出中断或设定报警时间到来时向 CPU 提出中断(类似
闹钟功能)。
NVRAM(非易失去性 RAM)具有掉电不丢失数据的特性,可以用于保存系统的设置
信息,譬如网络协议参数等。在系统掉电或重新启动后,仍然可以读取先前的设置信息。其
位宽为 8 位,比 CPU 字长小。文章特意选择一个与 CPU 字长不一致的存储芯片,为后文中
一节的讨论创造条件。
UART 则完成 CPU 并行数据传输与 RS-232 串行数据传输的转换,它可以在接收到
[1~MAX_BUFFER]字节后向 CPU 提出中断,MAX_BUFFER 为 UART 芯片存储接收到字节
的最大缓冲区。
键盘控制器和显示控制器则完成系统人机界面的控制。
以上提供的是一个较完备的嵌入式系统硬件架构,实际的系统可能包含更少的外设。之
所以选择一个完备的系统,是为了后文更全面的讨论嵌入式系统 C 语言编程技巧的方方面
面,所有设备都会成为后文的分析目标。
嵌入式系统需要良好的软件开发环境的支持,由于嵌入式系统的目标机资源受限,不可
能在其上建立庞大、复杂的开发环境,因而其开发环境和目标运行环境相互分离。因此,嵌
入式应用软件的开发方式一般是,在宿主机(Host)上建立开发环境,进行应用程序编码和交
叉编译,然后宿主机同目标机(Target)建立连接,将应用程序下载到目标机上进行交叉调试,
经过调试和优化,最后将应用程序固化到目标机中实际运行。
CAD-UL 是适用于 x86 处理器的嵌入式应用软件开发环境,它运行在 Windows 操作系
统之上,可生成 x86 处理器的目标代码并通过 PC 机的 COM 口(RS-232 串口)或以太网口
下载到目标机上运行,如图 2。其驻留于目标机 FLASH 存储器中的 monitor 程序可以监控
宿主机 Windows 调试平台上的用户调试指令,获取 CPU 寄存器的值及目标机存储空间、I/O
空间的内容。
图 2 交叉开发环境
后续章节将从软件架构、内存操作、屏幕操作、键盘操作、性能优化等多方面阐述 C
语言嵌入式系统的编程技巧。软件架构是一个宏观概念,与具体硬件的联系不大;内存操作
主要涉及系统中的 FLASH、RAM 和 NVRAM 芯片;屏幕操作则涉及显示控制器和实时钟;
![](https://csdnimg.cn/release/download_crawler_static/86569292/bg5.jpg)
C 语言嵌入式系统编程修炼之道
5
键盘操作主要涉及键盘控制器;性能优化则给出一些具体的减小程序时间、空间消耗的技巧。
在我们的修炼旅途中将经过 25 个关口,这些关口主分为两类,一类是技巧型,有很强
的适用性;一类则是常识型,在理论上有些意义。
So, let’s go.
2. 软件架构篇
2.1 模块划分
模块划分的"划"是规划的意思,意指怎样合理的将一个很大的软件划分为一系列功能独
立的部分合作完成系统的需求。C 语言作为一种结构化的程序设计语言,在模块的划分上主
要依据功能(依功能进行划分在面向对象设计中成为一个错误,牛顿定律遇到了相对论),
C 语言模块化
程序设计需理解如下概念:
模块即是一个.c 文件和一个.h 文件的结合,头文件(.h)中是对于该模块接口的声明;
某模块提供给其它模块调用的外部函数
及数据需在.h 中文件中冠以 extern 关键字声明;
模块内的函数和全局变量需在.c 文件开头冠以 static
关键字声明;
永远不要在.h 文件中定义变量!定义变量和声明变量的区别在于定义会产生内存分配的
操作,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其它模块寻找
外部函数和变量。如:
/*module1.h*/
int a = 5; /* 在模块 1 的.h 文件中定义 int a */
/*module1 .c*/
#include "module1.h" /* 在模块 1 中包含模块 1 的.h 文件 */
/*module2 .c*/
#include "module1.h" /* 在模块 2 中包含模块 1 的.h 文件 */
/*module3 .c*/
#include "module1.h" /* 在模块 3 中包含模块 1 的.h 文件 */
以上程序的结果是在模块 1、2、3 中都定义了整型变量 a,a 在不同的模块中对应不同
的地址单元,这个世界上从来不需要这样的程序。正确的做法是:
/*module1.h*/
extern int a; /* 在模块 1 的.h 文件中声明 int a */
/*module1 .c*/
#include "module1.h" /*
在模块
1
中包含模块
1
的
.h
文件
*
/