单片机延时1ms程序
51单片机常见程序,附带注释

51 单片机常见程序附带注释三位数分离成 3 个一位数,截取bai=num/100;// 输出百位数shi=num%100/10;// 输出十位数ge=num/10;// 输出个位数//跑马灯程序。
当时间约为20ms形成动态扫描,#include<intrins.h>#define uint unsigned int // 无符号整型,占16 位数,表示围0~65536#define uchar unsigned char // 无符号字符型占八位数,表示围0~255void delayms(uint);uchar aa;// 定义变量void main(){aa=0xfe;while(1){aa=_crol_(aa, 1);P2=aa; // 控制单片机接口p2, 循环亮delayms(500); 灯一直亮灭,原因是视觉延迟// 当500 换成5,看起来全亮,实际上#include<reg52.h> 看上去全亮。
void delayms(uint xms) // 子程序,延时,通过数数uint i, j; for(i=xms;i>0;i--) for(j=110;j>0;j--);#include<reg52.h> // 跑马灯程序。
现在时间较长,多以是亮灭的流动,当时间约为20ms形成动态扫描,看上去全亮。
#include<intrins.h>#define uint unsigned int #define uchar unsigned char void delayms(uint);uchar aa;void main(){aa=0xfe;while(1){P2=aa; delayms(500); 灯一直亮灭,原因是视觉延迟// 无符号整型,占16 位数,表示围0~65536 // 无符号字符型占八位数,表示围0~255// 定义变量// 控制单片机接口p2, 循环亮// 当500 换成5,看起来全亮,实际上aa=_crol_(aa, 1); }}void delayms(uint xms) // 子程序,延时,通过数数 {uint i, j; for(i=xms;i>0;i--) for(j=110;j>0;j--);}#include <reg52.h> //52 系列单片机头文件 (目标:用单片机和两个共阴极数码 管:使用单片机的引脚 1和 2,控制两个数码管静态显示 00到59) #define uchar unsigned char #define uint unsigned int sbit dula1=P1A7;uchar num,num1; // 共阴极数码管 0123456789abcdef0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; void delayms(uint) ; void main (){while(1){for(num1=0;num1<=5;num1++)// 申明 U1 锁存器锁存端 段选 sbit dula2=P0A7;// 申明 U1 锁存器锁存端段选uchar code table[]={{for(num=0;num<=9;num++){dula2=1; // 打开U1 锁存端P1=table[num]; // 送入位选信号器dula2=0; // 关闭U1 锁存500 毫秒约0.3sdelayms(100); // 延时dula1=1; // 打开U1 锁存端P2=table[num1]; // 送入位选信号器dula1=0;// 关闭U1 锁存500 毫秒约0.3s}delayms(100); // 延时}}}void delayms (uint xms){uint x, y ;dula1=0;// 关闭 U1 锁存器for (y=200;y>0;y--);}#include <reg52.h> //52 系列单片机头文件 (目标:用单片机和两个共阴极数码 管)#define uchar unsigned char #define uint unsigned int sbit dula1=P1A7; sbit dula2=P2A7; uchar num,num1; uchar code table[]={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; void delayms(uint) ; void main (){while(1){for(num1=0;num1<=9;num1++){dula1=1; //打开U1锁存端P1=table[num1]; // 送入位选信号for (x=xms;x>0;x--) //x=xms 即延时约为 xms 毫秒// 申明 U1 锁存器锁存端 段选 // 申明 U1 锁存器锁存端段选// 共阴极数码管 0123456789abcdefdelayms(1000);// 延时 500 毫秒约0xc0,0xf9,0xa4, 0xb0,// 共阳极数字: 0123456789abcdefg0.3s for(num=0;num<=9;num++)dula2=1; // 打开 U1 锁存端P1=table[num]; // 送入位选信号 dula2=0;// 关闭 U1 锁存器 500 毫秒约 0.3s }} } void delayms (uint xms) { uint x, y ; for (x=xms;x>0;x--) delayms(1000);// 延时//x=xms 即延时约为 xms 毫秒for (y=200;y>0;y--); 有语法错误 #include <reg52.h> //52 系列单片机头文件 #define uchar unsigned char // 无符号字符型占八位数,表示围 0~255 #define uint unsigned int //无符号整型 占 16 位数,表示围 sbit dula1=P1A 6; //申明U1锁存器锁存端 段选 sbit dula2=P0A7; //申明U1锁存器锁存端段选uchar code table[]={0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e};void delayms(uint) ;void display(uchar,uchar) ;uchar num,num2,shi,ge;void main (){TMOD=Ox11;〃设置定时器0和1为工作方式1 (M1M0为01, 0001 00THO= (65535-50000)/256;// 装初值12.00M 晶振定时50s 数为50000 TL0= (65535-50000)%256;TH1= (65535-50000)/256;// 装初值12.00M 晶振定时50s 数为50000 TL1= (65535-50000)%256;EA=1;// 开总中断ET0=1; // 开定时器0 中断ET1=1; // 开定时器 1 中断TR0=1;// 启动定时器0TR1=1;// 启动定时器 1while(1)// 程序停止在这里不停的对数码管动态扫描同时等待中断的发生display(shi,ge);dula2=1; // 打开U1 锁存端P1=table[shi]; // 送入位选信号dula2=0; // 关闭U1 锁存器delayms(1175); // 延时0.1 毫秒void delayms(uint xms) // 延时子程序{uint i,j;for (i=xms;i>0;i--)//i=xms 即延时约为xms 毫秒for (j=110;j>0;j--); }void T1_time()interrupt 1{TH1= (65536-50000)/256; // 重装初值TL1= (65536-50000)%256;num2++; //num 每加 1 次判断一次是否到20 次if(num2==20){num2=0; // 然后把num2 清0 重新再计数20 次num++;if (num==60) // 这个数用来送数码管显示,到60 后归0num=0;shi=num/10; // 把一个 2 位数分离后分别送数码管显示,十位数ge=num%10; // 个位数#include <reg52.h> //52 系列单片机头文件 (目标:控制时间24 小时一循环) #define uchar unsigned char#define uint unsigned intsbit dula1=P1A7; //申明U1锁存器锁存端段选sbit dula2=P0A7; //申明U1锁存器锁存端段选uchar num,num1,num2,num3,num4;uchar code table[]={0xc0,0xf9,0xa4, 0xb0, // 共阳极数字:0123456789abcdefg0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e};void delayms(uint) ;void main (){while(1){for(num3=0;num3<=23;num3++) // 每天24 小时进位一{for(num2=0;num2<=59;num2++)// 每60 分进位一{for(num1=0;num1<=5;num1++) //每6*10s 进位一{dula2=1; // 打开U1 锁存端P1=table[num1]; // 送入位选信号dula2=0; // 关闭U1 锁存0.1 毫秒// 每1s 进位一打开U1锁存端// 送入位选信号// 关闭U1 锁存器// 延时0.1 毫秒}}}}}void delayms (uint xms){uint x, y ;for (x=xms;x>0;x--)for (y=110;y>0;y--); }delayms(1175); //for(num=0;num<=9;num++){dula2=1;P1=table[num];dula2=0;delayms(1000);}//x=xms 即延时约为xms 毫秒延时//#include <reg52.h> //52 系列单片机头文件 (目标:控制时间 24 小时一循环,蜂鸣器每过一段时间响一次)#define uchar unsigned char #define uint unsigned int sbit dula1=P1A7; sbit dula2=P2A7; sbit f=P0;// 声明单片机 P0 口的第一位 ,也就是三极管基级的位置单片机第 39 接口uchar num,num1,num2,num3,num4; uchar code table[]={ 0xc0,0xf9,0xa4, 0xb0,// 共阳极数字: 0123456789abcdefg0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,// 申明 U1 锁存器锁存端// 申明 U1 锁存器锁存段选 段选0xcd,0xa1,0x86,0x8e}; void delayms(uint) ; void main (){while(1)f=0; // 控制蜂鸣器的不响 每 1ms 进位一for(num=0;num<=9;num++)//{锁存端dula2=1;// 打开 U1选信号P2=table[num];// 送入位U1锁存器dula2=0;// 关闭// 延时 0.1 毫秒delayms(1074);}// 控制蜂鸣器的响delayms(1000); }}}{进位一for(num2=0;num2<=59;num2++){for(num4=0;num2<=59;num4++)// 每 60 分// 每 60s 进位一{for(num3=0;num3<=23;num3++) // 每天进位一f=1;void delayms (uint xms){uint x, y ;for (x=xms;x>0;x--) //x=xms 即延时约为xms 毫秒for (y=10;y>0;y--);}#include <reg52.h> //52 系列单片机头文件(目标:用单片机和两个共阳极数码管,控制依次显示0到59,然后循环,有合适的时间间隔,程序停止)#define uchar unsigned char#define uint unsigned intsbit dula1=P1A7; // 申明U1 锁存器锁存端段选sbit dula2=P2A7; // 申明U1 锁存器锁存端段选uchar num,num1;uchar code table[]={0xc0,0xf9,0xa4, 0xb0,// 共阳极数字:0123456789abcdefg0x99,0x92,0x82,0xf8,}void delayms (uint xms)uint x, y ;0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e}; void delayms(uint) ; void main (){while(1)for(num1=0;num1<6;num1++){dula1=1; P1=table[num1]; dula1=0;delayms(100);// 打开 U1 锁存端 // 送入位选信号 // 关闭 U1 锁存器// 延时 500 毫秒约0.3s器500 毫秒约 0.3s for(num=0;num<=9;num++){dula2=1; P2=table[num]; dula2=0;delayms(100);// 打开 U1 锁存端 // 送入位选信号 // 关闭 U1 锁存// 延时dula1=0; // 关闭 U1 锁存器uchar num,num1; uchar code table[]={0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e};void delayms(uint) ; void main ()while(1){for(num=0;num1<6;num1++){dula1=1;//打开U1锁存端P1=table[num1]; // 送入位选信号for (x=xms;x>0;x--)//x=xms 即延时约为 xms 毫秒for (y=200;y>0;y--);}#include <reg52.h> //52 管,控制依次显示 0到 59, 系列单片机头文件 (目标:用单片机和两个共阳极数码 时间间隔约 0.5, 程序停止) #define uchar unsigned char #define uint unsigned int sbit dula1=P1A7; // 申明 U1 锁存器锁存端 段选 sbit dula2=P2A7;// 申明 U1 锁存器锁存端段选0xc0,0xf9,0xa4, 0xb0, // 共阳极数字: 0123456789abcdefgdelayms(100); // 延时500 毫秒约0.3sfor(num=0;num<=9;num++){dula2=1; // 打开U1 锁存端P2=table[num]; // 送入位选信号器dula2=0; // 关闭U1 锁存500 毫秒约0.3sdelayms(100);// 延时}}}}void delayms (uint xms)//延时子程序{uint x, y ;for (x=xms;x>0;x--) //x=xms 即延时约为xms毫秒for (y=300;y>0;y--);0.3sfor(num=0;num<=9;num++){dula2=1; //打开U2锁存端 P2=table[num];// 送入位选信号#include <reg52.h> //52 系列单片机头文件 (目标:用单片机和两个共阳极数码 管,控制依次显示 0到 59,时间间隔约 0.5, 程序停止) #define uchar unsigned char #define uint unsigned intsbit dula1=P1A7; sbit dula2=P2A7; // 申明 U1 锁存器锁存端段选 段选uchar num,num1; uchar code table[]={ 0xc0,0xf9,0xa4, 0xb0, // 共阳极数字: 0123456789abcdefg0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e}; voiddelayms(uint) ; void main ()while(1){for(num=0;num1<6;num1++) {dula1=1; P1=table[num1]; dula1=0; delayms(100);// 打开 U1 锁存端 // 送入位选信号 // 关闭 U1 锁存器// 延时 500 毫秒约#include <reg52.h> //52 系列单片机头文件 (目标:用单片机和共阳极数码管, 控制依次显示 0到 9,时间间隔约 0.5s ;)#define uchar unsigned char #define uint unsigned int500 毫秒约 0.3sdelayms(100);// 延时}}}}void delayms (uint xms){uint x, y ;for (x=xms;x>0;x--)〃x=xms 即延时约为xms 毫秒for (y=300;y>0;y--);器// 关闭 U1 锁存}dula2=0;sbit dula1=P1A7;// 申明 U1 锁存器锁存端 段选// 打开 U1 锁存端 // 送入位选信号 // 关闭 U1 锁存器// 延时 500 毫秒约 0.3//打开U2锁存端 // 送入位选信号//关闭U2锁存器// 延时 500 毫秒约 0.3sbit dula2=P2A7; // 申明 U2 锁存器锁存端 段选uchar num; uchar codetable[]={ 0xc0,0xf9,0x a4, 0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83, 0xcd,0xa1,0x86,0x8e}; void delayms(uint) ; void main (){while(1)// 共阳极数字: 0123456789abcdefgfor(num=0;num<10;num++){dula1=1; P1=table[num]; dula1=0; delayms(100);dula2=1; P2=table[num]; dula2=0; delayms(100);void delayms (uint xms) {uint x, y ;for (x=xms;x>0;x--)//x=xms 即延时约为xms 毫秒for (y=300;y>0;y--);}#include <reg52.h> //52 系列单片机头文件(目标:用定时器0 的方式 1 实现第一个灯管以200ms闪烁;用定时器1的方式1实现数码管前两位59s循环计时)#define uchar unsigned char // 无符号字符型占八位数,表示围0~255#define uint unsigned int // 无符号整型,占16 位数,表示围sbit dula=P2A6; //申明U1锁存器锁存端段选sbit wela=P2A7; //申明U2锁存器锁存位选sbit led1=P1A0; // 申明灯 1 点0uchar code table[]={ // 共阴极数码管0123456789abcdef0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; void delayms(uint) ; voiddisplay(uchar,uchar) ; uchar num,num1,num2,shi,ge; void main (){TMOD=0x01;〃设置定时器0和1为工作方式1 (M1M0为01, 0001 00THO= (65535-50000)/256;// 装初值12.00M 晶振定时50s 数为50000 TL0= (65535-50000)%256; TH1= (65535-50000)/256;// 装初值12.00M 晶振定时50s 数为50000 TL1= (65535-50000)%256; EA=1;// 开总中断ET0=1; // 开定时器0 中断ET1=1; // 开定时器 1 中断TR0=1;// 启动定时器 0TR1=1;// 启动定时器 1while(1)//程序停止在这里不停的对数码管动态扫描同时等待中断的发生 {display(shi,ge);}}void display (uchar shi,uchar ge) // 控制数码管{ dula=1;// 打开 U1 锁存端 段选 P0=table[shi];//送入段选信号 dula=0;// 关闭 U1 锁存器 P0=0xff;// 送位选数据前关闭所有显示,防止打开位选锁存器时 wela=1;// 原来的段选数据通过位选锁存器造成混乱 P0=0xfe;// 送位选数据 wela=0;delayms(5); // 延时dula=1; // 打开 U1 锁存端 段选P0=table[ge]; // 送入段选信号dula=0;// 关闭 U1 锁存器 P0=0xff;// 送位选数据前关闭所有显示,防止打开位选锁存器时 wela=1; // 原来的段选数据通过位选锁存器造成混乱P0=0xfe; // 送位选数据wela=0;delayms(5); // 延时} void delayms(uint xms) // 延时子程序{uint i,j;for (i=xms;i>0;i--) //i=xms 即延时约为 xms 毫秒for (j=110;j>0;j--);} void T0_time()interrupt 1{TH0= (65536-50000)/256; TL0= (65536-50000)%256;num++;//num1 每加 1次判断一次是否到 4次 ,时间间隔200ms // 重装初值if(num1==4)num1=0; // 然后把num1 清0 重新再计数 4 次led1=~led1; // 让发光管状态取反}} void T1_time()interrupt 3{TH1= (65536-50000)/256; // 重装初值TL1= (65536-50000)%256;num2++; //num 每加 1 次判断一次是否到20 次if(num2==20){num2=0; // 然后把num2 清0 重新再计数20 次num++;if (num==60) // 这个数用来送数码管显示,到60 后归0num=0;shi=num/10; // 把一个 2 位数分离后分别送数码管显示,十位数ge=num%10; // 个位数// 共阴极数码管 0123456789abcdef0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delayms(uint) ;void display(uchar,uchar) ;uchar num,num1,num2,shi,ge;void main (){TMOD=0x01;〃 设置定时器0和1为工作方式1 ( M1M (为01, 0001 0001 )TH0= (65535-50000)/256;// 装初值 12.00M 晶振定时 50s 数为 50000TL0= (65535-50000)%256;TH1= (65535-50000)/256;// 装初值 12.00M 晶振定时 50s 数为 50000 TL1=(65535-50000)%256;EA=1;// 开总中断ET0=1; // 开定时器 0 中断ET1=1; // 开定时器 1 中断TR0=1;// 启动定时器 0TR1=1;// 启动定时器 1#include <reg52.h> //52 系列单片机头文件 (目标:用定时器 0 的方式 1 实现第 一个灯管以200ms 闪烁;用定时器1的方式1实现数码管前两位59s 循环计时)#define uchar unsigned char 占八位数,表示围 0~255// 无符号字符型 #define uint unsignedint 数,表示围// 无符号整型, 占 16位 sbit dula=P2A 6;//申明U1锁存器锁存端 段选 sbit wela=P2A7;//申明U2锁存器锁存 位选sbit led1=P1A0;// 申明灯 1 点 0 uchar code table[]={while(1)// 程序停止在这里不停的对数码管动态扫描同时等待中断的发生{display(shi,ge);}}void display (uchar shi,uchar ge) // 控制数码管{dula=1; // 打开U1 锁存端段选P0=table[shi];//送入段选信号dula=0; // 关闭U1 锁存器P0=0xff;// 送位选数据前关闭所有显示,防止打开位选锁存器时wela=1; // 原来的段选数据通过位选锁存器造成混乱P0=0xfe; // 送位选数据wela=0;delayms(5); // 延时dula=1; // 打开U1 锁存端段选P0=table[ge];//送入段选信号dula=0; // 关闭U1 锁存器P0=0xff; // 送位选数据前关闭所有显示,防止打开位选锁存器时wela=1; // 原来的段选数据通过位选锁存器造成混乱P0=0xfe; // 送位选数据wela=0;delayms(5); // 延时{void delayms(uint xms) // 延时子程序uint i,j;for (i=xms;i>O;i--) 〃i=xms 即延时约为xms毫秒for (j=110;j>0;j--);}#include <reg52.h> //52 系列单片机头文件 (目标:中断程序,控制 1 点0 二极管10ms闪烁)#define uchar unsigned char#define uint unsigned intsbit led1=P1A0; II声明单片机P1 口的第一位uchar num;void main (){TMOD=0x01;〃设置定时器0为工作方式1 (M1M(为01)TH0= (65535-50000)/256;// 装初值12.00M 晶振定时50ms数为50000TL0= (65535-50000)%256;EA=1;// 开总中断ET0=1; // 开定时器0 中断TR0=1;// 启动定时器0while(1)// 程序停止在这里等待中断的发生{if(num==200)// 判断一次是否到20{num=0; // 然后把num 清0 重新再计数20 次led1=~led1; // 让发光管状态取反}}}void T0_time()interrupt 1{TH0= (65535-50000)/256; // 重装初值TL0= (65535-50000)%256;num++; //num 加上1#include <reg52.h> //52 系列单片机头文件 (目标:中断程序,控制 1 点0 二极管100ms 闪烁,若num=10则0.05s闪烁,换句话控制5000或者num都可以控制时间。
51单片机作的电子钟程序及电路图

51单片机作的电子钟程序在很多地方已经有了介绍,对于单片机学习者而言这个程序基本上是一道门槛,掌握了电子钟程序,基本上可以说51单片机就掌握了80%。
常见的电子钟程序由显示部分,计算部分,时钟调整部分构成。
时钟的基本显示原理:时钟开始显示为0时0分0秒,也就是数码管显示000000,然后每秒秒位加1 ,到9后,10秒位加1,秒位回0。
10秒位到5后,即59秒,分钟加1,10秒位回0。
依次类推,时钟最大的显示值为23小时59分59秒。
这里只要确定了1秒的定时时间,其他位均以此为基准往上累加。
开始程序定义了秒,十秒,分,十分,小时,十小时,共6位的寄存器,分别存在30h,31h,32h,33h,34h,35h单元,便于程序以后调用和理解。
6个数码管分别显示时、分、秒,一个功能键,可以切换调整时分秒、增加数值、熄灭节电等功能全部集一键。
以下是部分汇编源程序,购买我们产品后我们用光盘将完整的单片机汇编源程序和烧写文件送给客户。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 中断入口程序 ;; (仅供参考) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ORG 0000H ;程序执行开始地址LJMP START ;跳到标号START执行ORG 0003H ;外中断0中断程序入口RETI ;外中断0中断返回ORG 000BH ;定时器T0中断程序入口LJMP INTT0 ;跳至INTTO执行ORG 0013H ;外中断1中断程序入口RETI ;外中断1中断返回ORG 001BH ;定时器T1中断程序入口LJMP INTT1 ;跳至INTT1执行ORG 0023H ;串行中断程序入口地址RETI ;串行中断程序返回;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 主程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;START: MOV R0,#70H ;清70H-7AH共11个内存单元MOV R7,#0BH;clr P3.7 ;CLEARDISP: MOV @R0,#00H ;INC R0 ;DJNZ R7,CLEARDISP ;MOV 20H,#00H ;清20H(标志用)MOV 7AH,#0AH ;放入"熄灭符"数据MOV TMOD,#11H ;设T0、T1为16位定时器MOV TL0,#0B0H ;50MS定时初值(T0计时用)MOV TH0,#3CH ;50MS定时初值MOV TL1,#0B0H ;50MS定时初值(T1闪烁定时用)MOV TH1,#3CH ;50MS定时初值SETB EA ;总中断开放SETB ET0 ;允许T0中断SETB TR0 ;开启T0定时器MOV R4,#14H ;1秒定时用初值(50M S×20)START1: LCALL DISPLAY ;调用显示子程序JNB P3.7,SETMM1 ;P3.7口为0时转时间调整程序SJMP START1 ;P3.7口为1时跳回START1 SETMM1: LJMP SETMM ;转到时间调整程序SETMM; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 1秒计时程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;T0中断服务程序INTT0: PUSH ACC ;累加器入栈保护PUSH PSW ;状态字入栈保护CLR TR0 ;关闭定时器T0MOV A,#0B7H ;中断响应时间同步修正ADD A,TL0 ;低8位初值修正MOV TL0,A ;重装初值(低8位修正值)MOV A,#3CH ;高8位初值修正ADDC A,TH0 ;MOV TH0,A ;重装初值(高8位修正值)SETB TR0 ;开启定时器T0DJNZ R4, OUTT0 ;20次中断未到中断退出ADDSS: MOV R4,#14H ;20次中断到(1秒)重赋初值MOV R0,#71H ;指向秒计时单元(71H-72H)ACALL ADD1 ;调用加1程序(加1秒操作)MOV A,R3 ;秒数据放入A(R3为2位十进制数组合)CLR C ;清进位标志CJNE A,#60H,ADDMM ;ADDMM: JC OUTT0 ;小于60秒时中断退出ACALL CLR0 ;大于或等于60秒时对秒计时单元清0MOV R0,#77H ;指向分计时单元(76H-77H)ACALL ADD1 ;分计时单元加1分钟MOV A,R3 ;分数据放入ACLR C ;清进位标志CJNE A,#60H,ADDHH ;ADDHH: JC OUTT0 ;小于60分时中断退出ACALL CLR0 ;大于或等于60分时分计时单元清0MOV R0,#79H ;指向小时计时单(78H-79H)ACALL ADD1 ;小时计时单元加1小时MOV A,R3 ;时数据放入ACLR C ;清进位标志CJNE A,#24H,HOUR ;HOUR: JC OUTT0 ;小于24小时中断退出ACALL CLR0 ;大于或等于24小时小时计时单元清0OUTT0: MOV 72H,76H ;中断退出时将分、时计时单元数据移MOV 73H,77H ;入对应显示单元MOV 74H,78H ;MOV 75H,79H ;POP PSW ;恢复状态字(出栈)POP ACC ;恢复累加器RETI ;中断返回; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 闪动调时程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;T1中断服务程序,用作时间调整时调整单元闪烁指示INTT1: PUSH ACC ;中断现场保护PUSH PSW ;MOV TL1, #0B0H ;装定时器T1定时初值MOV TH1, #3CH ;DJNZ R2,INTT1OUT ;0.3秒未到退出中断(50MS中断6次)MOV R2,#06H ;重装0.3秒定时用初值CPL 02H ;0.3秒定时到对闪烁标志取反JB 02H,FLASH1 ;02H位为1时显示单元"熄灭"MOV 72H,76H ;02H位为0时正常显示MOV 73H,77H ;MOV 74H,78H ;MOV 75H,79H ;INTT1OUT: POP PSW ;恢复现场POP ACC ;RETI ;中断退出FLASH1: JB 01H,FLASH2 ;01H位为1时,转小时熄灭控制MOV 72H,7AH ;01H位为0时,"熄灭符"数据放入分MOV 73H,7AH ;显示单元(72H-73H),将不显示分数据MOV 74H,78H ;MOV 75H,79H ;AJMP INTT1OUT ;转中断退出FLASH2: MOV 72H,76H ;01H位为1时,"熄灭符"数据放入小时MOV 73H,77H ;显示单元(74H-75H),小时数据将不显示MOV 74H,7AH ;MOV 75H,7AH ;AJMP INTT1OUT ;转中断退出; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 加1子程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ADD1: MOV A,@R0 ;取当前计时单元数据到ADEC R0 ;指向前一地址SWAP A ;A中数据高四位与低四位交换ORL A,@R0 ;前一地址中数据放入A中低四位ADD A,#01H ;A加1操作DA A ;十进制调整MOV R3,A ;移入R3寄存器ANL A,#0FH ;高四位变0MOV @R0,A ;放回前一地址单元MOV A,R3 ;取回R3中暂存数据INC R0 ;指向当前地址单元SWAP A ;A中数据高四位与低四位交换ANL A,#0FH ;高四位变0MOV @R0,A ;数据放入当削地址单元中RET ;子程序返回; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 清零程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;............. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 时钟调整程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;当调时按键按下时进入此程序SETMM: cLR ET0 ;关定时器T0中断CLR TR0 ;关闭定时器T0LCALL DL1S ;调用1秒延时程序JB P3.7,CLOSEDIS ;键按下时间小于1秒,关闭显示(省电)MOV R2,#06H ;进入调时状态,赋闪烁定时初值SETB ET1 ;允许T1中断SETB TR1 ;开启定时器T1SET2: JNB P3.7,SET1 ;P3.7口为0(键未释放),等待SETB 00H ;键释放,分调整闪烁标志置1SET4: JB P3.7,SET3 ;等待键按下LCALL DL05S ;有键按下,延时0.5秒JNB P3.7,SETHH ;按下时间大于0.5秒转调小时状态MOV R0,#77H ;按下时间小于0.5秒加1分钟操作LCALL ADD1 ;调用加1子程序MOV A,R3 ;取调整单元数据CLR C ;清进位标志CJNE A,#60H,HHH ;调整单元数据与60比较HHH: JC SET4 ;调整单元数据小于60转SET4循环LCALL CLR0 ;调整单元数据大于或等于60时清0CLR C ;清进位标志AJMP SET4 ;跳转到SET4循环CLOSEDIS: SETB ET0 ;省电(LED不显示)状态。
单片机的C语言程序设计与应用——基于Proteus仿真(第2版)

{TL0=0xb0; //访问定时器0,设置时间常数
TH0=ox3c;
TR0=1; //启动定时器0
…
}
3-3 sbit型变量的定义示例
程序如下:
sfr PSW=0xD0;
sbit OV=PSW^2;
sbit OV=0xd0^2;
sbit OV=0xD2;
unsigned char bdata flag;
if(a==b)
{ a++;b++;}
{ a--;b--;}
printf("a=%d,b=%d\n",a,b);
while(1);
}
执行结果如下:
a=11,b=20
3-16选择语句程序示例
#include<stdio.h>
void main()
{ int score;
char grade;
score=45;
if(score>=90)
grade='A';
else if(score>=80)
grade='B';
else if(score>=70)
grade='C';
else if(score>=60)
grade='D';
else grade='E'
printf("score=%d,grade=%c\n",score,grade);
}
}
}由于不知道什么时候能够超过4000,所以使用一个‘无限循环’,每次计算和之后判断当前sum的值,当sum超过4000时使用break退出整个循环,不再执行。
温控程序

#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit DQ=P1^0;//ds18b20与单片机连接口sbit DQ1=P1^1;//ds18b201与单片机连接口sbit RS=P2^5;sbit RW=P2^6;sbit EN=P2^7;sbit beef = P3^4;sbit P36 = P3^6;sbit P37 = P3^7;unsigned char code str1[]={"1:"};unsigned char code str2[]={"H:"};unsigned char code str3[]={"2:"};unsigned char code str4[]={"L:"};unsigned char code str5[]={"23.5"}; //最低温门限unsigned char code str6[]={"28.5"}; //最高温门制uchar data disdata[4];uchar data disdata1[4];uint temp,temp1,tempL=23.5,tempH=28.5;uint tvalue,tvalue1;//温度值uchar tflag,tflag1;//温度正负标志/*************************lcd1602程序**************************/ void delay1ms(unsigned int ms)//延时1毫秒(不够精确的){unsigned int i,j;for(i=0;i<ms;i++)for(j=0;j<100;j++);}void wr_com(unsigned char com)//写指令//{ delay1ms(1);RS=0;RW=0;EN=0;delay1ms(1);EN=1;delay1ms(1);EN=0;}void wr_com1(unsigned char com1)//写指令// { delay1ms(1);RS=0;RW=0;EN=0;P0=com1;delay1ms(1);EN=1;delay1ms(1);EN=0;}void wr_dat(unsigned char dat)//写数据// { delay1ms(1);;RS=1;RW=0;EN=0;P0=dat;delay1ms(1);EN=1;delay1ms(1);EN=0;}void wr_dat1(unsigned char dat1)//写数据// { delay1ms(1);;RS=1;RW=0;EN=0;P0=dat1;delay1ms(1);delay1ms(1);EN=0;}void lcd_init()//初始化设置//{delay1ms(15);wr_com(0x38);delay1ms(5);wr_com(0x08);delay1ms(5);wr_com(0x01);delay1ms(5);wr_com(0x06);delay1ms(5);wr_com(0x0c);delay1ms(5);}void display(unsigned char *p)//显示//{while(*p!='\0'){wr_dat(*p);p++;delay1ms(1);}}init_play()//初始化显示{ lcd_init(); //lcd_initwr_com(0x80);display(str1);wr_com(0x89);display(str2);wr_com(0xc0);display(str3);wr_com(0xc9);display(str4);return 0;}/******************************ds1820程序void delay_18B20(unsigned int i)//延时1微秒{while(i--);}void ds1820rst()/*ds1820复位*/{DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480us DQ = 1; //拉高delay_18B20(40);}void ds1820rst1()/*ds1820复位*/{DQ1= 1; //DQ复位delay_18B20(4); //延时DQ1= 0; //DQ拉低delay_18B20(100); //精确延时大于480us DQ1= 1; //拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DQ = 0; //给脉冲信号dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;}return(dat);}uchar ds1820rd1()/*读数据*/ //读第二个温度传感器// {unsigned char j=0;unsigned char dat1 = 0;for (j=8;j>0;j--){DQ1= 0; //给脉冲信号dat1>>=1;DQ1= 1; //给脉冲信号if(DQ1)dat1|=0x80;delay_18B20(10);}return(dat1);}void ds1820wr(uchar wdata)/*写数据*/{unsigned char i=0;for (i=8; i>0; i--){ DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}void ds1820wr1(uchar wdata1)/*写数据*/ //写第二个温度传感器// { unsigned char j=0;for (j=8; j>0; j--){DQ1= 0;delay_18B20(10);DQ1= 1;wdata1>>=1;}}read_temp()/*读取温度值并转换*/{uchar a,b;ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0x44);//*启动温度转换*/ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0x0fff)tflag=0;else{tvalue=~tvalue+1;tflag=1;}tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数return(tvalue);}read_temp1()/*读取温度值并转换*/ //读第二个温度传感器//{uchar c,d;ds1820rst1();ds1820wr1(0xcc);//*跳过读序列号*/ds1820wr1(0x44);//*启动温度转换*/ds1820wr1(0xcc);//*跳过读序列号*/ds1820wr1(0xbe);//*读取温度*/c=ds1820rd1(); //温度2进制低8位d=ds1820rd1(); //温度2进制高8位tvalue1=d;tvalue1<<=8;tvalue1=tvalue1|c; //合并高低位if(tvalue1<0x0fff)tflag1=0;else{tvalue1=~tvalue1+1;tflag1=1;}tvalue1=tvalue1*(0.625);//温度值扩大10倍,精确到1位小数return(tvalue1);}/*******************************************************************/ void ds1820disp()//温度值显示{ uchar flagdat;disdata[0]=tvalue/1000+0x30;//百位数disdata[1]=tvalue%1000/100+0x30;//十位数disdata[2]=tvalue%100/10+0x30;//个位数disdata[3]=tvalue%10+0x30;//小数位temp=tvalue/10+tvalue%10;if(tflag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}wr_com(0x82);wr_dat(flagdat);//显示符号位wr_com(0x83);wr_dat(disdata[0]);//显示百位wr_com(0x84);wr_dat(disdata[1]);//显示十位wr_com(0x85);wr_dat(disdata[2]);//显示个位wr_com(0x86);wr_dat(0x2e);//显示小数点wr_com(0x87);wr_dat(disdata[3]);//显示小数位}void ds1820disp1()//温度值显示*************第二个温度传感器********************//{ uchar flagdat1;disdata1[0]=tvalue1/1000+0x30;//百位数disdata1[1]=tvalue1%1000/100+0x30;//十位数disdata1[2]=tvalue1%100/10+0x30;//个位数disdata1[3]=tvalue1%10+0x30;//小数位temp1=tvalue1/10+tvalue1%10;if(tflag1==0)flagdat1=0x20;//正温度不显示符号elseflagdat1=0x2d;//负温度显示负号:-if(disdata1[0]==0x30){disdata1[0]=0x20;//如果百位为0,不显示if(disdata1[1]==0x30){disdata1[1]=0x20;//如果百位为0,十位为0也不显示}}wr_com1(0xc0+0x02);wr_com1(0xc0+0x03);wr_dat1(disdata1[0]);//显示百位wr_com1(0xc0+0x04);wr_dat1(disdata1[1]);//显示十位wr_com1(0xc0+0x05);wr_dat1(disdata1[2]);//显示个位wr_com1(0xc0+0x06);wr_dat1(0x2e);//显示小数点wr_com1(0xc0+0x07);wr_dat1(disdata1[3]);//显示小数位}/**********************报警程序******************************/ void alarm(){unsigned char j;for (j=10;j>0;j--){beef=1;delay1ms(20);beef=0;}}/********************主程序***********************************/ main(){P37=1;init_play();//初始化显示while(1){beef=0;delay1ms(400);ds1820disp1();//显示read_temp();//读取温度ds1820disp();//显示wr_com(0xcb);display(str5);wr_com(0x8b);display(str6);if((temp<tempL||temp>tempH)||(temp1<tempL||temp1>tempH)) {unsigned char i;for(i=20;i>0;i--){alarm();P37=0;P36=1;delay1ms(100);P36=0;}}elseP37=1;}return 0;}。
C8051F单片机C程序精确延时的方法

