EDN首页   博客首页 用户登陆  |  注册
aaa
发表于 2009/12/21 11:36:07

1

关于投票

单片机教程:算术运算类指令

不带进位位的加法指令

ADD A,#DATA ;例:ADD A#10H

ADD A,direct ;例:ADD A10H

ADD A,Rn ;例:ADD AR7

ADD A,@Ri ;例:ADD A@R0

用途:将A中的值与其后面的值相加,最终结果否是回到A中。

例:MOV A#30H

ADD A#10H

则执行完本条指令后,A中的值为40H

下面的题目自行练习

MOV 34H#10H

MOV R0#13H

MOV A34H

ADD AR0

MOV R1#34H

ADD A@R1

带进位位的加法指令

ADDC ARn

ADDC A,direct

ADDC A,@Ri

ADDC A,#data

用途:将A中的值和其后面的值相加,并且加上进位位C中的值。

说明:由于51单片机是一种8位机,所以只能做8位的数学运算,但8位运算的范围只有0-255,这在实际工作中是不够的,因此就要进行扩展,一般是将28位的数学运算合起来,成为一个16位的运算,这样,可以表达的数的范围就可以达到0-65535。如何合并呢?其实很简单,让我们看一个10进制数的例子:

66+78

这两个数相加,我们根本不在意这的过程,但事实上我们是这样做的:先做6+8(低位),然后再做6+7,这是高位。做了两次加法,只是我们做的时候并没有刻意分成两次加法来做罢了,或者说我们并没有意识到我们做了两次加法。之所以要分成两次来做,是因为这两个数超过了一位数所能表达的范置(0-9)。

在做低位时产生了进位,我们做的时候是在适当的位置点一下,然后在做高位加法是将这一点加进去。那么计算机中做16位加法时同样如此,先做低8位的,如果两数相加产生了进位,也要“点一下”做个标记,这个标记就是进位位C,在PSW中。在进行高位加法是将这个C加进去。例:1067H+10A0H,先做67H+A0H=107H,而107H显然超过了0FFH,因此最终保存在A中的是7,而1则到了PSW中的CY位了,换言之,CY就相当于是100H。然后再做10H+10H+CY,结果是21H,所以最终的结果是2107H

带借位的减法指令

SUBB ARn

SUBB A,direct

SUBB A,@Ri

SUBB A,#data

