随笔-11  评论-0  文章-0  trackbacks-0
  置顶随笔

:本文主要介绍汽车电子产品供应商给车厂供货时,由于严酷EMC要求,往往电磁兼容验证不能通过,导致供货受到一定的影响;本文结合实际设计一个普通的产品 EMC进行分析,说明车厂的EMC要求以及常见问题与解决方法。

关键词BCI(大电流注入实验)        CE(电源端口的传导骚扰实验)

         RE(辐射发射实验)            RS(抗扰度实验)

随着汽车电控技术的不断发展,汽车电子设备数量大大增加,电路工作频率逐渐提高,功率逐渐增大,使得汽车工作环境中充斥着电磁波,导致电磁干扰问题日益突出,轻则影响电子设备的正常工作,重则损坏相应的电器元件。

因此,汽车应用电子产品都会涉及到共性问题——汽车电磁兼容技术。汽车电磁兼容技术关乎汽车特定电子系统及其周围电子系统运行的安全可靠性,关乎电子控制功能的运行的安全可靠性。诸如电子控制汽车制动系统电子控制传动系统、电子控制转向系统。乃至影响汽车整车的安全可靠性。因此,汽车电子设备的电磁兼容性能越来越受重视,目前迫切要求能广泛应用针对汽车子设备的电磁改进技术.

国内外各个车厂就针对这种环境制定出一系列的抗扰度测试标准,同时为了保证良好的电磁兼容环境,同时也对产品提出了一系列的电磁骚扰标准。

以下表格为国外汽车电子需要满足的标准,国内大体上也是根据国外标准制定,同时在我们国内的合资汽车厂商,以及我们国内的相关汽车厂商也是遵循以下标准,只是在具体要求上略有差异。

标准协会

标准号

标准名称

汽车电磁兼容国际标准

ISO 11451

道路车辆——窄带辐射电磁能量所产生的电气干扰——整车测试法

Road vehicles—Electrical disturbances by narrowband radiated electromagnetic energy—Vehicle test methods

ISO 11452

道路车辆——窄带辐射电磁能量所产生的电气干扰——零部件测试法

Road ISO vehicles—Electrical disturbances by narrowband radiated electromagnetic energy —Component test methods

ISO 7637

道路车辆——由传导和耦合产生的电气干扰

road vehicles—electrical disturbances by conduction and coupling

ISO TR 1O6O

道路车辆——静电放电产生的电气干扰

road vehicles—electrical disturbances from electrostatic discharge

CISPR 12

车辆、机动船和内燃发动机驱动装置的无线电骚扰特性的限值和测量方法

Vehiclesboatsand internal combustion engine driven devices radio disturbance characteristics limits and methods of measurement

CISPR 25

用于保护用在车辆、机动船和装置上车载接受机的无线电骚扰特性的限值和测量方法

Limits and methods of measurement of radio disturbance characteristics for the protection of receivers used on board vehiclesboats and on devices

以上标准可以分为两类,一类是设备对外的无线电骚扰,一类是外部对我们设备的干扰,要求我们的设备具有一定的抗干扰特性。这两方面大部分产品都不能顺利的测试通过,满足整车厂家的要求。那么如何提高我们汽车电子产品的自身抗扰度以及降低自身对外的电磁发射,满足各类整车制造厂家的要求?下面我们针对车载DVD产品作一些详细的分析。

车载DVD一般带有FM以及AM功能,同时DVD播放器必须带显示系统,所以一般配备一个7寸的LCD屏。设计技术比较高的厂商为了增加实用性,在DVD上面配备USB Host功能,以及GPS导航功能,车载DVD最终变成了车载娱乐导航系统。

由于车载娱乐系统功能复杂,大多采用高速数字电路,大家都知道由于数字电路上升沿比较陡,谐波分量比较丰富,最终导致设备对外界的辐射很强;通常不能满足CISPR25的要求。如何降低娱乐系统对外的干扰,我们还需要将对外干扰进行分类,从干扰的性质来讲干扰主要分二类:

一、             传导发射(沿着设备对外电缆进行发射)

对于传导发射我们一般有几种方式来解决:

A、源头抑制:查找发射的源头,精确定位到某个器件、信号,进行分析处理,主要针对时钟,高速时钟线进行处理;

B、在对外电缆接口处进行滤波处理,针对干扰的频率,性质有针对性的选用器件进行滤波,常用的器件有电感,电容等。

二、             空间发射(通过设备缝隙或本身对外进行发射)

对于空间发射我们一般的处理方法如下:

A、通过源头抑制对空间发射是一个很好的方法,主要是通过滤波电路,接口处理,PCB布局,布线,多层板设计解决;

B、加强设备的屏蔽,对设备的结构缝隙进行处理;

以上方法有利有弊;比如降低源头的后果会导致信号质量变差,我们在降低源头的时候必须要首先保证功能的正常以及稳定;增加滤波器件,对信号质量不会有大的影响(选择器件的时候要有针对性的选择并且结合实际的信号频率进行滤波选择),但是会导致设备成本增加;所以我们在操作的过程中要结合自己的情况灵活运用;

如何提高电子设备的抗扰度呢?我们先介绍车载DVD系统抗扰度实验常见的现象与解决方法:

1、 音频输出喇叭出现啸叫

对于音频输出喇叭啸叫,我们要分清楚啸叫的本质原因,常见的喇叭啸叫多数是因为干扰信号通过设备接口电缆耦合至内部电路(极少数是因为音频功放内部电路设计不合理所至),然后通过各种路径耦合至音频功放输入端,导致功放将无用的1KHz干扰载波信号进行放大输出,从而导致啸叫;解决方法一般有以下几种:

A、找出并切断耦合路径;

寻找耦合路径是一个复杂的分析过程,要具体的结合PCB布局、布线、原理图设计等各个因素综合进行分析,必要的时候可以借助示波器进行测试;一般可以用CS(传导敏感度试验)进行BCI模拟试验;

B、在设备信号口进行滤波,让干扰信号无法进入设备内部;

在信号口滤波,一般选用共模滤波方式进行抑制(有时候也会用电容进行滤波);选用共模电感时要有针对性的进行选择;如啸叫发生在60MHz,需要选择针对60MHZ有效滤波器件;

2、   屏幕乱码、抖动、系统死机、复位;

对于这几种情况,我们就要重点找出受干扰的具体电路,比如系统复位,此时我们就要关注复位电路、电源电路、控制电路等;如果屏幕乱码,我们就要关注视频处理电路、视频处理电路的控制信号、逻辑信号等;具体可以结合示波器进行观察,最终找出敏感源,一般按照以下两类情况进行分析。

一类:从设备信号口注入或者耦合至设备信号口的干扰;

对于这类干扰,最节省成本的办法是找出我们设备的敏感点,提高此点的抗干扰能力,但是这需要花费大量的时间以及精力,而且还必须要具备良好的电路、电磁场理论知识;我们现行的企业,一般到做EMC试验的时候,时间都是非常紧急,根本就没有足够的时间对设备进行详细的分析定位以及试验;所以在设备信号接口进行滤波不外是一个不错的选择;由于我们很明确干扰直接从电缆传导至设备内部,我们完全可以运用EMC器件将干扰在接口进行滤除,避免干扰传导至单板其他的电路;只要干扰在信号接口被滤除,我们的设备出现的问题也会随之消失;这种方法往往会导致成本有一定的上升;所以这种方法需要结合实际的情况进行考虑;

二类:从设备缝隙耦合至设备内部的干扰;

从缝隙耦合的干扰,直接可以将缝隙“堵住”进行试验;一般由缝隙引起的抗扰度问题着重处理缝隙即可,如果需要查找敏感源,就需要结合实际试验现象进行分析;

小结

对于汽车电子产品来讲,要通过严格的汽车电子电磁兼容标准要求,需要在结构,接口,单板滤波设计,PCB设计方面进行全方位考虑。

posted @ 2009-06-04 15:14 cxie's personal note 阅读(625) | 评论 (0)编辑 收藏
  2009年6月25日

指令系统的来源由相关资料和书籍整理,仅供参考,以帮助理解记忆,尽快掌握PIC单片机的指令系统。

指令                                 指令缩写来源
ADDWF        f,d                 ADD W and F
ANDWF        f,d                 AND W with F
CLRF             f                  CLeaR F
CLRW            -                  CLeaR W
COMF           f,d                COMplement F
DECF            f,d                DECrement F
DECFSZ        f,d                DECrement F,Skip if 0(Zero)
INCF             f,d                INCrement F
INCFSZ         f,d                INCrement F,Skip if 0(Zero)
IORWF          f,d                Inclusive OR W with F
MOVF           f,d                 MOVe F
MOVWF        f                   MOV W to F
NOP              -                   NO Operation
RLF               f,d                Rotate Left F through carry
RRF               f,d                Rotate Right F through carry
SUBWF         f,d                 SUBtract W from F
SWAPF          f,d                SWAP nibbles in F
XORWF         f,d                eXclusive OR W with F
BCF               f,b                Bit Clear F
BSF               f,b                 Bit Set F
BTFSC           f,b                Bit Test F,Skip if Clear
BTFSS           f,b                Bit Test F,Skip if Set
ADDLW         k                  ADD Literal and W
ANDLW         k                  AND Literal with W
CALL            k                   CALL subroutine
CLRWDT       -                   CLeaR WatchDog Timer
GOTO            k                  GO TO address
IORLW          k                   Inclusive OR Literal with W
MOVLW        k                   MOVe Literal to W
RETFIE         -                    RETurn From IntErrupt
RETLW          k                  RETurn with Literal in W
RETURN       -                    RETURN from subroutine
SLEEP           -                   go into SLEEP mode
SUBLW         k                   SUBtract Literal from W
XORLW         k                  eXclusive OR Literal with W

