1〉我的背景:
生于江南,自认为较有追求,本科是二本普通学校,研究生是北京一个二流重点大学,当然我深爱着自己的这两个学校。专业都是计算机。个子长得不高,男性,喜欢交朋友。(搞得有点像征婚启事,见笑!)
在读研时,听到一个刚毕业的博士师兄说他现在月薪1万多,我当时真是艳羡不已,垂涎3千丈。
2〉A公司
2004年研究生毕业前夕到处找工作,想高薪又想搞到北京户口,颇费了不少周折。由于对高薪的向往和自己的傲气,在简历上写着月薪不低于8k。找了2个月,没搞到offer,心里甚急,觉得自己狂了点,便把那行删掉了,果然面试机会纷至沓来,终于有个公司,行业内还算知名的大公司,说给我offer,问我要多少钱,我说要7.5k,他说给我8.5k.当时心里真是狂喜。回校后还很炫了一下,可惜好景不长,1周后说要我和他签5年,ft,违约金5w,当然户口可以解决。我感觉难以承受,只好婉言拒绝,继续找,终于在年后,找到了A公司,痛快地说可以给户口,可是工资较低,只有5k,签3年,违约金2万。考虑了半天,还是答应了,毕竟解决户口不容易。再说A公司做的方向跟我吻合,于是6月份上班,A公司对我不薄,去了1个月后,立即升我为...

>> 阅读全文