编译情况相同。3种循环语句在Keil C51中具有不同编 译特点的原因在于它们的流程不同。do—while语句是先 执行后判断,while和for语句都是先判断后执行。进行
多层循环时,使用do—while语句具有更大的优势:编译的 汇编代码就如直接用汇编语言编写的程序,结构紧凑,编
译效率高,条件转移控制循环次数的过程简单。因此,虽
C8051F单片机是完全集成的混合信号系统级芯片 (S0c),其MCU系统控制器的内核是CIP一51微控制器。 CIP一51的指令集与标准8051指令集完全兼容。CIP一 51采用流水线指令结构,指令时序与标准805l不同: 70%指令的执行时间为l或2个系统时钟周期;所有指令 时序都以时钟周期计算;大多数指令执行所需的时钟周期 数与指令的字节数一致;条件转移指令在不发生转移时和 发生转移时的时钟周期数不同。同标准8051相比, C8051F单片机实现程序延时的方法更复杂些。
void SingleCircle(unsigned char t){ unsigned char X=t,Y 5 tl
t基金项目:福建省教育厅科技硬目(jB07277)。
do(
;
}while(一一t); while(x一一);
for(;y--一;); }
使用Keil C51 V7.50编译器编泽,得到的汇编代码如 下:
2丁+(7l+3)T·(X一1)+(,l+2)T=ZT+(行+3)T·X一1’
同理,可得Delay函数的延时时间: {2T+[2T+(咒+3)T·x—T+3T]·y一丁+3丁)·
£一1’+5丁={[4y+(咒+3)X·y+4]·£+4}·T 其中,5丁为返回指令RET的时钟周期数。考虑调用De- lay函数的LCALL指令(时钟周期数为4T)和参数传递的 MOV指令(时钟周期数为2n,则总延时时间t且为
MCS-51练习题

MCS-51练习题一、单项选择题(本大题共11小题,每小题1分,共11分)在每小题列出的四个选项中只有一个选项是符合题目要求的,请将正确选项前的字母字母填在题后的括号内。
16.8位二进制所表示的无符号整数,其相应的十进制数范围是()A.0-255 B.1-256 C.1-255D.0-25617.字母“b”的ASCⅡ码是()A. 11H B.OBH C.BOH D.62H18.十进制数-1用二进制补码表示,该补码是()0A. FFH B.00H C.FEH D.81H19.8031单片机外接ROM时,使用()引脚来选通74LS373芯片A.ALE B. C. D20.如果8031单片机的一个机器周期为2微秒,则其时钟频率为()MHzA.6 B.8 C.12 D.1621.8031单片机内含定时器和串行口的个数分别为()A. 2和1 B.1和2 C.3和1 D.2和222.对程序存储区数据传送,应采用助记符为()A. MOV B.MOVX C.MOVC D.PUSH23.下列各指令中()才属于MCS-51指令系统的位指令A. ANLC.,/bit B.XRLC,bit C.ORLbit,C D.MOVC,/bit24.8031单片机外部中断0请示信号输入的引脚是()A. RXD B. C. D.25.8031单片机的定时器1的中断程序入口地址为()A.001BH B.0003H C.000BH D.0013H26.8031片可扩展数据存储器()KB0A. 64 B.32 C.8 D.4二、改错题(本大题共3小题,每小题2分,共6分)下面的程序或程序段存在一个错误或不妥处,请在其下划一条线,并将改正的内容写到每小题的空白处。
27.某8031单片机时钟频率12MHz,T1为工作方式1,2毫秒定时中断,其部分初始化程序如下,请指出错误,并改正之。
MOV TMOD,#01HMOV TH1,#0F8HMOV TL1,#30HMOV IP,#8MOV IE,#88H………T1方式字段T0方式字段GATE C/T M1 M0 GATE C/T M1 M0TMOD寄存器格式―-- PS PT1 PX1 PT0 PX0IP寄存器格式EA -- ES ET1 EX1 ET0 EX0IE寄存器格式28.下列程序要完成16位无符号数相加,两数分别存于30H,31H和40H,41H(低位在前),并把和存于30H,31H中(设和无进位输出)。
单片机习题答案
《单片机应用技术》习题答案第一章概述1. 什么是总线?总线主要有哪几部分组成?各部分的作用是什么?总线是连接计算机各部件之间的一组公共的信号线。
一般情况下,可分为系统总线和外总线。
系统总线应包括:地址总线(AB)控制总线(CB)数据总线(DB)地址总线(AB):CPU根据指令的功能需要访问某一存储器单元或外部设备时,其地址信息由地址总线输出,然后经地址译码单元处理。
地址总线为16位时,可寻址范围为216=64K,地址总线的位数决定了所寻址存储器容量或外设数量的范围。
在任一时刻,地址总线上的地址信息是惟一对应某一存储单元或外部设备。
控制总线(CB):由CPU产生的控制信号是通过控制总线向存储器或外部设备发出控制命令的,以使在传送信息时协调一致的工作。
CPU还可以接收由外部设备发来的中断请求信号和状态信号,所以控制总线可以是输入、输出或双向的。
数据总线(DB):CPU是通过数据总线与存储单元或外部设备交换数据信息的,故数据总线应为双向总线。
在CPU进行读操作时,存储单元或外设的数据信息通过数据总线传送给CPU;在CPU进行写操作时,CPU把数据通过数据总线传送给存储单元或外设2.什么是接口电路? CPU与接口电路连接一般应具有哪些信号线?外部设备与接口电路连接一般应具有哪些信号线?CPU通过接口电路与外部输入、输出设备交换信息,一般情况下,外部设备种类、数量较多,而且各种参量(如运行速度、数据格式及物理量)也不尽相同。
CPU为了实现选取目标外部设备并与其交换信息,必须借助接口电路。
一般情况下,接口电路通过地址总线、控制总线和数据总线与CPU连接;通过数据线(D)、控制线(C)和状态线(S)与外部设备连接。
3. 存储器的作用是什么?只读存储器和随机存储器有什么不同?存储器具有记忆功能,用来存放数据和程序。
计算机中的存储器主要有随机存储器(RAM)和只读存储器(ROM)两种。
随机存储器一般用来存放程序运行过程中的中间数据,计算机掉电时数据不再保存。
单片机控制的语音模块WT588D一线示例代码
//---------------------------------////WT588D-16P 一线示例代码//MCU:STC89C52 晶振:11.0592M//作者:单片机语音电子群94622432 眼大5子//功能:一线连接,通过按键循环播放7到12地址的语音#include <reg52.H>sbit KEY=P0^2; //sbit RST=P0^1; //WT588D复位引脚sbit SDA=P0^0; //P0.0有外部上拉,连接WT588D的DATA void delay1ms(unsigned char count) //1MS 延时子程序{unsigned char i,j,k;for(k=count;k>0;k--)for(i=2;i>0;i--)for(j=248;j>0;j--);}void delay100us(unsigned char count) //100US 延时子程序{unsigned char i;unsigned char j;for(i=count;i>0;i--)for(j=50;j>0;j--);}void Send_oneline(unsigned char addr){unsigned char i;RST=0;delay1ms(5); /* 复位延时5MS*/RST=1;delay1ms(20); /* delay 20ms */SDA=0;delay1ms(5); /* delay 5ms */for(i=0;i<8;i++){if(addr & 1){SDA=1;delay100us(6); /* 600us */SDA=0;delay100us(2); /* 200us */}else{SDA=1;delay100us(2); /* 200us */SDA=0;delay100us(6); /* 600us */}addr>>=1;}SDA=1;}void main(){unsigned char FD=7;while(1){if(KEY==0){delay1ms(10);if(KEY==0) // 通过按键P0.2 来进行发码值的递增{while(KEY==0); //按键释放有效Send_oneline(FD);FD++;if(FD>12) //我的语音只放到了地址12{FD=7; //我的语音是从地址7开始存取}}}}}。
汇编延时程序讲解
延时程序在单片机编程中使用非常广泛,但一些读者在学习中不知道延时程序怎么编程,不知道机器周期和指令周期的区别,不知道延时程序指令的用法, ,本文就此问题从延时程序的基本概念、机器周期和指令周期的区别和联系、相关指令的用法等用图解法的形式详尽的回答读者我们知道程序设计是单片机开发最重要的工作,而程序在执行过程中常常需要完成延时的功能。
例如在交通灯的控制程序中,需要控制红灯亮的时间持续30秒,就可以通过延时程序来完成。
延时程序是如何实现的呢?下面让我们先来了解一些相关的概念。
一、机器周期和指令周期1.机器周期是指单片机完成一个基本操作所花费的时间,一般使用微秒来计量单片机的运行速度,51 单片机的一个机器周期包括12 个时钟振荡周期,也就是说如果51 单片机采用12MHz 晶振,那么执行一个机器周期就只需要1μs;如果采用的是6MHz 的晶振,那么执行一个机器周期就需要2 μs。
2 .指令周期是指单片机执行一条指令所需要的时间,一般利用单片机的机器周期来计量指令周期。
在51 单片机里有单周期指令(执行这条指令只需一个机器周期),双周期指令(执行这条指令只需要两个机器周期),四周期指令(执行这条指令需要四个机器周期)。
除了乘、除两条指令是四周期指令,其余均为单周期或双周期指令。
也就是说,如果51 单片机采用的是12MHz 晶振,那么它执行一条指令一般只需1~2 微秒的时间;如果采用的是6MH 晶振,执行一条指令一般就需2~4 微秒的时间。
现在的单片机有很多种型号,但在每个型号的单片机器件手册中都会详细说明执行各种指令所需的机器周期,了解以上概念后,那么可以依据单片机器件手册中的指令执行周期和单片机所用晶振频率来完成需要精确延时时间的延时程序。
二、延时指令在单片机编程里面并没有真正的延时指令,从上面的概念中我们知道单片机每执行一条指令都需要一定的时间,所以要达到延时的效果,只须让单片机不断地执行没有具体实际意义的指令,从而达到了延时的效果。
·单片机晶振为12mhs延时1ms计算依据
一、单片机晶振的作用与原理单片机晶振是单片机系统中的一个重要部件,它通过振荡产生稳定的时钟信号,为单片机的运行提供基准。
在单片机系统中,晶振的频率对系统的稳定性、精度和速度有着重要的影响。
二、晶振频率为12MHz的延时计算在单片机系统中,为了实现延时操作,一般需要通过编程来控制计时器或者循环延时的方式来实现。
对于晶振频率为12MHz的单片机系统,延时1ms的计算依据如下:1. 首先需要计算出12MHz晶振的周期,即一个晶振振荡周期的时间。
12MHz晶振的周期为1/12MHz=0.0833us。
2. 接下来将1ms转换成晶振周期数。
1ms=1000us,将1000us除以0.0833us得到12000。
即延时1ms需要进行12000个晶振周期的振荡。
3. 最后根据单片机的指令周期和频率来确定代码延时的实现方法。
以常见的晶振频率为12MHz的单片机为例,根据单片机的指令周期(一般为1/12MHz=0.0833us)和延时周期数(12000),可以编写相应的延时函数或者循环来实现1ms的延时操作。
三、12MHz晶振延时1ms的应用场景在实际的单片机应用中,常常需要进行一定时间的延时操作,例如驱动液晶屏显示、控制外围设备响应等。
12MHz晶振延时1ms的应用场景包括但不限于:LED闪烁控制、按键消抖、舵机控制、多任务调度等。
四、晶振频率选择与延时精度的关系晶振频率的选择对延时精度有着直接的影响。
一般来说,晶振频率越高,对延时精度要求越高的应用场景,而对于一般的延时控制,12MHz的晶振已经能够满足大多数的要求。
延时的精度还受到单片机的指令执行速度的影响,需要在实际应用中进行综合考量与测试。
五、总结在单片机系统中,晶振的频率选择与延时操作密切相关,12MHz晶振延时1ms的计算依据可以帮助工程师们更好地进行单片机程序的设计与开发。
需要根据实际应用场景和需求来选择合适的晶振频率,并对延时精度进行充分的考量和测试,以确保单片机系统的稳定可靠性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
精确的C语言延时子程序表/自己测试,11.0592M晶振ms延时程序,绝对精确
51单片机,需要用MS 延时程序的时候才发现网上的好多程序不好用,
下面这个忘记从哪里找的,但是已经相当精确,keil亲测。
=======================================================
/*--------------------ms延时函数-----------------------*/
void delay_ms(unsigned int ms_number) // ms延时函数(A T89C51 @ 11.0592MHz)
{
unsigned int i;
unsigned char j;
for(i=0;i<ms;i++)
{
for(j=0;j<200;j++);
for(j=0;j<102;j++);
}
}
/--------------------------------------------------------------------
用法:在参数传入时填上几就是几毫秒啦
比如,想延时100ms,就把ms_number赋值为50
×××××××××××××××××××××××××××××××××××××××××××××
=============================================
以下为原来转载的资料
=============================================
文章转自Proteus仿真社区作者:liaoguobao00
未作验证,如有问题请和原作者联系:lsygrzzh@
=============================================
用C语言写出来程序非常的简练,它是一种模块化的语言,一种比汇编更高级的语言,但是就是这样一种语言也还是有它不足之处:它的延时很不好控制,我们常常很难知道一段延时程序它的精确延时到底是多少,这和汇编延时程序没法比。
但有时后写程序又不得不要用到比较精确的延时,虽然说可以用混合编程的方式解决,但这种方式不是每个人都能掌握,且写起来也麻烦。
所以,通过测试我给大家提供一个延时子程序模块,并以此给一个出我们经常用到的延时的数据表格。
(注意:表格中的数据只适合我的延时模块,对其他的延时程序不适用,切忌!!!!!!!!别到时候延时不对来骂我)
延时模块:其中问号代表要填的数,要延时多少,到表格中去找数据,然后填上就OK!切忌3条FOR语句不能颠倒顺序
void Delay()
{
unsigned char a,b,c;
for(a=0;a<?;a++)
for(b=0;b<?;b++)
for(c=0;c<?;c++);
}
数据表如下
/****************************************************************************************************** ****************/
延时时间a的值b的值c的值延时误差(us)
10us 1 1 1 -0.5
20us 1 1 8 0
30us 1 1 15 +0.5
40us 2 1 9 0
50us 1 1 28 0
60us 1 1 35 +0.5
70us 1 1 42 +1
80us 1 1 48 0
90us 1 1 55 +0.5
100us 1 1 61 -0.5
200us 1 1 128 0
300us 3 1 63 +1.5
400us 2 1 129 0
500us 5 1 63 +0.5
600us 6 1 63 0
700us 7 1 63 -0.5
800us 1 3 175 +0.5
900us 9 1 63 -1.5
1ms 1 3 219 -1.5
2ms 2 3 220 +3
3ms 3 3 220 +3
Xms X 3 220 +3
(X的范围为2到255)
基本上我们平时用到的延时都在这里了,每种延时的误差都很小,最大也不过3us,有的甚至没有误差,已经很精确了,如果想延时1秒钟,你可以连续调用延时250ms的程序4次,总共延时误差12us,这样的误差已经不算误差了,用汇编语言编写还达不到这个程度。
现在你不再为延时不精确担忧了,参照表中的数据写延时,想延时多少就能延时多少。
再次重申:此表格是根据我的延时模块编写,这也是大多数朋友都习惯用的一个模块,如果你用其他模块或是改动了我的模块,延时都不准的,不信大家可以试试!!!
for循环编写延时函数的方法
2011-01-21 12:55:47 来源:互联网
很多初学者对于程序中ms级延时函数的编写方法比较疑惑,其原理和方式虽然简单,但是却没有相关资料。
这里用一个例程详细介绍一下。
过程参考如下:
在编译器下建立一个新项目,也可以利用已有项目。
此过程中需要注意,单片机晶振的选择,因为for循环里指令的执行时间和晶振有直接关系,本例中晶振使用11.0592M。
编写一段关于延时的函数,主要利用for循环,代码如下:
void delay_ms(unsigned int ms)
{
unsigned int i;
unsigned char j;
for(i=0;i<ms;i++)
{
for(j=0;j<200;j++);
for(j=0;j<102;j++);
}
}
其中ms是输入参数,如果输入1,就是要求程序延时1ms。
j变量是调整程序运行的时间参数。
调整j的数值,使1次循环的时间在1ms。
将此程序编译通过,然后利用软件仿真,调整时间。
两次时间差就是延时函数使用的时间,如果与1ms相差比较多,用户可以调整j参数的值,使延时时间尽量接近1ms。
如增大j的值for(j=0;j<105;j++);
此方法得出延时函数,在晶振不同的情况下,延时时间会不准。
另外这种方法不是完全精确的延时,所以不要太深研究误差的问题。
软件调试结果,这个程序的延时时间为:1.01779ms,一般的单片机系统中都可以应用
(本文转自电子工程世界:/mcu/2011/0121/article_2576.html)。