当前位置:文档之家› 单片机C语言的延时计算

单片机C语言的延时计算

单片机C语言的延时计算
单片机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,最长。

-----------------------------------------------------------------------------------------

采用软件定时的计算方法

利用指令执行周期设定,以下为一段延时程序:

指令周期

MOV 1

DJNZ 2

NOP 1

采用循环方式定时,有程序:

MOV R5,#TIME2 ;周期1

LOOP1: MOV R6,#TIME1 ; 1

LOOP2: NOP ; 1

NOP ; 1

DJNZ R6,LOOP2 ; 2

DJNZ R5,LOOP1 ; 2

定时数=(TIME1*4+2+1)*TIM2*2+4

刚刚又学了一条,用_nop_();时记得加上#include 头文件

如:

//==================

#include //包含库函数

......

......

//============

......

......

_nop_(); //引用库函数

敬礼。

我一直都是借助仿真软件编。一点一点试时间。

C语言最大的缺点就是实时性差,我在网上到看了一些关于延时的讨论,其中有篇文章

51单片机 Keil C 延时程序的简单研究,作者:InfiniteSpace Studio/isjfk

写得不错,他是用while(--i);产生DJNZ 来实现精确延时,后来有人说如果while里面不能放其它语句,否则也不行,用do-while就可以,具体怎样我没有去试.所有这些都没有给出具体的实例程序来.还看到一些延时的例子多多少少总有点延时差.为此我用for循环写了几个延时的子程序贴上来,希望能对初学者有所帮助.(晶振12MHz,一个机器周期1us.)

一. 500ms延时子程序

程序:

void delay500ms(void)

{

unsigned char i,j,k;

for(i=15;i>0;i--)

for(j=202;j>0;j--)

for(k=81;k>0;k--);

}

产生的汇编:

C:0x0800 7F0F MOV R7,#0x0F

C:0x0802 7ECA MOV R6,#0xCA

C:0x0804 7D51 MOV R5,#0x51

C:0x0806 DDFE DJNZ R5,C:0806

C:0x0808 DEFA DJNZ R6,C:0804

C:0x080A DFF6 DJNZ R7,C:0802

C:0x080C 22 RET

计算分析:

程序共有三层循环

一层循环n:R5*2 = 81*2 = 162us DJNZ 2us

二层循环m:R6*(n+3) = 202*165 = 33330us DJNZ 2us + R5赋值 1us = 3us 三层循环: R7*(m+3) = 15*33333 = 499995us DJNZ 2us + R6赋值 1us = 3us 循环外: 5us 子程序调用 2us + 子程序返回 2us + R7赋值 1us = 5us 延时总时间 = 三层循环 + 循环外 = 499995+5 = 500000us =500ms

计算公式:延时时间=[(2*R5+3)*R6+3]*R7+5

二. 200ms延时子程序

程序:

void delay200ms(void)

{

unsigned char i,j,k;

for(i=5;i>0;i--)

for(j=132;j>0;j--)

for(k=150;k>0;k--);

}

产生的汇编

C:0x0800 7F05 MOV R7,#0x05 C:0x0802 7E84 MOV R6,#0x84 C:0x0804 7D96 MOV R5,#0x96 C:0x0806 DDFE DJNZ R5,C:0806 C:0x0808 DEFA DJNZ R6,C:0804 C:0x080A DFF6 DJNZ R7,C:0802 C:0x080C 22 RET

三. 10ms延时子程序

程序:

void delay10ms(void)

{

unsigned char i,j,k;

for(i=5;i>0;i--)

for(j=4;j>0;j--)

for(k=248;k>0;k--);

}

产生的汇编

C:0x0800 7F05 MOV R7,#0x05 C:0x0802 7E04 MOV R6,#0x04 C:0x0804 7DF8 MOV R5,#0xF8 C:0x0806 DDFE DJNZ R5,C:0806 C:0x0808 DEFA DJNZ R6,C:0804 C:0x080A DFF6 DJNZ R7,C:0802 C:0x080C 22 RET

四. 1s延时子程序

程序:

void delay1s(void)

{

unsigned char h,i,j,k;

for(h=5;h>0;h--)

for(i=4;i>0;i--)

for(j=116;j>0;j--)

for(k=214;k>0;k--);

}

产生的汇编

C:0x0800 7F05 MOV R7,#0x05

基于单片机的电子钟C语言程序

