基于STC89C52-51基础学习单片机万年历作品功能实现

作品功能
1.时钟的时,分,秒的自走
2.闹钟的设定,闹铃时出现流水灯和蜂鸣器滴滴,按S2键停止闹钟,时钟继续工作
3.使用独立按键S2切换时钟和闹钟调节模式,用一杆和两杠区分时钟和闹钟模式
4.使用S3,S4,S5可分别调节闹钟和时钟的时,分,秒位
5.掉电存储当前时间和闹钟设定时间,通电时再读取上一次掉电时的数据

#include<reg52.h>  
#include<intrins.h>
#include<stdlib.h>
#define uchar unsigned char
#define uint unsigned int 
#define ulong unsigned long  
sbit wx = P2^7;	//数码管位选
sbit dx = P2^6;	//数码管段选
sbit key_s2 = P3^0;//S2按键位定义
uchar code smg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x41};
uchar second=0,minute=0,hour=0,count=0;
uchar nsecond=10,nminute=0,nhour=0;
uchar o=0;
sbit xiang= P2^3;
sbit Key1 = P3^0; //时钟的停止与开始
sbit Key2 = P3^1; //小时的调节
sbit Key3 = P3^2; //分钟的调节
sbit Key4 = P3^3; //秒数的调节  
sbit sda=P2^0;    //IO口
sbit scl=P2^1;
int music[40] = {1,2,3,1,1,2,3,1,3,4,5,5,3,4,5,5,5,6,5,4,3,1,5,6,5,4,3,1,1,5,1,1,1,5,1,1,};//想实现两只老虎的闹钟蜂鸣器,中断方式1冲突
unsigned char High,Low;
unsigned char code freq[][2] = 
{ 
  0xD8,0xF7,//00440HZ 1   
  0xBD,0xF8,//00494HZ 2  
  0x87,0xF9,//00554HZ 3  
  0xE4,0xF9,//00587HZ 4    
  0x90,0xFA,//00659HZ 5     
  0x29,0xFB,//00740HZ 6     
  0xB1,0xFB,//00831HZ 7      
  0xEF,0xFB,//00880HZ `1
};	//闹钟的音阶   
//延时函数
void delay(uint x)
{
uint i,j;
for(i=0;i<x;i++)
  for(j=0;j<110;j++); 
}
//数码管显示数据
void dispw(uchar i,j)
{
 
 dx=0;
 wx=1;
 P0= _cror_(0x7f,j);
 wx=0; 
 dx=1;
 P0=smg[i];
 delay(1);
 wx=1;
 P0=0xff;
 wx=0;
}
//定时器初始化
void timeint()
{
	TR0  = 1;	 //启动定时器0
	TMOD = 0X01; //定时器工作模式1
    TH0=(65536-10000)/256; 
    TL0=(65536-10000)%256;//时间设置为10ms
	ET0 = 1;
	EA = 1;
}

//时钟的中断
void time_int(void) interrupt 1	
{
    TH0=(65536-10000)/256;
    TL0=(65536-10000)%256;
	count++;
	if(count==100)//时间度过1s,秒数显示加1
	{
		count=0;
		second++;
	if(second==60)
	{
		second=0;
		minute++;
	    if(minute==60)
		{
			minute=0;
			hour++;
			if(hour==24)
			{
				hour=0;
				
			}
		}
	}
   }
   //整点报时
if(second==00&&minute==00)								   
	xiang=0;
else
	xiang=1; 
   //当前时间为闹钟设置时间时,流水灯和蜂鸣器
if(second==nsecond&&minute==nminute&&hour==nhour)
	{
	uchar a=0;
	//按键关闭流水灯和蜂鸣器    
	   while(Key1==1)
	   {
              xiang=~xiang;
			  P1=_crol_(0xfe,a);
			  delay(50);	
			  a++;
		}

    }
	//LED灯全部置为熄灭状态	  
	P1=0xff;	
	
}
void nop()
{
	_nop_();
	_nop_();
}
//24c02初始化
void init()  
{
	scl=1;
	nop();
	sda=1;
	nop();
}
//启动I2C总线
void start()        
{
	sda=1;
	nop();
	scl=1;
	nop();
	sda=0;
	nop();
	scl=0;
	nop();
}
//停止I2C总线
void stop()         
{
	sda=0;
	nop();
	scl=1;
	nop();
	sda=1;
	nop();
}
//写一个字节的数据
void writebyte(unsigned char j) 
{
	unsigned char i,temp;
   	temp=j;
   	for (i=0;i<8;i++)
   {
	   temp=temp<<1;
	   scl=0;
	   nop();
	   sda=CY;		//temp左移时,移出的值放入了CY中
	   nop();
	   scl=1;		//待sda线上的数据稳定后,将scl拉高
	   nop();
   }
   scl=0;
   nop();
   sda=1;
   nop();
}
//读一个字节的数据
unsigned char readbyte()   
{
   unsigned char i,j,k=0;
   scl=0; nop(); sda=1;
   for (i=0;i<8;i++)
   {  
		nop(); scl=1; nop();
      	if(sda==1) 
		j=1;
      	else
		j=0;
      	k=(k<<1)|j;
	  	scl=0;
	}
   	nop();
	return(k);
}
//I2C总线时钟
void clock()         
{
   unsigned char i=0;
   scl=1;
   nop();
   while((sda==1)&&(i<255))
   	  i++;
   scl=0;
   nop();
}

