基于51单片机的定时/计数器设计

1 篇文章 0 订阅
1 篇文章 0 订阅

一、设计目的

  1. 掌握定时/计数器工作的基本原理;
  2. 掌握一个完整的C语言程序结构;熟悉定时/计数器的编程

二、设计环境

  1. Keil开发环境
  2. Proteus软件。

三、设计及调试
(1) 设计内容

  1. 通过定时计数器实现秒与分的定时;
  2. 将定时的秒与分在LCD上显示。

(2) 设计硬件电路
在这里插入图片描述
AT89C51单片机,LCD1602

(3) 设计过程及调试关键步骤
首先在Proteus仿真软件上进行硬件电路的连接,连接完后用一个简单的显示程序检测能否显示,显示无误后开始编程。编程需要在原来LCD1602程序上添加初始化、中断,写入时钟三个子函数,首先在Keil中设置晶振频率为12MHz,之后根据晶振频率进行初值的运算与转载,运用T1定时器进行方式1中断。调试时观察显示位置并进行调整

四、设计结果与分析
(1) 程序

#include <reg51.h>
#include <intrins.h>  //包含_nop_( )空函数指令的头文件
#define uchar unsigned char
#define uint unsigned int 
sbit RS=P2^0; 	//位变量
sbit RW=P2^1;	//位变量
sbit E=P2^2; 	//位变量
void lcduchar digit;//全局变量判断中断次数
uchar second;        //秒
uchar minute;        //分
void clock_initial();//时钟初始化
void clock_write(uchar s,uchar m);//写入时钟
void lcd_initial(void);	//LCD初始化函数
void check_busy(void); 	//检查忙标志函数
void write_command(uchar com); 	//写命令函数
void write_data(uchar dat);//写数据函数
void delay(uint);//延时函数
uchar displaydata1[]=" LYZ CLOCK TIME "; //LCD显示第一行的内容
uchar displaydata2[]=" 00:00          ";//LCD显示第二行的内容
void main(void) //主函数
{	
lcd_initial( );	//调用对LCD初始化函数	
clock_initial(); //时钟初始化	
TMOD=0x10;  //设置定时器T1以方式1定时	
EA=1;       //开总中断	
ET1=1;      //允许T1中断	
TH1=(65536-50000)/256;  //12MHz下装载高八位初值	
TL1=(65536-50000)%256;  //12MHz下装载低八位初值	
TR1=1;      //启动定时器	
digit=0;    //开始计数	
second=0;//初值	
minute=0;	
while(1){		
clock_write(second,minute);}}
void T1_interserve(void) interrupt 3//T1中断服务
{	
digit++;	
if(digit==20){		
digit=0;		
second++;}	
if(second==60){		
second=0;		
minute++;}	
if(minute==60){		
minute=0;}	
TH1=(65536-50000)/256;  //12MHz下装载高八位初值	
TL1=(65536-50000)%256;  //12MHz下装载低八位初值
}
void clock_initial()//时钟初始化
{	
uchar i;	
write_command(0x80);	
for(i=0;i<16;i++){		
write_data(displaydata1[i]);}	
write_command(0xc0);	
for(i=0;i<16;i++){		
write_data(displaydata2[i]);}	}
void clock_write(uchar s,uchar m) //写入时钟
{	
write_command(0xc1);	
write_data(m/10+0x30);	
write_data(m%10+0x30);	
write_command(0xc4);	
write_data(s/10+0x30);	
write_data(s%10+0x30);}
void delay(uint j)//1ms延时子程序
{	
uchar i=250;	
for(;j>0;j--)	
{		
while(--i);		
i=249;		
while(--i);		
i=250;	}}
void check_busy(void) {	//检查忙标志函数	
uchar dt;	
do	
{		
dt=0xff;		
E=0;		
RS=0;			
RW=1;		
E=1;		
dt=P3;	}
while(dt&0x80);	
E=0;}
void write_command(uchar com) {     //写命令函数	
check_busy();	
E=0;	
RS=0;	
RW=0;	
P3=com;	E=1;	
_nop_( );	
E=0;	
delay(1);}
void write_data(uchar dat) //写数据函数
{	
check_busy();	
E=0;	
RS=1;	
RW=0;	
P3=dat;	
E=1;	
_nop_();	
E=0;	
delay(1);	}
void LCD_initial(void)	 //液晶显示器初始化函数
{	
write_command(0x38);	//写入命令0x38:8位两行                 
显示,5×7点阵字符	
write_command(0x0c);	//写入命令0x0C:开整体	         
显示,光标关,无黑块	
write_command(0x06);	//写入命令0x06:光标右移	
write_command(0x01); 	//写入命令0x01:清屏	
delay(1);}

(2) 实现结果及现象
最初,LCD1602第一行显示LYZ CLOCK TIME,第二行显示00:00表示0分0秒
在这里插入图片描述
时钟开始计数
在这里插入图片描述
计数到分时
在这里插入图片描述
(3) 实验结果的分析与总结,有无改进方案?
实验结果的分析与总结:第一行第二行都显示清晰,时钟计时与实际中相差不大,由于使用的是方式1的计时,会有些许误差。改进方案:可使用方式2的方式进行计时,减小误差。

  • 7
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Is_LiuYiZheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值