基于 5 1 单片机的电子钟 C 语言程序 #include #include #defineucharunsignedchar #defineuintunsignedint /* 七段共阴管显示定义*/ ucharcodedispcode[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F, 0xBF,0x86,0xCB,0xCF,0xEF,0xED,0xFD,0x87,0xFF,0xDF}; /* 定义并初始化变量*/ ucharseconde=0; ucharminite=0; ucharhour=12; ucharmstcnt=0; sbitP1_0=PM0;//seco nd 调整定义 sbitP1_ 仁P1A1;//mi nite 调整定义 sbitP1_2=P1A2;//hour 调整定义 /* 函数声明*/ voiddelay(uintk);// 延时子程序 voiddelay1(ucharh); voidtime_pro();// 时间处理子程序 voiddisplay();// 显示子程序 voidkeyscan();// 键盘扫描子程序 /*****************************/ /* 延时子程序*/ voiddelay1(ucharh) { ucharj; while((h--)!=0) { for(j=0;j<125;j++) {;} } } voiddelay(uintk) { uinta,b,c; for(c=k;c>0;c--) for(b=38;b>0;b--) for(a=130;a>0;a--); } /************************* /* 时间处理子程序*/ */ voidtime_pro(void) { if(seconde==60)// 秒钟设为60 进制 {seconde=0; minite++; if(minite==60)// 分钟设为60 进制 {minite=0; hour++;

C语言延时程序

C51精确延时程序 一、、看了网上延时程序的帖子挺多,我也说点。 用keil调试, void yanshi( uint n ) { uchar data i="0"; for(i=0;i<N;I++); return; } 延时时间=12*(n*12+17)/fosc 用keil测时功能很容易得到这个关系,很精确,偏差不过几us. 可以自己编一些延时程序,也可以很方便的得到关系式,只是系数不同. 二、、//我看到的地方也是从别的地方转贴,所以我不知道原作者是谁,但相信这么成熟的东西转一下他也不会见意。看到了个好帖,我在此在它得基础上再抛抛砖! 有个好帖,从精度考虑,它得研究结果是: void delay2(unsigned char i) { while(--i); } 为最佳方法。 分析:假设外挂12M(之后都是在这基础上讨论) 我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据: delay2(0):延时518us 518-2*256=6 delay2(1):延时7us(原帖写“5us”是错的,^_^) delay2(10):延时25us 25-20=5 delay2(20):延时45us 45-40=5 delay2(100):延时205us 205-200=5 delay2(200):延时405us 405-400=5 见上可得可调度为2us,而最大误差为6us。 精度是很高了! 但这个程序的最大延时是为518us 显然不 能满足实际需要,因为很多时候需要延迟比较长的时间。 那么,接下来讨论将t分配为两个字节,即uint型的时候,会出现什么情况。

模拟电子时钟c语言程序

算法:将当前时间显示到屏幕,当时间发生变化时,清屏,显示新的时间(当有键盘操作时退出程序)。 显示时间格式:小时:分钟:秒 /* DEV C++ Win XP*/ #include #include #include #include typedef struct { int x; int y; }Point; time_t now; struct tm *pt,t1,t2; int printpoint(Point p) { Point p1; p1.x=p.x+2; p1.y=p.y+4; gotoxy(p1.x,p1.y); printf("%c%c",2,2); gotoxy(p1.x, p1.y+1); printf("%c%c",2,2); p1.y+=4; gotoxy(p1.x,p1.y); printf("%c%c",2,2); gotoxy(p1.x,p1.y+1); printf("%c%c",2,2); return 0; } int print0(Point p) { int i=0; for(;i<13;i++) { gotoxy(p.x+1, p.y+i); if(i==0||i==12) printf("%c%c%c%c%c%c",2,2,2,2,2,2); else printf("%c%4s%c",2," ",2); } return 0; }