其中,有朋友说,上面指令系统中的

RETFIE         -                    RETurn From IntErrupt

应理解为RETurn From Interrupt with interrupt Enable,ANY电子觉得还是十分有道理的。当然,其缩写来源其实并不是十分重要,关键是你要理解这其中的意义,记住并能灵活运用这些指令。

posted @ 2009-06-25 14:52 cxie's personal note 阅读(177) | 评论 (0)编辑 收藏
  2009年6月15日

[资料收集与整理]Proteus元件库
太极天驹 发表于 2008-2-18 9:56:16

元件名称 中文名 说明
7407 驱动门  
1N914 二极管  
74Ls00 与非门  
74LS04 非门  
74LS08 与门  
74LS390 TTL 双十进制计数器  
7SEG 4针BCD-LED 输出从0-9 对应于4根线的BCD码
7SEG 3-8译码器电路BCD-7SEG转换电路  
ALTERNATOR 交流发电机  
AMMETER-MILLI mA安培计  
AND 与门  
BATTERY 电池/电池组  
BUS 总线  
CAP 电容  
CAPACITOR 电容器  
CLOCK 时钟信号源  
CRYSTAL 晶振  
D-FLIPFLOP D触发器  
FUSE 保险丝  
GROUND 地  
LAMP 灯  
LED-RED 红色发光二极管  
LM016L 2行16列液晶 可显示2行16列英文字符,有8位数据总线D0-D7,RS,R/W,EN三个控制端口(共14线),工作电压为5V。没背光,和常用的1602B功能和引脚一样(除了调背光的二个线脚)
LOGIC ANALYSER 逻辑分析器  
LOGICPROBE 逻辑探针  
LOGICPROBE[BIG] 逻辑探针 用来显示连接位置的逻辑状态
LOGICSTATE 逻辑状态 用鼠标点击,可改变该方框连接位置的逻辑状态
LOGICTOGGLE 逻辑触发  
MASTERSWITCH 按钮 手动闭合,立即自动打开
MOTOR 马达  
OR 或门  
POT-LIN 三引线可变电阻器  
POWER 电源  
RES 电阻  
RESISTOR 电阻器  
SWITCH 按钮 手动按一下一个状态
SWITCH-SPDT 二选通一按钮  
VOLTMETER 伏特计  
VOLTMETER-MILLI mV伏特计  
VTERM 串行口终端  
Electromechanical 电机  
Inductors 变压器  
Laplace Primitives 拉普拉斯变换  
Memory Ics  
Microprocessor Ics  
Miscellaneous 各种器件 AERIAL-天线;ATAHDD;ATMEGA64;BATTERY;CELL;CRYSTAL-晶振;FUSE;METER-仪表;
Modelling Primitives 各种仿真器件 是典型的基本元器模拟,不表示具体型号,只用于仿真,没有PCB
Optoelectronics 各种发光器件 发光二极管,LED,液晶等等
PLDs & FPGAs  
Resistors 各种电阻  
Simulator Primitives 常用的器件  
Speakers & Sounders  
Switches & Relays 开关,继电器,键盘  
Switching Devices 晶阊管  
Transistors 晶体管(三极管,场效应管)  
TTL 74 series  
TTL 74ALS series  
TTL 74AS series  
TTL 74F series  
TTL 74HC series  
TTL 74HCT series  
TTL 74LS series  
TTL 74S series  
Analog Ics 模拟电路集成芯片  
Capacitors 电容集合  
CMOS 4000 series  
Connectors 排座,排插  
Data Converters ADC,DAC  
Debugging Tools 调试工具  
ECL 10000 Series 各种常用集成电路

more.asp?name=zjcsharp&id=3892
 

amen 2006-05-04 19:22
自己做的两个例子
 

 
proteus常用快捷键


F8:全部显示   当前工作区全部显示
F6:放大 以鼠标为中心放大
F7:缩小 以鼠标为中心缩小
G:栅格开关 栅格网格
Ctrl+F1:栅格宽度0.1mm 显示栅格为0.1mm,在pcb的时候很有用
F2:栅格威0.5mm 显示栅格为0.5mm,在pcb的时候很有用
F3:栅格威1mm 显示栅格为1mm,在pcb的时候很有用
F4:栅格威2.5mm 显示栅格为2.5mm,在pcb的时候很有用
Ctrl+s:打开关闭磁吸 磁吸用于对准一些点的,如引脚等等
x:打开关闭定位坐标 显示一个大十字射线
m:显示单位切换 mm和th之间的单位切换,在右下角显示
o:重新设置原点 将鼠标指向的点设为原点
u:撤销键
Pgdn:改变图层
Pgup:改变图层
Ctrl+Pgdn:最底层
Ctrl+pgup:最顶层
Ctrl+画线:可以划曲线
R:刷新
+-:旋转
F5:重定位中心

posted @ 2009-06-15 11:12 cxie's personal note 阅读(374) | 评论 (0)编辑 收藏
  2009年6月12日


一、预处理器(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);

二、数据声明(Data declarations) 用变量a给出下面的定义 a) 一个整型数(An integer) b) 一个指向整型数的指针(A pointer to an integer) c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer) 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 关键字static的作用是什么?

在C语言中,关键字static有三个明显的作用:

 1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

四、Const 关键字const是什么含意? 1). 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。 2). 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。 3). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)

#include <stdio.h>

using namespace std;

int main(){  const char *pa;    char const *pb;    char ca = 'a';    char cb = 'b';    char * const pc = &ca;    const char * const pd = &cb;    pa = &ca;    pa = &cb;    pb = &ca;    pb = &cb;    *pc = 'd';    printf("ca = %c\n", ca);    return 0;}

 经过以上测试 const char *pa; char const *pb; 上面两种定义方法一样都是 pa(pb)指向的变量的值不可改变,及*pa,*pb, 而pa,和pb本身是可变的,如: pa = &ca; //ok ×pa = 'c' //error   char * const pc = &ca; pc本身是不可变的(只能在定义时初始化),但指向的变量值是可变的,如 pc = &ca;  //error *pc = 'd'; //ok   const char * const pd = &cb; pd本身是不可变的,且指向的变量也是不可变的(只能在定义时初始化) pd = &cb;  //error *pd = 'c'; /error   通过以上总结,无论怎样定义p都是一指针如果const在*左边,表示该指针指向的变量是不可变的如果const在*右边,表示该指针本身是不可变得

五、Volatile 关键字volatile有什么含意 并给出三个不同的例子。一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

1). 并行设备的硬件寄存器(如:状态寄存器) 2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 3). 多线程应用中被几个任务共享的变量 这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求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)嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 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) 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下: int *ptr; ptr = (int *)0x67a9; *ptr = 0xaa55; 一个较晦涩的方法是: *(int * const)(0x67a9) = 0xaa55; 建议采用第一种方法;

八、代码例子(Code examples) 1.下面的代码输出是什么,为什么?(考查有符号类型与无符号类型之间的转换) void foo(void) {     unsigned int a = 6; int b = -20; (a+b > 6) ? puts("> 6") : puts("<= 6"); } 这个问题测试你是否懂得C语言中的整数自动转换原则;这无符号整型问题的答案是输出是“>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。 因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。 2. 评价下面的代码片断:(考查是否懂得处理器字长) unsigned int zero = 0; unsigned int compzero = 0xFFFF; /*1's complement of zero */ 对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下: unsigned int compzero = ~0; 这一问题真正能揭露出应试者是否懂得处理器字长的重要性。好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。

九、Typedef Typedef作用是声明一个新的类型名代替已有的类型名;也可以用预处理器做类似的事。例如,思考一下下面的例子: #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 两个指针。      

#define 在预编译时处理,只作简单的字符串替换;    

Typedef 在编译时处理,不是简单的字符串替换;

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chlu520/archive/2008/05/19/2458284.aspx

posted @ 2009-06-12 11:14 cxie's personal note 阅读(336) | 评论 (0)编辑 收藏
  2009年6月10日

(电子信息类专业)

对于初学者来说,要学的知识点很多,到底从哪里下手,人们常常感到非常迷茫。

    大一学生先从C语言开始入门,在大一阶段由于对计算机还非常陌生,因此不可能写出一个具有完整图形界面的软件,重点以“与硬件无关的计算方法、数据结构”为基础学习C语言,至少练习编写一万行C代码,否则不会找到编程的感觉,也体会不到编程乐趣,很多人就是因为缺乏一定量的训练,所以对编程没有兴趣,以至于未到毕业时就全部忘记了,程序设计是一项实践性很强的实践活动,没有大量的实践作为基础是很难入门的,因此我认为编写一万行代码是判定是否入门的依据。请初学者记住:当你编写了一万行代码时,这是你能够从事专业的开始,否则你不要期望在这个领域混下去。与此同时,C语言也是学习和使用Verilog的重要基础,所以千万不可小视C语言。更重要的是,如果你的C语言不好的话,你将来就业选择的路子就会受到很大的限制,要么只能做硬件工程师、销售工程师或者转行,别无选择!

    有了一万行编程的经验后,大二接着开始学习数字电路和模拟电路了,这是你的机会!将来的开发工作有几种选择,但这两门都很重要,学好了你有可能成为顶尖的高手、专家和系统级水平的人才,即便学得不太好,你也有可能成为一个优秀的工程师。如果你精通了C/C++,即便你的硬件水平一般,你也可以成为一个优秀的开发工程师,即由硬件工程师负责逻辑电路和模拟电路的设计,由你来编程——你可以编写基于WinCE、Linux、Vxworks或者Windows等操作系统的程序。那么怎样才算基本上“精通”呢?至少编写五万行代码,当你已经编写了10万行代码时,可以说你已经完全精通了,这个时候你如果有很大的造化的话,那完全取决于你当初学习的基础是否牢固了。所以我在前面提到了,精通一门可以成为优秀的开发工程师,但绝对不可能成为系统级的开发工程师,因为你的知识结构不行。

    最好在学习数字电路时购买一个开发学习板(如:EasyFPGA030--99元),能够在学习数字电路时同步学习FPGA和Verilog,强化课程之间的关联。生产企业为开发板撰写了30万字的配套资料和适合各种水平的范例,录制Verilog语言视频讲座,这些都是免费的。学好数字电路和模拟电路以及FPGA应用技术,除了成为电子产品开发工程师之外(高附加值的嵌入式系统产品几乎离不开FPGA),还有一个就业方向就是号称“金饭碗”的集成电路设计。

     作为初学者,在学习《电子技术基础(数字部分)》时同步学习FPGA与Verilog技术的重点是快速入门和打下一定的基础,根据配套的教材和数字电路教材的内容将基本的数字电路用FPGA实现即可,这是本阶段的学习目标,不要将学习高深难度的应用技术作为重点。并利用课余和暑假期间的空余时间,将一些图书上现成的使用数字电路实现的例子用FPGA来完成设计即可,比方如何使用FPGA 实现一个计数器,并动手做出来。到大三阶段在做出选择,到底是选择成为一个专业的FPGA应用设计工程师、还是嵌入式系统与FPGA混合应用系统设计工程师或集成电路开发工程师,以自己的兴趣和志向为基础而定,所以在学习嵌入式系统技术的同时学习FPGA,两者之间并不矛盾。

    最好在大一开始自学单片机,因为这能帮你建立计算机控制系统的大局观。有了单片机基础之后,在大二阶段学习数字电路与模拟电路的同时,结合单片机学习接口扩展技术与模拟前向通道数据采集技术,并编写相应的程序实现一个一个的小系统设计,大三时根本不再需要学习所谓的接口技术与微机原理了。
    有了大一、二阶段强化训练,后续的很多课程度可以理论与实践并重地学习,比方目前大学开设的《自动控制理论》几乎都是空对空地教学与联系,如果结合自动控制理论的教学,让学生学习设计一个自动穿越迷宫的电脑鼠,并举办相应的大赛,则能够很好地将嵌入式系统应用技术、数字电路与模拟电路、计算方法与数据结构、机构设计......相关课程有机地结合起来,学生的兴趣将大大地得到提高。

    当学生有了学习的兴趣和动力之后,教学势必由老师个人在课堂上演“独角戏”的场面转变为研讨会,学生也一定会竭尽全力由被动学习向主动学习转变,这就是教育要达到的目标。

    进入大三阶段则需要有选择地重点学习嵌入式操作系统原理与编程、嵌入式系统与FPGA的混合系统设计或者全力以赴钻研FPGA应用技术等技术方向,大四阶段就可以真刀真?地完成一个漂亮的毕业设计,并能够写出一篇比硕士水平还要高的论文。 


posted @ 2009-06-10 16:33 cxie's personal note 阅读(195) | 评论 (0)编辑 收藏
  2009年6月4日

:本文主要介绍汽车电子产品供应商给车厂供货时,由于严酷EMC要求,往往电磁兼容验证不能通过,导致供货受到一定的影响;本文结合实际设计一个普通的产品 EMC进行分析,说明车厂的EMC要求以及常见问题与解决方法。

关键词BCI(大电流注入实验)        CE(电源端口的传导骚扰实验)

         RE(辐射发射实验)            RS(抗扰度实验)

随着汽车电控技术的不断发展,汽车电子设备数量大大增加,电路工作频率逐渐提高,功率逐渐增大,使得汽车工作环境中充斥着电磁波,导致电磁干扰问题日益突出,轻则影响电子设备的正常工作,重则损坏相应的电器元件。

因此,汽车应用电子产品都会涉及到共性问题——汽车电磁兼容技术。汽车电磁兼容技术关乎汽车特定电子系统及其周围电子系统运行的安全可靠性,关乎电子控制功能的运行的安全可靠性。诸如电子控制汽车制动系统电子控制传动系统、电子控制转向系统。乃至影响汽车整车的安全可靠性。因此,汽车电子设备的电磁兼容性能越来越受重视,目前迫切要求能广泛应用针对汽车子设备的电磁改进技术.

国内外各个车厂就针对这种环境制定出一系列的抗扰度测试标准,同时为了保证良好的电磁兼容环境,同时也对产品提出了一系列的电磁骚扰标准。

以下表格为国外汽车电子需要满足的标准,国内大体上也是根据国外标准制定,同时在我们国内的合资汽车厂商,以及我们国内的相关汽车厂商也是遵循以下标准,只是在具体要求上略有差异。

标准协会

标准号

标准名称

汽车电磁兼容国际标准

ISO 11451

道路车辆——窄带辐射电磁能量所产生的电气干扰——整车测试法

Road vehicles—Electrical disturbances by narrowband radiated electromagnetic energy—Vehicle test methods

ISO 11452

道路车辆——窄带辐射电磁能量所产生的电气干扰——零部件测试法

Road ISO vehicles—Electrical disturbances by narrowband radiated electromagnetic energy —Component test methods

ISO 7637

道路车辆——由传导和耦合产生的电气干扰

road vehicles—electrical disturbances by conduction and coupling

ISO TR 1O6O

道路车辆——静电放电产生的电气干扰

road vehicles—electrical disturbances from electrostatic discharge

CISPR 12

车辆、机动船和内燃发动机驱动装置的无线电骚扰特性的限值和测量方法

Vehiclesboatsand internal combustion engine driven devices radio disturbance characteristics limits and methods of measurement

CISPR 25

用于保护用在车辆、机动船和装置上车载接受机的无线电骚扰特性的限值和测量方法

Limits and methods of measurement of radio disturbance characteristics for the protection of receivers used on board vehiclesboats and on devices

以上标准可以分为两类,一类是设备对外的无线电骚扰,一类是外部对我们设备的干扰,要求我们的设备具有一定的抗干扰特性。这两方面大部分产品都不能顺利的测试通过,满足整车厂家的要求。那么如何提高我们汽车电子产品的自身抗扰度以及降低自身对外的电磁发射,满足各类整车制造厂家的要求?下面我们针对车载DVD产品作一些详细的分析。

车载DVD一般带有FM以及AM功能,同时DVD播放器必须带显示系统,所以一般配备一个7寸的LCD屏。设计技术比较高的厂商为了增加实用性,在DVD上面配备USB Host功能,以及GPS导航功能,车载DVD最终变成了车载娱乐导航系统。

由于车载娱乐系统功能复杂,大多采用高速数字电路,大家都知道由于数字电路上升沿比较陡,谐波分量比较丰富,最终导致设备对外界的辐射很强;通常不能满足CISPR25的要求。如何降低娱乐系统对外的干扰,我们还需要将对外干扰进行分类,从干扰的性质来讲干扰主要分二类:

一、             传导发射(沿着设备对外电缆进行发射)

对于传导发射我们一般有几种方式来解决:

A、源头抑制:查找发射的源头,精确定位到某个器件、信号,进行分析处理,主要针对时钟,高速时钟线进行处理;

B、在对外电缆接口处进行滤波处理,针对干扰的频率,性质有针对性的选用器件进行滤波,常用的器件有电感,电容等。

二、             空间发射(通过设备缝隙或本身对外进行发射)

对于空间发射我们一般的处理方法如下:

A、通过源头抑制对空间发射是一个很好的方法,主要是通过滤波电路,接口处理,PCB布局,布线,多层板设计解决;

B、加强设备的屏蔽,对设备的结构缝隙进行处理;

以上方法有利有弊;比如降低源头的后果会导致信号质量变差,我们在降低源头的时候必须要首先保证功能的正常以及稳定;增加滤波器件,对信号质量不会有大的影响(选择器件的时候要有针对性的选择并且结合实际的信号频率进行滤波选择),但是会导致设备成本增加;所以我们在操作的过程中要结合自己的情况灵活运用;

如何提高电子设备的抗扰度呢?我们先介绍车载DVD系统抗扰度实验常见的现象与解决方法:

1、 音频输出喇叭出现啸叫

对于音频输出喇叭啸叫,我们要分清楚啸叫的本质原因,常见的喇叭啸叫多数是因为干扰信号通过设备接口电缆耦合至内部电路(极少数是因为音频功放内部电路设计不合理所至),然后通过各种路径耦合至音频功放输入端,导致功放将无用的1KHz干扰载波信号进行放大输出,从而导致啸叫;解决方法一般有以下几种:

A、找出并切断耦合路径;