设(每个H,(R2=55HCY=1,执行指令SUBB AR2之后,A中的值为73H

说明:没有不带借位的减法指令,如果需要做不带位的减法指令(在做第一次相减时),只要将CY清零即可。

乘法指令

MUL AB

此指令的功能是将AB中的两个8位无符号数相乘,两数相乘结果一般比较大,因此最终结果用116位数来表达,其中高8位放在B中,低8位放在A中。在乘积大于FFFFFH65535)时,0V1(溢出),否则OV0,而CY总是0

例:(A=4EH,(B=5DH,执行指令

MUL AB后,乘积是1C56H,所以在B中放的是1CH,而A中放的则是56H

除法指令

DIV AB

此指令的功能是将A中的8位无符号数除了B中的8位无符号数(A/B)。除法一般会出现小数,但计算机中可没法直接表达小数,它用的是我们小学生还没接触到小数时用的商和余数的概念,如13/5,其商是2,余数是3。除了以后,商放在A中,余数放在B中。CYOV都是0。如果在做除法前B中的值是00H,也就是除数为0,那么0V=1

1指令

INC A

INC Rn

INC direct

INC @Ri

INC DPTR

用途很简单,就是将后面目标中的值加1。例:(A=12H,(R0=33H,(21H=32H,(34H=22HDPTR=1234H。执行下面的指令:

INC A A=13H

INC R2 R0=34H

INC 21H 21H=33H

INC @R0 34H=23H

INC DPTR DPTR=1235H

后结果如上所示。

说明:从结果上看INC AADD A#1差不多,但INC A是单字节,单周期指令,而ADD #1则是双字节,双周期指令,而且INC A不会影响PSW位,如(A=0FFHINC A后(A=00H,而CY依然保持不变。如果是ADD A #1,则(A=00H,而CY一定是1。因此加1指令并不适合做加法,事实上它主要是用来做计数、地址增加等用途。另外,加法类指令都是以A为核心的��其中一个数必须放在A中,而运算结果也必须放在A中,而加1类指令的对象则广泛得多,可以是寄存器、内存地址、间址寻址的地址等等。

1指令

1指令

DEC A

DEC RN

DEC direct

DEC @Ri

与加1指令类似,就不多说了。

综合练习:

MOV A#12H

MOV R0#24H

MOV 21H#56H

ADD A#12H

MOV DPTR#4316H

ADD ADPH

ADD AR0

CLR C

SUBB ADPL

SUBB A#25H

INC A

SETB C

ADDC A21H

INC R0

SUBB AR0

MOV 24H#16H

CLR C

ADD A@R0

先写出每步运行结果,然后将以上题目建入,并在软件仿真中运行,观察寄存器及有关单元的内容的变化,是否与自已的预想结果相同。

系统分类: 单片机  |  用户分类: 嵌入式  |  标签: 无标签  |  来源: 整理  | 

点击查看原文

发表评论 阅读全文(265) | 回复(0)

发表于 2009/11/6 11:28:22

0

关于投票

验证 STC12C2052AD 系列单片机的看门狗程序及其溢出时间计算公式

本程序用于验证 STC12C2052AD 系列单片机的看门狗及其溢出时间计算公式
;看门狗及其溢出时间 = (12 * Pre_scale *32768)/Oscillator frequency

WDTCR           EQU 0E1H ;看门狗地址
WDT_TIME_LED    EQU P1.5 ;用 P1.5 控制看门狗溢出时间指示灯,
                         ;看门狗溢出时间可由该指示灯亮的时间长度或熄灭的时间长度表示
WDT_FLAG_LED    EQU P1.7 ;用 P1.7 控制看门狗溢出复位指示灯, 如点亮表示为看门狗溢出复位

Last_WDT_Time_LED_Status  EQU 00H ;位变量, 存储看门狗溢出时间指示灯的上一次状态位

;WDT 复位时间(Oscillator frequency = 18.432MHz):
;Pre_scale_Word  EQU 00111100B   ;清0、启动看门狗,预分频数=32   0.68S
Pre_scale_Word  EQU 00111101B   ;清0、启动看门狗,预分频数=64   1.36S
;Pre_scale_Word  EQU 00111110B   ;清0、启动看门狗,预分频数=128  2.72S
;Pre_scale_Word  EQU 00111111B   ;清0、启动看门狗,预分频数=256  5.44S

    ORG   0000H
    AJMP  MAIN

    ORG   0100H
MAIN:
    MOV   A, WDTCR              ;检测是否为看门狗复位
    ANL   A, #10000000B
    JNZ   WDT_Reset             ;WDTCR.7 = 1, 看门狗复位, 跳转到看门狗复位程序

;上电复位, 冷启动, RAM 单元内容为随机值
    SETB  Last_WDT_Time_LED_Status       ;上电复位,
                                         ;初始化看门狗溢出时间指示灯的状态位 = 1
    CLR   WDT_TIME_LED                   ;上电复位, 点亮看门狗溢出时间指示灯
    MOV   WDTCR, #Pre_scale_Word ;启动看门狗

WAIT1:
    SJMP  WAIT1                 ;循环执行本语句(停机),等待看门狗溢出复位

;看门狗复位, 热启动, RAM 单元内容不变, 为复位前的值
WDT_Reset:                      ;看门狗复位, 热启动
    CLR   WDT_FLAG_LED          ;点亮看门狗溢出复位指示灯

    JB   Last_WDT_Time_LED_Status, Power_Off_WDT_TIME_LED
    ;根据看门狗溢出时间指示灯的上一次状态位设置 WDT_TIME_LED 灯,
    ;若上次亮本次就熄灭, 若上次熄灭本次就亮
    CLR   WDT_TIME_LED          ;上次熄灭本次点亮看门狗溢出时间指示灯
    CPL   Last_WDT_Time_LED_Status ;将看门狗溢出时间指示灯的上一次状态位取反
WAIT2:   
    SJMP  WAIT2                 ;循环执行本语句(停机),等待看门狗溢出复位

Power_Off_WDT_TIME_LED:
    SETB  WDT_TIME_LED          ;上次亮本次就熄灭看门狗溢出时间指示灯
    CPL   Last_WDT_Time_LED_Status ;将看门狗溢出时间指示灯的上一次状态位取反
WAIT3:  
    SJMP  WAIT3                 ;循环执行本语句(停机),等待看门狗溢出复位

    END

系统分类: 单片机  |  用户分类: 嵌入式  |  标签: 无标签  |  来源: 整理  | 

点击查看原文

发表评论 阅读全文(263) | 回复(1)

发表于 2008/12/5 12:00:09

9

关于投票

五大嵌入式市场值得关注

五大嵌入式市场值得关注

“无处不在”的嵌入式系统“无所不能”

嵌入式系统作为一个热门领域,涵盖了微电子技术、电子信息技术、计算机软件和硬件等多项技术领域的应用。在全球半导体市场快速复苏,消费电子、通信以及嵌入式系统各个应用领域快速发展,嵌入式微处理器技术不断进步的情况下,全球嵌入式系统产业规模继续保持稳步增长,2007年达到4081.6亿美元,增速达到17.50%。2007年,国内的嵌入式系统产业规模也达到了2218.1亿元,增长32.3%。
嵌入式计算技术的进步,正在以前所未有的程度影响和改变着我们的生活。迄今为止,只要我们目之能及,嵌入式系统已经“无处不在”、“无所不能”。其中“无所不能”是指嵌入式系统将人工智能技术和超级计算技术有机结合,而“无所不在”则是指嵌入式系统存在着广阔的应用天地,如人们平常用的手机、摄像机、医疗仪器、汽车、以至工业控制、航天、航空等设备都嵌有嵌入式系统。事实上,这些都只是嵌入式应用的冰山一角。由于迅速发展的Internet和非常廉价的微处理器的出现,不远的将来嵌入式设备将会嵌入在桌子、椅子、餐具、窗帘等各种日常用品中,全面走入人类的生活,而且还会在人类的工业、军事、自然探索等各方面广泛应用。而我国信息化与全面小康社会建设更是对嵌入式系统市场提出巨大需求,信息家电产品年需求量已达到几亿台,每一类数字化家电产品都有几千万台市场需求量,工业控制用嵌入式系统有百十万台(套)需求量,商用嵌入式系统需求量突破几百万台。


最值得关注的5个主要嵌入式产品市场

嵌入式系统的应用覆盖航天、航空、交通、网络、电子、通讯、金融、智能电器、智能建筑、仪器仪表、工业自动控制、数控机床、掌上型电脑、智能IC卡、第二代身份证验证、公共交通收费系统、医药系统以及军事等等各种领域,但目前最值得关注的嵌入式产品市场主要有如下几类:


第一、家庭信息网络:家用电器已经开始向数字化和网络化发展,电视机、微波炉、数字电话等都将嵌入微处理机并通过家庭网关与Internet连接,构成家庭信息网络。但不论是高度集成的智能数字终端,还是各类数字融合产品,都离不开嵌入式系统的支持,可以说,嵌入式系统是家庭信息网络、IT融合的重要技术基础。具有丰富功能,高度集成的智能数字终端将是未来的发展方向。


第二、移动计算设备:移动计算设备包括手机、PDA、掌上电脑等各种移动设备。中国拥有最大规模的手机用户,而掌上电脑或PDA由于易于使用、携带方便、价格便宜,未来几年将在我国得到快速发展。PDA与手机也已呈现融合趋势。使用掌上电脑或PDA上网,人们可以随时随地获取信息。


第三、网络设备:随着下一代Internet的研发成功和投入使用,必然要有更多更强的嵌入式网络设备和产品面世,这意味着巨大的嵌入式网络设备和产品市场需求。嵌入式系统也在向无线网络WLAN发展,它有望部署到住宅及商用建筑自动化、工业设备监测以及其他无线传感和控制应用中。


第四、自动化与测控仪器仪表:测控仪器仪表种类繁多,而新型的测控仪器仪表无一不是嵌入式系统。此外,在工控和仿真领域,嵌入式设备也早已得到广泛应用。中国的工业生产需要完成智能化、数字化改造,而智能控制设备、智能仪表、自动控制等,这些都为嵌入式系统提供了巨大的市场。


第五、交通电子设备:汽车智能驾驶设备、汽车模拟驾驶器、汽车喷油泵调试台、轮船智能驾驶设备等都面临更新换代,而这类新型设备都离不开嵌入式系统。中国汽车业的发展必然为汽车电子的嵌入式系统应用带来良好商机。因此,嵌入式系统在交通指挥系统、高速公路收费监控、汽车自导航、GPS车载终端、电子警察和汽车检测中的将会拥有良好的市场前景。


发展嵌入式系统,推进从“中国制造”走向“中国创造”

当前中国的工业能力大而不强,面对越来越严峻的资源和环境压力,科学发展已经不仅仅是一个口号。要想转变在国际产业链竞争中的不利态势,走创新型发展的路子几乎是惟一可选之道。嵌入式系统是中国企业从“中国制造”向“中国创造”转变的最佳契机。一则因为嵌入式系统领域的产品和技术高度分散,留给各个行业的中小规模高技术公司的创新余地很大;二则因为嵌入式系统的各个应用领域是在不断向前发展的,构成了推动嵌入式工业发展的强大动力。国内的嵌入式系统厂商应当积极利用所掌握的优势资源,确立其在中国嵌入式应用开发领域的领导地位。

系统分类: 模拟技术  |  用户分类: 嵌入式  |  标签: 无标签  |  来源: 整理  | 

点击查看原文

发表评论 阅读全文(385) | 回复(0)

发表于 2007/4/23 12:54:59

0

关于投票

C语言嵌入式系统编程修炼之屏幕操作[转]

模拟MessageBox函数

  MessageBox函数,这个Windows编程中的超级猛料,不知道是多少入门者第一次用到的函数。还记得我们第一次在Windows中利用MessageBox输出 "Hello,World!"对话框时新奇的感觉吗?无法统计,这个世界上究竟有多少程序员学习Windows编程是从MessageBox("Hello,World!",…)开始的。在我本科的学校,广泛流传着一个词汇,叫做"’Hello,World’级程序员",意指入门级程序员,但似乎"’Hello,World’级"这个说法更搞笑而形象。

  
图2 经典的Hello,World!

  图2给出了两种永恒经典的Hello,World对话框,一种只具有"确定",一种则包含"确定"、"取消"。是的,MessageBox的确有,而且也应该有两类!这完全是由特定的应用需求决定的。

  嵌入式系统中没有给我们提供MessageBox,但是鉴于其功能强大,我们需要模拟之,一个模拟的MessageBox函数为:

/******************************************
/* 函数名称: MessageBox
/* 功能说明: 弹出式对话框,显示提醒用户的信息
/* 参数说明: lpStr --- 提醒用户的字符串输出信息
/* TYPE --- 输出格式(ID_OK = 0, ID_OKCANCEL = 1)
/* 返回值: 返回对话框接收的键值,只有两种 KEY_OK, KEY_CANCEL
/******************************************
typedef enum TYPE { ID_OK,ID_OKCANCEL }MSG_TYPE;
extern BYTE MessageBox(LPBYTE lpStr, BYTE TYPE)
{
 BYTE keyValue = -1;

 ClearScreen(); /* 清除屏幕 */
 DisplayString(xPos,yPos,lpStr,TRUE); /* 显示字符串 */
 /* 根据对话框类型决定是否显示确定、取消 */
 switch (TYPE)
 {
  case ID_OK:
   DisplayString(13,yPos+High+1, " 确定 ", 0);
   break;
  case ID_OKCANCEL:
   DisplayString(8, yPos+High+1, " 确定 ", 0);
   DisplayString(17,yPos+High+1, " 取消 ", 0);
   break;
  default:
   break;
 }
 DrawRect(0, 0, 239, yPos+High+16+4); /* 绘制外框 */
 /* MessageBox是模式对话框,阻塞运行,等待按键 */
 while( (keyValue != KEY_OK) || (keyValue != KEY_CANCEL) )
 {
  keyValue = getSysKey();
 }
 /* 返回按键类型 */
 if(keyValue== KEY_OK)
 {
  return ID_OK;
 }
 else
 {
  return ID_CANCEL;
 }
}

  上述函数与我们平素在VC++等中使用的MessageBox是何等的神似啊?实现这个函数,你会看到它在嵌入式系统中的妙用是无穷的。

  总结

  本篇是本系列文章中技巧性最深的一篇,它提供了嵌入式系统屏幕显示方面一些很巧妙的处理方法,灵活使用它们,我们将不再被LCD上凌乱不堪的显示内容所困扰。

  屏幕乃嵌入式系统生存之重要辅助,面目可憎之显示将另用户逃之夭夭。屏幕编程若处理不好,将是软件中最不系统、最混乱的部分,笔者曾深受其害。

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

点击查看原文

发表评论 阅读全文(1266) | 回复(0)

发表于 2007/4/23 12:51:21

0

关于投票

C语言嵌入式系统编程修炼之屏幕操作[转]

动画显示

  动画是无所谓有,无所谓无的,静止的画面走的路多了,也就成了动画。随着时间的变更,在屏幕上显示不同的静止画面,即是动画之本质。所以,在一个嵌入式系统的LCD上欲显示动画,必须借助定时器。没有硬件或软件定时器的世界是无法想像的:

  (1) 没有定时器,一个操作系统将无法进行时间片的轮转,于是无法进行多任务的调度,于是便不再成其为一个多任务操作系统;

  (2) 没有定时器,一个多媒体播放软件将无法运作,因为它不知道何时应该切换到下一帧画面;

  (3) 没有定时器,一个网络协议将无法运转,因为其无法获知何时包传输超时并重传之,无法在特定的时间完成特定的任务。

  因此,没有定时器将意味着没有操作系统、没有网络、没有多媒体,这将是怎样的黑暗?所以,合理并灵活地使用各种定时器,是对一个软件人的最基本需求!

  在80186为主芯片的嵌入式系统中,我们需要借助硬件定时器的中断来作为软件定时器,在中断发生后变更画面的显示内容。在时间显示"xx:xx"中让冒号交替有无,每次秒中断发生后,需调用ShowDot:

void ShowDot()
{
 static BOOL bShowDot = TRUE; /* 再一次领略static关键字的威力 */
 if(bShowDot)
 {
  showChar(’:’,xPos,yPos);
 }
 else
 {
  showChar(’ ’,xPos,yPos);
 }
 bShowDot = ! bShowDot;
}

  菜单操作

  无数人为之绞尽脑汁的问题终于出现了,在这一节里,我们将看到,在C语言中哪怕用到一丁点的面向对象思想,软件结构将会有何等的改观!

  笔者曾经是个笨蛋,被菜单搞晕了,给出这样的一个系统:

点击看大图
图1 菜单范例

  要求以键盘上的"← →"键切换菜单焦点,当用户在焦点处于某菜单时,若敲击键盘上的OK、CANCEL键则调用该焦点菜单对应之处理函数。我曾经傻傻地这样做着:

/* 按下OK键 */
void onOkKey()
{
 /* 判断在什么焦点菜单上按下Ok键,调用相应处理函数 */
 Switch(currentFocus)
 {
  case MENU1:
   menu1OnOk();
   break;
  case MENU2:
   menu2OnOk();
   break;
  …
 }
}
/* 按下Cancel键 */
void onCancelKey()
{
 /* 判断在什么焦点菜单上按下Cancel键,调用相应处理函数 */
 Switch(currentFocus)
 {
  case MENU1:
   menu1OnCancel();
   break;
  case MENU2:
   menu2OnCancel();
   break;
  …
 }
}

  终于有一天,我这样做了:

/* 将菜单的属性和操作"封装"在一起 */
typedef struct tagSysMenu
{
 char *text; /* 菜单的文本 */
 BYTE xPos; /* 菜单在LCD上的x坐标 */
 BYTE yPos; /* 菜单在LCD上的y坐标 */
 void (*onOkFun)(); /* 在该菜单上按下ok键的处理函数指针 */
 void (*onCancelFun)(); /* 在该菜单上按下cancel键的处理函数指针 */
}SysMenu, *LPSysMenu;

  当我定义菜单时,只需要这样:

static SysMenu menu[MENU_NUM] =
{
 {
  "menu1", 0, 48, menu1OnOk, menu1OnCancel
 }
 ,
 {
  " menu2", 7, 48, menu2OnOk, menu2OnCancel
 }
 ,
 {
  " menu3", 7, 48, menu3OnOk, menu3OnCancel
 }
 ,
 {
  " menu4", 7, 48, menu4OnOk, menu4OnCancel
 }
 …
};

  OK键和CANCEL键的处理变成:

/* 按下OK键 */
void onOkKey()
{
 menu[currentFocusMenu].onOkFun();
}
/* 按下Cancel键 */
void onCancelKey()
{
 menu[currentFocusMenu].onCancelFun();
}

  程序被大大简化了,也开始具有很好的可扩展性!我们仅仅利用了面向对象中的封装思想,就让程序结构清晰,其结果是几乎可以在无需修改程序的情况下在系统中添加更多的菜单,而系统的按键处理函数保持不变。

  面向对象,真神了!

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

点击查看原文

发表评论 阅读全文(1062) | 回复(0)

发表于 2007/4/23 12:44:44

0

关于投票

C语言嵌入式系统编程修炼之屏幕操作[转]

汉字处理

  现在要解决的问题是,嵌入式系统中经常要使用的并非是完整的汉字库,往往只是需要提供数量有限的汉字供必要的显示功能。例如,一个微波炉的LCD上没有必要提供显示"电子邮件"的功能;一个提供汉字显示功能的空调的LCD上不需要显示一条"短消息",诸如此类。但是一部手机、小灵通则通常需要包括较完整的汉字库。

  如果包括的汉字库较完整,那么,由内码计算出汉字字模在库中的偏移是十分简单的:汉字库是按照区位的顺序排列的,前一个字节为该汉字的区号,后一个字节为该字的位号。每一个区记录94个汉字,位号则为该字在该区中的位置。因此,汉字在汉字库中的具体位置计算公式为:94*(区号-1)+位号-1。减1是因为数组是以0为开始而区号位号是以1为开始的。只需乘上一个汉字字模占用的字节数即可,即:(94*(区号-1)+位号-1)*一个汉字字模占用字节数,以16*16点阵字库为例,计算公式则为:(94*(区号-1)+(位号-1))*32。汉字库中从该位置起的32字节信息记录了该字的字模信息。

  对于包含较完整汉字库的系统而言,我们可以以上述规则计算字模的位置。但是如果仅仅是提供少量汉字呢?譬如几十至几百个?最好的做法是:

  定义宏:

# define EX_FONT_CHAR(value)
# define EX_FONT_UNICODE_VAL(value) (value),
# define EX_FONT_ANSI_VAL(value) (value),

  定义结构体:

typedef struct _wide_unicode_font16x16
{
 WORD value; /* 内码 */
 BYTE data[32]; /* 字模点阵 */
}Unicode;
#define CHINESE_CHAR_NUM … /* 汉字数量 */

  字模的存储用数组:

Unicode chinese[CHINESE_CHAR_NUM] =
{
{
EX_FONT_CHAR("业")
EX_FONT_UNICODE_VAL(0x4e1a)
{0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x44, 0x44, 0x46, 0x24, 0x4c, 0x24, 0x48, 0x14, 0x50, 0x1c, 0x50, 0x14, 0x60, 0x04, 0x40, 0x04, 0x40, 0x04, 0x44, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00}
},
{
EX_FONT_CHAR("中")
EX_FONT_UNICODE_VAL(0x4e2d)
{0x01, 0x00, 0x01, 0x00, 0x21, 0x08, 0x3f, 0xfc, 0x21, 0x08, 0x21, 0x08, 0x21, 0x08, 0x21, 0x08, 0x21, 0x08,
0x3f, 0xf8, 0x21, 0x08, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}
},
{
EX_FONT_CHAR("云")
EX_FONT_UNICODE_VAL(0x4e91)
{0x00, 0x00, 0x00, 0x30, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xff, 0xfe, 0x03, 0x00, 0x07, 0x00,

0x06, 0x40, 0x0c, 0x20, 0x18, 0x10, 0x31, 0xf8, 0x7f, 0x0c, 0x20, 0x08, 0x00, 0x00}
},
{
EX_FONT_CHAR("件")
EX_FONT_UNICODE_VAL(0x4ef6)
{0x10, 0x40, 0x1a, 0x40, 0x13, 0x40, 0x32, 0x40, 0x23, 0xfc, 0x64, 0x40, 0xa4, 0x40, 0x28, 0x40, 0x2f, 0xfe,

0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40}
}
}

  要显示特定汉字的时候,只需要从数组中查找内码与要求汉字内码相同的即可获得字模。如果前面的汉字在数组中以内码大小顺序排列,那么可以以二分查找法更高效的查找到汉字的字模。

  这是一种很有效的组织小汉字库的方法,它可以保证程序有很好的结构。

  系统时间显示

  从NVRAM中可以读取系统的时间,系统一般借助NVRAM产生的秒中断每秒读取一次当前时间并在LCD上显示。关于时间的显示,有一个效率问题。因为时间有其特殊性,那就是60秒才有一次分钟的变化,60分钟才有一次小时变化,如果我们每次都将读取的时间在屏幕上完全重新刷新一次,则浪费了大量的系统时间。

  一个较好的办法是我们在时间显示函数中以静态变量分别存储小时、分钟、秒,只有在其内容发生变化的时候才更新其显示。

extern void DisplayTime(…)
{
 static BYTE byHour,byMinute,bySecond;
 BYTE byNewHour, byNewMinute, byNewSecond;
 byNewHour = GetSysHour();
 byNewMinute = GetSysMinute();
 byNewSecond = GetSysSecond();
 
 if(byNewHour!= byHour)
 {
  … /* 显示小时 */
  byHour = byNewHour;
 }
 if(byNewMinute!= byMinute)
 {
  … /* 显示分钟 */
  byMinute = byNewMinute;
 }
 if(byNewSecond!= bySecond)
 {
  … /* 显示秒钟 */
  bySecond = byNewSecond;
 }
}

  这个例子也可以顺便作为C语言中static关键字强大威力的证明。当然,在C++语言里,static具有了更加强大的威力,它使得某些数据和函数脱离"对象"而成为"类"的一部分,正是它的这一特点,成就了软件的无数优秀设计。

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

点击查看原文

发表评论 阅读全文(853) | 回复(0)

发表于 2007/1/10 8:38:57

2

关于投票

嵌入式常用IC芯片索引

《嵌入式常用IC芯片索引》2006-12-30 20:44×     【目录】
×   1.电源变换IC芯片
×   2.数字式传感器,电位器及精密运放芯片
×   3.电机控制及驱动芯片
×   4.数字通信IC芯片及接口
×   5.AD转换芯片
×   6.DA转换芯片
×     【说明】
×    1.“...”表示未完成待补充,因为采用增量模型,所以没有结束的一天。:-)
×    2.全部一个一个敲的,注意版权,引用时注明出处,呵呵 ×
××××××××××××××××××××××××××××××××××××××××
1.电源变换IC芯片
——————————————————————————————
指标:
1.输出电压范围(正/负)
2.输入电压范围
3.输入输出电阻及电流(直流交流)
4.纹波抑制比
5.温漂
6.
7.
...
————————————————————————————————————
7800     三端,固定正电压输出稳压器(块)芯片
7900     三端,固定负电压输出稳压器(块)芯片
AD580    三端,精密电压基准芯片
ADR290/291/292/293  高精度,新型XFET 3端基准电源芯片
D14,D24  DC-DC隔离电源模块
HV-2405E  50mA,5~24V,AC/DC电源IC芯片
HQA-2405E AC/DC电源变换器模块
IMP706  低功耗,uP电源监控IC芯片
LM117/217/317 3端,可调正电压输出稳压芯片
LM137/237/337 3端,可调负电压输出稳压(块)芯片
LM138/238/338 3端,大电流,可调正电压输出稳压(块)芯片
LM150/250/350 3端,大电流,可调正电压输出稳压(块)芯片
LM2930 汽车用3端稳压器芯片
LT108X/SP116XX 3端,低电压,输出可调稳压器芯片
M5236L/37L 灵活方便,低电压差,3端稳压驱动芯片
MAX610  无变压器式,AC/DC电源变换器IC芯片
MAX619  输入2V,输出5V,充电泵DC/DC变换器IC芯片
MAX629  DC/DC转换芯片
MAX638  过低电压检测报警,降压开关型,DC/DC电源变换器IC芯片
MAX639  过低电压检测报警,降压开关型,DC/DC电源变换器IC芯片
MAX682-685  低电压差,微功耗稳压器芯片
MAX706  电压监控芯片
MAX813L  看门狗,电压监控芯片
MAX889   2MHZ稳压型电荷泵,负电压输出,DC/DC变换器芯片
MAX1606  输入5V,输出28V,LCD偏置电源DC/DC芯片
MAX1642/1643  输入电压仅为1V的DC/DC变换器芯片
MAX1692    1.8V,降压型,微型开关,DC/DC芯片
MAX1725/1726  更低功耗,低压差,线性稳压器芯片
MAX1742/1842  内含1A开关,1MHz,降压型DC/DC芯片
MAX1744/1745  36V输入,10W输出,降压型转换器芯片
MAX1730/1759  稳压型,电荷泵,DC/DC芯片
MAX1775    双路,降压型,2A以上,DC/DC芯片
MAX1832/1833/1834/1835   电池反接保护,升压型DC/DC转换器芯片
MAX1864/1865  降压型,DC/DC,5路输出线缆MODEM电源芯片
MAX5130+PIC   精确可编程,8000基准电压值,DC/DC发生器芯片
MAX6125   微封装,微功耗,微漂移,DC/DC芯片
MAX6129   功耗更低,串联型,3端,电压基准芯片
MAX6333   监视电压可低至1.6V的新型单片复位IC芯片
MAX6821-6825   手动复位,“看门狗”定时器,低功耗,UP监控电路芯片
MAX828/829     充电泵,反压型,DC/DC芯片
MAX8880/8881   带有电源好2(POWDWR-OK)输出的DC/DC芯片
MAX8883    双路,低压差,线性稳压器芯片
MC1403    8脚精密电压基准芯片
MIC2141   微功耗,升压型,V0可控,DC/DC变换器芯片
PS0500-5  500mA,超小型,AC/DC电源变换芯片
TOP1xx-2xx  无变压器,5W以上,AC/DC变换式精密开关电源IC芯片
TL499AC     可调线型串联稳压器和升压型开关稳压器(合成稳压器)芯片
TPS7350   5V固定输出,掉电延时复位,低压差稳压器芯片
W431    3端,可调式电压基准芯片
YA-S     AC/DC电源变换器模块
2.数字式传感器,电位器及精密运放芯片
————————————————————————————————————————————
2.1 运放指标:
1.增益大小,是否增益可编程,
2.温漂,低功耗,高精度
3.放大器类型:Rail-Rail放大器,仪表放大器,功率放大器
4.工作频率,增益带宽积,共模抑制比
5.
6.
7.
...
——————————————————————————————————————————————
2.2 数字温度传感器指标:
1.测温范围
2.测温误差
3.转换时间
4.通信方式:并口,IIC,一(二,三)线
5.温度制表达方式:字节数据,脉宽
6.编程告警温度
7.辅助功能:带实时时钟?微处理器核?
8.
9.
...
——————————————————————————————————————————————
AD526  增益可编程运算放大器芯片
AD620  低功耗,高精密度仪器用运放芯片
AD623  单电源Rail-Rail仪表运放芯片
AD625  增益可编程运算放大器芯片
AD626  单电源差分运算放大器芯片
AD7416  带IIC接口,10位低功耗数字温度传感器芯片
AD8571/8572/8574  0温漂,单电源,运算放大器芯片
AD8591/8592/8594  带节能控制端的CMOS,单电源工作,满电源输入输出,运算放大器芯片
DS1620   数字式温度传感器IC芯片
DS1621  数字式温度传感器IC芯片及恒温控制器IC芯片
DS1625  数字温度计和控温器芯片
DS1629  2线接口,带有实时时钟的温度传感器芯片
DS1820  数字式温度传感器IC芯片
ITT2301AF 射频功率放大器芯片
LM76    带数字温度传感器,IIC总线接口,12位信号输出,测温芯片
LM92    数字式温度传感器芯片
MAX54xx 体积更小,256级,数字电位器芯片
MAX4265~4270  超低失真,单+5V,300MHz,运算放大器芯片
MAX4430/4431/4432/4433  高速(280MHz),高精度,宽频带,单/双运算放大器芯片
MAX6627/6628   兼容SPI接口的远端结温检测器芯片
MAX6629/6630/6631/6632  微型SOT封装,+-1摄氏度精度的数字温度传感器芯片
MAX6657/6658/6659    +-1摄氏度的本地和远端结温检测器芯片
OP193/293/493  精密,微功耗,运算放大器芯片
OP177   超精密运算放大器芯片
OP777   精密,微功耗,单电源,运算放大器芯片
MIC91x  高速(100~350MHz)运算放大器芯片
X9241   IIC接口,数字电位器(EEPOT)IC芯片
X9312   数字电位器IC芯片
X9313   数控电位器芯片
X9511   PushPOT按钮控制电位器芯片
3.电机控制及驱动芯片
87C196MC  电机控制专用微处理器芯片
CIPH9803  可编程步进电机控制IC芯片
FR-Z240-7.5K  变频调速器芯片
HEF4752V  PWM大规模集成电路芯片
IR2110    高压浮动MOSFET,栅极步进电机驱动器IC芯片
LM628     直流电机运动控制芯片
LM1542    无刷直流电机控制器芯片
LMD18200  H桥组件电机驱动芯片
MA818     3相PWM,变频调速专用控制器芯片
MAX1749   微型直流电机驱动控制芯片
MC33033   带温度补偿的直流电机控制器芯片
ML4428    无传感器PWM,无刷直流电机控制器芯片
MOC30xx   双向晶闸管电机控制驱动器(双向光电耦合器)IC芯片
MTE1122   智能型电机驱动运放芯片
PA03      大功率(1000w)运放电机驱动芯片
PA21/25/26  双功率电机驱动运放芯片
PA61     大功率运放电机驱动芯片
PA85    高压,高速,大功率,运放驱动芯片
PBL3772/PBM3960   高性能步进电机驱动IC芯片组
PH2083   多模式步进电机控制器IC芯片
PMM8713  步进电机专用控制芯片
SA06     脉宽调制运放,电机驱动芯片
SA60     脉宽调制型功放芯片
SA866    可编程,全数字化,3相PWM,变频调速控制器IC芯片
ST6210   通用电机驱动电路(MCU)IC芯片
TDA1085C  通用电机速度控制器芯片
UCx637XC9536  PWM型直流电机驱动芯片
XC9536  步进电机CPLD控制芯片 4.数字通信IC芯片及接口—————————————————————————————
—————————
数据通信IC芯片指标:
1.支持的协议类型:无线/有线,蓝牙,FSK,RS232,RS485,RS422,EIA/TIA-232
2,全双工/半双工
3.工作频率,是否ESD保护
4.是否为编解码芯片
5.
6.
7.
...
——————————————————————————————————————
5G16C550
ACM1330E/1550D
ACMTX16/ACMRX18
ADM101E
AM7910
Core 01
DS14C232C/232T
DS26F31
DS26C32
DS3695/3696/3697/3698
DS8921
DS8922
DS9637
DS9638
DS14185
DS75176
DS96172/96174
DS96173/96175
HT9200A
ICL232
KX50xx
LM1893
LMx3162
M303S/303R
M-8888
MAX48x/49x
MAX202
MAX202E/211E/213E/232E/241E
MAX214
MAX220/232/232A
MAX250/251
MAX1480A/1480B
MAX3080E-3089E
MAX3082
MAX3100
MAX3140
MAX3222/3232
MAX3224~3227
MAX3238E/3248E
...————————————————————————————————————————
AD/DA芯片指标:
1.几位,几通道
2.低/高速
3.接入方式:并行/串行/IIC
4.是/否内含参考电压源,自校准,片内运放
5.是/否带微处理核
6.辅助功能:温度传感,时钟发生
7.工作频率
8.
9.
10.
...
————————————————————————————————————————
5.AD转换芯片
...6.DA转换芯片 

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

点击查看原文

发表评论 阅读全文(1511) | 回复(0)

发表于 2007/1/7 10:51:16

1

关于投票

嵌入式系统有着良好的市场前景

问:作为嵌入式系统的学习者来说,在确认嵌入式系统的良好前景的前提下,应该怎样去做呢?


个人的看法是,嵌入式的技术有个脉络:8位mcu(51或者avr...)+can2.0B+arm7+arm9,学习的时候可以按照这个脉络来进行;


第一步:先熟悉51,可以自己做一个学习板,熟悉c51,精通c51,可以自己做一个学习板或者买我的学习板;


第二步:熟悉can2.0,回头给群里把学习板已经玩的比较好的,提供一个51的can接口板;


第三步:熟悉arm7,我计划在5月底推出一个atmel的91sam7x256的学习板的测试版,发布在网络上,以成本价提供给愿意帮助完善学习板的软件和实验指导书的同仁;争取能找到合适的下载和调试工具;等完善之后再按照商业行为来运作。

通过这3步,使得喜欢嵌入式开发的学者能够顺利的进入到嵌入式开发的行业。


问:怎样定义嵌入式系统?


我认为,使用mcu,8位、16位、32位、PC104、X86的机电一体化设备的控制系统都可以成为嵌入式系统;当然,8位mcu做不了太复杂的事情,有时候被排除在外;实际上应该也可以算在嵌入式系统里面。


问:在工业控制领域,51+CANbus和ARM+CAN分别应用在哪些产品比较多?


我根据学习相关资料,51+CANbus作为小节点,次级的节点;ARM+CAN作为主控制器,主节点;

问:你怎样看待电子专业考研?我现在大三,很矛盾。


假设你能毕业一出来就上路做嵌入式开发的工作,而不是打杂,我不赞成考研;

毕竟应用不需要考研,而在于你实战的水平!

按照我的建议就是,哪怕是你的c语言很熟练有这样一个强项,我就认为,可以出来工作了!

而应用的好,实际上大有前途的。


问:那应该学习硬件还是软件呢?


是这样,嵌入式,本身也是多方面的,硬件软件都有,但是,要有自己的最强项,企业都是用你的最强项。我认为,对于在校的学生,应该重点放在c语言的熟练上;一方面是因为硬件没有实际的实践,很难能拿得出手,当然实践的成本也高;当然自己动手做一个学习板还是很有必要的,也不算很难;还有就是在企业中,软件和硬件的配置基本上是1:4的情况;对于程序产品,基本上,硬件修改的情况非常小,升级都是在软件的功能的增加和完善上。


 

附录:嵌入式系统有着良好的市场前景(转载)

中国机电设备目前的主流控制器是PLC,随着计算机技术的发展,嵌入式产品在这一领域迅速增长,并在一些特殊运用中取得优势地位,对小型PLC形成强大的竞争压力,在一些领域甚至出现取代PLC的趋势。

例如:

在塑料机械行业,基于嵌入式产品的塑料机械专用电脑已经占据了主导地位;

而在电梯上,基于嵌入式产品的控制器已经占据了半壁江山,在客梯和高速电梯上更是占据了绝对优势,PLC仅仅在货梯和低速电梯上存有一席之地;

在高端印刷机械上,基于嵌入式产品的印刷机械电脑系统是运用最多的控制方案。 

相对小型PLC而言,嵌入式控制器具有下面这些优势:

1)      运算处理能力强

2)      与PC通讯方便、成本低(相对相同性能指标的PLC)

3)      针对应用优化设计、用户使用方便

当然嵌入式控制器也存在一些问题:

1)      用户技术基础薄弱,不如PLC的应用开发工程师普遍

2)      产品需要由运用开发商开发;可靠性不如PLC

