smile默白 smile默白
关注数: 5 粉丝数: 111 发帖数: 315 关注贴吧数: 5
单片机C语言延时需注意的问题 标准的C语言中没有空语句。但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果。这在汇编语言中很容易实现,写几个nop就行了。 在keil C51中,直接调用库函数: #include // 声明了void _nop_(void); _nop_(); // 产生一条NOP指令 作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒。NOP指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1uS。对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。 在选择C51中循环语句时,要注意以下几个问题 第一、定义的C51中循环变量,尽量采用无符号字符型变量。 第二、在FOR循环语句中,尽量采用变量减减来做循环。 第三、在do…while,while语句中,循环体内变量也采用减减方法。 这因为在C51编译器中,对不同的循环方法,采用不同的指令来完成的。 下面举例说明: unsigned char i; for(i=0;i<255;i++); unsigned char i; for(i=255;i>0;i--); 其中,第二个循环语句C51编译后,就用DJNZ指令来完成,相当于如下指令: MOV 09H,#0FFH LOOP: DJNZ 09H,LOOP 指令相当简洁,也很好计算精确的延时时间。 同样对do…while,while循环语句中,也是如此 例: unsigned char n; n=255; do{n--} while(n); 或 n=255; while(n) {n--}; 这两个循环语句经过C51编译之后,形成DJNZ来完成的方法, 故其精确时间的计算也很方便。 其三:对于要求精确延时时间更长,这时就要采用循环嵌套的方法来实现,因此,循环嵌套的方法常用于达到ms级的延时。对于循环语句同样可以采用for,do…while,while结构来完成,每个循环体内的变量仍然采用无符号字符变量。 unsigned char i,j for(i=255;i>0;i--) for(j=255;j>0;j--); 或 unsigned char i,j i=255; do{j=255; do{j--} while(j); i--; } while(i); 或 unsigned char i,j i=255; while(i) {j=255; while(j) {j--}; i--; } 这三种方法都是用DJNZ指令嵌套实现循环的,由C51编译器用下面的指令组合来完成的 MOV R7,#0FFH LOOP2: MOV R6,#0FFH LOOP1: DJNZ R6,LOOP1 DJNZ R7,LOOP2 这些指令的组合在汇编语言中采用DJNZ指令来做延时用,因此它的时间精确计算也是很简单,假上面变量i的初值为m,变量j的初值为n,则总延时时 间为:m×(n×T+T),其中T为DJNZ指令执行时间(DJNZ指令为双周期指令)。这里的+T为MOV这条指令所使用的时间。同样对于更长时间的延 时,可以采用多重循环来完成。 只要在程序设计循环语句时注意以上几个问题。 下面给出有关在C51中延时子程序设计时要注意的问题 1、在C51中进行精确的延时子程序设计时,尽量不要或少在延时子程序中定义局部变量,所有的延时子程序中变量通过有参函数传递。 2、在延时子程序设计时,采用do…while,结构做循环体要比for结构做循环体好。 3、在延时子程序设计时,要进行循环体嵌套时,采用先内循环,再减减比先减减,再内循环要好。 unsigned char delay(unsigned char i,unsigned char j,unsigned char k) {unsigned char b,c; b="j"; c="k"; do{ do{ do{k--}; while(k); k="c"; j--;}; while(j); j=b; i--;}; while(i); } 这精确延时子程序就被C51编译为有下面的指令组合完成 delay延时子程序如下: MOV R6,05H MOV R4,03H C0012: DJNZ R3, C0012 MOV R3,04H DJNZ R5, C0012 MOV R5,06H DJNZ R7, C0012 RET 假设参数变量i的初值为m,参数变量j的初值为n,参数变量k的初值为l,则总延时时间为:l×(n×(m×T+2T)+2T)+3T,其中T为 DJNZ和MOV指令执行的时间。当m=n=l时,精确延时为9T,最短;当m=n=l=256时,精确延时到16908803T,最长。
单片机程序死机跑飞查错指南 单片机程序死机,跑飞了可以从以下几个方面查找原因: 1. 意外中断。是否打开了某个中断,但是没有响应和清除中端标志,导致程序一直进入中断,造成死机假象; 2. 中断变量处理不妥。若定义某些会在中断中修改的全局变量,这时要注意两个问题:首先为了防止编译器优化中断变量,要在这些变量定义时前加volatile,其次在主循环中读取中断变量前应该首先关闭全局中断,防止读到一半被中断给修改了,读完之后再打开全局中断;否则出现造成数据乱套。 3. 地址溢出,常见错误为指针操作错误。我要着重说的是数组下标使用循环函数中循环变量,如果循环变量没控制好则会出现数组下标越界,意外修改系统的寄存器造成死机,这种情况下如果死机说明运气好,否则后面不知道发生什么头疼的事。 4. 无条件的死循环;比如使用while(x);等待电平变化,正常情况下x都会变成0,就怕万一,因此最好加上时间限制; 5. 看门狗没有关闭。有的单片机即使没使用看门狗开机时也有可能意外自动开启了最小周期的看门狗,导致软件不断复位,造成死机,这个要看芯片手册,最好在程序复位后首先应该显式清除看门狗再关闭看门狗; 6. 堆栈溢出。最难查找的问题,对于容量小的单片机,尽量减少函数调用层级,减少局部变量,从而减少压栈的时候所需的空间。当你把以上几条都试过不能解决问题,试一试把你的被调用少函数直接内置到调用的地方并且把占用RAM大的局部变量改成全局变量,试一试说不定就可以了。
单片机外围电路设计 注: AT89S52单片机是ATMEL的比较经典的一款,随着单片机竞争激烈,已经成了老型号了。现在的单片机,资源越来越丰富,越来越多的外围都被集成,如:RTC、LDO、LED驱动、LCD驱动、按键、EEPROM、RF、SPI、UART、USB、ISO77816、电表计量7755等等等,更要命的是价格无底线。 导读:本文以带语音提醒的家用多功能定时器为例,进行单片机应用系统的硬件电路设计。   一、单片机电路   单片机采用AT89S52   1.时钟电路Xl、C2、C3与单片机内部的反相放大器一起构成时钟振荡电路,采用12MHz晶振,AT89S52的机器周期为12个振荡周期,每个机器周期正好lμs.   2.复位电路Cl、R9构成上电复位电路,S5是手动复位按键。   3.其他AT89S52单片机内部有8k字节FlashROM、256字节RAM,不用外扩程序存储器和数据存储器,因此其EA脚固定接高电平,ALE和:IPSEN脚悬空。   二、电源   由于AT89S52的工作电压为4V~5.5V,而输出驱动的继电器采用9V直流电,故直接采用市售的9V直流稳压电源,再加5V稳压电路组成其电源电路。   三、键盘电路   根据系统要求,需要用按键来完成定时时间输入、定时工作启动等。按键的状态通过与其相连的I/O口送到单片机中,根据所按的键去执行相应的程序。常用的按键电路有矩阵式键盘和独立式按键两种。   1.矩阵式键盘矩阵式键盘如图2所示。矩阵由若干行和若干列组成,按键跨接在行和列之间,而行、列分别接至单片机的I/O口。单片机则通过先将某行置为特定状态,再读取列来获知是否有键按下,逐行设置状态,再读取列,便可知道所按的键的行列位置。   2.独立式按键独立式按键如图3所示。每个按键直接接到单片机的一个I/O口,单片机读取该口可获知按键的状态。   3.多功能定时器的键盘具体到本产品,可以用设置、加、减共3个键来完成16个定时时间的设置和选择,用启动键来启动定时器工作,故只需要4个按键(Sl~S4),分别接至单片机的P1.4~P1.7口。AT89S52的P1口是内部带上拉电阻的准双向口,将P1.4~P1.7置为输人状态,断开时读取相应的口线为高电平,按键按下时为低电平,故不必外接上拉电阻。   四、显示电路   根据系统要求,需要用数码管来显示预置时间及剩余时间。显示时、分、秒共需要6位数码管,显示定时的路数需要1位数码管,而单片机当前的工作状态,则用一只双色发光二极管指示。   1.LED数码管带小数点的LED数码管由8段发光二极管组成,分别定义为a、b、c、d、e、f、g和dp,8段发光二极管的一个同名端接在一起,定义为公共端(com)。根据所接同名端的不同,LED数码管分为共阴和共阳两种,图4为其外形及结构图。要令数码管显示不同的字符,一要分别控制各段的独立端的电平,二要控制公共端,使相应的发光二极管点亮。如要显示“1”,则应使b、c点亮。以共阴数码管为例,应向b、c端送高电平,其余段送低电平,向com端送低电平。我们通常称控制a~g和dp的信号为段码,控制com端的信号为位码。   2.单片机与LED数码管的接口单片机与LED数码管的接口分为静态显示和动态显示两种。静态显示时,数码管的段信号和位信号始终保持不变,在多位显示时,每一位数码管的段信号都需要用锁存器进行锁存。动态显示则采取I/O口分时复用的方式输出数码管的段信号,由位选信号决定某一时刻哪一位数码管显示。由于人眼的视觉暂留效应,只要让多位数码管轮流显示,而同一位数码管每次显示相同的字符,则所看到就是固定的字符串了。   3.多功能定时器的显示电路如图l所示,显示电路由共阴数码管PLL~PL4、达林顿驱动电路UI~N2803A、R卜R8等组成,采用动态显示方式。PLl~PL3分别显示秒、分和时,PL4显示时间段。Po口为数码管的段选输出口。P2.0~P2.6为数码管的位选输出口。由于AT89S52只有4个TTL门的驱动能力,因此需要外接驱动电路。   五、语音电路   语音芯片采用APl840芯片。   单片机的P1.O~P1.3口用于控制语音段的输出。   六、输出驱动电路   输出驱动电路由ULN2803A和继电器K1组成,Kl的触点通过J3引出,可供用户控制相关电器。   七、其他   为了使用户设置的数据在系统断电后能够保持,在电路中还增加了串行E2PROM存储器24C02,用单片机的P3.3~P3.5分别控制其数据的读写。   IC5为一体化的红外接收头,可以接收红外遥控信号。用户也可以采用遥控方式控制定时器的工作。J2是ISP编程口,有了该接口,用户可以通过计算机对电路中的单片机编程。
1 下一页