寻找耦合路径是一个复杂的分析过程,要具体的结合PCB布局、布线、原理图设计等各个因素综合进行分析,必要的时候可以借助示波器进行测试;一般可以用CS(传导敏感度试验)进行BCI模拟试验;

B、在设备信号口进行滤波,让干扰信号无法进入设备内部;

在信号口滤波,一般选用共模滤波方式进行抑制(有时候也会用电容进行滤波);选用共模电感时要有针对性的进行选择;如啸叫发生在60MHz,需要选择针对60MHZ有效滤波器件;

2、   屏幕乱码、抖动、系统死机、复位;

对于这几种情况,我们就要重点找出受干扰的具体电路,比如系统复位,此时我们就要关注复位电路、电源电路、控制电路等;如果屏幕乱码,我们就要关注视频处理电路、视频处理电路的控制信号、逻辑信号等;具体可以结合示波器进行观察,最终找出敏感源,一般按照以下两类情况进行分析。

一类:从设备信号口注入或者耦合至设备信号口的干扰;

对于这类干扰,最节省成本的办法是找出我们设备的敏感点,提高此点的抗干扰能力,但是这需要花费大量的时间以及精力,而且还必须要具备良好的电路、电磁场理论知识;我们现行的企业,一般到做EMC试验的时候,时间都是非常紧急,根本就没有足够的时间对设备进行详细的分析定位以及试验;所以在设备信号接口进行滤波不外是一个不错的选择;由于我们很明确干扰直接从电缆传导至设备内部,我们完全可以运用EMC器件将干扰在接口进行滤除,避免干扰传导至单板其他的电路;只要干扰在信号接口被滤除,我们的设备出现的问题也会随之消失;这种方法往往会导致成本有一定的上升;所以这种方法需要结合实际的情况进行考虑;

二类:从设备缝隙耦合至设备内部的干扰;

从缝隙耦合的干扰,直接可以将缝隙“堵住”进行试验;一般由缝隙引起的抗扰度问题着重处理缝隙即可,如果需要查找敏感源,就需要结合实际试验现象进行分析;

小结

对于汽车电子产品来讲,要通过严格的汽车电子电磁兼容标准要求,需要在结构,接口,单板滤波设计,PCB设计方面进行全方位考虑。

posted @ 2009-06-04 15:14 cxie's personal note 阅读(625) | 评论 (0)编辑 收藏
  2007年1月3日
Shell编程基础

为什么要使用Shell编程?
Linux操作系统是由UNIX操作系统发展起来的.UNIX操作系统中所体现出来的思想和哲学深沉的影响了现代其他的操作统.在UNIX系统中提供了许多不同的Shell程序.大多数的商业UNIX提供了Korn Shell,当然了我们也还有其他的Shell可以来用.虽然Shell看起来与Windows的命令行相类似,但是他显得更为的强大,可以以他的方式来运行更为复杂的程序.我们可以使用Shell进行更为快速和简单的编辑.另外在大多数的Linux基系统的安装提供了Shell,所以我们可能很方便的来检测我们的工作是否可以正常的进行工作.而且Shell可以提供许多的实用程序,我们可以用这样的内容来很好的进行我们的工作,而且这样的程序易于维护和移植.
一些哲学:
现在我们来认识一下UNIX和Linux哲学.UNIX是建立在代码高度重用的基础上的.我们可以建立一个简单的实用程序,那么其他的人就可以用字符串链接或是其他的形式来使用我们的程序.Linux的一大优点就是提供了许多优秀的工具.如:
$ ls -al | more
这个命令使用了ls和more命令,而且使用了管道来重定向输出.我们可以使用简单的脚本来创建立大的复杂的程序.
例如,如果我们要打印bash的man手册页我们可以用下面的命令:
$ man bash | col -b | lpr
因为Linux的自动文件处理,这些程序的使用者一般并不要知道这些程序是以哪种语言写成的.
管道和重定向:
在我们详细的说明Shell编程之前,我们先来说明一下Linux的程序(不仅是Shell程序)如何来重定向输入和输出.
重定向输出:
也许我们已经对输出重定向较为熟悉了.如:
$ ls -l > lsoutput.txt
这个命令会将ls命令的输出保存期在一个名为lsoutput.txt的文件中.
然而事实上要有比我们在这个例子中显示的还要多的重定向.现在我们要知道的就是文件修饰0是程序的标准的输入,1为标准输出,2为标准的错误输出.我们可以独立的重定向这些中的任何一个.事实上我们也可以重定向其他的文件修饰,但是一般的情况下为0,1,2.
在上面的这个例子中,我们使用>修饰符来重定向标准输出到一个文件.在默认的情况,如果这个文件已经存在了,他就会被重写.
如果要增加文件内容,我们可以使用>>运算符.如:
$ ps >> lsoutput.txt
这个就会在文件后面增加新的输出内容.
如果要重定向标准错误输出,我们可以使用>运算符和我们要使用的文件修饰符来进行重定向.因为标准的错误输出修饰符为2,我们就可以使用2>运算符.这在忽略错误信息而又不显示在屏幕上时就会显得尤为有用.
假如我们要在脚本中使用kill命令来杀掉一个进程,然而却是常用这样的情况,在这个命令运行之前这个进程已经不存在了.如果是这样的情况,kill命令就会产生一个标准的错误输出,而在默认的情况下,这个输出要显示在屏幕上.通过重定向输出和错误,我们就可以阻止在屏幕上显示任何内容.如下面的命令:
$ kill -HUP 1234 >killout.txt 2>killerr.txt
这个命令就会将输出和错误信息存放在一个单独的文件中.
如果我们要将这两个输出放在一个文件中,我们可以使用>&来组合这两种输出.如:
$ kill -1 1234 >killouterr.txt 2>&1
这个命令就可以将所有的输出放在同一个文件中.在这里我们要注意的就是命令的顺序.这个命令的顺序可以解释为重定向标准输出到文件killouterr.然后重定向标准错误输出到与标准输出同一的地方.如果我们弄错了顺序,我们就不会得到我们希望的输出.
在这里我们会看到kill命令的结果使用了返回代码,然而常常是我们并不需要保存标准输出或是标准错误输出.我们可以使用UNIX中的/dev/null来忽略所有的错误输出.如:
$ kill -1 1234 >/dev/null 2>&1
重定向输入:
与重定向输出相类似,我们也可以重定向输入.如:
$ more < killout.txt
管道:
我们可以使用管道符|来连接进程.在Linux系统中,由管道连接起来的进程可以自动运行,就如同在他们有一个数据流一样.在下面的这个例子中,我们要使用sort命令来排序ps的输出.而如果我们不使用管道,我们就要分几步来完成:
$ ps > psout.txt
$ sort psout.txt >pssort.out
一个更好的办法就是可以用管道来处理:
$ ps | sort > pssort.out
因为我们要在屏幕上看到他们,我们要使用第三个进程:
$ ps | sort | more
使用的管道数并没有一个量的限制.如果我们要看到正在运行的除了shell以外的不同名字的进程,我们可以用下面的命令:
$ ps -xo comm | sort | uniq | grep -v sh | more
在这个命令中,使用了ps的输出,将这个输出以字母的顺序进行排序,使用uniq来解压进程,使用grep -v sh来移除名为sh的进程,最后在屏幕上显示结果.
在这里我们就可以看到,这样的方式式要比单个执行的命令好得多.在这里我们要注意的一点点就是,在这个命令中我们不要两次使用同一个文件.如下面的命令:
$ cat mydate.txt | sort | uniq | >mydate.txt
这样我们就会得到一个空文件,因为在我们读取这个之前已经改写了这个文件.
Shell作为编程语言:
现在我们已经知道了一些基本的Shell操作,下面我们就进入脚本编程.有两种写Shell程序的方法:我们可以输入命令队列,让Shell来交互的执行他们,或者是将这些命令存放在一个文件中,然后作为程序进行调用.
交互程序:
在命令行输入脚本是可以快速方便的试出小的代码段,如果我们正在学习或是进行测试这是一个相当好的方式.假如我们有许多的C文件,而我们希望找出其中含有POSIX字符串的文件.我们可以如下面的样子进行整体的操作:
$ for file in *
> do
> if grep -l POSIX $file
> then
> more $file
> fi
> done
在这里我们就会看到Shell提示符由$变成了>.我们可以输入命令由Shell来决定如何时停止并且立即执行脚本程序.
在这个例子中,grep命令查找其中含有POSIX字符串的文件,然后more将这个文件中的内容打印在屏幕上.最后Shell返回提示符.
Shell也会允许我们使用通配符进行扩展.我们可以使用*来匹配字符串,我们还可以使用?来匹配单个的字符,而[set]可以允许检测在这里列出的任何一个单个字符.[^set]则正好相反,要除去在这里所列出的字符.我们还可以使用花括号{}进行扩展,这可以允许我们将任意的字符串放在一起.如下面的例子:
$ ls my_{finger,toe}s
这个命令会列出文件my_fingers,my_toes.
有经验的用户也许会用一种更有效率的方式来运行这些命令.也许我们会使用下面的命令:
$ more `grep -l POSIX *`
或者是下面的命令:
$ more $(grep -l POSIX *)
$ grep -l POSIX * | more
这些命令都会打印出含有POSIX的文件名.
然而事实上如果我们每一次要完成这样的任务就要输入一系列命令的做法是相当麻烦的一件事.我们需要就是将这些命令放在一个文件中,作为一个Shell脚本来引用,这样就可以在我们需要的时候来运行他了.
创建一个脚本:
首先我们可以使用任何一个我们喜欢的文本编辑来创建一个含有下面命令的文件,命名为first:
#!/bin/bash
#  first
#  This file looks through all the files in the current
#  directory for the string POSIX, and then prints the names of
#  those files to the standard output.
for file in *
do
   if grep -q POSIX $file
   then
      echo $file
   fi
