⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1602_8563.c

📁 avr单片机的程序
💻 C
字号:
/*************************************
*         PCF8563时钟程序			 *
* 文 件 名:1602_8563.c				 *
* 建立日期:2007年07月04日			 *
* 设    计:铜河					 *
* 修改日期:2007年07月08日			 *
* 版    本:V22.02				 	 *
* 主控芯片:Mega16L					 *
* 工作频率:7.3728MHz				 *
*************************************/
#include <iom16v.h>
#include <macros.h>
#include <stdio.h>
#include <D:\PCF8563\1602_time\timer_io.h>
#include <D:\PCF8563\1602_time\delay.h>
#include <D:\PCF8563\1602_time\lcd1602_4h.h>
#include <D:\PCF8563\1602_time\TWI_8563.h>

//数据简化宏定义
#define uchar unsigned char
#define uint unsigned int

//全局变量定义
uchar timer[8];		  				 //时钟数据

/**********************************
*         蜂鸣器发声函数  	  	  *
* 函数功能:蜂鸣器发出声响		  *
* 入    口:n 声次数	  		  *
* 			i 声时长,i*10ms	  *
* 返    回:无		  			  *
* 发声频率:固定1KHz 无源		  *
**********************************/
void spk(uchar i,uchar n)
    {
	uint a;
	for(;n;n--)
	    {
		a=i*10;	   	 		       //计算每声响的长度:MS
		for(;a;a--)
		    {
			delay_us(500);		   //响声频率为1KHZ
			SPK_TG;
			delay_us(500);
			SPK_TG;
			}
		SPK_OFF;   		  		   //响完关闭蜂鸣器
		delay_ms(100);			   //每声响之间隔100MS
		}
	}

/**********************************
*          读出数据函数			  *
**********************************/
uchar read_timer(void)
    {
	start();		 	 	          //启动总线
	waitack();						  //等待启动完成
	if(chkack()!=START)return I2C_ERR;		  //检查是否启动成功
	write_tim(SLA_W);				  //发送写地址
	write_tim(0x02);				  //写数据地址
	
	start();
	waitack();						  //等待启动完成
	if(chkack()!=RESTART)return I2C_ERR;	  //检查是否启动成功
	write_tim(SLA_R);				  //发送读地址
	
	timer[0]=read_tim()&0x7F;		  //读出秒数据
	timer[1]=read_tim()&0x7F;		  //读出分数据
	timer[2]=read_tim()&0x3F;		  //读出时数据
	timer[3]=read_tim()&0x3F;		  //读出日数据
	timer[4]=read_tim()&0x07;		  //读出周数据
	   if(timer[4]==0)timer[4]=7;
	timer[5]=read_tim();	  		  //读出月数据
	   if((timer[5]&0x80)==0)
	        timer[7]=0x20;	 		  //世纪位为0,是21世纪
	   else timer[7]=0x19;			  //世纪位不为0,是20世纪
	timer[5]=timer[5]&0x1F;
	timer[6]=read_tim();			  //读出年数据
	stop();
	return I2C_CRR;
	}

/**********************************
*          写入时钟函数			  *
**********************************/
uchar write_timer(void)
    {
	start();		 	 	          //启动总线
	waitack();						  //等待启动完成
	if(chkack()!=START)return I2C_ERR;		  //检查是否启动成功
	write_tim(SLA_W);				  //发送写地址
	write_tim(0x00);				  //写数据首地址
	write_tim(0x20);				  //写控制/状态寄存器1,暂停计时
	write_tim(0x00);				  //写控制/状态寄存器2
	write_tim(0x00);				  //写秒数据为0
	write_tim(timer[1]);			  //写分数据
	write_tim(timer[2]);			  //写时数据
	write_tim(timer[3]);			  //写日数据
	write_tim(timer[4]);			  //写周数据
	write_tim(timer[5]);			  //写月数据
	write_tim(timer[6]);			  //写年数据
	stop();
	return I2C_CRR;
	}
	
/**********************************
*          启动时钟函数			  *
**********************************/
uchar start_timer(void)
    {
	start();		 	 	          //启动总线
	waitack();						  //等待启动完成
	if(chkack()!=START)return I2C_ERR;		  //检查是否启动成功
	write_tim(SLA_W);				  //发送写地址
	write_tim(0x00);				  //写数据首地址
	write_tim(0x00);				  //写控制/状态寄存器1,暂停计时
	stop();
	return I2C_CRR;
	}

