一、混合编程1、模块内接口:使用如下标志符:#pragmaasm汇编语句#pragmaendasm注意:如果在c51程序中使用了汇编语言,注意在keil编译器中需要激活Properties中的“GenerateAssemblerSRCFile”和“AssemblerSRCFile”两个选项来个实例吧:#includevoidmain(void){P2=1;#pragmaasmMOVR7,#10DEL:MOVR6,#20DJNZR6,$DJNZR7,DEL#pragmaendasmP2=0;}另:1、把xx.c加入工程中,右击xx.c选择“optionsforfilexx.c选择“GenerateAssemblerSRCFile”和“AssembleSRCFile”打上黑勾有效;2、根据选择的编译模式,把相应的库文件象加xx.c一样加入工程中并放在xx.c下面,如smail模式下选keil\c51\lib\c51s.lib加入工程中,如果要进行浮点运算把keil\c51\lib\c51fpl.lib也加入工程中。在Keil安装目录下的\C51\LIB\目录的LIB文件如下:C51S.LIB-没有浮点运算的SmallmodelC51C.LIB-没有浮点运算的CompactmodelC51L.LIB-没有浮点运算的LargemodelC51FPS.LIB-带浮点运算的SmallmodelC51FPC.LIB-带浮点运算的CompactmodelC51FPL.LIB-带浮点运算的Largemodel3、在xx.c头文件中加入优化:比如#pragmaOT(4,speed)4、在xx.c中加入汇编代码#pragmaASM;AssemblerCodeHere#pragmaENDASM5、编译生成xx.hex注意:没有做第一步会有如下警告:'asm/endasm'requiressrc-controltobeactive没有做第二步会有如下警告:UNRESOLVEDEXTERNALSYMBOL;REFERENCEMADETOUNRESOLVEDEXTERNAL等没有做第三步会有如下警告:UNDEFINEDSYMBOL(PASS-2)二、中断使用interruptxxusingy跟在interrupt后面的xx值得是中断号,就是说这个函数对应第几个中断端口,一般在51中0外部中断01定时器02外部中断13定时器14串行中断其它的根据相应的单片机有自己的含义,实际上c在编译的时候就是把你这个函数的入口地址放到这个对应中断的跳转地址。usingy这个y时说这个中断函数使用的那个寄存器组就是51里面一般有4个r0--r7寄存器,如果你的终端函数和别的程序用的不是同一个寄存器组则进入中断的时候就不会将寄存器组压入堆栈返回时也不会弹出来节省代码和时间。三、关于reentrant的使用方法云清燕发表于2006-11-1521:27:00我在程序中出现了如下警告:***WARNINGL15:MULTIPLECALLTOSEGMENTSEGMENT:?PR?_CRCDATA?PANEL_DISPCALLER1:?C_C51STARTUPCALLER2:?PR?UART_RECV?PANEL_DISP***WARNINGL15:MULTIPLECALLTOSEGMENTSEGMENT:?PR?ANALOGALLBECKON?PANEL_DISPCALLER1:?C_C51STARTUPCALLER2:?PR?UART_RECV?PANEL_DISP***WARNINGL15:MULTIPLECALLTOSEGMENTSEGMENT:?PR?SWITCHALLBECKON?PANEL_DISPCALLER1:?C_C51STARTUPCALLER2:?PR?UART_RECV?PANEL_DISP我的程序编译出来就这3个警告,但是程序可以正常下载运行。但是我觉得有这些警告会使程序存在bug。从字面上看是它的意思是我程序中接受函数UART_RECV()多调用了analogAllBeckon()、switchAllBeckon()。因为51的普通函数是不可重入的,变量放在固定的地址,两个函数同时运行时,就会修改同一个变量,从而导致结果错误。于是我在analogAllBeckon()、switchAllBeckon()函数后面加了voidanalogAllBeckon()reentrant{//AllAnalogdatabeckon使程序消除了警告。这种方法是表明函数是可被多哥任务调用而不修改函数里边的变量值,以此来实现函数的重入性。关于reentrant的使用keil的官方论坛上有详细的讨论.AndyNeil(官方工程师)建议Areyousurethatyoureallyneedtomakeeverythingreentrant?...AreadingoftheKeilappnotes&knowledgebasearticlesonthissubjectshowedthatitwasnotnecessary.由于每一次调用被reentrant声明的函数都要把函数的参数和内部变量压栈,所以很容易使堆栈区溢出,S52只有256Bytes的data段,一个简单的函数如果有一个参数三个内部变量,则需要压栈4字节以上,这还不包括函数调用堆栈.reentrant其实并不是适合低端的单片机,keil论坛上有人说对于那些有KB以上RAM的单片机reentrant才适合.四、变量声明有关在51系列中data,idata,xdata,pdata的区别data:固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。idata:固定指前面0x00-0xff的256个RAM,其中前128和data的128完全相同,只是因为访问的方式不同。idata是用类似C中的指针方式访问的。汇编中的语句为:moxACC,@Rx.(不重要的补充:c中idata做指针式的访问效果很好)xdata:外部扩展RAM,一般指外部0x0000-0xffff空间,用DPTR访问。pdata:外部扩展RAM的低256个字节,地址出现在A0-A7的上时读写,用movxACC,@Rx读写。这个比较特殊,而且C51好象有对此BUG,建议少用。但也有他的优点,具体用法属于中级问题,这里不提。startup.a51的作用和汇编一样,在C中定义的那些变量和数组的初始化就在startup.a51中进行,如果你在定义全局变量时带有数值,如unsignedchardataxxx=100;,那startup.a51中就会有相关的赋值。如果没有=100,startup.a51就会把他清0。(startup.a51==变量的初始化)。这些初始化完毕后,还会设置SP指针。对非变量区域,如堆栈区,将不会有赋值或清零动作。有人喜欢改startup.a51,为了满足自己一些想当然的爱好,这是不必要的,有可能错误的。比如掉电保护的时候想保存一些变量,但改startup.a51来实现是很笨的方法,实际只要利用非变量区域的特性,定义一个指针变量指向堆栈低部:0xff处就可实现。,为什么还要去改?可以这么说:任何时候都可以不需要改startup.a51,如果你明白它的特性。五、类型有关用bit能够定义一个变量,用sbit却不行,sbit能够定义端口。51单片机系统设计与实际应用作者:转载正确估计单片机的能力,知道单片机能做什么,最大程度的挖掘单片机的潜力对一个单片机系统设计者来说是至关重要的。我们应该有这样一个认识,即单片机的处理能力是非常强大的。早期的PC机,其CPU(8086)处理能力和8051相当,却能处理相当复杂的任务。单片机的能力的关键就在软件设计者编写的软件上。只有充分地了解到单片机的能力,才不会做出“冗余”的系统设计。而采用许多的外围芯片来实现单片机能实现的功能。这样做,即增加了系统成本,也可能会降低了系统的可靠性。1.2系统可靠性至关重要【规则2】使用看门狗。看门狗电路通常是一块在有规律的时间间隔中进行更新的硬件。更新一般由单片机来完成,如果在一定间隔内没能更新看门狗,那看门狗将产生复位信号,重新复位单片机。更新看门狗的具体形式多是给看门狗芯片相关引脚提供一个电平上升沿或读写它的某个寄存器。使用看门狗电路将在单片机发生故障进行死机状态时,重新复位单片机。当前有多种看门狗的芯片,如MAXIM公司的MAX802,MAX813等。而且,有好多种单片机中本身就集成有看门狗。一个外部的看门狗是最好的,因为它不依赖于单片机。如果可能的话,看门狗更新程序不应该放在中断或是子程序中,原则上应该放在主程序中。我曾经见过一个工程师,他所调试的程序在运行时偶而会引起看门狗的复位动作,于是他干脆在每10ms就中断一次的时钟中断程序中清看门狗。我相信他也知道使看门狗失去作用,可他却没有不是去查明引起这个现象的真正原因。因此,我想提醒大家:不论什么理由,绝对不要忽略系统故障的真正原因。高质量的产品来自于高素质的工程师,高质量的产品造就高素质的工程师。【规则3】确定系统的复位信号可靠。这是一个很容易忽略的问题。当你在设计单片机系统时,你脑中有这个概念吗?什么样的复位信号才是可靠的吗?你用示波器查看过你设计的产品的复位信号吗?不稳定的复位信号可能会产生什么样的后果?你有没有发现过你所设计的单片机系统,每次重新上电启动后,数据变得乱七八糟,并且每一次现象并不相同,找不出规律,或者有时候干脆不运行,或者有时候进入一种死机状态,有时候又一点事都没有正常运行?在这种情况下,你应该查一下你的系统的复位信号。一般在单片机的数据手册(Datasheet)中都会提到该单片机需要的复位信号的要求。一般复位信号的宽度应为。复位电平的宽度和幅度都应满足芯片的要求,并且要求保持稳定。还有特别重要的一点就是复位电平应与电源上电在同一时刻发生,即芯片一上电,复位信号就已产生。不然,由于没有经过复位,单片机中的寄存器的值为随机值,上电时就会按PC寄存器中的随机内容开始运行程序,这样很容易进行误操作或进入死机状态。【规则4】确定系统的初始化有效。系统程序开始应延时一段时间。这是很多单片机程序设计中的常用方法,为什么呢?因为系统中的芯片以及器件从上电开始到正常工作的状态往往有一段时间,程序开始时延时一段时间,是让系统中所有器件到达正常工作状态。究竟延时多少才算合适?这取决于系统的各芯片中到达正常工作状态的时间,通常以最慢的为准。一般来说,延时20-100毫秒已经足够。对于系统中使用嵌入式MODEM等“慢热”型的器件来说,则应更长。当然,这都需要在系统实际运行中进行调整。【规则5】上电时对系统进行检测。上电时对系统中进行检测是单片机程序中的一个良好设计。在硬件设计时也应该细细考虑将各个使用到的芯片、接口设计成容易使用软件进行测试的模式。很多有经验的单片机设计者都会在系统上电时(特别是第一次上电时)进行全面的检测,或者更进一步,将系统的运行状态中分为测试模式和正常运行模式,通过加入测试模式对系统进行详细的检测,使得系统的批量检测更为方便容易。另外要注意的是,一个简单明了的故障显示界面也是颇要费得心思的。比如:系统的外部RAM(数据存储器)是单片机系统中常用的器件。外部RAM如果存在问题,程序通常都会成为一匹脱缰的野马。因此,程序在启动时(至少在第一次上电启动时)一定要对外部RAM进行检测。检测内容包括:1)检测RAM中的单元。这主要通过写入和读出的数据保持一致。2)检测单片机与RAM之间的地址数据总线。总线即没有互相短路,也没有连接到“地”上。另外,很多芯片,都提供了测试的方法。如串行通信芯片UART,都带环路测试的功能。【规则6】按EMC测试要求设计硬件。EMC测试要求已经成为产品的必需。有很多的文章关于这方面的。1.3软件编程和调试【规则7】尽可能使用Small模式编译对比起Large模式和Compact模式,Small模式能生成更为紧凑的代码。在S