作者:宋宝华 
摘要
在性能优化方面永远注意80-20准备,不要优化程序中开销不大的那80%,这是劳而无功的。宏定义是C语言中实现类似函数功能而又不具函数调用和返回开销的较好方法,但宏在本质上不是函数,因而要防止宏展开后出现不可预料的结果,对宏的定义和使用要慎而处之。
使用宏定义  在C语言中,宏是产生内嵌代码的唯一方法。对于嵌入式系统而言,为了能达到性能要求,宏是一种很好的代替函数的方法。  写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的一个:  错误做法:
#define MIN(A,B)  ( A   正确做法:
#define MIN(A,B) ((A)  对于宏,我们需要知道三点:  (1)宏定义"像"函数;  (2)宏定义不是函数,因而需要括上所有"参数";  (3)宏定义可能产生副作用。  下面的代码:
least = MIN(*p++, b);  将被替换为:
( (*p++)   发生的事情无法预料。   因而不要给宏定义传入有副作用的"参数"。  使用寄存器变量  当对一个变量频繁被读写时,需要反复访问内存,从而花费大量的存取时间。为此,C语言...

>> 阅读全文

作者:宋宝华 
摘要
本篇给出了键盘操作所涉及的各个方面:功能键处理、数字键处理及用户输入整理,基本上提供了一个全套的按键处理方案。对于功能键处理方法,将LCD屏幕与Windows窗口进行类比,提出了较新颖地解决屏幕、键盘繁杂交互问题的方案。
处理功能键  功能键的问题在于,用户界面并非固定的,用户功能键的选择将使屏幕画面处于不同的显示状态下。例如,主画面如图1:
图1 主画面  当用户在设置XX上按下Enter键之后,画面就切换到了设置XX的界面,如图2:
图2 切换到设置XX画面  程序如何判断用户处于哪一画面,并在该画面的程序状态下调用对应的功能键处理函数,而且保证良好的结构,是一个值得思考的问题。  让我们来看看WIN32编程中用到的"窗口"概念,当消息(message)被发送给不同窗口的时候,该窗口的消息处理函数(是一个callback函数)最终被调用,而在该窗口的消息处理函数中,又根据消息的类型调用了该窗口中的对应处理函数。通过这种方式,WIN32有效的组织了不同的窗口,并处理不同窗口情况下的消息。  我们从中学习到的就是:  (1)将不同的画面类比为WIN32中不同的...

>> 阅读全文

作者:宋宝华
摘要
屏幕乃嵌入式系统生存之重要辅助,面目可憎之显示将另用户逃之夭夭。屏幕编程若处理不好,将是软件中最不系统、最混乱的部分,笔者曾深受其害。
汉字处理  现在要解决的问题是,嵌入式系统中经常要使用的并非是完整的汉字库,往往只是需要提供数量有限的汉字供必要的显示功能。例如,一个微波炉的LCD上没有必要提供显示"电子邮件"的功能;一个提供汉字显示功能的空调的LCD上不需要显示一条"短消息",诸如此类。但是一部手机、小灵通则通常需要包括较完整的汉字库。  如果包括的汉字库较完整,那么,由内码计算出汉字字模在库中的偏移是十分简单的:汉字库是按照区位的顺序排列的,前一个字节为该汉字的区号,后一个字节为该字的位号。每一个区记录94个汉字,位号则为该字在该区中的位置。因此,汉字在汉字库中的具体位置计算公式为:94*(区号-1)+位号-1。减1是因为数组是以0为开始而区号位号是以1为开始的。只需乘上一个汉字字模占用的字节数即可,即:(94*(区号-1)+位号-1)*一个汉字字模占用字节数,以16*16点阵字库为例,计算公式则为:(94*(区号-1)+(位号-1))*32。汉字库中从该位置起的32...

>> 阅读全文

作者:宋宝华 
摘要
本篇主要讲述了嵌入式系统C编程中内存操作的相关技巧。掌握并深入理解关于数据指针、函数指针、动态申请内存、const及volatile关键字等的相关知识,是一个优秀的C语言程序设计师的基本要求。
数据指针  在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能力。以指针直接操作内存多发生在如下几种情况:  (1) 某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于某特定地址;  (2) 两个CPU之间以双端口RAM通信,CPU需要在双端口RAM的特定单元(称为mail box)书写内容以在对方CPU产生中断;  (3) 读取在ROM或FLASH的特定单元所烧录的汉字和英文字模。  譬如:
unsigned char *p = (unsigned char *)0xF000FF00;*p=11;  以上程序的意义为在绝对地址0xF0000+0xFF00(80186使用16位段地址和16位偏移地址)写入11。  在使用绝对地址指针时,要注意指针自增自减操作的结果取决于指针指向的数据类别。上例中p++...

>> 阅读全文

作者:宋宝华 
摘要
本篇介绍了嵌入式系统编程软件架构方面的知识,主要包括模块划分、多任务还是单任务选取等,从宏观上给出了一个嵌入式系统软件所包含的主要元素。
模块划分  模块划分的"划"是规划的意思,意指怎样合理的将一个很大的软件划分为一系列功能独立的部分合作完成系统的需求。C语言作为一种结构化的程序设计语言,在模块的划分上主要依据功能(依功能进行划分在面向对象设计中成为一个错误,牛顿定律遇到了相对论),C语言模块化程序设计需理解如下概念:  (1) 模块即是一个.c文件和一个.h文件的结合,头文件(.h)中是对于该模块接口的声明;  (2) 某模块提供给其它模块调用的外部函数及数据需在.h中文件中冠以extern关键字声明;  (3) 模块内的函数和全局变量需在.c文件开头冠以static关键字声明;  (4) 永远不要在.h文件中定义变量!定义变量和声明变量的区别在于定义会产生内存分配的操作,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其它模块寻找外部函数和变量。如:
/*module1.h*/int a = 5; /* 在模块1的.h文件中定义int a *//*module1 .c*/#include...

>> 阅读全文

作者:宋宝华 
摘要
在我们的修炼旅途中将经过25个关口,这些关口主分为两类,一类是技巧型,有很强的适用性;一类则是常识型,在理论上有些意义。
不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力。无疑,汇编语言具备这样的特质。但是,归因于汇编语言开发过程的复杂性,它并不是嵌入式系统开发的一般选择。而与之相比,C语言--一种"高级的低级"语言,则成为嵌入式系统开发的最佳选择。笔者在嵌入式系统项目的开发过程中,一次又一次感受到C语言的精妙,沉醉于C语言给嵌入式开发带来的便利。  图1给出了本文的讨论所基于的硬件平台,实际上,这也是大多数嵌入式系统的硬件平台。它包括两部分:   (1) 以通用处理器为中心的协议处理模块,用于网络控制协议的处理;  (2) 以数字信号处理器(DSP)为中心的信号处理模块,用于调制、解调和数/模信号转换。  本文的讨论主要围绕以通用处理器为中心的协议处理模块进行,因为它更多地牵涉到具体的C语言编程技巧。而DSP编程则重点关注具体的数字信号处理算法,主要涉及通信领域的知识,不是本文的讨...

>> 阅读全文

当进行便携设备的设计时,工程师在选择模拟开关时必须特别关注RON、串扰、THD、带宽、电荷注入、插损等参数。本文阐述了模拟开关的工作原理以及选择这种器件时对各种关键参数的折衷考虑。
图1:FSTU3125型4位总线开关。
最近几年,开关正进入到PC、服务器、笔记本电脑及扩展基座(docking station)应用等市场中,这随后导致众多芯片厂商蜂拥推出各种“总线开关”。这些总线开关之所以具有吸引力,是因为通过在应用中与(缓存或存储器中的)多路复用/解复用数据隔离或进行电压转换,在插入(连接)或断开期间就很方便地将总线电容与插卡或设备隔开。大多数总线开关产品都是能处理奇偶或非奇偶应用数据通信总线宽度的8、10、16、18、24或32位器件。这些产品还被用于字节交换、纵横(交叉)路由及存储器交错等。总线开关一般被设计成单NMOS器件,且由于其双向本质、低(或“零”)传播延时(典型为250ps)、低电容及低电流源要求而常常被用作缓冲器或收发器的替代器件。但单NMOS通道的缺点是,随着源极电压接近Vcc,栅极下面的漏-源区会逐渐被夹紧,从而限制电流供应能力并使输出电压箝位。但请记住,电流源是以驱动缓冲器为特征,而开关并非天然就具有电流供应能...

>> 阅读全文