3)      产品不像PLC随处可得;

4)      行业特性强,通用性差。 

嵌入式控制器通常由应用开发商提供,一些大的设备制造商自己开发相关的嵌入式实控制器。开发嵌入式专用控制器的成本较高,周期也比较长,因此目前嵌入式控制器目前仅仅用于大批量、控制功能相对固定的运用,对于批量小的非标设备,嵌入式控制器的整体成本和开发周期相对PLC处于劣势。 

基于以下原因,嵌入式控制器的前景光明: 

1)       相对小型PLC,嵌入式控制器具有更好的性能和更多的功能; 

2)       嵌入式控制器系统成本具有优势; 

3)       由于上述嵌入式控制器的诸多优点,将出现更多的运用开发商开发嵌入式控制器产品; 

4)       大的机电设备制造商也开始开发用于自己设备的嵌入式控制器; 

5)       用户基础和技术基础逐步提升。

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

点击查看原文

发表评论 阅读全文(1884) | 回复(0)

发表于 2006/12/31 14:08:46

1

关于投票

嵌入式软件测试的十大秘诀

嵌入式软件测试的十大秘诀

来源:bbs.21ic.com 人才聘任  作者:bjfarsight 转
 

    在嵌入式软件开发过程中,一般来说,花在测试和花在编码的时间比为3:1(实际上可能更多)。这个比例随着你的编程和测试水平的提高而不断下降,但不论怎样,软件测试对一般人来讲很重要。很多年前,一位开发人员为了对嵌入式有更深层次的理解,向Oracle询问了这样的一个问题:我怎么才能知道并懂得我的系统到底在干些什么呢? Oracle面对这个问题有些吃惊,因为在当时没有人这么问过,而同时代的嵌入式开发人员问的最多的大都围绕“我怎么才能使程序跑的更快”、“什么编译器最好”等肤浅的问题。所以,面对这个不同寻常却异乎成熟的问题,Oracle感到欣喜并认真回复了他:你的问题很有深度很成熟,因为只有不断地去深入理解才有可能不断地提高水平。并且Oracle为了鼓励这位执着的程序员,把10条关于嵌入式软件开发测试的秘诀告诉了他:

  1.懂得使用工具

  2.尽早发现内存问题

  3.深入理解代码优化

  4.不要让自己大海捞针

  5.重现并隔离问题

  6.以退为进

  7.确定测试的完整性

  8.提高代码质量意味着节省时间

  9.发现它,分析它,解决它

  10.利用初学者的思维

  这十条秘诀在业界广为流传,使很多人受益。本文围绕这十条秘诀展开论述。

  1.懂得使用工具

  通常嵌入式系统对可靠性的要求比较高。嵌入式系统安全性的失效可能会导致灾难性的后果,即使是非安全性系统,由于大批量生产也会导致严重的经济损失。这就要求对嵌入式系统,包括嵌入式软件进行严格的测试、确认和验证。随着越来越多的领域使用软件和微处理器控制各种嵌入式设备,对门益复杂的嵌入式软件进行快速有效的测试愈加显得重要。

  就象修车需要工具一样,好的程序员应该能够熟练运用各种软件工具。不同的工具,有不同的使用范围,有不同的功能。使用这些工具,你可以看到你的系统在干些什么,它又占用什么资源,它到底和哪些外界的东西打交道。让你郁闷好几天的问题可能通过某个工具就能轻松搞定,可惜你就是不知道。那么为什么那么多的人总是在折腾个半死之后才想到要用测试工具呢?原因很多,主要有两个。一个是害怕,另一个是惰性。害怕是因为加入测试用具或测试模块到代码需要技巧同时有可能引入新的错误,所以他们总喜欢寄希望于通过不断地修改重编译代码来消除bug,结果却无济于事。懒惰是因为他们习惯了使用printf之类的简单测试手段。下面来介绍一些嵌入式常用的测试工具。

  .源码级调试器[Source-level Debugger]

  这种调试器一般提供单步或多步调试、断点设置、内存检测、变量查看等功能,是嵌入式调试最根本有效的调试方法。比如VxWorks TornadoII提供的gdb就属于这一种。

  .简单实用的打印显示工具[printf]

  printf或其它类似的打印显示工具估计是最灵活最简单的调试工具。打印代码执行过程中的各种变量可以让你知道代码执行的情况。但是,printf对正常的代码执行干扰比较大(一般printf占用CPU比较长的时间),需要慎重使用,最好设置打印开关来控制打印。

  .ICE或JTAG调试器[In-circuit Emulator]

  ICE是用来仿真CPU核心的设备,它可以在不干扰运算器的正常运行情况下,实时的检测CPU的内部工作情况。像桌面调试软件所提供的:复杂的条件断点、先进的实时跟踪、性能分析和端口分析这些功能,它也都能提供。ICE一般都有一个比较特殊的CPU,称为外合(bond-out)CPU。这是一种被打开了封装的CPU,并且通过特殊的连接,可以访问到CPU的内部信号,而这些信号,在CPU被封装时,是没法“看到”的。当和工作站上强大的调试软件联合使用时,ICE就能提供你所能找到的最全面的调试功能。但ICE同样有一些缺点:昂贵;不能全速工作;同样,并不是所有的CPU都可以作为外合CPU的,从另一个角度说,这些外合CPU也不大可能及时的被新出的CPU所更换。JTAG(Joint Test Action Group)虽然它最初开发出来是为了监测IC和电路连接,但是这种串行接口扩展了用途,包括对调试的支持。AD公司为Blackfin设计的Visual Dsp++就支持高速的JTAG调试。

  .ROM监视器[ROM Monitor]

  ROM监控器是一小程序,驻留在嵌入系统ROM中,通过串行的或网络的连接和运行在工作站上的调试软件通信。这是一种便宜的方式,当然也是最低端的技术。它除了要求一个通信端口和少量的内存空间外,不需要其它任何专门的硬件。并提供了如下功能:下载代码、运行控制、断点、单步步进、以及观察、修改寄存器和内存。因为ROM监控器是操作软件的一部分,只有当你的应用程序运行时,它才会工作。如果你想检查CPU和应用程序的状态,你就必须停下应用程序,再次进入ROM监控器。

  .Data监视器[Data Monitor]

  这种监视器在不停止CPU运行的情况下不仅可以显示指定变量内容,还可以收集并以图形形式显示各个变量的变化过程。

  .OS监视器[Operating System Monitor]

  操作系统监视器可以显示诸如任务切换、信号量收发、中断等事件。一方面,这些监视器能够为你呈现事件之间的关系和时间联系;另一方面,还可以提供对信号量优先级反转、死锁和中断延时等问题的诊断。

  .性能分析工具[Profiler]

  可以用来测试CPU到底耗在那里。profiler工具可以让你知道系统的瓶颈在那里、CPU的使用率以及需要优化的地方。

  .内存测试工具[Memory Teseter]

  可以找到内存使用的问题所在,比如内存泄露、内存碎片、内存崩溃等问题。如果发现系统出现一些不可预知的或间歇性的问题,就应该使用内存测试工具测测看。

  .运行跟踪器[Execution Tracer]

  可以显示CPU执行了哪些函数、谁在调用、参数是什么、何时调用等情况。这种工具主要用于测试代码逻辑,可以在大量的事件中发现异常的那些。

  .覆盖工具[Coverage Tester]

  主要显示CPU具体执行了那些代码,并让你知道那些代码分支没有被执行到。这样有助于提高代码质量并消除无用代码。

  .GUI测试工具[GUI Tester]

  很多嵌入式应用带有某种形式的图形用户界面进行交互,有些系统性能测试足根掘用户输入响应时间进行的。GUI测试工具可以作为脚本工具有开发环境中运行测试用例,其功能包括对操作的记录和回放、抓取屏幕显示供以后分析和比较、设置和管理测试过程(Rational公司的robot和Mercury的Loadrunner工具是杰出的代表)。很多嵌入式设备没有GUI,但常常可以对嵌入式设备进行插装来运行GUI测试脚本,虽然这种方式可能要求对被测代码进行更改,但是节省了功能测试和回归测试的时间。

  .自制工具[Home-made tester]

  在嵌入式应用中,有时候为了特定的目的,需要自行编写一些工具来达到某种测试目的。本人曾经编写的视频流录显工具在测试视频会议数据流向和变化上帮了大忙,帮公司找到了几个隐藏很深的bug。

  2.尽早发现内存问题

  内存问题危害很大,不容易排查,主要有三种类型:内存泄露、内存碎片和内存崩溃。对于内存问题态度必须要明确,那就是早发现早“治疗”。在软件设计中,内存泄露的“名气”最大,主要由于不断分配的内存无法及时地被释放,久而久之,系统的内存耗尽。即使细心的编程老手有时后也会遭遇内存泄露问题。有测试过内存泄露的朋友估计都有深刻地体验,那就是内存泄露问题一般隐藏很深,很难通过代码阅读来发现。有些内存泄露甚至可能出现在库当中。有可能这本身是库中的bug,也有可能是因为程序员没有正确理解它们的接口说明文档造成错用。

  在很多时候,大多数的内存泄露问题无法探测,但可能表现为随机的故障。程序员们往往会把这种现象怪罪于硬件问题。如果用户对系统稳定性不是很高,那么重启系统问题也不大;但,如果用户对系统稳定很高,那么这种故障就有可能使用户对产品失去信心,同时也意味着你的项目是个失败的项目。由于内存泄露危害巨大,现在已经有许多工具来解决这个问题。这些工具通过查找没有引用或重复使用的代码块、垃圾内存收集、库跟踪等技术来发现内存泄露的问题。每个工具都有利有弊,不过总的来说,用要比不用好。总之,负责的开发人员应该去测试内存泄露的问题,做到防患于未然。

  内存碎片比内存泄露隐藏还要深。随着内存的不断分配并释放,大块内存不断分解为小块内存,从而形成碎片,久而久之,当需要申请大块内存是,有可能就会失败。如果系统内存够大,那么坚持的时间会长一些,但最终还是逃不出分配失败的厄运。在使用动态分配的系统中,内存碎片经常发生。目前,解决这个问题最效的方法就是使用工具通过显示系统中内存的使用情况来发现谁是导致内存碎片的罪魁祸首,然后改进相应的部分。

  由于动态内存管理的种种问题,在嵌入式应用中,很多公司干脆就禁用malloc/free的以绝后患。

  内存崩溃是内存使用最严重的结果,主要原因有数组访问越界、写已经释放的内存、指针计算错误、访问堆栈地址越界等等。这种内存崩溃造成系统故障是随机的,而且很难查找,目前提供用于排查的工具也很少。

  总之,如果要使用内存管理单元的话,必须要小心,并严格遵守它们的使用规则,比如谁分配谁释放。

  3.深入理解代码优化

  讲到系统稳定性,人们更多地会想到实时性和速度,因为代码效率对嵌入式系统来说太重要了。知道怎么优化代码是每个嵌入式软件开发人员必须具备的技能。就象女孩子减肥一样,起码知道她哪个地方最需要减,才能去购买减肥药或器材来减掉它。可见,代码优化的前提是找到真正需要优化的地方,然后对症下药,优化相应部分的代码。前面提到的profile(性能分析工具,一些功能齐全IDE都提供这种内置的工具)能够记录各种情况比如各个任务的CPU占用率、各个任务的优先级是否分配妥当、某个数据被拷贝了多少次、访问磁盘多少次、是否调用了网络收发的程序、测试代码是否已经关闭等等。

  但是,profile工具在分析实时系统性能方面还是有不够的地方。一方面,人们使用profile工具往往是在系统出现问题即CPU耗尽之后,而profile工具本身对CPU占用较大,所以profile对这种情况很可能不起作用。根据Heisenberg效应,任何测试手段或多或少都会改变系统运行,这个对profiler同样适用!

  总之,提高运行效率的前提是你必须要知道CPU到底干了些什么干的怎么样。

  4.不要让自己大海捞针

  大海捞针只是对调试的一种生动比喻。

  经常听到组里有人对自己正在调试的代码说shit!可以理解,因为代码不是他写的,他有足够的理由去shit bug百出的代码,只要他自己不要写出这种代码,否则有一天同组的其它人可能同样会shit他写的代码。为何会有大海捞针呢?肯定是有人把针掉到海里咯;那针为何会掉在海里呢?肯定是有人不小心或草率呗。所以当你在抱怨针那么难找的时候,你是否想过是你自己草率地丢掉的。同样,当你调试个半死的时候,你是否想过你要好好反省一下当初为了寻求捷径可能没有严格地遵守好的编码设计规范、没有检测一些假设条件或算法的正确性、没有将一些可能存在问题的代码打上记号呢?关于如何写高质量请参考林锐的《高质量c++/c编程指南》或《关于C的0x8本“经书”》。

  如果你确实已经把针掉在海里是,为了防止在找到之前刺到自己,你必须要做一些防范工作,比如戴上安全手套。同样,为了尽能地暴露和捕捉问题根源,我们可以设计比较全面的错误跟踪代码。怎么来做呢?尽可能对每个函数调用失败作出处理,尽可能检测每个参数输入输出的有效性包括指针以及检测是否过多或过少地调用某个过程。错误跟踪能够让你知道你大概把针掉在哪个位置。

  5.重现并隔离问题

  如果你不是把针掉在大海了,而是掉在草堆里,那要好办写。因为至少我们可以把草堆分成很多块,一块一块的找。对于模块独立的大型项目,使用隔离方法往往是对付那些隐藏极深bug的最后方法。如果问题的出现是间歇性的,我们有必要设法去重现它并记录使其重现的整个过程以备在下一次可以利用这些条件去重现问题。如果你确信可以使用记录的那些条件去重现问题,那么我们就可以着手去隔离问题。怎么隔离呢?我们可以用#ifdef把一些可能和问题无关的代码关闭,把系统最小化到仍能够重现问题的地步。如果还是无法定位问题所在,那么有必要打开“工具箱”了。可以试着用ICE或数据监视器去查看某个可疑变量的变化;可以使用跟踪工具获得函数调用的情况包括参数的传递;检查内存是否崩溃以及堆栈溢出的问题。

  6.以退为进

  猎人为了不使自己在森林里迷路,他常常会在树木上流下一些标记,以备自己将来有一天迷路时可以根据这些标记找到出路。对过去代码的修改进行跟踪记录对将来出现问题之后的调试很有帮助。假如有一天,你最近一次修改的程序跑了很久之后忽然死掉了,那么你这时的第一反映就是我到底改动了些什么呢,因为上次修改之前是好的。那么如何检测这次相对于上次的修改呢?没错,代码控制系统SCS或称版本控制系统VCS(Concurrent Version Control,CVS是VCS的演化版本)。将上个版本check in下来后和当前测试版本比较。比较的工具可以是SCS/VCS/CVS自带的diff工具或其它功能更强的比较工具,比如BeyondCompare和ExamDiff。通过比较,记录所有改动的代码,分析所有可能导致问题的可疑代码。

  7.确定测试的完整性

  你怎么知道你的测试有多全面呢?覆盖测试(coverage testing)可以回答这个问题。覆盖测试工具可以告诉你CPU到底执行了那些代码。好的覆盖工具通常可以告诉你大概20%到40%代码没有问题,而其余的可能存在bug。覆盖工具有不同的测试级别,用户可以根据自己的需要选择某个级别。即使你很确信你的单元测试已经很全面并且没有dead code,覆盖工具还是可以为你指出一些潜在的问题,看下面的代码:

  if (i >= 0 && (almostAlwaysZero == 0 || (last = i)))

  如果almostAlwaysZero为非0,那么last="i"赋值语句就被跳过,这可能不是你所期望的。这种问题通过覆盖工具的条件测试功能可以轻松的被发现。

  总之,覆盖测试对于提高代码质量很有帮助。

  8.提高代码质量意味着节省时间

  有研究表明软件开发的时间超过80%被用在下面几个方面:

  .调试自己的代码(单元测试)

  .调试自己和其他相关的代码(模块间测试)

  .调试整个系统(系统测试)

  更糟糕的是你可能需要花费10-200倍的时间来找一个bug,而这个bug在开始的时候可能很容易就能找到。一个小bug可能让你付出巨大的代价,即使这个bug对整个系统的性能没有太大的影响,但很可能会影响让那些你可以看得到的部分。所以我们必须要养成良好的编码和测试手段以求更高的代码质量,以便缩短调试的代码。

  9.发现它,分析它,解决它

  这世界没有万能的膏药。profile再强大也有力不从心的时候;内存监视器再好,也有无法发现的时候;覆盖工具再好用,也有不能覆盖的地方。一些隐藏很深的问题即使用尽所有工具也有可能无法查到其根源,这时我们能做的就是通过这些问题所表现出来的外在现象或一些数据输出来发现其中的规律或异常。一旦发现任何异常,一定要深入地理解并回溯其根源,直到解决为止。

  10.利用初学者的思维

  有人这样说过:“有些事情在初学者的脑子里可能有各种各样的情况,可在专家的头脑里可能就很单一”。有时候,有些简单的问题会被想的很复杂,有些简单的系统别设计的很复杂,就是由于你的“专家思维”。当你被问题难住时,关掉电脑,出去走走,把你的问题和你的朋友甚至你的小狗说说,或许他们可以给你意想不到的启发。

  总结:嵌入式调试也是一门艺术。就想其它的艺术一样,如果你想取得成功,你必须具备智慧、经验并懂得使用工具。只要我们能够很好地领悟Oracle这十条秘诀,我相信我们在嵌入式测试方面就能够取得成功。

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