/**********************************
*   将时钟数据转换后在LCD上显示	  *
**********************************/ 
void timer_lcd(void)
    {
	locate(1,4);			 	 	 //写指令:第1行第4列地址

	lcd_da((timer[7]>>4)+0x30);
	lcd_da((timer[7]&0x0f)+0x30);
	lcd_da((timer[6]>>4)+0x30);		 //显示年
	lcd_da((timer[6]&0x0f)+0x30);
	lcd_da('/');
	lcd_da((timer[5]>>4)+0x30);		 //显示月
	lcd_da((timer[5]&0x0f)+0x30);
	lcd_da('/');
	lcd_da((timer[3]>>4)+0x30);		 //显示日
	lcd_da((timer[3]&0x0f)+0x30);

	locate(2,2);			 		 //写指令:第2行地址
   
   	lcd_da((timer[2]>>4)+0x30);		 //时
	lcd_da((timer[2]&0x0f)+0x30);
	lcd_da(':');
	lcd_da((timer[1]>>4)+0x30);		 //分
	lcd_da((timer[1]&0x0f)+0x30);
	lcd_da(':');   
	lcd_da((timer[0]>>4)+0x30);		 //秒
	lcd_da((timer[0]&0x0f)+0x30);

	lcd_da(20);						 //时间与星期间留1空格
	lcd_da('W');					 //星期的前导字
	lcd_da('e');
	lcd_da('e');
	lcd_da('k');
	lcd_da((timer[4]&0x0f)+0x30);	 //星期数据
	}

//定时器1:每秒从8563中读取4次数据,更新显示
void timer1_init(void)	       //定时器1初始化:250毫秒定时,预分频256
    {
	TCCR1B = 0x00; 		   	   //停止定时器
	TCNT1H = 0x8F;			   //初值高字节
	TCNT1L = 0x81;			   //定时初值低字节
	TCCR1A = 0x00;
	TCCR1B = 0x03; 	 	   	   //启动定时器
	}

#pragma interrupt_handler timer1_ovf_isr:9
void timer1_ovf_isr(void) 	   //定时器1中断入口:250MS中断一次
    {
	TCNT1H = 0x8F;			   //重装初值
	TCNT1L = 0x81;   
	read_timer();	   	   	   //读出当前时钟
	timer_lcd();		   	   //显示数据转换
	}

/**********************************
*          调整显示函数1		  *
**********************************/
void set_xs1(uchar i)
    {
	lcd_da((timer[i]>>4)+0x30);		 //显示数据
	lcd_da((timer[i]&0x0f)+0x30);
	}

/**********************************
*          调整显示函数2		  *
**********************************/
void set_xs2(uchar data)
    {
	lcd_da((data>>4)+0x30);		 //显示数据
	lcd_da((data&0x0f)+0x30);
	lcd(0x20);
	}