int print1(Point p) { int i=0; for(;i<13;i++) { gotoxy(p.x+1, p.y+i); printf("%5s%c"," ",2); } return 0; } int print2(Point p) { int i=0; for(;i<13;i++) { gotoxy(p.x+1, p.y+i); if(i==0||i==6||i==12) printf("%c%c%c%c%c%c",2,2,2,2,2,2); else if(i>0&&i<6) printf("%5s%c"," ",2); else printf("%c",2); } return 0; } int print3(Point p) { int i=0; for(;i<13;i++) { gotoxy(p.x+1, p.y+i); if(i==0||i==6||i==12) printf("%c%c%c%c%c%c",2,2,2,2,2,2); else printf("%5s%c"," ",2); } return 0; } int print4(Point p) {

基于51单片机的精确延时(微秒级)

声明: *此文章是基于51单片机的微秒级延时函数,采用12MHz晶振。 *此文章共包含4个方面,分别是延时1us,5us,10us和任意微秒。前三个方面是作者学习过程中从书本或网络上面总结的,并非本人所作。但是延时任意微秒函数乃作者原创且亲测无误。欢迎转载。 *此篇文章是作者为方便初学者使用而写的,水平有限,有误之处还望大家多多指正。 *作者:Qtel *2012.4.14 *QQ:97642651 ----------------------------------------------------------------------------------------------------------------------序: 对于某些对时间精度要求较高的程序,用c写延时显得有些力不从心,故需用到汇编程序。本人通过测试,总结了51的精确延时函数(在c语言中嵌入汇编)分享给大家。至于如何在c 中嵌入汇编大家可以去网上查查,这方面的资料很多,且很简单。以12MHz晶振为例,12MHz 晶振的机器周期为1us,所以,执行一条单周期指令所用时间就是1us,如NOP指令。下面具体阐述一下。 ----------------------------------------------------------------------------------------------------------------------1.若要延时1us,则可以调用_nop_();函数,此函数是一个c函数,其相当于一个NOP指令,使用时必须包含头文件“intrins.h”。例如: #include #include void main(void){ P1=0x0; _nop_();//延时1us P1=0xff; } ----------------------------------------------------------------------------------------------------------------------2.延时5us,则可以写一个delay_5us()函数: delay_5us(){ #pragma asm nop #pragma endasm } 这就是一个延时5us的函数,只需要在需要延时5us时调用此函数即可。或许有人会问,只有一个NOP指令,怎么是延时5us呢? 答案是:在调用此函数时,需要一个调用指令,此指令消耗2个周期(即2us);函数执行完毕时要返回主调函数,需要一个返回指令,此指令消耗2个周期(2us)。调用和返回消耗了2us+2us=4us。然后再加上一个NOP指令消耗1us,不就是5us吗。

STC12系列单片机C语言的延时程序

STC12系列单片机C语言的延时程序 本举例所用CPU 为STC12C5412 系列12 倍速的单片机,只要修改一下参数值其它系例单片机也通用,适用范围宽。共有三条延时函数说明如下:函数调用 分两级:一级是小于10US 的延时,二级是大于10US 的延时 //====================小于10US 的【用1US 级延时】 ====================//----------微秒级延时---------for(i=X;i>X;i--) 延时时间 =(3+5*X)/12 提示(单位us, X 不能大于255)//================大于10US0;Ms--)for(i=26;i>0;i--);}i=[(延时值-1.75)*12/Ms-15]/4 如想延时60US 则 i=[(60-1.75)*12/6-15]/4=25.375≈26; 修改i 的值=26,再调用上面的【10US 级延时函数】Delay10us(6); 则就精确延时60US;如果想延时64US 可以用这二种函数组合来用: Delay10us(6); for(i=9;i>X;i--) 共延时64US//============== 对于大于20Ms 的可用中断来实现程序运行比较好===============中断用定 时器0, 1Ms 中断:void timer0(void) interrupt 1{ TL0=(0xffff-1000+2)% 0x100;TH0=(0xffff-1000+2)/0x100; //每毫秒执行一次if(DelayMs_1>0) DelayMs_1--;//大于20Ms 延时程序}函数调用void DelayMs(uint a)//延时 a 乘以1(ms)的时间。{ DelayMs_1=a; while(DelayMs_1);}如果延时50Ms 则函数值为DelayMs(50)tips:感谢大家的阅读,本文由我司收集整编。仅供参阅!

基于c语言单片机电子时钟课程设计报告书

课程设计报告 课程名称:单片机程序设计 报告题目:电子时钟 学生: 所在学院:信息科学与工程学院专业班级: 学生学号: 指导教师:

2013年12月25日课程设计任务书

摘要 单片计算机即单片微型计算机。由RAM、ROM、CPU构成。定时,计数和多种接口于一体的微控制器。它体积小,成本低,功能强,广泛应用于智能产业和工业自动化上。而51系列单片机是各单片机中最为典型和最有代表性的一种。这次课程设计通过对它的学习,应用,从而达到学习、设计、开发软、硬的能力。 本设计主要设计了一个基于AT89C51单片机的电子时钟。并在数码管上显示相应的时间。并通过一个控制键用来实现时间的调节和是否进入省电模式的转换。应用Proteus的ISIS软件实现了单片机电子时钟系统的设计与仿真。该方法仿真效果真实、准确,节省了硬件资源。 关键词:单片机;子时钟;键控制

目录 一、概述 (5) 1.1电子时钟简介 (5) 1.2电子时钟的基本特点 (5) 1.3电子时钟的原理 (5) 二、方案设计选择 (5) 2.1计时方案 (5) 2.2显示方案 (5) 三、硬件设计 (6) 3.1单片机型号选择 (6) 3.2数码管显示工作原理 (6) 3.3键盘电路设计 (7) 3.4电路原理图 (7) 四、软件设计 (7) 五、结论与心得 (15) 六、参考文献 (16)

一、概述 1.1 电子时钟简介 1957年,Ventura发明了世界上第一个电子表,从而奠定了电子时钟的基础,电子时钟开始迅速发展起来。现代的电子时钟是基于单片机的一种计时工具,采用延时程序产生一定的时间中断用于一秒的定义,通过计数方式进行满六十秒分钟进一,满六十分小时进一,满二十四小时小时清零。从而达到计时的功能,是人民日常生活补课缺少的工具。 1.2 电子时钟的基本特点 现在高精度的计时工具大多数都使用了石英晶体振荡器,由于电子钟、石英钟、石英表都采用了石英技术,因此走时精度高,稳定性好,使用方便,不需要经常调试,数字式电子钟用集成电路计时时,译码代替机械式传动,用LED

单片机应用技术(c语言版 第3版)[王静霞]_习题答案

习题 1 1.1 单项选择题 (1) A (2)C (3)C 1.2 填空题 (1)硬件系统、软件系统 (2)时钟电路、复位电路 (3)XTAL1、XTAL2、RESET、EA (4)晶振 1.3 问答题 什么是单片机它由哪几部分组成什么是单片机应用系统 答:单片微型计算机(Single Chip Microcomputer)简称单片机,是指集成在一个芯片上的微型计算机,它的各种功能部件,包括CPU(Central Processing Unit)、存储器(memory)、基本输入/输出(Input/Output,简称I/O)接口电路、定时/计数器和中断系统等,都制作在一块集成芯片上,构成一个完整的微型计算机。 单片机应用系统是以单片机为核心,配以输入、输出、显示等外围接口电路和控制程序,能实现一种或多种功能的实用系统。 1.4 上机操作题 (1) 参考程序: #include //包含头文件reg51.h,定义了51单片机的专用寄存器 //函数名:delay //函数功能:实现软件延时 //形式参数:无符号整型变量i,控制空循环的循环次数 //返回值:无 void delay(unsigned int i) //延时函数 { unsigned int k; for(k=0;k //包含头文件reg51.h,定义了51单片机的专用寄存器 //函数名:delay

单片机一些常用的延时与中断问题及解决方法

延时与中断出错,是单片机新手在单片机开发应用过程中,经常会遇到的问题,本文汇总整理了包含了MCS-51系列单片机、MSP430单片机、C51单片机、8051F的单片机、avr单片机、STC89C52、PIC单片机…..在内的各种单片机常见的延时与中断问题及解决方法,希望对单片机新手们,有所帮助! 一、单片机延时问题20问 1、单片机延时程序的延时时间怎么算的? 答:如果用循环语句实现的循环,没法计算,但是可以通过软件仿真看到具体时间,但是一般精精确延时是没法用循环语句实现的。 如果想精确延时,一般需要用到定时器,延时时间与晶振有关系,单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。本程序中假设使用频率为12 MHz的晶振。最长的延时时间可达216=65 536 μs。若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。 2、求个单片机89S51 12M晶振用定时器延时10分钟,控制1个灯就可以 答:可以设50ms中断一次,定时初值,TH0=0x3c、TL0=0xb0。中断20次为1S,10分钟的话,需中断12000次。计12000次后,给一IO口一个低电平(如功率不够,可再加扩展),就可控制灯了。 而且还要看你用什么语言计算了,汇编延时准确,知道单片机工作周期和循环次数即可算出,但不具有可移植性,在不同种类单片机中,汇编不通用。用c的话,由于各种软件执行效率不一样,不会太准,通常用定时器做延时或做一个不准确的延时,延时短的话,在c中使用汇编的nop做延时 3、51单片机C语言for循环延时程序时间计算,设晶振12MHz,即一个机器周期是1us。for(i=0,i<100;i++) for(j=0,j<100;j++) 我觉得时间是100*100*1us=10ms,怎么会是100ms 答: 不可能的,是不是你的编译有错的啊 我改的晶振12M,在KEIL 4.0 里面编译的,为你得出的结果最大也就是40ms,这是软件的原因, 不可能出现100ms那么大的差距,是你的软件的原因。 不信你实际编写一个秒钟,利用原理计算编写一个烧进单片机和利用软件测试的秒程序烧进单片机,你会发现原理计算的程序是正确的

项目单片机应用技能实训C语言教案

单片机应用技能实训(C语言)教案—项目2 项目2 广告灯电路制作 任务1 MCS-51单片机I/O端口及C语言相关指令

二、教学实施过程 实 施 环 节 教学内容导 学 方 法组 织 教 学 1、检查学生出勤情况并做好记录。 2、调整学生的注意力,为上课作准备。 互 动 交 流复 习 提 问 1、MCS-51单片机由哪几部分组成 2、MCS-51单片机有多少个I/O口引脚 提 问 导 思导 入 夜晚的商业街上,各种各样的广告彩灯光彩夺目,变幻无穷,非常好看。那么功能强大的单片机是否能完成广告彩灯的控制任务呢本项目的任务就是制作一个用单片机控制的广告灯电路。为完成项目制作,先进行相关基本知识的学习。 启 发 学 习 积 极 性讲 授 新 课 一、MCS-51单片机并行接口 1、P0口的结构和工作原理 P0口每一位的结构如图2-2所示,它由一个输出锁存器,上下两个三态缓冲器,一个输出驱动电路和一个输出控制电路组成。 图2-2 P0口的结构 从P0口输出数据的方法有两种,一种是执行以P0口为目的操作数的数据传送指令来实现,另一种是执行以P0口位为目的操作数的位操作指令来实现。分别举例如下: P0=0x66; 12 fsoc 1 ?12 10 6 1 6 ? ? sμ

1、

89C1’ex),默认情况下该项未被选中,如果要写片做硬件实验,就必须选中该项,这一点是初学者易疏忽的,在此特别提醒注意。 4、编译、连接 在设置好工程后,即可进行编译、连接。点击Build target 按钮,对当前工程进行连接,如果当前文件已修改,软件会先对该文件进行编译,然后再连接以产生目标代码。 编译过程中的信息将出现在输出窗口中的Build页中,如果源程序中有语法错误,会有错误报告出现。 三、布置作业学生练习,老师指导。 1、单片机控制广告灯电路的仿真验证。 2、观察现实中广告灯的变化情况,通过改写程序,完成不同的灯光效果。比一比,看谁制作的变化效果又多又好。 3、本项目中采用低电平驱动,是否能采用高电平驱动,试一试,想想为什么利用多媒体或机房相关软件进行操作演示。讲解各步骤的含义。 讲解各步骤的含义。完成程序编译后,展示仿真效果。 课堂小结1、proteus的基本操作步骤。 2、keil的操作步骤。