点击查看原文

发表评论 阅读全文(718) | 回复(0)

发表于 2006/12/30 15:41:19

0

关于投票

微缩的力量:透过数据看CPU技术进步

微缩的力量:透过数据看CPU技术进步

微处理器的发展史,就是集成度不断提高的历史。按照摩尔定律,芯片内晶体管的数量每18个提高一倍。Intel 4004核心尺寸为3 x 4mm2,共集成有2,300个晶体管,集成度不足200个晶体管/mm2;而Pentium 4核心尺寸是112mm2,包含了1.25亿颗晶体管,集成度高达110万个晶体管/mm2。从4004到P4E,集成度提高了5千多倍。在摩尔定律的背后,是一种什么样的力量不断地压缩晶体管的尺寸呢?

点击看大图

微处理器内的晶体管数量按摩尔定律增长

一、半导体技术路线图:推动芯片技术发展的软性力量

 在1992年以前,技术节点由半导体制造大厂自行决定,而从1992年开始,芯片制造商、设备供应商、材料供应商和软件供应商组建了的国际半导体行业协会(SIA),SIA通过制定“国际半导体技术路线图(ISTR)”,协调各方步调。ISTR包括芯片设计、工艺集成、前端工艺、光刻、互联、工厂集成、测试和封装和装配等技术规范和工作进展,所有厂商都按照统一的时间表进行工作。

晶元(wafer),半导体工业的粮食

 ISTR规定:每个技术节点将半节距缩小0.7倍(或两个节点缩小0.5倍),过渡到下一个节点的期限为2~3年。

点击看大图

 半导体技术的进步像110米栏比赛,不断地跨越一个又一个障碍。ISTR作为一种软性的力量,把各项技术研发工作整体向前推进。众多厂商的风险和利益通过ISTR绑在了一起,减少了不确定性。1995年以来,微处理器的技术节点基本上是按照ISTR的时间表从500nm、350nm、250nm、180nm、50nm、130nm走到了今天的90nm和65nm。

二、光学微影设备:提高集成度的金刚钻

 没有金刚钻揽不下瓷器活。在芯片工厂,光学微影设备(即光刻机)是最昂贵的设备,单台价格高达2000万美元左右。光刻机当然也是芯片制作中最关键的设备,发出的激光波长越短,分辨率越高,形成微电路的线宽也就越窄。线宽缩小了,芯片的集成度才能得以提高。

点击看大图

芯片光刻工艺进展

 历年来,光刻机曝光光源的激光波长不断缩短,从436nm、365nm的近紫外(NUV)激光进入到246nm、193nm的深紫外(DUV)激光。为获得这些激光,先后使用了汞灯光源和准分子光源。在45nm节点之后,将需要使用波长更短、能量更大的光源,如极紫外、X射线、电子束和离子束等。

                       1  芯片发展各个阶段使用的光源

 

