89C51单片机定时器所定时间的计算以及写法
- 格式:docx
- 大小:17.60 KB
- 文档页数:3
89C51单片机时钟程序第一篇:89C51单片机时钟程序SECOND EQU 40H;给内存RAM空间中40H单元起名SECOND MINUTE EQU 41H ;给内存RAM空间中41H单元起名MINUTE HOUR EQU 42H;给内存RAM空间中42H单元起名HOUR SECONDGEWEI EQU 43H;给43H单元起名SECONDGEWEI存秒的个位SECONDSHIWEI EQU 44H;给44H单元起名SECONDSHIWEI存秒的十位MINUTEGEWEI EQU 45H;给45H单元起名MINUTEGEWEI存分的个位MINUTESHIWEI EQU 46H;给46H单元起名MINUTESHIWEI存分的十位HOURGEWEI EQU 47H;给47H单元起名HOURGEWEI存小时的个位HOURSHIWEI EQU 48H;给48H单元起名HOURSHIWEI存小时的十位 ORG 0000H;复位时程序从此开始 SJMP START;跳到START进行初始化 ORG 000BH;定时器 0中断入口 AJMP TIMER0;跳转到TIMER0处ORG 0030H;初始化程序从30H开始;---------------初始化START------------------------------START:MOV SECOND, #0;给秒存储单元SECOND赋初始值0 MOV MINUTE, #0;给分存储单元MINUTE赋初始值0 MOV HOUR , #12;给小时存储单元HOUR赋初始值12 MOV DPTR , #TAB;给数据指针赋值,将DPTR指向TAB数据表头处 MOV 30H, #0 ;给30H单元赋初始值0(用于计20次的50ms中断)MOV TH0,#3CH;给计数容器的高8位TH0赋初始值3CH MOV TL0,#0B0H;给计数容器的低8位TL0赋初始值B0H MOV TMOD,#00000001B;C/T位设置为0,M1M0设置位10,即模式1定时MOV TCON,#00010000B;TR0设置为1,即启动定时器0开始工作 SETB ET0;IE中的ET0位设置为1,开定制器中断0 SETB EA;IE中的EA位设置为1,开总中断;-----------------------主程序MAIN-----------------------------MAIN:CALL KEY;调按键子程序KEY CALL PROCESS;调数据处理子程序PROCESS CALL DISPLAY;调显示子程序DISPLAY SJMP MAIN;跳转到MAIN标号处;------------------------------按键子程序KEY调时-------------------KEY:MOV P1,#0FEH;行扫描 LCALL DELAY;JNB P1.4,HOURJIA;P1.4引脚如果是低电平就跳到HOURJIA处JNB P1.5,HOURJIAN;P1.5引脚如果是低电平就跳到HOURJIAN处JNB P1.6,MINUTEJIA;P1.6引脚如果是低电平就跳到MIMUTEJIA处JNB P1.7,MINUTEJIAN;P1.7引脚如果是低电平就跳到MIMUTEJIAN处 FANHUI:RET;子程序返回(如果没有按键按下)HOURJIA:CALL DELAY;调延时程序目的是跳过按键抖动期(去抖)JB P1.4,FANHUI;P1.4如果是高电平就跳到FANHUI处(没键按)JNB P1.4,$;如果P1.4是低电平就停在当前位置等键释放MOV R4,HOUR CJNE R4,#23,A1;判断时数字是否为23 AJMP A2A1:INC HOUR;把小时位加1 MOV SECOND, #0;小时进位,秒归0RETA2:MOV HOUR,#0;小时数为23时加一为0MOV SECOND, #0;小时进位,秒归0RET;子程序返回HOURJIAN:CALL DELAY;调延时程序目的是跳过按键抖动期(去抖)JB P1.5,FANHUIJNB P1.5,$MOV R5,HOUR CJNE R5,#0,A3AJMP A4 A3:DEC HOURMOV SECOND, #0RET A4:MOV HOUR,#23MOV SECOND, #0 RETMINUTEJIA:CALL DELAYJB P1.6,FANHUIJNB P1.6,$MOV R6,MINUTECJNE R6,#59,A5AJMP A6 A5:INC MINUTEMOV SECOND, #0RET A6:MOV SECOND, #0MOV MINUTE, #0MOV R4,HOUR CJNE R4,#23,A10MOV HOUR,#0RET A10:INC HOURRETMINUTEJIAN:CALL DELAYJB P1.7,FANHUIJNB P1.7,$MOV R7,MINUTE CJNE R7,#0,A7AJMP A8 A7:DEC MINUTE;P1.5如果是高电平就跳到FANHUI处(没键按) ;如果P1.5是低电平就停在当前位置等键释放;判断时数字是否为23;把小时位减1;小时数为0时减一为23;子程序返回;调延时程序目的是跳过按键抖动期(去抖);P1.6如果是高电平就跳到FANHUI处(没键按) ;如果P1.6是低电平就停在当前位置等键释放;判断分钟数是否为59;把分钟位加1;给秒存储单元SECOND赋初始值0;分钟数为59则分钟归0;判断时数字是否为23;23时增1归0;分钟数为59 自增1后小时增1;子程序返回;调延时程序目的是跳过按键抖动期(去抖);P1.7如果是高电平就跳到FANHUI处(没键按) ;如果P1.7是低电平就停在当前位置等键释放;判断分钟数是否为0;分钟不为0把分钟位减1MOV SECOND, #0RETA8:MOV MINUTE, #59;分钟数为0时减一为59 MOV R4,HOUR CJNE R4,#0,A9;判断时钟数是否为0 MOV HOUR,#23;时钟数为0减1为23 MOV SECOND, #0 RETA9:DEC HOUR;时钟数不为0则减1 MOV SECOND, #0RET;子程序返回;-------------------处理子程序PROCESS-----------------------PROCESS:MOV A, SECOND;把SECOND中的秒值拷贝给A MOV B, #10;给寄存器B赋值10 DIV AB;A除以B,结果存入A中,余数存入B中 MOV SECONDSHIWEI , A;结果即秒的十位数拷贝给SECONDSHIWEI MOV SECONDGEWEI , B;余数即秒的个位拷贝给SECONDGEWEI MOV A, MINUTE;把MINUTE中的分值拷贝给A MOV B, #10;给寄存器B赋值10 DIV AB;A除以B,结果存入A中,余数存入B中 MOV MINUTESHIWEI , A;结果即分的十位拷贝给MINUTESHIWEI MOV MINUTEGEWEI , B;余数即分的个位拷贝给MINUTEGEWEI MOV A, HOUR;把HOUR中的小时值拷贝给A MOV B, #10;给寄存器B赋值10 DIV AB;A除以B,结果存入A中,余数存入B中 MOV HOURSHIWEI , A;结果即小时的十位拷贝给HOURSHIWEI MOV HOURGEWEI , B ;余数即小时的个位拷贝给HOURGEWEI RET;子程序结束返回到主程序;-----------------显示子程序DISPLAY--------------DISPLAY:MOV A, HOURSHIWEI;小时的十位拷贝给A MOVC A, @A+DPTR;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(小时的十位)送到P0 CLR P2.0;将P2.0置低电平,对应的三极管导通 CALL DELAY;调延时(让显示小时十位的数码管持续亮一段时间)SETB P2.0 ;将P2.0置高电平,对应三极管截止,对应数码管灭MOV A, HOURGEWEI;小时的个位拷贝给A MOVC A,@A+DPTR;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(小时的个位)送到P0 CLR P2.1;将P2.1置低电平,对应的三极管导通CALL DELAY;调延时(让显示小时个位的数码管持续亮一段时间)SETB P2.1 MOV P0,#7FH CLR P2.1 CALL DELAY SETB P2.1;将P2.1置高电平,对应三极管截止,对应数码管灭MOV A, MINUTESHIWEI;分钟的十位拷贝给A MOVC A,@A+DPTR;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(分钟的十位)送到P0 CLR P2.2;将P2.2置低电平,对应的三极管导通 CALL DELAY;调延时(让显示分钟十位的数码管持续亮一段时间)SETB P2.2 ;将P2.2置高电平,对应三极管截止,对应数码管灭MOV A, MINUTEGEWEI;分钟的个位拷贝给A MOVC A,@A+DPTR;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(分钟的个位)送到P0 CLR P2.3;将P2.3置低电平,对应的三极管导通CALL DELAY;调延时(让显示分钟个位的数码管持续亮一段时间)SETB P2.3 ;将P2.3置高电平,对应三极管截止,对应数码管灭MOV P0,#7FH CLR P2.3 CALL DELAY SETB P2.3MOV A, SECONDSHIWEI;秒的十位拷贝给A MOVC A,@A+DPTR;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(秒钟的十位)送到P0 CLR P2.4;将P2.4置低电平,对应的三极管导通 CALL DELAY;调延时(让显示秒钟十位的数码管持续亮一段时间)SETB P2.4 ;将P2.4置高电平,对应三极管截止,对应数码管灭MOV A, SECONDGEWEI;秒的个位拷贝给A MOVC A,@A+DPTR;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(秒钟的个位)送到P0 CLR P2.5;将P2.5置低电平,对应的三极管导通CALL DELAY;调延时(让显示秒钟个位的数码管持续亮一段时间)SETB P2.5 ;将P2.5置高电平,对应三极管截止,对应数码管灭 RET;显示子程序结束返回主程序;--------------------中断服务子程序----------------------------TIMER0:MOV R3, A;把A中的数据送入R3保护起来 INC 30H;30H单元中的数加1 MOV A, 30H;30H单元中的数据拷贝给A CJNE A,#20,JIXU;A中的数据与20比较不相等就跳转到JIXU处 MOV 30H,#0;(如果30H单元计满20了)给30H赋值0 INC SECOND;把SECOND中的秒钟数加1 MOV A,SECOND;把SECOND中的数据拷贝给A CJNE A, #60, JIXU;A中的数据与60比较不相等就跳转到JIXU处MOV SECOND,#0;给秒SECOND赋值0 INC MINUTE;把MINUTE中的分钟数加1 MOV A, MINUTE;把MINUTE中的数据拷贝给A CJNE A, #60, JIXU;A中的数据与60比较不相等就跳转到JIXU处 MOV MINUTE, #0 ;给分钟MINUTE赋值0 INC HOUR;把HOUR中的小时数据加1 MOV A, HOUR;把HOUR中的数据拷贝给A CJNE A, #24, JIXU;A中的数据与24比较不相等就跳转到JIXU处 MOV HOUR, #0 ;给小时HOUR赋值0 JIXU: MOV A,R3;把刚才送入R3中的数据还给A MOV TH0,#3CH;给计数容器的高8位TH0赋初始值3CH MOV TL0,#0B0H;给计数容器的低8位TL0赋初始值B0H RETI;中断子程序返回主程序;---------------------------延时子程序----------------------------DELAY:MOV R0, #50;给R0赋值50 D2:MOV R1, #10;给R1赋值10 D1:DJNZ R1, D1;R1减1不等于0跳到D1处 DJNZ R0, D2;R0减1不等于0跳到D2处RET;延时子程序结束返回调用该程序的下一条;---------------下面的数据表中存储的是显示段码(共阳)-------------------TAB:DB 0C0H,0F9H,0A4H,0B0H,99H;从TAB处开始存储0、1、2、3、4DB 92H ,82H ,0F8H,80H ,90H;5、6、7、8、9对应的显示段码 END;程序结束第二篇:基于单片机的时钟控制器设计时钟控制器设计任务书1.设计目的与要求设计出一个用于数字时钟的控制器,准确地理解有关要求,独立完成系统设计,要求所设计的电路具有以下功能:(1)显示:可以显示时、分和秒(2)调时功能:时(0-24)、分和秒(0-60)可以连续可调(3)时间日误差< 2秒(4)增加整点报时功能(5)增加闹钟任意设定功能 2.设计内容(1)画出电路原理图,正确使用逻辑关系;(2)确定元器件及元件参数;(3)进行电路模拟仿真;(4)SCH文件生成与打印输出;(5)PCB文件生成与打印输出; 3.编写设计报告写出设计的全过程,附上有关资料和图纸,有心得体会。
毕业回馈-89c51之定时器计数器(TimerCount)今天分享的是89c51系列单⽚机的内部资源定时器/计数器,在所有的嵌⼊式系统中都包含这两个内部功能。
⾸先先了解⼏个定时器/计数器相关的概念:•时钟周期:时钟周期 T 是时序中最⼩的时间单位,具体计算的⽅法就是1/时钟源频率,(⼀般单⽚机采⽤的是11.0592mHz)•机器周期:我们的单⽚机完成⼀个操作的最短时间。
标准51单⽚机,⼀个机器周期是 12 个时钟周期,也就是 12/11059200 秒。
•定时器:当T/C⼯作在定时器时,对振荡源12分频的脉冲计数,即每个机器周期计数值加1,计数频率=当前单⽚机⼯作频率/12。
当单⽚机⼯作在12MHz时,计数频率=1MHz,单⽚机每1us计数值加1。
•计数器:计数脉冲来⾃外部脉冲输⼊引脚 T0(P3.4)或T1(P3.5)。
当T0或T1引脚上负跳变时计数值加1。
识别引脚上的负跳变需要2个机器周期,即24个振荡周期。
所以T0或者T1 输⼊的可计数外部脉冲的最⾼频率为当前单⽚机⼯作频率/24。
当单⽚机⼯作在12MHz时,最⾼计数频率为500KHz,⾼于该频率将计数出错。
定时器/计数器所涉及到的寄存器如下:其中TCON为定时器/计数器T0,T1的可控制及窜起,同时也锁存T0,T1溢出中断源和外部请求中断源等。
TCON寄存器可以进⾏位寻址TCON中每⼀位的使⽤如下:注:TF1:定时器/计数器T1溢出标志。
T1被允许计数以后,从初值开始加1计数。
当最⾼位产⽣溢出时由硬件置‘1’TF1,向CPU发送中断请求,⼀直保持到CPU响应中断时,由硬件⾃动清零,当不执⾏中断时,也可以通过查询的⽅式对TF1标志位进⾏软件清零TR1:定时器T1的运⾏控制位。
由软件置位和清零。
当GATE(TMOD.7)=0,TR1=1时就运⾏T1开始计数,TR1=0时禁⽌T1计数。
当GATE(TMOD.7)=1,TR1=1且INTI外部输⼊⾼电平时,才允许T1计数TF0:同TF1拥有两种清零⽅式TMOD寄存器不可位寻址:每⼀位的使⽤如下:THx/TLx(x=0,1)介绍如下:T/C是16位的,计数寄存器由TH⾼8位和TL低8位构成。
单片机89C51精确延时高手从菜鸟忽略作起之(六)一,晶振与周期:89C51晶振频率约为12MHZ。
在此基础上,计论几个与单片机相关的周期概念:时钟周期,状态周期,机器周期,指令周期。
晶振12MHZ,表示1US振动12次,此基础上计算各周期长度。
时钟周期(W sz):Wsz=1/12=0.083us状态周期(W zt) Wzt=2*Wsz=0.167us机器周期(W jq): Wjq=6*Wzt=1us指令周期(W zl): W zl=n*Wjq(n=1,2,4)二,指令周期汇编指令有单周期指令,双周期指令,四周期指令。
指令时长分别是1US,2US,4US.指令的周期可以查询绘编指令获得,用下面方法进行记忆。
1.四周期指令:MUL,DIV2.双周期指令:与SP,PC相关(见汇编指令周期表)3.单周期指令:其他(见汇编指令周期表)三,单片机时间换算单位1.1秒(S)=1000毫秒(ms)2.1毫秒(ms)=1000微秒(us)3.1微秒(us)=1000纳秒(ns)单片机指令周期是以微秒(US)为基本单位。
四,单片机延时方式1.计时器延时方式:用C/T0,C/T1进行延时。
2.指令消耗延时方式:本篇单片机精确延时主要用第2种方式。
五,纳秒(ns)级延时:由于单片机指令同期是以微秒(US)为基本单位,因此,纳秒级延时,全部不用写延时。
六,微秒(US)级延时:1.单级循环模式:delay_us_1最小值:1+2+2+0+2+1+2+2=12(US),运行此模式最少需12US,因此12US以下,只能在代码中用指定数目的NOP来精确延时。
最大值:256*2+12-2=522(US),256最大循环次数,2是指令周期,12是模式耗时,-2是模式耗时中计1个时钟周期。
延时范围:值域F(X)[12,522],变量取值范围[0,255].函数关系:Y=F(x):y=2x+12,由输入参数得出延时时间。
反函数:Y=F(x):y=1/2x-6:由延时时间,计算输入参数。
AT89C51定时器/计数器1.定时和计数功能:AT89C51有两个可编程的定时器和计数器:T0和T1。
它们可以工作在定时状态也可以工作在计数状态。
做定时器时不能用作计数,反之亦然。
2.计数器:当定时器/计数器作“计数器”用时,可对接到14引脚(T0/P3.4)或15引脚(T1/P3.5)的脉冲信号数进行计数,每当引脚发生从“1”到“0”的负跳变时,计数器加1.3.定时器:当定时器/计数器作“定时器”用时,定时信号来自内部的时钟发生电路,每个机器周期等于十二个震荡周期,每过一个机器周期,计数器加1.当晶振频率为12MHz时,则机器周期为1微秒;在此情况下,若计数器为100,则所定时的时间为:100x1=100微秒。
4.与定时器/计数器有关的特殊功能寄存器5.定时器/计数器的控制AT89C51单片机定时器/计数器的工作由两个特殊的寄存器TMOD和TCON的相关位来控制,TMOD用于设置它的工作方式,TCON用于控制其启动和中断的请求。
1).TMOD用于设置定时器/计数器的工作方式,其字节地址为89H。
低四位用于T0,高四位用于T1。
虽有位名称,但无位地址,不可进行位操作。
TMOD中的结构和各位名称○1M1,M0:工作方式选择位。
M1、M0为两位二进制数,可表示四种工作方式,见下表:○2C/T:计数/定时方式选择位。
C/T = 1,为计数工作方式,对输入到单片机T0、T1引用的外部信号脉冲计数,负跳变脉冲有效,用作计数器。
C/T = 0,为定时工作方式,对片内机器周期(1个机器周期等于12晶振周期)信号计数,用作定时器。
○3GATE:门控位。
GATE = 0,定时器/计数器的运行只受TCON中的运行控制位TR0/TR1的控制。
GATE = 1,定时器/计数器的运行同时受TR0/TR1和外中断输入信号(INT0和INT1)的双重控制。
GATE对TR0/TR1的制约2).控制寄存器TCONTCON是可位寻址的特殊功能寄存器,其字节地址为88H,位地址由低到高顺序分别为88H~8FH,TCON的低四位只与外中断有关,其高四位与定时器/计数器有关。
AT89C51定时器/计数器1.定时和计数功能:AT89C51有两个可编程的定时器和计数器:T0和T1。
它们可以工作在定时状态也可以工作在计数状态。
做定时器时不能用作计数,反之亦然。
2.计数器:当定时器/计数器作“计数器”用时,可对接到14引脚(T0/P3.4)或15引脚(T1/P3.5)的脉冲信号数进行计数,每当引脚发生从“1”到“0”的负跳变时,计数器加1.3.定时器:当定时器/计数器作“定时器”用时,定时信号来自内部的时钟发生电路,每个机器周期等于十二个震荡周期,每过一个机器周期,计数器加1.当晶振频率为12MHz时,则机器周期为1微秒;在此情况下,若计数器为100,则所定时的时间为:100 x 1 =100微秒。
14.与定时器/计数器有关的特殊功能寄存器5.定时器/计数器的控制AT89C51单片机定时器/计数器的工作由两个特殊的寄存器TMOD和TCON的相关位来控制,TMOD用于设置它的工作方式,TCON用于控制其启动和中断的请求。
1).TMOD用于设置定时器/计数器的工作方式,其字节地址为89H。
低四位用于T0,高四位用于T1。
虽有位名称,2但无位地址,不可进行位操作。
TMOD中的结构和各位名称○1M1,M0:工作方式选择位。
M1、M0为两位二进制数,可表示四种工作方式,见下表:○2C/T:计数/定时方式选择位。
C/T = 1,为计数工作方式,对输入到单片机T0、T1引用的外部信号脉冲计数,负跳变脉冲有效,用作计数器。
C/T = 0,为定时工作方式,对片内机器周期(1个机器周期等于12晶振周期)信号计数,用作定时器。
3○3GATE:门控位。
GATE = 0,定时器/计数器的运行只受TCON中的运行控制位TR0/TR1的控制。
GATE = 1,定时器/计数器的运行同时受TR0/TR1和外中断输入信号(INT0和INT1)的双重控制。
GATE对TR0/TR1的制约2).控制寄存器TCONTCON是可位寻址的特殊功能寄存器,其字节地址为88H,位地址由低到高顺序分别为88H~8FH,4TCON的低四位只与外中断有关,其高四位与定时器/计数器有关。
//data: 2010-07-06//writer: wu xian dian//fame: wan nian li//function:a时分秒的精确显示及设定;b定时的精确显示及设定;c定时时刻不影响时钟精确走时;// d当输入数值有误将蜂鸣报警且数值归1或0;e可以进行定时时间的查看;// f可进行星期的设定及查看g可进行年月日的设定及查看// h可进行平、闰年的分辨;i拥有定时时间到报时1分及整点提示,显示不会闪烁;// j定时、调时为移位显示,设定万年历为单显;星期、定时、调时、年、月日分屏显示;// k可进行数码管和蜂鸣器的检验;L当闹钟响起可随时关闭;#include<at89x51.h>void control(void);//判断是否进行键盘操作;void display(char,char);//显示,位控和段控;void delayms(unsigned int x);//延时;void common(void);//定时、调时显示控制;void fixed_times(void);//定时,进行时分秒输入。
先按11号键,再按六位数字键,自动返回运行;void swap_times(void);//调时,进行时分秒输入。
先按12号键,再按六位数字键,自动返回运行;void fixed_show(void);//全显示,检查数码管和蜂鸣器好坏,按零号键;void week(void);//星期设定8返回7;void week_show(void);//星期显示6返回5;void calendar_show(void);//日历显示4显示年,3显示月日,2返回;void calendar(void);//日历设定2显示年,3显示月日,4返回;char key(void);//键盘;void initial(void);//初始化;定时中断char hour1=1,hour0=2,min1=0,min0=0,sec1=0,sec0=0,n=0,w=1,v=1,//主显示全局变量;n循环次数w星期显示v闹铃判断位;fhour1=0,fhour0=0,fmin1=0,fmin0=0,fsec1=0,fsec0=0,//定时、调时共用全局变量;t6=0,t5=6,t4=0,t3=0,t2=0,t1=0,//定时显示全局变量;year3=2,year2=0,year1=1,year0=0,mouts1=0,mouts0=7,day1=0,day0=7;//年月日全局变量;int a1[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年;int a0[12]={31,29,31,30,31,30,31,31,30,31,30,31};//闰年;int *p;//为a1.a0设置指针;//********************************************************************定义和声明;void main(void){initial();//初始化while(1){P1=0x0f;if(P1!=0x0f)//判位进入调控程序;control();P1=0xff;display(5,hour1);///主显示程序;delayms(150);display(4,hour0);delayms(150);display(3,min1);delayms(150);display(2,min0);delayms(150);display(1,sec1);delayms(150);display(0,sec0);delayms(150);}}//*************************************************判位操作显示;void control(void){P1=0xbf;if(P1==0xbe)// 1显示数码管和蜂鸣器,自动返回;{P2=0x00;P0=0xff;delayms(2000);}else if(P1==0xb7)//4显示某年,3显示某月日,2返回;calendar_show();else if(P1==0xbb)// 3定时年,2定时月日,1返回;calendar();P1=0xef;if(P1==0xeb)// 11定时,自动返回;fixed_times();else if(P1==0xe7)// 12调时,自动返回;swap_times();else if(P1==0xed)// 10显示定时9返回;fixed_show();P1=0xdf;if(P1==0xd7)// 8星期设置7返回;week();else if(P1==0xdd)// 6星期显示5返回;week_show();else if(P1==0xde)//关闭闹铃;v=1;}//******************************************************中断入口;void time0(void) interrupt 1//定时中断0;{ unsigned int q;if(v==0)//盘闹铃是否工作;P2_7=0;elseP2_7=1;q=year3*1000+year2*100+year1*10+year0;//平、闰年判别;if((q%4==0&&q%100!=0)||(q%400==0))p=a0;//闰年指针指向;else p=a1;//平年指针指向;TH0=0xb8;//20ms定时;TL0=0x00;n==50? n=0:++n;//循环次数;if(n==0)//时分秒的进位;{++sec0;if(sec0==10){sec0=0;++sec1;if(sec1==6){sec1=0;++min0;if(hour1==t6&&hour0==t5&&min1==t4&&min0==t3)//判蜂鸣器响,v=0;//闹铃标志位;else//判蜂鸣器,虽然雍杂,但蜂鸣时数码管不闪烁;v=1;if(min0==10){min0=0;++min1;if(min1==6){min1=0;++hour0;P2_7=0;delayms(8000);if(hour0==10){hour0=0;++hour1;}}}}}}if((hour1==2)&&(hour0==4))//判是否大于24点{hour1=0;hour0=0;++w;if(w>7||w<1)//星期控制1-7天;w=1;if(++day0==10)//日的判断进位;{day0=0;++day1;}if(day1*10+day0>*(p+(mouts1*10+mouts0-1))){day0=1;day1=0;++mouts0;}if(mouts0==10)//月的判断进位;{mouts0=0;++mouts1;}if(mouts1*10+mouts0>12){mouts0=1;mouts1=0;++year0;}if(year0==10)//年的判断进位;{year0=0;++year1;if(year1==10){year1=0;++year2;if(year2==10){year2=0;++year3;if(year3==10){year3=0;}}}}}}////*****************************************************************显示程序;void display(char m,char n){unsigned char y[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};unsigned char z[6]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};P2=z[m];P0=y[n];}///*********************************************************************延时程序;void delayms(unsigned int x){unsigned int y;for(y=0;y<x;++y);}////****************************************************************键盘程序;char key(void){P1=0x0f;loop: if(P1==0x0f)goto loop;delayms(3350);if(P1==0x0f)goto loop;while(1){ P1=0xbf;if(P1_0==0) {while(P1!=0xbf); return 0;}if(P1_1==0) {while(P1!=0xbf); return 1;}if(P1_2==0) {while(P1!=0xbf); return 2;}if(P1_3==0) {while(P1!=0xbf); return 3;}P1=0xdf;if(P1_0==0) {while(P1!=0xdf); return 4; }if(P1_1==0) {while(P1!=0xdf); return 5;}if(P1_2==0) {while(P1!=0xdf); return 6;}if(P1_3==0) {while(P1!=0xdf); return 7;}P1=0xef;if(P1_0==0) {while(P1!=0xef); return 8;}if(P1_1==0) {while(P1!=0xef); return 9;}}}//*************************************************************定时时间程序;void fixed_times(void){P2=0xfe;P0=0x71;common();t6=fhour1;t5=fhour0;t4=fmin1;t3=fmin0;t2=fsec1;t1=fsec0;}///************************************************************调时程序;void swap_times(void){P2=0xfe;P0=0x6d;common();hour1=fhour1;hour0=fhour0;min1=fmin1;min0=fmin0;sec1=fsec1;sec0=fsec0;}//************************************************************初始化程序;void initial(void){TH0=0xb8;TL0=0x00;IE=0x82;TMOD=0x01;TR0=1;}//*******************************************调时、定时共用设定和显示程序;void common(void){char f=0,j=0,k;for(k=0;k<6;++k){switch(++f){case 1:{for(fsec0=key();fsec0>2;fsec0=0){P2_7=0;delayms(3000);}P2_7=1;break;}case 2:{fsec1=fsec0;for(fsec0=key();fsec1>=2&&fsec0>=4;fsec0=0){P2_7=0;delayms(3000);}P2_7=1;break;}case 3:{fmin0=fsec1;fsec1=fsec0;for(fsec0=key();fsec0>5;fsec0=0){P2_7=0;delayms(3000);}P2_7=1;break;}case 4:{fmin1=fmin0;fmin0=fsec1;fsec1=fsec0;fsec0=key();break;}case 5:{fhour0=fmin1;fmin1=fmin0;fmin0=fsec1;fsec1=fsec0;for(fsec0=key();fsec0>5;fsec0=0){P2_7=0;delayms(3000);}P2_7=1;break;}case 6:{fhour1=fhour0;fhour0=fmin1;fmin1=fmin0;fmin0=fsec1;fsec1=fsec0;fsec0=key();break;}}for(P1=0x0f;(P1==0x0f)&&(f<=6);j=0){if(++j<=f){display(0,fsec0);delayms(200);if(++j<=f){display(1,fsec1);delayms(200);if(++j<=f){display(2,fmin0);delayms(200);if(++j<=f){display(3,fmin1);delayms(200);if(++j<=f){display(4,fhour0);delayms(200);if(++j<=f){display(5,fhour1);delayms(200);}}}}}}}}}///********************************************************定时显示程序;void fixed_show(void){do{P1=0xef;display(5,t6);delayms(150);display(4,t5);delayms(150);display(3,t4);delayms(150);display(2,t3);delayms(150);display(1,t2);delayms(150);display(0,t1);delayms(150);}while(P1!=0xee);}//*****************************************星期设定程序;void week(void){delayms(5000);for(w=key();w>7||w<1;w=1);P1=0xdf;dodisplay(5,w);while(P1!=0xdb);P1=0xff;}//******************************************星期显示程序;void week_show(void){P1=0xdf;dodisplay(5,w);while(P1!=0xde);P1=0xff;}///*****************************************万年历显示程序;void calendar_show(void){do{display(4,year3);//年显示;delayms(150);display(3,year2);delayms(150);display(1,year1);delayms(150);display(0,year0);delayms(150);}while(P1!=0xbb);do{display(4,mouts1);//月日显示;delayms(150);display(3,mouts0);delayms(150);display(1,day1);delayms(150);display(0,day0);delayms(150);}while(P1!=0xbd);P1=0xff;}//*******************************************万年历设定程序;void calendar(void){P2=0xfe;P0=0x6e;do{}while(P1==0xbb);display(4,year3=key());//年设定;display(3,year2=key());display(1,year1=key());display(0,year0=key());do{P1=0xbf;}while(P1!=0xbd);P2=0xfe;P0=0x63;do{}while(P1==0xbd);//月日设定;display(4,mouts1=key());display(3,mouts0=key());if(mouts1*10+mouts0>12||mouts1*10+mouts0<1) {mouts1=0;mouts0=1;P2_7=0;delayms(1200);}P2_7=1;display(1,day1=key());display(0,day0=key());if(day1*10+day0>*p||day1*10+day0<1){day1=0;day0=1;P2_7=0;delayms(1200);}P2_7=1;do{P1=0xbf;}while(P1!=0xbe);P1=0xff;}。
89C51单片机定时器时间的计算以及写法
今晚学单片机的时候,有一点儿问题,就去网上看了看,发现了很多人不会单片机定时,也就是具体时间的设定,不知道如何设定,而且有关方面的书籍、资料讲解又太过术语化,所以就写一篇通俗些的语言讲述一下如何定时。
为了便于理解,先讲解一点儿关于单片机内部定时器和计数器的基本知识,如果学过数字电路,就不用管这些,看下边的就好了:
(1)由于单片机内部定时器、计数器均为八位,所以它们从0开始到计数计满,也就是能从0000 0000计数到1111 1111,即
2^0到2^16,转换成十进制,就是0——65536。
(2)外部的晶振电路提供的频率,到单片机内部,经过硬件电路,进行了12分频,不要问为什么,就这么记着就好了。
比如外
部晶振是12MHZ的,那么到了单片机内部,用的频率就是
1MHz的。
89C51单片机常使用的晶振频率为12MHz和11.0592MHz两种,主要讲述这两种频率的,如果用其他的,只需要相应改变即可,下面分别讲述如何定时:
(1)使用12MHz晶振:
单片机工作的频率f:12MHz/12=1MHz,
那么时钟周期T1:T1=1/f=1μs,
比如你要定时T2=50ms=50000μs,
你需要总时间T=T1 x T2=50000,也就是说你需要50000个周期才能走完你所要定的时间,当把数全都计满,是需要65536个周期,也就是说还有65536-50000=15536个周期没有走,那么,我们可以把这个初始值放到计数器里面,让它从15536开始计数,当计够50000个周期,也就计满了,即到达了65536。
就像水往水缸里流,你需要流满半缸水的时间,但是现在水缸是空的,你可以先把水缸灌半缸水,然后让它从半缸水开始流,当流满了的时候,也就到了你需要的那个时间。
然后,15536转成十六进制为:0x3CB0,将3C放到定时器的高8位,B0放到第8位,就完成了定时。
我们在写程序赋初始值的时候一般是这么写的,可以参考一下:TH0=0x3C;
TL0=0xB0;
或者
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
PS:如果你定时是其他的,可以把根据我上边讲解的,把T=50000换成相应的数值即可。
(2)使用11.0592MHz晶振:
单片机工作的频率f:11.0592MHz/12=0.9216MHz,
那么时钟周期T1:T1=(1/0.9216)μs,
比如你要定时T2=50ms=50000μs,那么总时间T= T1 x
T2=46080个周期才能走完,所以,剩下了65536-46080=19456个周期,只要把定时器的初始值设置为19456就可以了。
根据上边的,可以把19456转化成十六进制,为0x4C00,高8位放置4C,第8位放置00即可。
在赋初值的时候可以这么写:
TH0=0x4C;
TL0=0x00;
或者
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
PS:通过两个对比,可以看出,第二个程序会明显好于第一个,因为只需要改动里面的T=50000,即可,不需要进行进制的转换。
介绍完了之后,总结一下定时的步骤:
确定晶振为除以12,进行分频
频率求倒数Y,即为时钟周期所定时间为Z,总时间即为
(把十进制转为十六进制 HHLL )高八位放HH,第八位放LL。