51单片机延时时间计算和延时程序设计

一、关于单片机周期的几个概念 ●时钟周期 时钟周期也称为振荡周期,定义为时钟脉冲的倒数(可以这样来理解,时钟周期就是单片机外接晶振的倒数,例如12MHz的晶振,它的时间周期就是1/12 us),是计算机中最基本的、最小的时间单位。 在一个时钟周期内,CPU仅完成一个最基本的动作。 ●机器周期 完成一个基本操作所需要的时间称为机器周期。 以51为例,晶振12M,时钟周期(晶振周期)就是(1/12)μs,一个机器周期包 执行一条指令所需要的时间,一般由若干个机器周期组成。指令不同,所需的机器周期也不同。 对于一些简单的的单字节指令,在取指令周期中,指令取出到指令寄存器后,立即译码执行,不再需要其它的机器周期。对于一些比较复杂的指令,例如转移指令、乘法指令,则需要两个或者两个以上的机器周期。 1.指令含义 DJNZ:减1条件转移指令 这是一组把减1与条件转移两种功能结合在一起的指令,共2条。 DJNZ Rn,rel ;Rn←(Rn)-1 ;若(Rn)=0,则PC←(PC)+2 ;顺序执行 ;若(Rn)≠0,则PC←(PC)+2+rel,转移到rel所在位置DJNZ direct,rel ;direct←(direct)-1 ;若(direct)= 0,则PC←(PC)+3;顺序执行 ;若(direct)≠0,则PC←(PC)+3+rel,转移到rel 所在位置 2.DJNZ Rn,rel指令详解 例:

MOV R7,#5 DEL:DJNZ R7,DEL; rel在本例中指标号DEL 1.单层循环 由上例可知,当Rn赋值为几,循环就执行几次,上例执行5次,因此本例执行的机器周期个数=1(MOV R7,#5)+2(DJNZ R7,DEL)×5=11,以12MHz的晶振为例,执行时间(延时时间)=机器周期个数×1μs=11μs,当设定立即数为0时,循环程序最多执行256次,即延时时间最多256μs。 2.双层循环 1)格式: DELL:MOV R7,#bb DELL1:MOV R6,#aa DELL2:DJNZ R6,DELL2; rel在本句中指标号DELL2 DJNZ R7,DELL1; rel在本句中指标号DELL1 注意:循环的格式,写错很容易变成死循环,格式中的Rn和标号可随意指定。 2)执行过程

用C语言实现精确的延时

怎么用C语言做单片机的精确延时在单片机应用中,经常会遇到需要短时间延时的情况,一般都是几十到几百μs,并且需要很高的精度(比如用单片机驱动DS18B20时,误差容许的范围在十几μs以内,不然很容易出错);而某些情况下延时时间较长,用计时器往往有点小题大做。另外在特殊情况下,计时器甚至已经全部用于其他方面的定时处理,此时就只能使用软件定时了[1]。 1C语言程序延时 Keil C51的编程语言常用的有2种:一种是汇编语言;另一种是C语言。用汇编语言写单片机程序时,精确时间延时是相对容易解决的。比如,用的是晶振频率为12MHz 的AT89C51,打算延时20μs,51单片机的指令周期是晶振频率的1/12,即一个机器周期为1μs;“MOV R0,#X”需要2个机器周期,DJNZ也需要2个机器周期,单循环延时时间t=2X+3(X为装入寄存器R0的时间常数)[2]。这样,存入R0里的数初始化为8即可,其精度可以达到1μs。用这种方法,可以非常方便地实现512μs以下时间的延时。如果需要更长时间,可以使用两层或更多层的嵌套,当然其精度误差会随着嵌套层的增加而成倍增加。 虽然汇编语言的机器代码生成效率很高,但可读性却并不强,复杂一点的程序就更难读懂;而C语言在大多数情况下,其机器代码生成效率和汇编语言相当,但可读性和可移植性却远远超过汇编语言,且C语言还可以嵌入汇编程序来解决高时效性的代码编写问题。就开发周期而言,中大型软件的编写使用C语言的开发周期通常要比汇编语言短很多,因此研究C语言程序的精确延时性能具有重要的意义。 C程序中可使用不同类型的变量来进行延时设计。经实验测试,使用unsigned char类型具有比unsigned int更优化的代码,在使用时应该使用unsigned char作为延时变量。 2单层循环延时精度分析 下面是进行μs级延时的while程序代码。 延时函数: void delay1(unsigned char i){ while(i);} 主函数: void main(){ while(1){ delay1(i); } } 使用Keil C51的反汇编功能,延时函数的汇编代码如下: C:0x00E6AE07MOVR6,0x07 C:0x00E81FDECR7 C:0x00E9EEMOVA,R6 C:0x00EA70FAJNZC:00E6 C:0x00EC22RET 图1断点设置位置图 通过对i赋值为10,在主程序中图1所示的位置设置断点。经过测试,第1次执行到断点处的时间为457μs,再次执行到该处的时间为531μs,第3次执行到断点处的时间为605μs,10次while循环的时间为74μs,整个测试结果如图2所示。 图2使用i--方式测试仿真结果图 通过对汇编代码分析,时间延迟t=7X+4(其中X为i的取值)。测试表明,for循环方式虽然生成的代码与用while语句不大一样,但是这两种方法的效率几乎相同。C语言中的自减方式有两种,前面都使用的是i--的方式,能不能使用--i方式来获得不同的效果呢?将前面的主函数保持不变,delay1函数修改为下面的方式:void delay1(unsigned char i){ while(--i);} 同样进行反汇编,得到如下结果: C:0x00E3DFFEDJNZR7, C:00E3C:0x00E522RET 比较发现,--i的汇编代码效率明显高于i--方式。由于只有1条语句DJNZ,执行只需要2个时钟周期,1个时钟周期按1μs计算,其延时精度为2μs;另外,RET

51单片机精确延时源程序

51单片机精确延时源程序 一、晶振为 11.0592MHz,12T 1、延时 1ms: (1)汇编语言: 代码如下: DELAY1MS: ;误差 -0.651041666667us MOV R6,#04H DL0: MOV R5,#71H DJNZ R5,$ DJNZ R6,DL0 RET (2)C语言: void delay1ms(void) //误差 -0.651041666667us { unsigned char a,b; for(b=4;b>0;b--) for(a=113;a>0;a--); } 2、延时 10MS: (1)汇编语言: DELAY10MS: ;误差 -0.000000000002us MOV R6,#97H DL0: MOV R5,#1DH DJNZ R5,$ DJNZ R6,DL0

RET (2)C语言: void delay10ms(void) //误差 -0.000000000002us { unsigned char a,b; for(b=151;b>0;b--) for(a=29;a>0;a--); } 3、延时 100MS: (1)汇编语言: DELAY100MS: ;误差 -0.000000000021us MOV R7,#23H DL1: MOV R6,#0AH I

棋影淘宝店:https://www.doczj.com/doc/ec15406466.html,QQ:149034219 DL0: MOV R5,#82H DJNZ R5,$ DJNZ R6,DL0 DJNZ R7,DL1 RET (2)C语言: void delay100ms(void) //误差 -0.000000000021us { unsigned char a,b,c; for(c=35;c>0;c--) for(b=10;b>0;b--) for(a=130;a>0;a--); } 4、延时 1S: (1)汇编语言: DELAY1S: ;误差 -0.00000000024us MOV R7,#5FH DL1: MOV R6,#1AH DL0: MOV R5,#0B9H DJNZ R5,$ DJNZ R6,DL0 DJNZ R7,DL1 RET (2)C语言: void delay1s(void) //误差 -0.00000000024us { unsigned char a,b,c; for(c=95;c>0;c--) for(b=26;b>0;b--)

单片机c语言中nop函数的使用方法和延时计算

单片机c语言中nop函数的使用方法和延时计算 标准的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指令来完成,相当于如下指令: MOV09H,#0FFH LOOP:DJNZ09H,LOOP 指令相当简洁,也很好计算精确的延时时间。 同样对do…while,while循环语句中,也是如此 例: unsigned char n; n=255; do{n--}

电子钟显示时分秒c语言程序

/*电子钟显示时分秒*/ #include sbit INCH=P3^2; //小时加1 sbit INCM=P3^3; //分钟加1 #define LCDP P0 // 定义LCM 接至P0 sbit RS = P2^7; // 暂存器选择位元(0:指令,1:资料) sbit RW = P2^6; // 设定读写位元(0:写入,1:读取) sbit E = P2^5; // 致能位元(0:禁能,1:致能) sbit BF = P0^7; // 忙碌检查位元(0:不忙,1:忙碌) char count=20; // 中断次数计数,20次*50ms=1秒 char time0[]="CLOCK"; // 显示时间阵列(第1行) char time[11]; // 显示时间阵列(第2行) bit ampm=1; // 0:上午(am),1:下午(pm),初值下午 char hour=11; // 声明时,初值为11点 char minute=59; // 声明分,初值为59分 char second=50; // 声明秒,初值为50秒 void transfer(void); // 转换时分秒至time阵列中 void write_inst(char); // 写入指令函数 void write_char(char); // 写入字元函数 void write_pat(void); // 写入自建字型函数 void check_BF(void); // 检查忙碌函数 void init_LCM(void); // 声明LCM初始设定函数 void delay(int); //去抖函数 main() { char i; init_LCM(); // 初始设定 IE=0X87; // T0、INT0、INT1中断使能TMOD=0x01; // T0设为MODE1 TH0=(56636-50000) / 256; // 填入计时量之高位元组 TL0=(56636-50000) % 256; // 填入计时量之低位元组 TR0=1; // 启动Timer 0 write_inst(0x85); // 指定第1列位置 for (i=0;i<5;i++) write_char(time0[i]); //显示CLOCK while(1) { transfer(); // 转换时分秒至time阵列中write_inst(0xC0); // 指定第2列位置 for (i=0;i<11;i++) write_char(time[i]);// 显示时间 } } //转换函数 void transfer(void)

最新项目9单片机应用技能实训(C语言)教案教学内容

单片机应用技能实训(C语言)教案—项目9 项目9 点阵LED屏显示电路制作 任务1 项目相关知识学习

二、教学实施过程 实施环节教学内容导学方法组织教学1、检查学生出勤情况并做好记录。 2、调整学生的注意力,为上课作准备。 互动交流 复习提问1、项目8中数码管的显示方式是动态显示还是静态显示? 2、以同学们的理解,LED屏是什么? 本项目的终极目标是制作一个单片机控制的LED屏显示电路。 提问导思 导入在项目6和项目8中,用数码管来显示数字,也可以用来显示一些字符,但是,显示字符时有一定局限性,所以,当要显示一 些英文字符时,考虑用LED屏。在进行项目制作之前,学习LED 屏的相关知识。启发学习积极性 讲授新课一、LED点阵显示模块的结构、工作原理及显示方式 1、LED点阵显示模块结构及工作原理 LED点阵显示模块是一种能显示图形、字符和汉字的显示器件。一个LED点阵显示模块一般由8×8个LED发光二极管方阵组成,其外形如图9-2所示。8×8LED点阵显示模块原理结构如图9-3所示。我们可以把每一个LED发光点理解为一个像素,8×8点阵显示屏可以显示在64像素范围内的任何图形。 图9-3 图9-2 2、LED点阵显示模块的显示方式 LED点阵显示模块的显示方法必须采用动态扫描方式,一般采用逐行扫描。以图9-3所示为例,一幅图形的每行由一个8位二进制数据构成,将这些数据称为显示数据点阵码。比如显示字符“O”的点阵码为:3CH、42H、42H、42H、42H、42H、42H、3CH(如图9-4所示)。一般显示汉字采用的是16×16的点阵模式或者更多,但是原理是相同的。用多媒体展示图9-2、图9-3。对照图9-3介绍其工作原理。 细致说明点阵码的含义。

51单片机延时模块程序

51单片机独立模块 一、延时模块 1、for循环延时 void delayms(UINT8 ms) { UINT8 x,y; for(x=ms;x>0;x--) for(y=112;y>0;y--); } 2、while循环延时 void delayms(UINT8 ms) { UINT8 x; while(ms--) for(x=112;x>0;x--); } 3、精确的单片机常用延时函数:(c代码误差0us 12M)(1)、延时0.5ms void delay0.5ms(void) //误差 0us { unsigned char a,b; for(b=71;b>0;b--) for(a=2;a>0;a--); } (2)、延时1ms void delay1ms(void) //误差 0us { unsigned char a,b,c; for(c=1;c>0;c--) for(b=142;b>0;b--) for(a=2;a>0;a--); } (3)、延时2ms void delay2ms(void) //误差 0us { unsigned char a,b; for(b=4;b>0;b--) for(a=248;a>0;a--); _nop_; //if Keil,require use intrins.h } (4)、延时3ms void delay3ms(void) //误差 0us

{ unsigned char a,b; for(b=111;b>0;b--) for(a=12;a>0;a--); } (5)、延时4ms void delay4ms(void) //误差 0us { unsigned char a,b,c; for(c=7;c>0;c--) for(b=8;b>0;b--) for(a=34;a>0;a--); } (6)、延时5ms void delay5ms(void) //误差 0us { unsigned char a,b; for(b=19;b>0;b--) for(a=130;a>0;a--); } (7)、延时10ms void delay10ms(void) //误差 0us { unsigned char a,b,c; for(c=1;c>0;c--) for(b=38;b>0;b--) for(a=130;a>0;a--); } (8)、延时15ms void delay15ms(void) //误差 0us { unsigned char a,b,c; for(c=1;c>0;c--) for(b=238;b>0;b--) for(a=30;a>0;a--); } (9)、延时20ms void delay20ms(void) //误差 0us { unsigned char a,b; for(b=215;b>0;b--) for(a=45;a>0;a--); _nop_; //if Keil,require use intrins.h

单片机应用技术(C语言)试题

一、选择题 1、单片机8031的/EA引脚(C)。 A. 可悬空 B. 必须接+5V电源 C. 必须接地 D. 以上三种情况视需要而定 2、MCS-51单片机的4个并行I/O端口作为通用I/O端口使用,在输出数据时,必须外接上拉电阻的是(A)。 A. P0口 B. P1口 C. P2口 D. P3口 3、当MCS-51单片机应用系统需要扩展外部存储器或其它接口芯片时,(A)可作为低8位地址总线使用。 A. P0口 B. P1口 C. P2口 D. P0口和P2口 4、系统复位后,堆栈指针SP的内容是(B)。 A. 08H B. 07H C. 30H D. 50H 5、MCS-51单片机的位寻址区位于内部RAM的( D )单元。 A. 00H~7FH B. 20H~7FH C. 00H~1FH D. 20H~2FH 6、PSW中的RS1和RS0用来(A)。 A. 选择工作寄存器组 B. 指示复位 C. 选择定时器 D. 选择工作方式 7、MCS-51单片机规定一个机器周期共有(A)个节拍。 A. 12 B. 6 C. 8 D. 16 8、下面叙述不正确的是(C)。 A. 一个C源程序可以由一个或多个函数组成 B. 一个C源程序必须包含一个函数main() C. 在C51中,注释说明只能使用/*……*/注释 D. C程序的基本组成单位是函数 9、在C51程序中常常把(D)作为循环体,用于消耗CPU时间,产生延时效果。 A. 赋值语句 B. 表达式语句 C. 循环语句 D. 空语句 10、在单片机应用系统中,LED数码管显示电路通常有(C )显示方式。 A. 静态 B. 动态 C. 静态和动态 D. 查询 11、共阳极LED数码管加反向器驱动时显示字符“6”的段码是(B)。 A. 06H B. 7DH C. 82H D. FAH 12、LED数码管若采用动态显示方式,下列说法错误的是(C)。 A. 将各位数码管的段选线并联 B. 将段选线用一个8位I/O端口控制 C. 将各位数码管的公共端直接连接在+5V或者GND上 D. 将各位数码管的位选线用各自独立的I/O端口控制 13、按键开关的结构通常是机械弹性元件,在按键按下和断开时,触点在闭合和断开瞬间会产生接触不稳定,为消除抖动引起的不良后果,常采用的方法有(C)。 A. 硬件去抖动 B. 软件去抖动 C. 硬、软件两种方法 D. 单稳态电路去抖方法

单片机一些常用的延时与中断问题及解决方法

单片机一些常用的延时与中断问题及解决方法 延时与中断出错,是单片机新手在单片机开发应用过程中,经常会遇到的问题,本文汇总整理了包含了MCS-51系列单片机、MSP430单片机、C51单片机、8051F的单片机、avr单片机、STC89C52、PIC单片机…..在内的各种单片机常见的延时与中断问题及解决方法,希望对单片机新手们,有所帮助! 一、单片机延时问题20问 1、单片机延时程序的延时时间怎么算的? 答:如果用循环语句实现的循环,没法计算,但是可以通过软件仿真看到具体时间,但是一般精精确延时是没法用循环语句实现的。 如果想精确延时,一般需要用到定时器,延时时间与晶振有关系,单片机系统一般常选用 2 MHz、12 MHz或6 MHz晶振。第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。本程序中假设使用频率为12 MHz的晶振。最长的延时时间可达216=65 536 μs。若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。 2、求个单片机89S51 12M晶振用定时器延时10分钟,控制1个灯就可以 答:可以设50ms中断一次,定时初值,TH0=0x3c、TL0=0xb0。中断20次为1S,10分钟的话,需中断12000次。计12000次后,给一IO口一个低电平(如功率不够,可再加扩展),就可控制灯了。 而且还要看你用什么语言计算了,汇编延时准确,知道单片机工作周期和循环次数即可算出,但不具有可移植性,在不同种类单片机中,汇编不通用。用c的话,由于各种软件执行效率不一样,不会太准,通常用定时器做延时或做一个不准确的延时,延时短的话,在c中使用汇编的nop做延时 3、51单片机C语言for循环延时程序时间计算,设晶振12MHz,即一个机器周期是1us。for(i=0,i<100;i++) for(j=0,j<100;j++) 我觉得时间是100*100*1us=10ms,怎么会是100ms 答: 不可能的,是不是你的编译有错的啊 我改的晶振12M,在KEIL 里面编译的,为你得出的结果最大也就是40ms,这是软件的原因, 不可能出现100ms那么大的差距,是你的软件的原因。 不信你实际编写一个秒钟,利用原理计算编写一个烧进单片机和利用软件测试的秒程序烧进单片机,你会发现原理计算的程序是正确的 4 、51单片机c语言 _nop_()是一个空指令短时间延时的空几个机器周期?

相关主题
文本预览
相关文档 最新文档