done
exit 0
在这个文件中以#开始的行被看作是注释,在通常的情况下,我们会将#放在第一列.在这里我们要注意的是第一行的注释,#!  /bash/bash是一个特殊格式的注释.#!后面的字符告诉系统我们要执行这个文件的程序.在当前的情况下,/bin/bash是默认的Shell程序.
在这里指定的绝对路径最好的做法就是要少于32个字符,因为在一些老版本的UNIX系统有着这样的限制,我们这样做可以很好的做到向后兼容.
因为这个脚本被看作是标准的Shell输入,所以可以包含任何的Linux命令.
exit命令可以返回一个较为敏感的退出代码.如果这个程序是单独运行的,我们就没有必要来检测这个程序的返回代码,而如果我们要在另一个程序中进行调用,进行返回代码的检测以确定这个程序是否成功执行就显得尤为重要.虽然有时我们并不希望我们的程序被其他的程序调用,我们也要返回一个合理的代码.因为也许有一天我们的程序就会作为其他脚本的一部分而被重用.
0则表明这个程序成功执行.因为脚本并不会检测任何的失败,所以我们总是返回成功代码.
我们要注意的另外一点就是在这个文件中我们并没有使用任何的扩展名或是前缀.在Linux或是UNIX系统中并不依靠文件的扩展名来判断文件的类型.如果我们希望可以为这个文件加一个.sh或是其他的扩展名,但是Shell并不会在意这些.大多数预先安装的脚本并没有扩展名,而最好的用来检测文件类型的办法就是使用file命令.
使用脚本可执行:
现在我们就有了我们的脚本程序,我们可以用两种方式来运行.最简单的办法就是将脚本文件作为参数使用Shell进行调用:
$ /bin/bash first
这样就可以正常的工作了.如果我们可以将其与其他的Linux命令相分离而是直接输入命令文件名就可以运行这个程序就显得更好一些.如果我们要这样的做,我们首先要使用下面的命令来为他加上可执行属性:
$ chmod +x first
现在我们就可以用下面的命令来运行了:
$ ./first

 

Shell语法
变量:
在Shell中,我们在使用变量之前并不需要进行声明.相反我们可以在需要的时候进行简单的使用就可以了.在默认的情况下,所有的变量都是作为字符串进行存储的,虽然有时我们会用数字为其赋值.Shell以及其他的一些实用的转换程序会将数字字符串转换成相应的值为进行操作.在Linux系统中是要区分大小的,所以在Shell看来变量foo与Foo是不同的.
在Shell中我们要访问变量的值,我们要在变量前加上一个$.当我们要为变量赋值时,我们可以只使用变量的名字,Shell会在需要的时候进行动态创建.检测变量内容一个简单的办法就是在终端进行输出,这时要在变量前加上一个$.
在命令行中我们可以用下面的方法来设置和检测变量的值:
$ salutation=Hello
$ echo $salutation
Hello
$ salutation=”Yes Dear”
$ echo $salutation
Yes Dear
$ salutation=7+5
$ echo $salutation
7+5
我们还可使用read命令将用户的输入赋值给变量.这样就会将变量的名字作为参数并会等待用户的输入.read命令会在用户输入回车的时候结束.当从终端读入变量时我们并不需要使用引号.如下面的例子:
$ read salutation
Wie geht’s?
$ echo $salutation
Wie geht’s?
引号:
在继续我们的学习之前我们要清楚引号的作用.
通常脚本中的参数是由空白字符来分隔的,如空格,Tab或是回车.如果我们要我们的参数包含一个或是更多个参数,我们就要使用引号了.
例如变量$foo的行为要看我们使用的引号的类型了.如果我们是用双引号,在这一行执行时就会用他的值进行替换,而如果我们使用单引号就不会发生这样的替换.我们还可以使用转义字符\来除去$的特殊意义.
在通常的情况下,我们双引号来包含字符串,这样就可以防止变量被空白符所分隔,而且会用变量的值进行替换.
在下面的这个例子中我们就会看到引号对于变量输出的影响:
#!/bin/bash
myvar=”Hi there”
echo $myvar
echo “$myvar”
echo ‘$myvar’
echo \$myvar
echo Enter some text
read myvar
echo ‘$myvar’ now equals $myvar
exit 0
这个程序的输出为:
Hi there
Hi there
$myvar
$myvar
Enter some text
Hello World
$myvar now equals Hello World
工作原理
我们创建了变理myvar,并赋值为Hi there.变量的内容由命令echo显示出来,从而可以看出$字符扩展对变量内容的影响.从这输出我们可以看出双引号并不会影响变量的替换,而单引号和反斜线却会有这样的影响.我们同时使用一个read命令来从用户得到输入.
环境变量
当启动一个Shell脚本时,一些变量会由环境中的值进行初始化.在脚本中这些变量通常为大写字母,从而与用户定义的变量进行区分,而用户定义的变理常用小写字母来表示.创建的变量依赖于我们个人的配置.其中的许多列在手册页中,但是基本的一些列在下面的表中:
$HOME    当前用户的主目录
$PATH    用来进行命令查找的由冒号分隔的目录列表
$PS1    命令提示,通常为$,但是在bash中我们可以使用更为复杂的值.例如,字符串[\u@\h \W]$是流行的默认用法来告诉我们当前的用户,机器名称以及当前的工作目录,同时给出$提示.
$PS2    第二提示符,当提示额外的输入时使用,通常为>
$IFS    输入区域分隔符.当Shell读入输入时会使用一个字符列表来分隔输入的单词,通常是空格,tab和新行字符.
$0    Shell脚本的名称.
$#    传递的参数个数.
$$    脚本的进程ID,通常用在一个脚本内部用来建立唯一的一个临时文件,如/tmp/tmp-file_$$.
如果我们的脚本调用一些参数,那么会建立一些其他的变量.即使没有传递参数,环境变量$#仍然存在,但是值却为0.
参数变量列在下面这个表中:
$1,$2,...    传递给脚本的参数.
$*    以单变量的形式显示所有的参数列表,由环境变量IFS中的第一个字符分隔.
$@    $*的一个灵巧变形.他并不使用IFS环境变量,所以如果IFS为空那么所有的所有的参数会一起运行.
我们可以通过下面的测试容易的看出$@和$*的区别:
$ IFS=’’
$ set foo bar bam
$ echo “$@”
foo bar bam
$ echo “$*”
foobarbam
$ unset IFS
$ echo “$*”
foo bar bam
正如我们所看到的,在双引号内,$@将参数进行分隔显示,而与IFS的值无关.通常来说,如果我们要访问参数,$@是一个很灵敏的选择.
我们不仅可以用echo命令打印出变量的内容,而且我们可以使用read命令来读取他们的内容.
参数和环境变量
下面的脚本展示了简单变量的处理.在我们输入了下面的脚本内容并保存为try_var,我们一定要记得用命令chmod +x try_var为其加上可执行权限.
#!/bin/sh
salutation=”Hello”
echo $salutation
echo “The program $0 is now running”
echo “The second parameter was $2”
echo “The first parameter was $1”
echo “The parameter list was $*”
echo “The user’s home directory is $HOME”
echo “Please enter a new greeting”
read salutation
echo $salutation
echo “The script is now complete”
exit 0
如果我们运行这个脚本我们会得到下面的输出:
~$ ./try_var.sh foo bar baz
Hello
The program ./try_var.sh is now running
The second parameter was bar
The first parameter list was foo bar baz
The user's home directory is /home/mylxiaoyi
Please enter a new greeting
hello
The script is now complete
工作原理:
这个脚本创建了一个名为salutation的变量并显示他的内空,然后显示了各种参数变量,而环境变量$HOME已经存在并且已经有适当的值.
函数:
所有程序语言的基本原则是测试条件并在这些测试的基础上进行各种不同的操作.在我们讨论这个话题之前,我们先来看一下在Shell脚本中我们会用到的函数构造以及我们要使用的控制结构.
一个Shell脚本可以测试由命令行调用的任何命令的返回代码,包括我们自己书写的脚本.这就是我们在每一个Shell脚本最后包含exit代码的重要原因.
test或[命令:
事实上,大多数的脚本大量的使用了Shell真假检测的test或是[命令.在大多数的系统上,[和test命令是同义的,但是当使用了一个[命令时而同时为了可读在末尾使用了一个]命令.使用[命令看起来有一点奇怪,但是这个命令在代码中会使得命令的语法看起来要简单,整洁,并且与其他的程序语言很相像.
ls -l /usr/bin/[
-rwxr-xr-x 1 root root 25040 2005-11-16 21:17 /usr/bin/[
我们会使用一个简单的测试例子来介绍test命令:检测一个文件是否存在.用于这个目的的命令是test -f <filename>,所以我们可以用下面的脚本:
if test -f fred.c
then
...
fi
我们也可以像下面的样子来写:
if [ -f fred.c ]
then
...
fi
test命令的返回代码(条件是否满足)决定于条件代码是否运行.
在这里我们要注意是我们必须在[和条件之间用空格进行分隔.我们可以用下面的方法来记住这一点:[是test命令的另一种写法,而我们要在test命令后输入空格.
如果我们喜欢将then与if放在同一行,我们必须要加一个冒号来与then进行分隔:
if [ -f fred.c ]; then
...
fi
我们可以用的test命令的条件类型有以下的三种:字符串比较,算术比较和文件条件.下面的三张表展示了这些条件类型:
字符串比较:
string1 = string2    如果相等则为真
string1 != string2    如果不等则为真
-n string        如果不空则为真
-z string        如果为空则为真
算术比较:
expression1 -eq expression2    如果相等则为真
expression1 -ne expression2    如果不等则为真
expression1 -gt expression2    如果大于则为真
expression1 -ge    expression2    大于等于则为真
expression1 -lt expression2    如果小于则为真
expression1 -le expression2    小于等于则为真
!expression            如查为假则为真
文件:
-d file        如果为目录则为真
-e file        如果存在则为真(在这里要注意的是,由于历史原因,-e选项并不可移植,所以常用的是-f选项
-f file        如果为常规文件则为真
-g file        如果设置了组ID则为真
-r file        如果文件可读则为真
-s file        如果文件大小不为零则为真
-u file        如果设置了用户ID则为真
-w file        如果文件可写则为真
-x file        如果文件可执行则为真
现在我们似乎走得有一点的太前了,但是接下来的是一个例子.在这里我们要测试文件/usr/bash,这样我们就可以清楚的看到这些条件的用法:
#!/bin/sh
if [ -f /bin/bash ]
then
   echo “file /bin/bash exists”
fi
if [ -d /bin/bash ]
then
   echo “/bin/bash is a directory”
else
   echo “/bin/bash is NOT a directory”
fi
在测试为真以前,所有的文件测试条件要法度文件存在.这个列表包含了test命令常用的选项,所以我们可查看手册页得到一个完全的信息.如果我们正在使用bash,而其中内嵌了test,我们可以用命令help test得到详细的信息.


 控制结构
Shell有一结构控制集合,我们再一次说明他们与其他的程序语言非常相像.
If
if语句是相当简单的:他测试一个命令的结果,并且有选择的执行一组语句:
if condition
then
   statements
else
   statements
fi
使用if命令:
下面的这个例子中显示if的普通用法,他会询问一个问题并依据这个问题来进行回答:
#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
if [ $timeofday = “yes” ]; then
   echo “Good morning”
else
   echo “Good afternoon”
fi
exit 0
这会产生下面的输出:
$ ./if.sh
Is is morning? please answer yes or no
yes
Good morning
这个脚本使用[命令来测试变量timeofday的值.这个结果会被if命令来使用,从而会执行不同的程序代码.
elif
但是不是幸的是,对于这个简单的脚本却有着许多的问题.他会将yes以外的任何答案理解为no.为了防止这样的问题出现我们可以使用elif结构,这样就会允许我们在if执行else部分时添加第二个条件.
我们可以修改上面的脚本以使用当用户输入yes或no以外的内容时报告错误信息.我们的做法是用elif来代替else从而添加另一个条件.
#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
if [ $timeofday = “yes” ]
then
   echo “Good morning”
elif [  $timeofday = “no” ]; then
   echo “Good afternoon”
else
   echo “Sorry, $timeofday not recognized. Enter yes or no”
   exit 1
fi
exit 0
工作原理:
这与上一个例子较为相似,但是在这一次如果if的测试条件不为真则使用elif命令测试变量的值.如果这些没有一个成功,则会打印出一条错误信息并且脚本退出并返回代码1,而返回值则可以用作另一个调用此脚本的程序查看脚本是否成功.
变量的问题:
现在修正了一个最明显的问题,但是却潜伏着另一个更细小的问题.我们可以试一下这个新脚本,但是我们仅是输入回车(或是其他的内容)而不回答这个问题,我们就会得到下面的错误信息:
[: =: unary operator expected
出了什么样的错误呢?问题就在于第一个if语句,当这个变量timeofday进行了测试,他包含一个空串.所以这样if语句看起来就是下面的样子:
if [ = “yes” ]
而这并不是一个可用的条件.为了避免这样的问题,我们可以用双引号将变量括起来:
if [ “$timeofday” = “yes” ]
当传递一个空变量给这个测试时:
if [ “” = “yes” ]
我们的新脚本如下:
#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
if [ “$timeofday” = “yes” ]
then
   echo “Good morning”
elif [ “$timeofday” = “no” ]; then
   echo “Good afternoon”
else
   echo “Sorry, $timeofday not recognized. Enter yes or no”
   exit 1
fi
exit 0
这样对于只是回车的答案来说就是一个安全的脚本了.
for
我们用for结构在任何字符串的集合的值范围内进行循环.他们可以简单的列在程序中,或是更为一般的,可以是文件名的Shell扩展结果.
语法如下:
for variable in values
do
   statements
done
在下面的这个例子中,值为普通的字符,所以我们的脚本如下:
#!/bin/sh
for foo in bar fud 43
do
   echo $foo
done
exit 0
我们会得到下面的结果:
./for.sh
bar
fud
43
工作原理:
这个例子创建了一个变量foo,并且在for循环中每次赋于一个不同的值.因为Shell在默认的情况下认为所有的变量都包含字符串,所以在例子中就会像使用字符串fud一样的来使用43.
使用通配符
正如我们在前面的那样,通常情况下我们会在for循环中使用文件名的Shell扩展.我们这样说的意思是在字符串值中使用通配符,并且使得Shell在运行时填充所有的值.
我们已经在我们最初的例子中看到这个例子.这个脚本使用了Shell扩展,*扩展成为当前目录下的所有文件名.这些中的每一个在for循环中轮流用作变量$i的值.
下面我们看一下另一个通配符的例子.想像一下如果我们要打印所有当前的目录下文件名中含有f字符的文件,而且我们知道我们所有的脚本以.sh结尾.我们可以用下面的脚本来完成我们的工作
#!/bin/sh
for file in $(ls f*.sh); do
  lpr $file
done
exit 0
工作原理:
这里我们展示了$(command)的语法.基本来说,for命令所使用的参数列表是由包含在$()中的命令的输出来提供的.这个脚本将f*.sh扩展成所有与这个模式匹配的内容.
while
因为在默认的情况下认为Shell值为字符串,因而for循环对于在一系列的字符间进行循环是一个不错的选择,但是对于处理确定次数的循环命令来说就显得有一些笨拙了.
下面这个例了向我们展示了当我们用for循环来在20个数之间进行循环是一件多么麻烦的事情:
#!/bin/sh
for foo in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
do
   echo “here we go again”
done
exit 0
即使是我们使用通配符进行扩展,我们有时也会遇到不能确定我们所需要的循环次数.在这样的情况下,我们可以使用while循环,其语法格式如下:
while condition do
  statements
done
如下面的一个进行密码检测的例子:
#!/bin/sh
echo “Enter password”
read trythis
while [ “$trythis” != “secret” ]; do
  echo “Sorry, try again”
  read trythis
done
exit 0
其输出结果如下:
Enter password
password
Sorry, try again
secret
$
事实上这并不是安全的检测密码的方法,但是却可以很好的展示了while语句的用法.在do和done之间的语句将会被连续执行直到我们的测试条件不再为 真为止.在我们的输出例子中我们检测到trythis的值与secret并不相等,循环将会继续直到$trythis与secret相等为止.然后我们就 会执行done后的语句.
将while语句与算术运算进行组合我们就可以执行确定次数的循环操作.这要比我们刚才所看到的for的例子要简单得多.
#!/bin/sh
foo=1
while [ “$foo” -le 20 ]
do
   echo “Here we go again”
   foo=$(($foo+1))
done
exit 0
工作原理:
这个脚本使用[命令来检测foo的值并与20进行对比,如果小于或是等于则要执行循环体.在这个while循环中,(($foo+1))语法用来执行花括号内的算术运算,所以foo的值会在每一个循环后增加1.
因为foo不可以是一个空串,所以我们在在测试他的值时不需要用双引号来保护.我们这样做是因为这是一个好习惯.
until
until语句语法格式如下:
until condition
do
   statements
done
这与while循环十分相似,所不同的只是测试条件的相反.换句说,until是循环继续直到条件为真,而不是while的条件为真时才进行循环.
until语句适用于我们希望进行循环直到某件事发生时为止的情况.作为一个例子,我们可以考虑下面的情况:当我们在命令行中输入另一个用户名进行登陆时发出响铃.
#!/bin/sh
until who | grep “$1” > /dev/null
do
   sleep 60
done
# now ring the bell and announce the expected user.
echo -e \\a
echo “**** $1 has just logged in ****”
exit 0
下面我们要说是case结构.case结构比起我们已经讨论这些内容来说要显得有一些复杂.他的语法如下:
case variable in
  pattern [ | pattern] ...) statements;;
  pattern [ | pattern] ...) statements;;
  ...
esac
这种结构看起来有一些吓人,但是case结构却可以使得我们用一种诡异的方法来匹配变量的内容并且会依据所匹配的模式执行不同的语句.
在这里我们要注意第一个模式行是用双分号来分隔的.我们可以在第一个不同的模式之间放置多条不同的语句,所以我们需要使用双分号来标记一个模式的结束和另一个模式的开始.
case结构匹配多个模式并执行多个不同的相关的语句的能力使得这种结构可以很好的来处理用户的输入.展示case工作原理的最好的方法就是一个实际的例子.如下面的一个例子:
现在我们可以写一个新的处理用户输入的脚本版本,现在我们使用case结构,这样可以使得他更具选择并且可以处理不可辨识的输入.
#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
case “$timeofday” in
    yes) echo “Good Morning”;;
    no ) echo “Good Afternoon”;;
    y ) echo “Good Morning”;;
    n ) echo “Good Afternoon”;;
    * ) echo “Sorry, answer not recognized”;;
esac
exit 0
工作原理:
在这个脚本中,我们在每一种情况的输入中使用了多个字符串,这样case就会为每一个可能的语句检测一些不同的字符串.这样就会使得我们的脚本更为短小, 而且实际的来说也更为易读.我们同时展示了*通配符的用法,即使这也许会匹配不希望的情况.例如,如果用户输入了never,这样就会匹配n*并且会显示 Good afternoon,而这并不是我们所希望的行为.在这里我们要注意如果*通配符使用了引号就不会起作用了.
最后,如果我们要使得这个脚本可以重用,但使用最后一个匹配模式时我们需要一个不同的返回值.在这里我们同时也加入set结构.
#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
case “$timeofday” in
    yes | y | Yes | YES )
           echo “Good Morning”
           echo “Up bright and early this morning”
           ;;
    [nN]*)
           echo “Good Afternoon”
           ;;
    *)
           echo “Sorry, answer not recognized”
           echo “Please answer yes or no”
           exit 1
           ;;
esac
exit 0
工作原理:
为了显示模式匹配的一个不同的方法,我们改变量了no情况的使用方式.我们同时也显示了在case语句时中多条语句是如何执行的.在这里我们要注意的是我 们将最明显示匹配放在前面而将一般的匹配放在后面.这是比较重要的一点,因为case会首先执行他找到的第一个匹配模式,而并不是最佳的.如果我们将*) 放在前面,那么进行匹配的就是这种情况,而不论我们输入的是什么内容.
我们还要注意的一点就是esac前的;;是可选的.这里并不像C语言那样.
为了使得case的匹配更为强大的,我们可以用下面的形式:
[yY] | [Yy][Ee][Ss] )
这在允许多个答案时会限制允许输入的字符并且比*通配符有着更多的控制.
Lists:
有时我们会连接一系列的命令.例如我们在执行一个语句前需要多个限制条件,如下面的例子:
if [ -f this_file ]; then
    if [ -f that_file ]; then
        if [ -f the_other_file ]; then
            echo “All files present, and correct”
        fi
    fi
fi
或者是我们希望一系列的条件为真,如:
if [ -f this_file ]; then
   foo=”True”
elif [ -f that_file ]; then
   foo=”True”
elif [ -f the_other_file ]; then
   foo=”True”
else
   foo=”False”
fi
if [ “$foo” = “True” ]; then
   echo “One of the files exists”
fi
尽管我们可以用多个if语句来实现,但是我们会发现这样的结果是相当的烦人的.在Shell中有一对特殊的结构可以用来处理类似于这样的一列的命令:AND列和OR列.通常他们会在一起使用,但是在这里我们会分开来看他们的语法格式.
AND列:
AND列结构可以使得执行一系列的命令,只有在前面的命令都成功的情况下我们才可以执行下面的命令.他的语法如下:
statement1 && statement2 && statement3 && ...
这些命令会由左边开始执行每一个命令,如果返回值为真会执行接下来的右边的命令.这个过程会连续进行执行一个命令的返回值为假,在这之后这个列表的中命令 也不再执行.&&会检测前一个命令的执行结果.每一个语句可以单独执行,这样就会允许我们在一个列表中执行不同的命令,就如下面的例子所 显示那样.如果这个列表中的所有命令都执行成功,那么这就是一个成功的命令,否则就是失败的.
在下面的这个脚本中,我们创建了file_one(先检查是否存在,如果不存在就先创建这个文件)然后移除file_two.然后AND命令列会检测每一个文件是否存在并会输入命令之间一个文本.
#!/bin/sh
touch file_one
rm -f file_two
if [ -f file_one ] && echo “hello” && [ -f file_two ] && echo “ there”
then
    echo “in if”
else
    echo “in else”
fi
exit 0
如果我们运行这个脚本我们会得到下面的结果:
hello
in else
touch和rm命令来保证当前目录下的文件在一个已知的状态.&&表接下来执行[ -f file_one ]语句,这个语句是会成功的,因为我们刚刚保证这个文件的存在.因为前面一个语句成功了,所以执行echo命令.这也会成功(echo通常会返回真).然 后执行第三个语句,[ -f file_two ].这个语句不会成功,因为这个文件已经不存在.因为最后一个命令失败了,所以最后的echo语句并不会执行.&&表的结果为假,因为在 这个列表中有一个命令失败了,所以if语句会执行else条件.
OR表:
OR表的结构我可以允许我们执行一系列命令,直到有一个命令成功,然后就不再执行更多的命令.他的语法结构如下:
statement1 || statement2 || statement3 || ...
由左开始依次执行每一个语句.如果他的返回值为假,那么就会执行接下来的语句.这个过程会继续下去直到有一个语句返回真值,这样以后就不会再执行接下来的列表中的命令.
||列表与&&列表是非常相像的,所不同的只是执行下一个语句的条件.
如下面的一个例子:
#!/bin/sh
rm -f file_one
if [ -f file_one ] || echo “hello” || echo “ there”
then
    echo “in if”
else
    echo “in else”
fi
exit 0
我们会得到下面的输出结果:
hello
in if
工作原理:
脚本中的前两行只是简单的为脚本的其余部分设置文件.第一个命令 [ -f file_one ]会返回假,因为文件已经不存在.然后执行是echo命令.令人惊奇的是这会返回一个真值,所以在||命令列表就不会再有命令执行.因为在这个列表中有一 个命令返回真值,所以if语句成功.
这两个结构的结果是上一个要执行的语句的结果.
如果要进行多个条件的测试,我们可以偈在C语言中一样的来使用这些列表类的结构.我们可以将这两种结构结合在一起;
[ -f file_one ] && command for true || command for false
如果测试成功将会执行第一个语句否则则会执行第二个语句.我们可以试验这些并不太常用的列表结构,而在通常情况下我们需要使用花括号来强制执行的顺序.
语句块:
如果我们要在一个地方使用多个语句但却只允许一个的时候,例如在AND或是OR列表中,我们可以用花括号将他们括起来形成一个语句块.
函数:
我们可以在Shell中定义函数,如果我们希望形成任何尺寸的脚本文件,我们可以用函数来结构化我们的代码.
要定义一个函数,我们只要写上函数的名字并跟随一个空的括号并将语句括在一个花括号内:
function_name () {
  statements
}
如下面的一个简单的函数:
#!/bin/sh
foo() {
    echo “Function foo is executing”
}
echo “script starting”
foo
echo “script ended”
exit 0
执行这个脚本我们会得到下面的输出:
script starting
Function foo is executing
script ending
工作原理:
这个脚本是由顶部开始执行的,所以在这里并没有什么不同的.但是当他发现foo(){结构,他就会知道在这里定义了一个函数调用.他会将foo指向一个函 数的情况进行存储并在}后继续执行.当执行foo()行时,Shell知道这里要执行一个前面定义的函数.当这个函数执行结束后,脚本就会在foo行后继 续执行.
我们必须在调用一个函数之前进行定义,这种风格有一些像Pascal的函数定义,所不同的只是在Shell并需要在前面进行声明.这并不是一个问题,因为 所有的脚本都是由顶部开始执行的,所以我们只需要简单的将我们要定义的全部函数放在这些函数中第一次调用之前,这样我们就解决了函数要先定义用调用的问 题.
当调用一个函数时,脚本中的参数,$*,$@,$#,$1,$2等等将会被函数中的参数所替换.这也是我们读取传递给函数参数的方法.当函数结束时,他们就会恢复成以前的值.
我们可以使用return命令来使得函数返回数字值.常用的做法是将函数返回的字符串存放在一个变量中,这样就可以在函数结束以后使用.
在这里我们要注意的是我们可以用local关键字在Shell函数中定义局部变量.这样这个变量就会只在这个函数中起作用.否则,一个函数可以访问在另一 个函数中定义的全局变量.如果一个局部变量与全局变量同名,那么在一个函数中这个变量就会覆盖掉全局变量.例如下面的这个列子:
#!/bin/sh
sample_text=”global variable”
foo() {
    local sample_text=”local variable”
    echo “Function foo is executing”
    echo $sample_text
}
echo “script starting”
echo $sample_text
foo
echo “script ended”
echo $sample_text
exit 0
在没有用return命令返回值的情况下,函数会返回最后命令执行时的返回状态.
在我们下面的例子中,我们将会展示如何向函数传递一个参数以及一个函数如何返回一个真或是假的结果。我们可以使用一个名字作为参数来调用这个脚本。
1在脚本头后我们定义了一个yes_or_no函数:
#!/bin/sh
yes_or_no() {
  echo “Is your name $* ?”
  while true
  do
     echo -n “Enter yes or no: “
     read x
     case “$x” in
       y | yes ) return 0;;
       n | no ) return 1;;
       *)         echo “Answer yes or no”
     esac
  done
}
2接下的是这个程序的主要部分:
echo “Original parameters are $*”
if yes_or_no “$1”
then
   echo “Hi $1, nice name”
else
   echo “Never mind”
fi
exit 0
当我们运行这个脚本时我们会得到下面的输出:
$ ./my_name Rick Neil
Original parameters are Rick Neil
Is your name Rick ?
Enter yes or no: yes
Hi Rick, nice name
$
工作原理:
当这个脚本执行时,定义了yes_or_no函数但是却并没有运行这个函数。在if语句中,这个脚本执行了了我们所定义的这个函数,并且在将$1用传递给 原脚本的第一个参数Rick进行替换,在这以后将句子的其他部分作为参数传递给函数。这个函数使用这些参数并将他们存放在位置参数$1,$2等当中,并向 调用者提供一个返回值。依据这个返回值,if结构语句可以执行相应的操作。
正如我们所看到的,Shell有一个丰富的控制和条件结构语句。我们需要学习一些Shell中内建的命令。这样我们就可以解决一些不会被编译器所看到的真正的程序问题。


posted @ 2007-01-03 16:44 cxie's personal note 阅读(306) | 评论 (0)编辑 收藏
     摘要: 毫无疑问,UNIX/Linux最重要的软件之一就是shell,目前最流行的shell被称为Bash(Bourne Again Shell),几乎所有的Linux和绝大部分的UNIX都可以使用Bash。作为系统与用户之间的交互接口,shell几乎是你在UNIX工作平台上最亲密的朋友,因此,学好shell,是学习Linux/UNIX的的开始,并且它会始终伴随你的工作学习。shell是如此地重要,但令人...  阅读全文
posted @ 2007-01-03 16:31 cxie's personal note 阅读(1421) | 评论 (0)编辑 收藏
  2006年11月15日

2006-5                        first meeting:ended my May Day ---Xiamen----上岛咖啡
2006-10-8                  ended my National day   ---Xiamen  ---milestone of our sentiment
2006-10                     在世贸商城看《好奇害死猫》
2006-11-10                珍珠湾海边,第一次拍照,有了她的玉照。
2006-11-10~11晚      在卧龙晓城后山看星星,不过那两天都没星星
2006-11-13/15            Sally said missing me  a little.
2006-12-9                   caven dermine to marry with sally
2006-12-8                   first kiss
2006-12-16                 sally determine to marry with me(**)


2007 May day  婺源之旅
2007-11-8                      领证
2007-11                      caven下海去海南
2007-12                      Sally也去海南
2008-11                      回老家结婚
2008-12                      下海"溺水"回厦门
2009-2                        Caven&Sally新窝开始
2009-4

Caven&Sally prepare to BB
posted @ 2006-11-15 11:57 cxie's personal note 阅读(192) | 评论 (0)编辑 收藏
  2006年10月27日
二百五的来历(共6则)
1。从前有一个秀才,为了考取功名废寝忘食发奋苦读,可是终其一生都不曾中举,连儿子都没有生。到了晚年,老秀才终于心灰意冷淡泊名利了,于是喜得贵子,晚年膝下添得双丁。秀才回想一生成败,不由得感慨万千,于是给两个儿子起名:一个叫做成事,一个叫做败事。从此秀才在家闭门课子,日子过得和乐融融。一天,秀才吩咐妻子道:“我要去集市上逛逛,你在家督促二子写字,大的写三百,小的写二百。” 秀才赶集回来之后询问二子在家用功如何,老婆回答道:“写是写了,不过成事不足,败事有余,两个都是二百五!”

2。苏秦是战国时的一个说客,他身佩六国相印,一时很是威风,但也结下了很多仇人。后来,他终于在齐国被人杀了,齐王很恼怒,要为苏秦报仇。可一时拿不到凶手,于是,他想了一条计策,让人把苏泰的头从尸体上割下来,悬挂在城门上,旁边贴着一道榜文说:“苏秦是个内奸,杀了他黄金千两,望来领赏。”榜文一贴出,就有四个人声称是自己杀了苏秦。齐王说:“这可不许冒充呀!”四个人又都咬定说自己干的。齐王说:“一千两黄金,你们四个人各分得多少?”四个齐声回答:“一人二百五。”齐王拍案大怒道:“来人,把这四个‘二百五’推出去斩了!”“二百五”一词就这样流传下来。

3。牌九(旧时一种赌具)中有“二板”(四个点)和“么五”(六个点)两张牌,这两张牌配在一起就是十个点,在推牌九这一赌博活动中,被称为“毙十”。它在牌九里是最小的点,谁都比它大,它什么牌也“吃”不了,所以人们就用“二板五”(二板和么五的简称)这个词来戏称什么事也做不好也管不了的人。时间久了,就把“二板五”叫成了“二百五”。在香港,习惯上又称为“二五仔”。

4。唐朝的长安“市长”京兆尹权势很大,出巡时有庞大的仪仗队伍。在最前开路的小吏原为一员,官名叫喝道伍佰,他手里拿着一根长竿赶开路人。后来,喝道伍佰增为二员,但长安群众并没有以两个伍佰称他们,反而说他们是共称伍佰,于是每人就被称为二百五,又因为他们每人手中持一长竿,所以又称他们为二秆子。今天,二百五与二秆子都是莽撞、无礼、粗鲁之人的代名词,

5。古代人用银子按两划分,一般五百两是个整数单位,用纸包好,有点像我们把硬币包一包,当时包五百两是为“一封”,而二百五十两就是“半封”银子,因为跟“半疯”谐音,所以以后人们也城疯疯癫癫的人做“二百五”。

6。从前有一个傻瓜,有一天他去卖传家至宝,宝物上写“卖尽二百五十八两”,结果他卖的时候有人和他讨价还价,硬是只给250,他想250就250,于是卖得金子250两,很多人笑话他,八两金子很多的,笨蛋。从那以后人们就把做事糊涂的人称为二百五。


载取白云归去,问谁留楚佩,弄影中洲。折芦花赠远,零落一身秋。向寻常野桥流水,待招来、不是旧沙鸥。空怀感,有斜阳处,却怕登楼


很搞笑,今天看到“敲竹杠”的来历,顺便贴上

  清末,沿海一带贩卖烟土成风,清朝政府在各地设立关卡,严厉查禁。
  有个狡猾的云南客商,经常以贩卖土布、山药为名,夹运烟土,往返于云贵与江浙之间。因为他想的办法巧妙,所以从未被关卡查获过。原来,他在毛竹刚生长时,就偷偷剖开嫩竹,藏进烟土,等毛竹长大后,便将毛竹做成竹杠、船篙。因此,竹杠外面,天衣无缝,一点不露痕迹。
  这一天,云南商船来到浙江绍兴码头。关卡检查官照例上船检查,他们从船舱底下翻到船舱上面,从土布翻到药材,查不出一点烟土。正准备放行时,一个在关卡办事的绍兴师爷突然来到船上,似乎要再搜查一遍的样子。这时,他正吸着长管旱烟,一边吞云吐雾,一边走进船舱,提起长筒烟管,朝搁在船舱里的竹杠“笃、笃、笃”地敲了几下,准备把烟灰磕掉。
  谁知这“笃、笃、笃”一敲非同小可,吓得云南客商忙从船舱里钻了出来。他神色慌张,以为绍兴师爷看出了他窝藏禁物的秘密,敲敲竹杠,是打个暗号给他。
  云南客商早有准备,忙从怀里掏出一包银子,假称“云南旱烟”悄悄地塞给这位绍兴师爷,并强装笑脸说:“这是包上等‘云南旱烟’,烟味醇厚,与别处旱烟不同。请师爷笑纳。”
  绍兴师爷朝云南客商看了一眼,用手一掂,分量沉重,知道里面是银子。心想,他既然重金相赠,船中一定藏有禁品,但一时又查不出来,如今乐得做个人情,便闷声不响地将“云南旱烟”塞进腰包,径自上岸而去。
  后来,云南客船夹运的烟土,被别的关卡查获了,才知道烟土是暗藏在船上的竹杠中的。从此,“敲竹杠”一词便在民间流传开来。


载取白云归去,问谁留楚佩,弄影中洲。折芦花赠远,零落一身秋。向寻常野桥流水,待招来、不是旧沙鸥。空怀感,有斜阳处,却怕登楼。
posted @ 2006-10-27 10:06 cxie's personal note 阅读(263) | 评论 (0)编辑 收藏
  2006年9月21日
1.sudo permission setting
   # Defaults specification
       Defaults:cxie timestamp_timeout=-1   #set network timeout
  # Runas alias specification
  # User privilege specification
      root    ALL=(ALL) ALL
      cxie    ALL=(ALL) ALL                    #set root permission
2.firewall setting
     "Desktop"--->System Setting --->Security Level, enter "Security Level Configuration"
3.linux boot rescue
   a. plug in linux boot CD-ROM, then enter command line,input"linux rescue text"
   b. enter this route: cd /mnt/image/systemimage
                               cd  /boot/grub/
       then cat "grub.conf" file, get boot -sector info. from file.if  boot-sector is "hd0,1"
      you can do following setting:
      input command "grub" then set ->root(hd0,1)
                                                     -->setup(hd0)
                                                     -->quit-->exit
posted @ 2006-09-21 10:12 cxie's personal note 阅读(216) | 评论 (0)编辑 收藏
仅列出标题  下一页