//从24c02的地址address中读取一个字节数据
unsigned char read24c02(unsigned char address)
{
   unsigned char i;
   start();
   writebyte(0xa0);
   clock();
   writebyte(address);
   clock();
   start();
   writebyte(0xa1);
   clock();
   i=readbyte();
   stop();
   delay(1);
   return(i);
}

//向24c02的address地址中写入一字节数据info
void write24c02(unsigned char address,unsigned char info)
{
   EA=0;
   start();
   writebyte(0xa0);
   clock();
   writebyte(address);
   clock();
   writebyte(info);
   clock();
   stop();
   EA=1;
   delay(1);
}
//监视按键的读入
void Keyscan()
{	//调节当前时间 
	if(o%2==0) 
	{   
		if(Key4==0)
			{
				delay(10); 
				if(Key4==0)
				while(!Key4);
				second++;
				if(second==60)
				second=0;
			}
		if(Key3==0)
			{
				delay(10); 
				if(Key3==0)
				while(!Key3);
				minute++;
				if(minute==60)
				minute=0; 
			}
	
		if(Key2==0)
			{ 
				delay(10); 
				if(Key2==0)
				while(!Key2);
				hour++;
				if(hour==24)
				hour=0; 
			}
	 }
	 //调节闹钟设定时间
	 if(o%2==1)
	 {
		if(Key4==0)
			{
				delay(10); 
				if(Key4==0)
				while(!Key4);
				nsecond++;
				if(nsecond==60)
				nsecond=0;
			}
		if(Key3==0)
			{
				delay(10); 
				if(Key3==0)
				while(!Key3);
				nminute++;
				if(nminute==60)
				nminute=0; 
			}
	
		if(Key2==0)
			{ 
				delay(10); 
				if(Key2==0)
				while(!Key2);
				nhour++;
				if(nhour==24)
				nhour=0; 
			}	 
	 }

}
void main()
{	//定时器初始化
	timeint();

	//读出存入24C02的数据
	second=read24c02(1);
	minute=read24c02(2);
	hour=read24c02(3);
	nsecond=read24c02(4);
	nminute=read24c02(5);
	nhour=read24c02(6);
	
	
	while(1)
	{
		//判断按键s2的按压次数
		if(Key1==0) 
		{
			delay(10); 
			if(Key1==0) 
			while(!Key1); 
			o++;
		} 
		//按压为偶数次时显示当前时间
		if(o%2==0)
		{
		  dispw(second%10,0);
		  dispw(second/10,1);
		  dispw(minute%10,3);
		  dispw(minute/10,4);
		  dispw(hour%10,6);
		  dispw(hour/10,7);	
		  dispw(10,2);
		  dispw(10,5);
		} 
		//按压为奇数次时显示设置的闹钟时间
		if(o%2==1)
		{
		  dispw(nsecond%10,0);
		  dispw(nsecond/10,1);
		  dispw(nminute%10,3);
		  dispw(nminute/10,4);
		  dispw(nhour%10,6);
		  dispw(nhour/10,7);
		  dispw(11,2);
		  dispw(11,5);
		}   
		  //监视按键的读入分别调节时间和闹钟
		  Keyscan();
		  //断电时存入数据到24CO2中	 
		  write24c02(1,second);
		  write24c02(2,minute);
		  write24c02(3,hour);
		  write24c02(4,nsecond);
		  write24c02(5,nminute);
		  write24c02(6,nhour);
	}
	
}
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
基于STC89C52单片机和超声波模块的测距功能可以通过以下C语言实现。 首先,需要在程序中定义一些常量和变量以方便使用。定义TRIG_PIN作为超声波模块的发送引脚,ECHO_PIN作为接收引脚,以及定义时间和距离的变量。 ```c #include <reg52.h> #define TRIG_PIN P1_0 #define ECHO_PIN P1_1 unsigned int duration; // 声波往返时间 unsigned int distance; // 测距距离 ``` 接下来,可以编写初始化函数,选择超声波模块需要的IO口为输出或输入。 ```c void init() { TR0 = 1; // 启动定时器0,用于测量声波往返时间 IT0 = 1; // 外部中断0的触发方式为下降沿触发 EX0 = 1; // 开启外部中断0 } ``` 然后,编写触发超声波发送函数。首先将发送引脚置为高电平,延时10us,然后将发送引脚置为低电平,触发超声波发送。 ```c void trigger() { TRIG_PIN = 1; delay_us(10); TRIG_PIN = 0; } ``` 接下来,编写响应超声波接收的函数。当检测到超声波信号返回时,触发外部中断0,并计算声波往返时间。 ```c void echo() interrupt 0 { if (ECHO_PIN == 1) { TMOD |= 0x01; // 设置定时器0为模式1,16位定时器 TH0 = 0; // 定时器0高8位清0 TL0 = 0; // 定时器0低8位清0 TR0 = 1; // 启动定时器0 } else { TR0 = 0; // 停止定时器0 duration = (TH0 << 8) | TL0; // 获取定时器0的值 distance = duration * 0.034 / 2; // 距离计算,声速为340m/s } } ``` 最后,在主函数中调用初始化函数以及循环中调用触发函数实现测距功能。 ```c void main() { init(); while(1) { trigger(); // 触发超声波发射 delay_ms(100); // 延时100ms // 打印测距距离到数码管/显示屏等 } } ``` 上述代码实现了基于STC89C52单片机的超声波测距功能。通过初始化函数设定超声波模块的引脚,触发函数发送超声波信号,响应函数计算声波往返时间并计算测距距离。在主函数中循环触发超声波发射,并将测距结果打印到外部显示设备上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值