汞灯光源

准分子激光光源

KrF

ArF

F2

波长(nm

365

246

193

157

分辨率(μm

0.4

0.2

0.15

0.12

应用的工艺

(半节距)

0.5μm0.25μm

0.25μm0.18μm0.13μm

0.13μm90nm65nm

65nm45nm

三、多层布线实现立体“养植”

 早期的集成电路只有一层,随着对芯片内晶体管数量的要求不断增加,需要通过增加布线层数来实现。Prescott核心采用7层布线,到65nm工艺时将达到8层布线。AMD的Athlon XP的铜互联层已经做到了9层布线。

多层芯片的结构

 除了多层布线工艺外,现在研究人员正在研究如何在现有工艺和技术的基础上增加各层器件数量,并打破多年来一直采用平面化元器件布置工艺,走向立体化。

   PS:此文来自我的书稿《通俗硬件》,版权所有,禁止复制和传播!

系统分类: 嵌入式  |  用户分类: 嵌入式  |  标签: 微缩的力量 透过数据看CPU技术进步  |  来源: 转贴  | 

点击查看原文

发表评论 阅读全文(799) | 回复(0)

发表于 2006/12/29 22:48:01

2

关于投票

非计算机专业尤其理论基础比较差的家伙必读

非计算机专业尤其理论基础比较差的家伙必读

****************声明******************
以下内容未经整理,
随手打来,
编排混乱.
且一家之言,
定有偏颇,热切希望和欢迎大家补充更正
**************************************


哦,
你没福气进中国名校念大学念研究生念博士?
没福气进具备良好培训机制的公司或研究所工作?
没福气到海外留学?
呵呵,
这差不多注定了你在技术路上要碰上很多坎坷,
注定了你要走比别人更多的弯路,
可是有关系吗?

没有,
走比别人更多的弯路,
跌倒了趴下爬起来再跌倒再趴下再爬起来,
----------当你回头看着自己走过的路的时候,
你会发觉,
看着自己一步一个脚印地长大,
真的很有意思,
呵呵,
有什么事情比看着自己长大有意思呢?


好了,
废话少说切入正题,
下面列些清单,
看者自明其用.

1,计算机软件专业基础知识;

1.1,程序结构/面向对象编程思想.
1.2,数据结构.
1.3,计算机组成原理和结构体系.
1.4,离散数学.
1.5,操作系统原理(UNIX/MINIX/LINUX/UCOS/NT)
--->系统层次结构,任务管理,任务间通讯,IO管理,内存管理,文件系统,网络构成.
1.6,编译

系统分类: 嵌入式  |  用户分类: 嵌入式  |  标签: 非计算机专业尤其理论基础比较差的家伙必读  |  来源: 转贴  | 

点击查看原文

发表评论 阅读全文(1025) | 回复(1)

Total , Page /