/**********************************
*           程序主函数		      *
**********************************/
void main(void)
    {
	uchar set_flag=0;			   //调整与正常工作标志
	uchar set_time;				   //调整数据类型标志
	uchar set_bh=0;				   //调整变化标志
	uchar a,a1;
	
	port_init();
	LED_ON;			  			   //开LCD背光
	lcd_init();
	delay_ms(500);
	tonghe();
	delay_ms(2000);
	
	Twi_Init();
	delay_ms(100);
	CLI(); 	 						//关总中断
	timer1_init();					//定时器1初始化
	MCUCR = 0x00;
	GICR  = 0x00;
	TIMSK = 0x04; 					//开放定时器0中断和比较中断
	SEI(); 							//开总中断
	
	cls();
	delay_ms(50);

	while(1)
	    {
		a=KEY_RD;
		if(a!=0)
		    {
			delay_ms(20);
			a1=KEY_RD;
			if(a1==a)
			    {
				switch(a)
				    {
					case 0x01:
						spk(10,1);
						if(set_flag==0)
						    {
							TCCR1B=0x00;
							LED_ON;
							set_flag=1;
							cls();
							locate(1,4);		   //显示“时间调整”
							xs_lcd("SET:");
							}
						else
							{
							TCCR1B=0x04;  		   //开启时钟
							set_flag=0;
							if(set_bh==1)
							    {
								write_timer();	   //写入新时间
								set_bh=0;
								}
							}
						break;
					case 0x02:
					    if(set_flag==1)
						    {
							spk(10,1);
							set_time++;					
							locate(2,2);		   	//显示待调整的数据
							switch(set_time)
						        {
								case 1:
							        xs_lcd("year:");
									set_xs1(6);		 //显示年
									break;
								case 2:
							    	xs_lcd("muth:");
									set_xs1(5);		 //显示月
									break;
								case 3:
							    	xs_lcd(" day:");
									set_xs1(3);		 //显示日
									break;
								case 4:
							    	xs_lcd("hour:");
									set_xs1(2);		 //显示时
									break;
								case 5:
							    	xs_lcd("mine:");
									set_xs1(1);		 //显示分
									break;
								case 6:
							    	xs_lcd("week:");
									set_xs1(4);		 //显示周
									break;
								default:set_time=0;break;
								}
							}
						break;
					case 0x04:
					    if(set_flag==1)
						    {
							spk(10,1);
							set_bh=1;
							locate(2,7);		   //显示“时间调整”
							switch(set_time)
							    {
								case 1:
								    timer[6]-=0x01;
									if((timer[6]&0x0F)==0x0F)timer[6]&=0xF9;
									if(timer[6]>0x99)timer[6]=0x99;
									set_xs1(6);		 //显示年
									break;
								case 2:
								    timer[5]-=0x01;
									if((timer[5]&0x0F)==0x0F)timer[5]&=0xF9;
									if(timer[5]==0x00)timer[5]=0x12;
									set_xs1(5);		 //显示月
									break;
								case 3:
								    timer[3]-=0x01;
									if((timer[3]&0x0F)==0x0F)timer[3]&=0xF9;
									if(timer[3]==0x00)timer[3]=0x30;
									set_xs1(3);		 //显示日
									break;
								case 4:
								    timer[2]-=0x01;
									if((timer[2]&0x0F)==0x0F)timer[2]&=0xF9;
									if(timer[2]>0x24)timer[2]=0x23;
									set_xs1(2);		 //显示时
									break;
								case 5:
								    timer[1]-=0x01;
									if((timer[1]&0x0F)==0x0F)timer[1]&=0xf9;
									if(timer[1]>0x59)timer[1]=0x59;
									set_xs1(1);		 //显示分
									break;
								case 6:
								    timer[4]-=0x01;
									if(timer[4]>6)timer[4]=0x06;
									set_xs1(4);		 //显示周
									break;
								default:set_time=0;break;
								}
							}
						else
							start_timer();
						break;
					case 0x08:
					    if(set_flag==1)
						    {
							spk(10,1);
							set_bh=1;
							locate(2,7);		   //显示“时间调整”
							switch(set_time)
								{
								case 1:
									timer[6]+=0x01;
									if((timer[6]&0x0F)==0x0A)timer[6]=(timer[6]&0xF0)+0x10;
									if(timer[6]>0x99)timer[6]=0x00;
									set_xs1(6);		 //显示年
									break;
								case 2:
									timer[5]+=0x01;
									if((timer[5]&0x0F)==0x0A)timer[5]=(timer[5]&0xF0)+0x10;
									if(timer[5]>=0x13)timer[5]=0x01;
									set_xs1(5);		 //显示月
									break;
								case 3:
									timer[3]+=0x01;
									if((timer[3]&0x0F)==0x0A)timer[3]=(timer[3]&0xF0)+0x10;
									if(timer[3]>=0x31)timer[3]=0x01;
									set_xs1(3);		 //显示日
									break;
								case 4:
									timer[2]+=0x01;
									if((timer[2]&0x0F)==0x0A)timer[2]=(timer[2]&0xF0)+0x10;
									if(timer[2]>=0x24)timer[2]=0x00;
									set_xs1(2);		 //显示时
									break;
								case 5:
									timer[1]+=0x01;
									if((timer[1]&0x0F)==0x0A)timer[1]=(timer[1]&0xf0)+0x10;
									if(timer[1]>0x59)timer[1]=0x00;
									set_xs1(1);		 //显示分
									break;
								case 6:
									timer[4]+=0x01;
									if(timer[4]>6)timer[4]=0x00;
									set_xs1(4);		 //显示周
									break;
								default:set_time=0;break;
								}
							}
						else
							LED_OFF;					 //关背光
						break;
					default:break;
					}
				}
			while(a!=0)
			    {
				a=KEY_RD;
				delay_ms(10);
				}
			}
		}
	}
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -