EDN首页   博客首页

最新日志

发表于:2008-1-10 17:40:16
标签:无标签

1

DS18B20温度计制作全过程(出自http://avr.cnta.net)

元件盒一直躺着几只DS18B20,从没试过,决定用它做个电子温度计,说干就干......
  
  1、构思
  Mega8做大脑、小塑料盒做外壳、3位LED数码管显示、废弃手机电池做电源、线路板热转印制作、设置2个开关(1个按键式、1个拨动式可常开)、RS232升级程序。先想这些吧,开始干了。

  2、画电路出图
  电路原理图很简单,很快用PROTEL99SE画完;
  根据小塑料盒大小设计PCB板,布好线,这步也不复杂。
  裁好热转印纸,准备出图了,我喜欢打印时选择"Show Holes",这样在焊盘上就有孔。用我刚买的HP3050Z一体机,那天逛科技市场,看了感觉不错就搬回来了,从没用它打过转印纸,还不知道效果呢。
  ......图出来了,还不错!比较满意。

 3、制作线路板
  ①找块单面敷铜板, 按合适尺寸裁好,用很细很细的沙纸打磨光亮,冲洗干净,吹干。千万别省事,一定要干净,否则转印效果不好。也可以用稀三氯化铁擦涂一下,能稍微提高转印效果。

 ②对好位置,将打好的热转印 纸盖到敷铜板上,用不干胶粘到平整的耐热材料上,强烈建议别直接放在你家的红木写字台上,我用的是铺剩的复合地板。用电熨斗进行转印,慢慢移动,使图及板受热均匀,尤其是边缘部分,要特别照顾一下。力量和时间我全是靠经验,大概20秒左右,稍用力。

③加热后,纸与板粘在一起了,很烫,一定小心,别烫了你的小手手。扔到洗手池里,用凉水降温,我实在等不及它自然冷却。

④板子凉了,从一边轻轻撕下转印纸,看看效果吧,很不错!是10Mil的线啊,没断一根。

⑤扔到三氯化铁熔液里腐蚀。要想速度快,最好是热熔液+搅拌+毛刷轻刷。
  应该好了吧,看看......

 

 ⑥洗净炭粉。你们都是用什么洗啊,我用汽油,气味大点,但非常好用,用纸巾蘸一点就擦干净了,擦后用肥皂洗一下板子。什么?你没有汽油,这好办,拿个钢钉,拿把锤子,拿个瓶子,趁没人的时候到你家楼下找辆底盘高点的车,爬到车底下,在油箱上凿个洞,汽油就流出来了,接汽油的时候千万别抽烟,切记。接完汽油后,别忘了给人家油箱用什么东西堵上,以免漏光油耽误人家办急事。(取油方法仅限于想象,请勿模仿,哈哈)

 4、线路板钻孔,学学CNC
  线路板手动钻孔是件麻烦事,特别是IC脚的排孔,往往钻不垂直钻不整齐。今天试试用雕刻机自动钻孔,开始了......
  ①用PROTEL99SE将PCB输出PDF格式文件,分辨率设置为600DPI,如果你装了虚拟图形打印机,当然也可以直接输出BMP格式图像文件,我用的是PdfCreator虚拟打印机。用PhotoShop CS2打开PDF文件,分辨率输入600DPI...... 

点击开大图

 ②处理图像
  将图像水平翻转,将角上4个螺丝孔的焊盘染为另一种颜色,我将它染成了绿色,存为BMP格式文件。 


  ③生成刀路文件
  启动ArtCAM Pro 8.1,打开刚才处理好的BMP格式文件,不要使用快捷方式<通过图像产生模型>,否则调入的图像会转换为灰度,要使用菜单的[文件]-[打开]或打开文件按钮。确定后,会蹦出模型尺寸设置对话框,设置为600DPI,单位毫米...... 

双击绿色焊盘,选择绿色图形,然后在对话框上点<关闭>...... 

在<助手>里的<矢量-位图>点<位图到矢量>小图标...... 

 退出通过位图产生矢量对话框,点<接受>即可。这时4个绿色焊盘会由虚线框住。 

 下面要生成刀路文件了。在<刀具路径>的<二维刀具路径>里点击<钻孔>图标 

 

 在<钻孔>设置里,开始深度0,结束深度2.5,随便选择个尖刀,设置下切步距3,钻孔中心位于全部已选矢量,材料厚度3,起个名称叫“定位”吧,点击<现在>,再点<关闭>,在<刀具路径>框上方就出现了[定位]的名称,单击它变成蓝色,点击<保存刀具路径>...... 

选择Tryax格式,起个名字,还是叫“定位”吧,保存刀具路径文件。 

 

点击开大图

 

******焊盘钻孔的刀具路径与以上方法相同,不再赘述******

  ④开始自动钻孔啦
  启动MACH2,调入“定位的.tap”,我喜欢用诊断模式,可以输入XYZ值控制主轴位置,按<Alt+7>进入诊断模式。
  将线路板放到雕刻机工作面上,操控刻刀到线路图左下角位置,刀尖离板3mm,置XYZ全零。

不用开主轴电机,空跑一遍试试,看刀是否落位准确,根据偏差调整线路板位置,直到4个点能落位准确,用热熔胶固定线路板。刀置于X0,Y0位置。


  调入钻孔刀路文件。换上0.8mm钻头,控制主轴下降,将钻头尖贴近线路板,将Z置零,打开主轴电机,点<启动>,雕刻机开始自动钻孔了......
  外壳开孔的加工方法同上,测量好开孔位置,用雕刻机尖刀开孔......
 
  5、制作测温头
  找个大小合适的电解电容。
  首先脱了它的衣扒了它的皮,然后抽了它的筋剔了它的肉,剩下个骨头架;
  然后将里面灌上导热硅脂,把焊上线的DS18B20放进去,呵呵,有点象寄居蟹;

找根粗细合适的圆珠笔杆,将测温头用环氧树脂胶固定住,这样能测量液体温度,没事就测测水烧开了没有。

 6、开始总装了
  将半成品运到总装车间,在总工程师领导下,各部门协调有序地运作起来。
  动力部门找了块原装名牌废手机锂电池,其实还能用,就是待机时间太短;
  机械部门找来了一颗钢珠,用做按钮开关的按键,说是增加温度计金属感,提高档次,再者这么白白滑滑的,摸着也舒服;
  线路板元件很少,几只电阻、1个按钮开关、1个拔动开关、1只Mega8、引出排线接LED数码管,再连上DS18B20的3根线......很快就焊接完毕

把盖子安上,怎么样,不错吧!

还有2个接口需要交待,一个是充电口,一个是RS232口。Mega8里烧进了BootLoader升级程序,用RS232口更新程序。 请看下面这个图,右边是充电接口,中间是电源拔动开关,左边是RS232接口。

7、电路及程序
  电路非常简单,这是电路图:

 程序用BASCOM-AVR编写,也是比较简单,以前从没用过DS18B20,现学现编。采用9位精度,设置好后存入DS18B20的EEPROM。程序没仔细推敲,只是完成简单的显示温度功能。最多显示3位数字,(-10,100)显示1位小数,其它区间显示整数。

系统分类: 单片机   |    用户分类: 无分类    |    来源: 无分类

评论(4) | 阅读(1140)
发表于:2008-1-7 18:09:44
标签:无标签

1

单片机C语言程序设计师试题

填空题

1、设X=5AH,Y=36H,则X与Y“或”运算为__7EH_______,X与Y的“异或”运算为___6CH_____。

2、若机器的字长为8位,X=17,Y=35,则X+Y=__110100_____,X-Y=_11101110______(要求结果写出二进制形式)。

3、单片机的复位操作是____高电平______(高电平/低电平),单片机复位后,堆栈指针SP的值是___07h_____。

4、单片机中,常用作地址锁存器的芯片是__74HC373____________,常用作地址译码器芯片是_____74HC138____________。

5、若选择内部程序存储器, 应该设置为_____高_______(高电平/低电平),那么,PSEN信号的处理方式为___不用__________________。

6、单片机程序的入口地址是____0000H__________,外部中断1的入口地址是______0013H_________。

7、若采用6MHz的晶体振荡器,则MCS-51单片机的振荡周期为__0.5us_______,机器周期为_____2us__________。

8、外围扩展芯片的选择方法有两种,它们分别是___线选法_______________和_____译码法__________。

9、单片机的内部RAM区中,可以位寻址的地址范围是____20H~2FH______________,特殊功能寄存器中,可位寻址的地址是___是能被8整除的地址_________________。

10、子程序返回指令是___ret______,中断子程序返回指令是__  reti    。


单片机C语言程序设计师试题2(连载)

 

11、8051单片机的存储器的最大特点是   内部RAM           与     外部RAM         分开编址。

12、8051最多可以有   32    个并行输入输出口,最少也可以有   8    个并行口。

13、 函数          是C语言的基本单位。

14、串行口方式2接收到的第9位数据送   SCON         寄存器的   RB8       位中保存。

15、MCS-51内部提供  3    个可编程的  16     位定时/计数器,定时器有  4     种工作方式。

16、一个函数由两部分组成,即   说明部分            和    语句部分       。

17、串行口方式3发送的第9位数据要事先写入   SCON     寄存器的    TB8   位。

18、利用8155H可以扩展   3    个并行口,    256    个RAM单元。

19、C语言中输入和输出操作是由库函数 scanf         和    printf      等函数来完成。


单片机C语言程序设计师试题3

 

二、选择题

1、C语言中最简单的数据类型包括( B )。

A、整型、实型、逻辑型             B、整型、实型、字符型

C、整型、字符型、逻辑型           D、整型、实型、逻辑型、字符型

2、当MCS-51单片机接有外部存储器,P2口可作为 (  C  )。

A、数据输入口                     B、数据的输出口   

C、准双向输入/输出口             D、输出高8位地址

3、下列描述中正确的是(  D  )。

A、程序就是软件                   B、软件开发不受计算机系统的限制

C、软件既是逻辑实体,又是物理实体 D、软件是程序、数据与相关文档的集合

4、下列计算机语言中,CPU能直接识别的是(  D  )。

A、 自然语言     B、 高级语言      C、 汇编语言     D、机器语言

5、MCS-5l单片机的堆栈区是设置在(  C  )中。

  A、片内ROM区  B、片外ROM区  C、片内RAM区  D、片外RAM区

6、以下叙述中正确的是( C  )。

A、用C语言实现的算法必须要有输入和输出操作

B、用C语言实现的算法可以没有输出但必须要有输入

C、用C程序实现的算法可以没有输入但必须要有输出

D、用C程序实现的算法可以既没有输入也没有输出

7、定时器/计数器工作方式1是(  D   )。

  A、8位计数器结构                 B、2个8位计数器结构

  C、13位计数结构                  D、16位计数结构

8、C语言提供的合法的数据类型关键字是(  B   )。

A、Double       B、short          C、integer        D、Char

9、片内RAM的20H~2FH为位寻址区,所包含的位地址是(  B  )。

  A、00H~20H    B、00H~7FH     C、20H~2FH     D、00H~FFH

10、以下能正确定义一维数组的选项是(  B )。

A、int a[5]={0,1,2,3,4,5};            B、char a[ ]={0,1,2,3,4,5};

C、char a={'A','B','C'};               D、int a[5]="0123";
 


单片机C语言程序设计师试题4(连载)

 

11、数据的存储结构是指(D   )。

A、存储在外存中的数据            B、数据所占的存储空间量

C、数据在计算机中的顺序存储方式  D、数据的逻辑结构在计算机中的表示

12、下列关于栈的描述中错误的是(C    )。

A、栈是先进后出的先性表  B、栈只能顺序存储

C、栈具有记忆作用        D、对栈的插入和删除操作中,不需要改变栈底指针

13、在寄存器间接寻址方式中,间址寄存器中存放的数据是( B   )。

  A、参与操作的数据                B、操作数的地址值 

C、程序的转换地址                D、指令的操作码

14、MCS-51单片机的复位信号是(  A   )有效。

  A、高电平       B、低电平       C、脉冲           D、下降沿

15、为了使模块尽可能独立,要求( B )。

A、模块的内聚程度要尽量高,且各模块间的耦合程度要尽量强

B、模块的内聚程度要尽量高,且各模块间的耦合程度要尽量弱

C、模块的内聚程度要尽量低,且各模块间的耦合程度要尽量弱

D、模块的内聚程度要尽量低,且各模块间的耦合程度要尽量强

16、若MCS-51单片机使用晶振频率为6MHz时,其复位持续时间应该超过(  B   )。

  A、2μs          B、4μs           C、8μs           D、1ms

17、以下选项中可作为C语言合法常量的是(  A  )

A、-80         B、-080         C、-8e1.0       D、-80.0e

18、能够用紫外光擦除ROM中程序的只读存储器称为(  C   )。

  A、掩膜ROM    B、PROM        C、EPROM       D、EEPROM

19、以下不能定义为用户标识符是(  D  )。

A、Main         B、_0            C、_int          D、sizeof

20、下选项中,不能作为合法常量的是( B  )。//幂不能为小数

A、1.234e04      B、1.234e0.4      C、1.234e+4      D、1.234e0
 
 
 
21、以下叙述中错误的是(  C )

A、对于double类型数组,不可以直接用数组名对数组进行整体输入或输出

B、数组名代表的是数组所占存储区的首地址,其值不可改变

C、当程序执行中,数组元素的下标超出所定义的下标范围时,系统将给出“下标越界”的出错信息

D、可以通过赋初值的方式确定数组元素的个数

22、以下与函数fseek(fp,0L,SEEK_SET)有相同作用的是(  D   )

A、feof(fp)       B、ftell(fp)       C、fgetc(fp)       D、rewind(fp)

23、存储16×16点阵的一个汉字信息,需要的字节数为(  A  )

A、 32           B、 64           C、 128           D、 256

24、已知1只共阴极LED显示器,其中a笔段为字形代码的最低位,若需显示数字1,则它的字形代码应为(  B  )。

  A、06H         B、F9H          C、30H           D、CFH

25、在C语言中,合法的长整型常数是(    A  )

A、 OL          B、 4962710       C、 324562&      D、 216D

26、以下选项中合法的字符常量是(   B  )

A、 "B"          B、 ’\010’         C、 68            D、 D

27、若PSW.4=0,PSW.3=1,要想把寄存器R0的内容入栈,应使用(   D   )指令。

  A、PUSH  R0   B、PUSH  @R0   C、PUSH  00H   D、PUSH  08H

28、在片外扩展一片2764程序存储器芯片要(   B    )地址线。

  A、8根         B、13根          C、16根         D、20根

29、设MCS-51单片机晶振频率为12MHz,定时器作计数器使用时,其最高的输入计数频率应为(   C   )

  A、2MHz        B、1MHz        C、500kHz        D、250kHz

30、下列数据字定义的数表中,(   A   )是错误的。

  A、DW  “AA”     B、DW  “A”       C、DW  “OABC”   D、DW  OABCH
三、判断题

(  √ )1、在对某一函数进行多次调用时,系统会对相应的自动变量重新分配存储单元。

(  × )2、在C语言的复合语句中,只能包含可执行语句。

(  √ )3、自动变量属于局部变量。

( ×  )4、Continue 和break都可用来实现循环体的中止。

( √  )5、字符常量的长度肯定为1。

( ×  )6、在MCS-51系统中,一个机器周期等于1.5μs。

( √  )7、C语言允许在复合语句内定义自动变量。

( √  )8、若一个函数的返回类型为void,则表示其没有返回值。

( ×  )9、所有定义在主函数之前的函数无需进行声明。

(  × )10、定时器与计数器的工作原理均是对输入脉冲进行计数。

( ×  )11、END表示指令执行到此结束。

(  √ )12、ADC0809是8位逐次逼近式模/数转换接口。

(  √ )13、MCS-51的相对转移指令最大负跳距是127B。

( ×  )14、MCS-51的程序存储器只是用来存放程序的。

( √  )15、TMOD中的GATE=1时,表示由两个信号控制定时器的的启停。

(  × )16、MCS-51的特殊功能寄存器分布在60H~80H地址范围内。

(  × )17、MCS-51系统可以没有复位电路。

( ×  )18、片内RAM与外部设备统一编址时,需要专门的输入/输出指令。

( √  )19、锁存器、三态缓冲寄存器等简单芯片中没有命令寄存和状态寄存等功能。

( √  )20、使用8751且 =1时,仍可外扩64KB的程序存储器。

四、简答题

1、在使用8051的定时器/计数器前,应对它进行初始化,其步骤是什么?

答:   (1)确定T/C的工作方式——编程TMOD寄存器;

       (2)计算T/C中的计数初值,并装载到TH和TL;

       (3)T/C在中断方式工作时,须开CPU中断和源中断——编程IE寄存器;

       (4)启动定时器/计数器——编程TCON中TR1或TR0位。

 

2、什么是重入函数?重入函数一般什么情况下使用,使用时有哪些需要注意的地方?

答: 多个函数可以同时使用的函数,称为重入函数。

通常情况下,C51函数不能被递归调用,也不能应用导致递归调用的结构。有此限制是由于函数参数和局部变量是存储在固定的地址单元中。重入函数特性允许你声明一个重入函数。即可以被递归调用的函数。

重入函数可以被递归调用,也可以同时被两个或更多的进程调用。重入函数在实时应用中及中断服务程序代码和非中断程序代码必须共用一个函数的场合中经常用到。

 

3、8051引脚有多少I/O线?他们和单片机对外的地址总线和数据总线有什么关系?地址总线和数据总线各是几位?

答:8051引脚共有40个引脚,8051的地址总线由P2和P0口提供,P2口是地址总线的高8位,P0口是地址总线的低8位;数据总线由P0口提供;P0口的地址总线和数据总线是分时进行的,P0口的地址总线需要外接地址锁存器完成地址锁存。

    地址总线共16位,数据总线是8位。

 

4、在有串行通信时,定时器/计数器1的作用是什么,怎样确定串行口的波特率?

答:在有串行通信时,定时器/计数器1的作用是串行口发生器。

串行口的波特率根据串行口的工作方式具有不同的计算方式:

方式0的波特率固定为晶体振荡器的十二分之一;

方式1的波特率=2SMOD.(定时器1的溢出率)/32;

方式2波特率=2SMOD.(fosc/64);

方式3波特率同方式1(定时器l作波特率发生器)。

 

5、如何消除键盘的抖动?怎样设置键盘中的复合键?

答:由于按键是机械开关结构,所以当用手按下其中一个键时,往往会出现所按键在闭合位置和断开位置之间发生跳几下后才会稳定到闭合状态的情况。在释放一个键时,也会出现类似的情况,这就是键的抖动,抖动的持续时间不一,但通常不会大于10ms。

若抖动问题不解决,就会引起对闭合键的多次读入。对于键抖动最方便的解决方法就是当发现有键按下后,不是立即进行扫描,而是延时大约10ms后再进行。由于一个键按下的时间一般会持续上百毫秒,所以延迟10ms后再扫描处理并不迟。

复合键可以仿照计算机复合键的处理方法,通常可以假设一个键具有复合功能,再与其它减的键值组合成复合键。

系统分类: 单片机   |    用户分类:    |    来源: 转贴

评论(0) | 阅读(943)
发表于:2008-1-7 18:06:00
标签:无标签

1

用PROTEL99制作印刷电路版的基本流程

 

一、电路版设计的先期工作

  1、利用原理图设计工具绘制原理图,并且生成对应的网络表。当然,有些特殊情况下,如电路版比较简单,已经有了网络表等情况下也可以不进行原理图的设计,直接进入PCB设计系统,在PCB设计系统中,可以直接取用零件封装,人工生成网络表。

2、手工更改网络表 将一些元件的固定用脚等原理图上没有的焊盘定义到与它相通的网络上,没任何物理连接的可定义到地或保护地等。将一些原理图和PCB封装库中引脚名称不一致的器件引脚名称改成和PCB封装库中的一致,特别是二、三极管等。

二、画出自己定义的非标准器件的封装库

   建议将自己所画的器件都放入一个自己建立的PCB 库专用设计文件。

三、设置PCB设计环境和绘制印刷电路的版框含中间的镂空等

   1、进入PCB系统后的第一步就是设置PCB设计环境,包括设置格点大小和类型,光标类型,版层参数,布线参数等等。大多数参数都可以用系统默认值,而且这些参数经过设置之后,符合个人的习惯,以后无须再去修改。

   2、规划电路版,主要是确定电路版的边框,包括电路版的尺寸大小等等。在需要放置固定孔的地方放上适当大小的焊盘。对于3mm 的螺丝可用6.5~8mm 的外径和3.2~3.5mm 内径的焊盘对于标准板可从其它板或PCB izard 中调入。

   注意:在绘制电路版地边框前,一定要将当前层设置成Keep Out层,即禁止布线层。

四、打开所有要用到的PCB 库文件后,调入网络表文件和修改零件封装

   这一步是非常重要的一个环节,网络表是PCB自动布线的灵魂,也是原理图设计与印象电路版设计的接口,只有将网络表装入后,才能进行电路版的布线。

在原理图设计的过程中,ERC检查不会涉及到零件的封装问题。因此,原理图设计时,零件的封装可能被遗忘,在引进网络表时可以根据设计情况来修改或补充零件的封装。

当然,可以直接在PCB内人工生成网络表,并且指定零件封装。

五、布置零件封装的位置,也称零件布局

   Protel99可以进行自动布局,也可以进行手动布局。如果进行自动布局,运行"Tools"下面的"Auto Place",用这个命令,你需要有足够的耐心。布线的关键是布局,多数设计者采用手动布局的形式。用鼠标选中一个元件,按住鼠标左键不放,拖住这个元件到达目的地,放开左键,将该元件固定。Protel99在布局方面新增加了一些技巧。新的交互式布局选项包含自动选择和自动对齐。使用自动选择方式可以很快地收集相似封装的元件,然后旋转、展开和整理成组,就可以移动到板上所需位置上了。当简易的布局完成后,使用自动对齐方式整齐地展开或缩紧一组封装相似的元件。

   提示:在自动选择时,使用Shift+X或Y和Ctrl+X或Y可展开和缩紧选定组件的X、Y方向。  

注意:零件布局,应当从机械结构散热、电磁干扰、将来布线的方便性等方面综合考虑。先布置与机械尺寸有关的器件,并锁定这些器件,然后是大的占位置的器件和电路的核心元件,再是外围的小元件。

六、根据情况再作适当调整然后将全部器件锁定

   假如板上空间允许则可在板上放上一些类似于实验板的布线区。对于大板子,应在中间多加固定螺丝孔。板上有重的器件或较大的接插件等受力器件边上也应加固定螺丝孔,有需要的话可在适当位置放上一些测试用焊盘,最好在原理图中就加上。将过小的焊盘过孔改大,将所有固定螺丝孔焊盘的网络定义到地或保护地等。

   放好后用VIEW3D 功能察看一下实际效果,存盘。

七、布线规则设置

布线规则是设置布线的各个规范(象使用层面、各组线宽、过孔间距、布线的拓朴结构等部分规则,可通过Design-Rules 的Menu 处从其它板导出后,再导入这块板)这个步骤不必每次都要设置,按个人的习惯,设定一次就可以。

选Design-Rules 一般需要重新设置以下几点:

   1、安全间距(Routing标签的Clearance Constraint)

   它规定了板上不同网络的走线焊盘过孔等之间必须保持的距离。一般板子可设为0.254mm,较空的板子可设为0.3mm,较密的贴片板子可设为0.2-0.22mm,极少数印板加工厂家的生产能力在0.1-0.15mm,假如能征得他们同意你就能设成此值。0.1mm 以下是绝对禁止的。

   2、走线层面和方向(Routing标签的Routing Layers)

   此处可设置使用的走线层和每层的主要走线方向。请注意贴片的单面板只用顶层,直插型的单面板只用底层,但是多层板的电源层不是在这里设置的(可以在Design-Layer Stack Manager中,点顶层或底层后,用Add Plane 添加,用鼠标左键双击后设置,点中本层后用Delete 删除),机械层也不是在这里设置的(可以在Design-Mechanical Layer 中选择所要用到的机械层,并选择是否可视和是否同时在单层显示模式下显示)。

   机械层1 一般用于画板子的边框;

   机械层3 一般用于画板子上的挡条等机械结构件;

   机械层4 一般用于画标尺和注释等,具体可自己用PCB Wizard 中导出一个PCAT结构的板子看一下

   3、过孔形状(Routing标签的Routing Via Style)

   它规定了手工和自动布线时自动产生的过孔的内、外径,均分为最小、最大和首选值,其中首选值是最重要的,下同。

   4、走线线宽(Routing标签的Width Constraint)

   它规定了手工和自动布线时走线的宽度。整个板范围的首选项一般取0.2-0.6mm,另添加一些网络或网络组(Net Class)的线宽设置,如地线、+5 伏电源线、交流电源输入线、功率输出线和电源组等。网络组可以事先在Design-Netlist Manager中定义好,地线一般可选1mm 宽度,各种电源线一般可选0.5-1mm 宽度,印板上线宽和电流的关系大约是每毫米线宽允许通过1安培的电流,具体可参看有关资料。当线径首选值太大使得SMD 焊盘在自动布线无法走通时,它会在进入到SMD 焊盘处自动缩小成最小宽度和焊盘的宽度之间的一段走线,其中Board 为对整个板的线宽约束,它的优先级最低,即布线时首先满足网络和网络组等的线宽约束条件。下图为一个实例

   5、敷铜连接形状的设置(Manufacturing标签的Polygon Connect Style)

   建议用Relief Connect 方式导线宽度Conductor Width 取0.3-0.5mm 4 根导线45 或90 度。

   其余各项一般可用它原先的缺省值,而象布线的拓朴结构、电源层的间距和连接形状匹配的网络长度等项可根据需要设置。

   选Tools-Preferences,其中Options 栏的Interactive Routing 处选Push Obstacle (遇到不同网络的走线时推挤其它的走线,Ignore Obstacle为穿过,Avoid Obstacle 为拦断)模式并选中Automatically Remove (自动删除多余的走线)。Defaults 栏的Track 和Via 等也可改一下,一般不必去动它们。

   在不希望有走线的区域内放置FILL 填充层,如散热器和卧放的两脚晶振下方所在布线层,要上锡的在Top 或Bottom Solder 相应处放FILL。

布线规则设置也是印刷电路版设计的关键之一,需要丰富的实践经验。

八、自动布线和手工调整

   1、点击菜单命令Auto Route/Setup 对自动布线功能进行设置

   选中除了Add Testpoints 以外的所有项,特别是选中其中的Lock All Pre-Route 选项,Routing Grid 可选1mil 等。自动布线开始前PROTEL 会给你一个推荐值可不去理它或改为它的推荐值,此值越小板越容易100%布通,但布线难度和所花时间越大。

   2、点击菜单命令Auto Route/All 开始自动布线

   假如不能完全布通则可手工继续完成或UNDO 一次(千万不要用撤消全部布线功能,它会删除所有的预布线和自由焊盘、过孔)后调整一下布局或布线规则,再重新布线。完成后做一次DRC,有错则改正。布局和布线过程中,若发现原理图有错则应及时更新原理图和网络表,手工更改网络表(同第一步),并重装网络表后再布。

   3、对布线进行手工初步调整

需加粗的地线、电源线、功率输出线等加粗,某几根绕得太多的线重布一下,消除部分不必要的过孔,再次用VIEW3D 功能察看实际效果。手工调整中可选Tools-Density Map 查看布线密度,红色为最密,黄色次之,绿色为较松,看完后可按键盘上的End 键刷新屏幕。红色部分一般应将走线调整得松一些,直到变成黄色或绿色。

九、切换到单层显示模式下(点击菜单命令Tools/Preferences,选中对话框中Display栏的Single Layer Mode)

   将每个布线层的线拉整齐和美观。手工调整时应经常做DRC,因为有时候有些线会断开而你可能会从它断开处中间走上好几根线,快完成时可将每个布线层单独打印出来,以方便改线时参考,其间也要经常用3D显示和密度图功能查看。

   最后取消单层显示模式,存盘。

十、如果器件需要重新标注可点击菜单命令Tools/Re-Annotate 并选择好方向后,按OK钮。

   并回原理图中选Tools-Back Annotate 并选择好新生成的那个*.WAS 文件后,按OK 钮。原理图中有些标号应重新拖放以求美观,全部调完并DRC 通过后,拖放所有丝印层的字符到合适位置。

   注意字符尽量不要放在元件下面或过孔焊盘上面。对于过大的字符可适当缩小,DrillDrawing 层可按需放上一些坐标(Place-Coordinate)和尺寸((Place-Dimension)。

   最后再放上印板名称、设计版本号、公司名称、文件首次加工日期、印板文件名、文件加工编号等信息(请参见第五步图中所示)。并可用第三方提供的程序来加上图形和中文注释如BMP2PCB.EXE 和宏势公司ROTEL99 和PROTEL99SE 专用PCB 汉字输入程序包中的FONT.EXE 等。

十一、对所有过孔和焊盘补泪滴

   补泪滴可增加它们的牢度,但会使板上的线变得较难看。顺序按下键盘的S 和A 键(全选),再选择Tools-Teardrops,选中General 栏的前三个,并选Add 和Track 模式,如果你不需要把最终文件转为PROTEL 的DOS 版格式文件的话也可用其它模式,后按OK 钮。完成后顺序按下键盘的X 和A 键(全部不选中)。对于贴片和单面板一定要加。

十二、放置覆铜区

   将设计规则里的安全间距暂时改为0.5-1mm 并清除错误标记,选Place-Polygon Plane 在各布线层放置地线网络的覆铜(尽量用八角形,而不是用圆弧来包裹焊盘。最终要转成DOS 格式文件的话,一定要选择用八角形)。下图即为一个在顶层放置覆铜的设置举例:

   设置完成后,再按OK 扭,画出需覆铜区域的边框,最后一条边可不画,直接按鼠标右键就可开始覆铜。它缺省认为你的起点和终点之间始终用一条直线相连,电路频率较高时可选Grid Size 比Track Width 大,覆出网格线。

   相应放置其余几个布线层的覆铜,观察某一层上较大面积没有覆铜的地方,在其它层有覆铜处放一个过孔,双击覆铜区域内任一点并选择一个覆铜后,直接点OK,再点Yes 便可更新这个覆铜。几个覆铜多次反复几次直到每个覆铜层都较满为止。将设计规则里的安全间距改回原值。

十三、最后再做一次DRC

   选择其中Clearance Constraints Max/Min Width Constraints Short Circuit Constraints 和Un-Routed Nets Constraints 这几项,按Run DRC 钮,有错则改正。全部正确后存盘。

十四、对于支持PROTEL99SE 格式(PCB4.0)加工的厂家可在观看文档目录情况下,将这个文件导出为一个*.PCB 文件;对于支持PROTEL99 格式(PCB3.0)加工的厂家,可将文件另存为PCB 3.0 二进制文件,做DRC。通过后不存盘退出。在观看文档目录情况下,将这个文件导出为一个*.PCB 文件。由于目前很大一部分厂家只能做DOS 下的PROTEL AUTOTRAX 画的板子,所以以下这几步是产生一个DOS 版PCB 文件必不可少的:

   1、将所有机械层内容改到机械层1,在观看文档目录情况下,将网络表导出为*.NET 文件,在打开本PCB 文件观看的情况下,将PCB 导出为PROTEL PCB 2.8 ASCII FILE 格式的*.PCB 文件。

   2 、用PROTEL FOR WINDOWS PCB 2.8 打开PCB 文件,选择文件菜单中的另存为,并选择Autotrax 格式存成一个DOS 下可打开的文件。

   3、用DOS 下的PROTEL AUTOTRAX 打开这个文件。个别字符串可能要重新拖放或调整大小。上下放的全部两脚贴片元件可能会产生焊盘X-Y大小互换的情况,一个一个调整它们。大的四列贴片IC 也会全部焊盘X-Y 互换,只能自动调整一半后,手工一个一个改,请随时存盘,这个过程中很容易产生人为错误。PROTEL DOS 版可是没有UNDO 功能的。假如你先前布了覆铜并选择了用圆弧来包裹焊盘,那么现在所有的网络基本上都已相连了,手工一个一个删除和修改这些圆弧是非常累的,所以前面推荐大家一定要用八角形来包裹焊盘。这些都完成后,用前面导出的网络表作DRC Route 中的Separation Setup ,各项值应比WINDOWS 版下小一些,有错则改正,直到DRC 全部通过为止。

   也可直接生成GERBER 和钻孔文件交给厂家选File-CAM Manager 按Next>钮出来六个选项,Bom 为元器件清单表,DRC 为设计规则检查报告,Gerber 为光绘文件,NC Drill 为钻孔文件,Pick Place 为自动拾放文件,Test Points 为测试点报告。选择Gerber 后按提示一步步往下做。其中有些与生产工艺能力有关的参数需印板生产厂家提供。直到按下Finish 为止。在生成的Gerber Output 1 上按鼠标右键,选Insert NC Drill 加入钻孔文件,再按鼠标右键选Generate CAM Files 生成真正的输出文件,光绘文件可导出后用CAM350 打开并校验。注意电源层是负片输出的。

十五、发Email 或拷盘给加工厂家,注明板材料和厚度(做一般板子时,厚度为1.6mm,特大型板可用2mm,射频用微带板等一般在0.8-1mm 左右,并应该给出板子的介电常数等指标)、数量、加工时需特别注意之处等。Email发出后两小时内打电话给厂家确认收到与否。

十六、产生BOM 文件并导出后编辑成符合公司内部规定的格式。

十七、将边框螺丝孔接插件等与机箱机械加工有关的部分(即先把其它不相关的部分选中后删除),导出为公制尺寸的AutoCAD R14 的DWG 格式文件给机械设计人员。

二十一、整理和打印各种文档。如元器件清单、器件装配图(并应注上打印比例)、安装和接线说明等。

系统分类: PCB   |    用户分类: 无分类    |    来源: 转贴

评论(0) | 阅读(555)
发表于:2008-1-7 18:02:31
标签:无标签

0

嵌入式程序员C语言测试题

嵌入式程序员C语言测试题

C语言测试是招聘嵌入式系统程序员过程中必须而且有效的方法。这些年,我既参加也组织了许多这种测试,在这过程中我意识到这些测试能为面试者和被面试者提供许多有用信息,此外,撇开面试的压力不谈,这种测试也是相当有趣的。
  从被面试者的角度来讲,你能了解许多关于出题者或监考者的情况。这个测试只是出题者为显示其对ANSI标准细节的知识而不是技术技巧而设计吗?这是个愚蠢的问题吗?如要你答出某个字符的ASCII值。这些问题着重考察你的系统调用和内存分配策略方面的能力吗?这标志着出题者也许花时间在微机上而不是在嵌入式系统上。如果上述任何问题的答案是"是"的话,那么我知道我得认真考虑我是否应该去做这份工作。

  从面试者的角度来讲,一个测试也许能从多方面揭示应试者的素质:最基本的,你能了解应试者C语言的水平。不管怎么样,看一下这人如何回答他不会的问题也是满有趣。应试者是以好的直觉做出明智的选择,还是只是瞎蒙呢?当应试者在某个问题上卡住时是找借口呢,还是表现出对问题的真正的好奇心,把这看成学习的机会呢?我发现这些信息与他们的测试成绩一样有用。

  有了这些想法,我决定出一些真正针对嵌入式系统的考题,希望这些令人头痛的考题能给正在找工作的人一点帮助。这些问题都是我这些年实际碰到的。其中有些题很难,但它们应该都能给你一点启迪。

  这个测试适于不同水平的应试者,大多数初级水平的应试者的成绩会很差,经验丰富的程序员应该有很好的成绩。为了让你能自己决定某些问题的偏好,每个问题没有分配分数,如果选择这些考题为你所用,请自行按你的意思分配分数。

预处理器(Preprocessor)
1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
  #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在这想看到几件事情:
1) #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
2)懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
3) 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
4) 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。

2 . 写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A) <= (B) ? (A) : (B)) 这个测试是为下面的目的而设的:
1) 标识#define在宏中应用的基本知识。这是很重要的。因为在  嵌入(inline)操作符 变为标准C的一部分之前,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
2)三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
3) 懂得在宏中小心地把参数用括号括起来
4) 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
least = MIN(*p++, b);

3. 预处理器标识#error的目的是什么?
如果你不知道答案,请看参考文献1。这问题对区分一个正常的伙计和一个书呆子是很有用的。只有书呆子才会读C语言课本的附录去找出象这种问题的答案。当然如果你不是在找一个书呆子,那么应试者最好希望自己不要知道答案。

死循环(Infinite loops)
4. 嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
这个问题用几个解决方案。  
我首选的方案是:
  while(1)
  {

  }
  一些程序员更喜欢如下方案:
  for(;;)
  {

  }
  这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的基本原理。如果他们的基本答案是:"我被教着这样做,但从没有想到过为什么。"这会给我留下一个坏印象。
  第三个方案是用 goto
  Loop:
  ...
  goto Loop;
应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。

数据声明(Data declarations)
5. 用变量a给出下面的定义
  a) 一个整型数(An integer)
  b)一个指向整型数的指针( A pointer to an integer)
  c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)r
  d)一个有10个整型数的数组( An array of 10 integers)
  e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to
  integers)
  f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers)
  g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function
  that takes an integer as an argument and returns an  integer)
  h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of  ten pointers to functions that take an integer argument  and return an integer )
  答案是:
  a) int a; // An integer
  b) int *a; // A pointer to an integer
  c) int **a; // A pointer to a pointer to an integer
  d) int a[10]; // An array of 10 integers
  e) int *a[10]; // An array of 10 pointers to integers
  f) int (*a)[10]; // A pointer to an array of 10 integers
  g) int (*a)(int); // A pointer to a function a that
  takes an integer argument and returns an integer
  h) int (*a[10])(int); // An array of 10 pointers to
  functions that take an integer argument and return an
  integer
人们经常声称这里有几个问题是那种要翻一下书才能回答的问题,我同意这种说法。当我写这篇文章时,为了确定语法的正确性,我的确查了一下书。但是当我被面试的时候,我期望被问到这个问题(或者相近的问题)。因为在被面试的这段时间里,我确定我知道这个问题的答案。应试者如果不知道所有的答案(或至少大部分答案),那么也就没有为这次面试做准备,如果该面试者没有为这次面试做准备,那么他又能为什么出准备呢?

Static
6. 关键字static的作用是什么?
这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
2)在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
3)  在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代码范围的好处和重要性。

Const
7.关键字const有什么含意?
我只要一听到被面试者说:"const意味着常数",我就知道我正在和一个业余者打交道。去年Dan
Saks 已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着"只读"就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)
如果应试者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思?
  const int a;
  int const a;
  const int *a;
  int * const a;
  int const * a const;
  /******/
  前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字 ,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:
1) 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)
2) 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
3) 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

Volatile
8. 关键字volatile有什么含意?并给出三个不同的例子。
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1) 并行设备的硬件寄存器(如:状态寄存器)
2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3) 多线程应用中被几个任务共享的变量
  回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。 假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
1)一个参数既可以是const还可以是volatile吗?解释为什么。
2); 一个指针可以是volatile 吗?解释为什么。
3); 下面的函数有什么错误:
int square(volatile int *ptr)
  {
  return *ptr * *ptr;
  }
下面是答案:
  1)是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2); 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
  3) 这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
  {
  int a,b;
  a = *ptr;
  b = *ptr;
  return a * b;
  }
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
  long square(volatile int *ptr)
  {
  int a;
  a = *ptr;
  return a * a;
  }

位操作(Bit manipulation)
9. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。 对这个问题有三种基本的反应
1)不知道如何下手。该被面者从没做过任何嵌入式系统的工作。
2)  用bit fields。Bit  fields是被扔到C语言死角的东西,它保证你的代码在不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸看到 Infineon为其较复杂的通信芯片写的驱动程序,它用到了bit fields因此完全对我无用,因为我的编译器用其它的方式来实现bit  fields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。
3) 用 #defines 和 bit masks  操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:
  #define BIT3 (0x1 << 3)
  static int a;
void set_bit3(void)
  {
  a |= BIT3;
  }
  void clear_bit3(void)
  {
  a &= ~BIT3;
  }

  一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。

访问固定的内存位置(Accessing fixed memory locations)
10. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。
在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:
  int *ptr;
  ptr = (int *)0x67a9;
  *ptr = 0xaa55;
  A more obscure approach is: (   一个较晦涩的方法是):
  *(int * const)(0x67a9) = 0xaa55;
  即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。

中断(Interrupts)
11.  中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字  __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。
__interrupt double compute_area (double radius)
  {
  double area = PI * radius * radius;
  printf("\nArea = %f", area);
  return area;
  }
这个函数有太多的错误了,以至让人不知从何说起了:
1)ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。
2) ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。
3) 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。
4) 与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。

代码例子(Code examples)
12 . 下面的代码输出是什么,为什么?
  void foo(void)
  {
  unsigned int a = 6;
  int b = -20;
  (a+b > 6) ? puts("> 6") : puts("<= 6");
  }
  这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 ">6"。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于 6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。

13. 评价下面的代码片断:
  unsigned int zero = 0;
  unsigned int compzero = 0xFFFF;
  /*1's complement of zero */
  对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:
unsigned int compzero = ~0;
  这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。
到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希望更多看到应试者应付问题的方法,而不是答案。不管如何,你就当是这个娱乐吧...

动态内存分配(Dynamic memory allocation)
14. 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。这个主题已经在ESP杂志中被广泛地讨论过了(主要是 P.J. Plauger, 他的解释远远超过我这里能提到的任何解释),所有回过头看一下这些杂志吧!让应试者进入一种虚假的安全感觉后,我拿出这么一个小节目:下面的代码片段的输出是什么,为什么?
  char *ptr;
  if ((ptr = (char *)malloc(0)) == NULL)
  puts("Got a null pointer");
  else
  puts("Got a valid pointer");
  这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是"Got   a valid pointer"。我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。

Typedef
15 Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:
  #define dPS struct s *
  typedef struct s * tPS;
  以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?
  这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:
  dPS p1,p2;
  tPS p3,p4;
第一个扩展为
  struct s * p1, p2;
上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3   和p4 两个指针。

晦涩的语法
16 . C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?
  int a = 5, b = 7, c;
  c = a+++b;
  这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:c = a++ + b;
因此, 这段代码持行后a = 6, b = 7, c = 12。
  如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题。

        好了,伙计们,你现在已经做完所有的测试了。这就是我出的C语言测试题,我怀着愉快的心情写完它,希望你以同样的心情读完它。如果是认为这是一个好的测试,那么尽量都用到你的找工作的过程中去吧。天知道也许过个一两年,我就不做现在的工作,也需要找一个。

系统分类: 嵌入式   |    用户分类:    |    来源: 转贴

评论(0) | 阅读(472)
发表于:2008-1-7 17:55:02
标签:无标签

0

初学者系列(1)-嵌入式人才的发展方向(转发)

嵌入式系统无疑是当前最热门最有发展前途的IT应用领域之一。嵌入式系统用在一些特定专用设备上,通常这些设备的硬件资源(如处理器、存储器等)非常有限,并且对成本很敏感,有时对实时响应要求很高等。特别是随着消费家电的智能化,嵌入式更显重要。像我们平常常见到的手机、PDA、电子字典、可视电话、VCD/DVD/MP3 Player、数字相机(DC)、数字摄像机(DV)、U-Disk、机顶盒(Set Top Box)、高清电视(HDTV)、游戏机、智能玩具、交换机、路由器、数控设备或仪表、汽车电子、家电控制系统、医疗仪器、航天航空设备等等都是典型的嵌入式系统。
嵌入式系统是软硬结合的东西,搞嵌入式开发的人有两类。
一类是学电子工程、通信工程等偏硬件专业出身的人,他们主要是搞硬件设计,有时要开发一些与硬件关系最密切的最底层软件,如BootLoader、Board Support Package(像PC的BIOS一样,往下驱动硬件,往上支持操作系统),最初级的硬件驱动程序等。他们的优势是对硬件原理非常清楚,不足是他们更擅长定义各种硬件接口,但对复杂软件系统往往力不从心(例如嵌入式操作系统原理和复杂应用软件等)。
另一类是学软件、计算机专业出身的人,主要从事嵌入式操作系统和应用软件的开发。如果我们学软件的人对硬件原理和接口有较好的掌握,我们完全也可写BSP和硬件驱动程序。嵌入式硬件设计完后,各种功能就全靠软件来实现了,嵌入式设备的增值很大程度上取决于嵌入式软件,这占了嵌入式系统的最主要工作(目前有很多公司将硬件设计包给了专门的硬件公司,稍复杂的硬件都交给台湾或国外公司设计,国内的硬件设计力量很弱,很多嵌入式公司自己只负责开发软件,因为公司都知道,嵌入式产品的差异很大程度在软件上,在软件方面是最有“花头“可做的),所以我们搞软件的人完全不用担心我们在嵌入式市场上的用武之地,越是智能设备越是复杂系统,软件越起关键作用,而且这是目前的趋势。
从事嵌入式软件开发的好处是:
(1)
目前国内外这方面的人都很稀缺。一方面,是因为这一领域入门门槛较高,不仅要懂较底层软件(例如操作系统级、驱动程序级软件),对软件专业水平要求较高(嵌入式系统对软件设计的时间和空间效率要求较高),而且必须懂得硬件的工作原理,所以非专业IT人员很难切入这一领域;另一方面,是因为这一领域较新,目前发展太快,很多软硬件技术出现时间不长或正在出现(如ARM处理器、嵌入式操作系统、MPEG技术、无线通信协议等),掌握这些新技术的人当然很找。嵌入式人才稀缺,身价自然就高,越有经验价格就越高。其实嵌入式人才稀少,根本原因可能是大多数人无条件接触,这需要相应的嵌入式开发板和软件,另外需要有经验的人进行指导开发流程。
(2)
与企业计算等应用软件不同,嵌入式领域人才的工作强度通常低一些(但收入不低)。搞企业应用软件的IT企业,这个用户的系统搞完了,又得去搞下一个用户的,而且每个用户的需求和完成时间都得按客户要求改变,往往疲于奔命,重复劳动。相比而言,搞嵌入式系统的公司,都有自己的产品计划,按自己的节奏行事。所开发的产品通常是通用的,不会因客户的不同而修改。一个产品型号开发完了,往往有较长一段空闲时间(或只是对软件进行一些小修补),有时间进行充电和休整。另外,从事嵌入式软件的每个人工作范围相对狭窄,所涉及的专业技术范围就是那些(ARM、RTOS、MPEG、802.11等),时间长了这些东西会越搞越有经验,卖卖老本,几句指导也够让那些初入道者琢磨半年的。若搞应用软件,可能下一个客户要换成一个完全不同的软件开发平台,那就苦了。
(3)
哪天若想创业,搞自已的产品,那么嵌入式是一个不错的主意,这可不像应用软件那样容易被盗版。土木学院有一个叫启明星的公司开发出一个好象叫“工程e”的掌上PDA(南校区门口有广告),施工技术人员用该PDA可当场进行土木概预算和其它土木计算,据说销路特好。我认识的某大学老师,他开发的饭馆用的点菜PDA(WinCE平台,可无线连网和上网),据他说销路不错,饭馆点点PDA让客户点菜,多显派头档次。我记得00级2+2班当年有一组同学在学Windows程序设计课程时用VC++设计了一个功能很强的点菜系统做为课程项目,当时真想建议他们将这个软件做成PDA,估计会有些销路(上海火车站南广场的Macdonald便使用很漂亮的PDA给用户点食品,像摸像样的)。这些PDA的硬件设计一般都是请其它公司给订做(这叫“贴牌”:OEM),都是通用的硬件,我们只管设计软件就变成自己的产品了。
从事嵌入式软件开发的缺点是:
(1)
入门起点较高,所用到的技术往往都有一定难度,若软硬件基础不好,特别是操作系统级软件功底不深,则可能不适于此行。
(2)
这方面的企业数量要远少于企业计算类企业。特别是从事嵌入式的小企业数量较多(小企业要搞自己的产品创业),知名大公司较少(搞嵌入式的大公司主要有Intel、Motorola、TI、Philip、Samsung、Sony、Futjtum、Bell-Alcatel、意法半导体、Microtek、研华、华为、中兴通信、上广电等制造类企业)。这些企业的习惯思维方式是到电子、通信等偏硬专业找人。由于我院以前毕业生以企业计算为主,所以我院与这些企业联系相对较少。我院正积极努力,目前已与其中部分公司建立了联系,争取今后能有我院同学到这些企业中实习或就业。
(3)有少数公司经常要硕士以上的人搞嵌入式,主要是基于嵌入式的难度。但大多数公司也并无此要求,只要有经验即可。
我院同学若学习嵌入式,显然应偏重于嵌入式软件,特别是嵌入式操作系统方面,应是我们的强项。对于搞嵌入式软件的人,最重要的是:
(1) 掌握主流嵌入式微处理器的结构与原理
(2) 必须掌握一个嵌入式操作系统
(3) 必须熟悉嵌入式软件开发流程并至少做过一个嵌入式软件项目。
嵌入式软件方面最重要的课程包括:
(1)
嵌入式微处理器结构与应用:这是一门嵌入式硬件基础课程,我院用这门课取代了传统的“微机原理与接口”课程(目前国内已有少部分高校IT专业这样做了,因为讲x86微机原理与接口很难找到实际用处,只为教学而已)。我们说过,嵌入式是软硬件结合的技术,搞嵌入式软件的人应对ARM处理器工作原理和接口技术有充分了解,包括ARM的汇编指令系统。若不了解处理器原理,怎么能控制硬件工作,怎么能写出节省内存又运行高速的最优代码(嵌入式软件设计特别讲究时空效率),怎么能写出驱动程序(驱动程序都是与硬件打交道的)?很多公司招聘嵌入式软件人员时都要求熟悉ARM处理器,将来若同学到公司中从事嵌入式软件开发,公司都会给你一本该设备的硬件规格说明书
(xxx
Specification),您必须能看懂其中的内存分布和端口使用等最基本的说明(就像x86汇编一样),否则怎么设计软件。有些同学觉得嵌入式处理器课程较枯燥,这主要是硬件课程都较抽象的原因,等我们的嵌入式实验室10月份建好后,您做了一些实验后就会觉得看得见摸得着。还有同学对ARM汇编不感兴趣,以为嵌入式开发用C语言就足够了。其实不应仅是将汇编语言当成一个程序设计语言,学汇编主要是为了掌握处理器工作原理的。一个不熟悉汇编语言的人,怎么能在该处理器写出最优的C语言代码。在嵌入式开发的一些关键部分,有时还必须写汇编,如Bootloader等(可能还包括BSP)。特别是在对速度有极高要求的场合(如DSP处理器的高速图像采集和图像解压缩),目前主要还要靠汇编写程序(我看到过很多公司是这样做的)。当您在一个嵌入式公司工作时,在查看描述原理的手册时,可能很多都是用汇编描述的(我就遇到过),这是因为很多硬件设计人员只会写或者喜欢用汇编描述,此时您就必须看懂汇编程序,否则软硬件人员可能就无法交流。很多嵌入式职位招聘时都要求熟悉汇编。
(2) 嵌入式操作系统类课程
除了WinCE的实时性稍差外,大多数嵌入式操作系统的实时性都很强,所以也可称为实时操作系统Real Time
Operating
System.从事嵌入式的人至少须掌握一个嵌入式操作系统(当然掌握两个更好),这在嵌入式的所有技术中是最为关键的了。目前最重要的RTOS主要包括:
第一类、传统的经典RTOS:最主要的便是Vxworks操作系统,以及其Tornado开发平台。Vxworks因出现稍早,实时性很强(据说可在1ms内响应外部事件请求),并且内核可极微(据说最小可8K),可靠性较高等,所以在北美,Vxworks占据了嵌入式系统的多半疆山。特别是在通信设备等实时性要求较高的系统中,几乎非Vxworks莫属。Vxworks的很多概念和技术都和Linux很类似,主要是C语言开发。像Bell-alcatel、Lucent、华为等通信企业在开发产品时,Vxworks用得很多。但Vxworks因价格很高,所以一些小公司或小产品中往往用不起。目前很多公司都在往嵌入式Linux转(听说华为目前正在这样转)。但无论如何,Vxworks在一段长时间内仍是不可动摇的。与Vxworks类似的稍有名的实时操作系统还有pSOS、QNX、Nucleus等RTOS。
第二类、嵌入式Linux操作系统:Linux的前途除作为服务器操作系统外,最成功的便是在嵌入式领域的应用,原因当然是免费、开源、支持软件多、呼拥者众,这样嵌入式产品成本会低。Linux本身不是一个为嵌入式设计的操作系统,不是微内核的,并且实时性不强。目前应用在嵌入式领域的Linux系统主要有两类:一类是专为嵌入式设计的已被裁减过的Linux系统,最常用的是uClinux(不带MMU功能),目前占较大应用份额,可在ARM7上跑;另一类是跑在ARM
9上的,一般是将Linux
2.4.18内核移植在其上,可使用更多的Linux功能(当然uClinux更可跑在ARM
9上)。很多人预测,嵌入式Linux预计将占嵌入式操作系统的50%以上份额,非常重要。缺点是熟悉Linux的人太少,开发难度稍大。另外,目前我们能发现很多教材和很多大学都以ucOS/II为教学用实时操作系统,这主要是由于ucOS/II较简单,且开源,非常适合入门者学习实时操作系统原理,但由于ucOS/II功能有限,实用用得较少,所以我院不将其作为教学重点,要学习就应学直接实用的,比如
uClinux就很实用。况且熟悉了Linux开发,不仅在嵌入式领域有用,对开发Linux应用软件,对加深操作系统的认识也有帮助,可谓一举多得。据我所知,目前Intel、Philip都在大搞ARM+LINUX的嵌入式开发,Fujitum则是在自己的处理器上大搞Linux开发。目前在嵌入式Linux领域,以下几个方面的人特别难找,一是能将Linux移植到某个新型号的开发版上;二是能写Linux驱动程序的人;三是熟悉Linux内核裁减和优化的人。我院在该嵌入式Linux方面的课程系列是:本科生操作系统必修课,然后是Linux程序设计选修课,最后是嵌入式Linux系统选修课。我院在Linux方面目前已有较强力量,魏老师和张老师熟悉Linux开发,金老师和唐老师熟悉Linux系统管理。
第三类、 Windows
CE嵌入式操作系统:Microsoft也看准了嵌入式的巨大市场,MS永远是最厉害的,WinCE出来只有几年时间,但目前已占据了很大市场份额,特别是在PDA、手机、显示仪表等界面要求较高或者要求快速开发的场合,WinCE目前已很流行(据说有一家卖工控机的公司板子卖得太好,以至来不及为客户裁减WinCE)。WinCE目前主要为4.2版(.NET),开发平台主要为WinCE Platform Builder,有时也用EVC环境开发一些较上层的应用,由于WinCE开发都是大家熟悉的VC++环境,所以我院学过Windows程序设计课程的同学都不会有多大难度,这也是WinCE容易被人们接受的原因,开发环境方便快速,微软的强大技术支持,WinCE开发难度远低于嵌入式Linux。对于急于完成,不想拿嵌入式Linux冒险的开发场合,WinCE是最合适了(找嵌入式Linux的人可没那么好找的),毕竟公司不能像学生学习那样试试看,保证开发成功更重要。根据不同的侧重点 ,WinCE还有两个特殊版本,一个是MS PocketPC操作系统专用于PDA上(掌上电脑),另一个是MS SmartPhone操作系统用于智能手机上(带PDA功能的手机),两者也都属于WinCE平台。在PDA和手机市场上,除WinCE外,著名的PDA嵌入式操作系统还有Palm OS(因出现很早,很有名)、Symbian等,但在WinCE的强劲冲击下,Palm和Symbian来日还能有多长?我院可能是全国高校中唯一一家开设专门的“Windows CE嵌入式操作系统“课程的学校,这主要是基于以下原因:我院本身前面便有Windows程序设计课程,同学学过VC++后再学WinCE,非常方便自然,通过学习WinCE同样也可了解嵌入式软件的一般开发过程,对Linux有惧怕心理的同学也很合适。很显然,嵌入式Linux永远不可能替代WinCE,而且将来谁占份额大还很难讲,毕竟很多人更愿意接受MS的平台,就像各国政府都在大力推LINUX已好长时间,但您能看到几个在PC机上真正使用LINUX的用户?据我观察,目前在嵌入式平台上,LINUX是叫得最响,但还是WinCE实际用得更多.嵌入式LINUX可能更多地是一些有长远产品计划的公司,为降低成本而进行长远考虑;
二是微软亚洲研究院对我院WinCE课程的支持计划,我们也很希望将来我院能有同学通过微软的面试去实习。WinCE和多媒体(如MPEG技术)是微软亚洲工程院目前做得较多的项目领域之一,他们很需要精通WinCE的人。
总结关于嵌入式操作系统类课程,若您觉得自己功底较深且能钻研下去,则可去学嵌入式Linux;若您觉得自己VC++功底较好且想短平快地学嵌入式开发,则我院的WinCE课程是最好的选择。
(3) 嵌入式开发的其它相关软件课程
搞嵌入式若能熟悉嵌入式应用的一些主要领域,这样的人更受企业欢迎。主要的相关领域包括:
A、数字图像压缩技术:这是嵌入式最重要最热门的应用领域之一,主要是应掌握MPEG编解码算法和技术,如DVD、MP3、PDA、高精电视、机顶盒等都涉及MPEG高速解码问题。为此,我院已预订了一位能开设数字图像处理课程的博士。
B、通信协议及编程技术:这包括传统的TCP/IP协议和热门的无线通信协议。首先,大多数嵌入式设备都要连入局域网或Internet,所以首先应掌握TCP/IP协议及其编程,这是需首要掌握的基本技术;其次,无线通信是目前的大趋势,所以掌握无线通信协议及编程也是是很重要的。无结通信协议包括无线局域网通信协议802.11系列,Bluetooth,以及移动通信(如GPRS、GSM、CDMA等)。
C、网络与信息安全技术:如加密技术,数字证书CA等。我院有这方面的选修课。
D、DSP技术:DSP是Digital Signal
Process数字信号处理的意思,DSP处理器通过硬件实现数字信号处理算法,如高速数据采集、压缩、解压缩、通信等。数字信号处理是电子、通信等硬件专业的课程,对于搞软件的人若能了解一下最好。目前DSP人才较缺。如果有信号与系统、数字信号处理等课程基础,对于学习MPEG编解码原理会有很大帮助。
(4)嵌入式开发的相关硬件基础
对于软件工程专业的学生,从事嵌入式软件开发,像数字电路、计算机组成原理、嵌入式微处理器结构等硬件课程是较重要的。另外,汇编语言、C/C++、数据结构和算法、特别是操作系统等软件基础课也是十分重要的。我们的主要目地是能看懂硬件工作原理,但重点应是在嵌入式软件,特别操作系统级软件,那将是我们的优势。
我们的研究生里有些是学电子、通信类专业过来的,有较好的模拟电路和单片机基础,学嵌入式非常合适。嵌入式本身就是从单片机发展过来的,只是单片机不带OS,而现在很多嵌入式应用越来越复杂,以至不得不引入嵌入式操作系统。另外,为追求更高速的信号处理速度,现在在一些速度要求较高的场合,有不少公司是将一些DSP算法,如MPEG压缩解压缩算法等用硬件来实现,这就涉及到HDL数字电路设计技术及其FPGA/IP核实现技术,这方面的人目前市场上也很缺。
题外话
另外,能写驱动程序的人目前是非常紧缺的(驱动程序也可归于嵌入式范畴),包括桌面Windows中的DDK开发环境和WDM驱动程序。公司每时每刻都要推出新产品,每一个新产品出来了,要能被操作系统所使用,是必须写驱动程序的。写驱动程序就必须掌握操作系统(如Windows或Linux)的内部工作原理,还涉及到少量硬件知识,难度较大,所以这方面的人很难找。想成为高手的同学,也可从驱动程序方面获得突破。我可说一下自己的经历,三年前我曾短暂地在一家公司写过WinCE驱动程序(正是因为知道这方面的人紧缺,所以才要做这方面的事),尽管那以前从未做过驱动程序,应聘那个职位时正是看准了公司是很难招聘到这方面的人,既然都找不到人,驱动还得有人做,这正是可能有机会切入这一领域的大好机会。面试时大讲自己写过多少万行汇编程序,对计算机工作原