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

📄 ds1302.c

📁 AT89C51开发例程 protues仿真 keil编程
💻 C
字号:
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
/*********************共阳极***0****1****2*****3****4****5****6****7****8****9*/
const unsigned char led[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};	//led段码
const char dig[]   = { 0x01,0x02,0x04,0x08,0x10,0x20};	//led位选码
unsigned char bcd_dsp[6]={0,0,0};		//bcd码显示缓存
unsigned char dsp[6]={0,0,0,0,0,0};	//显示缓存
unsigned char dsp_state;	//显示选择:0显示修改数据;1显示时分秒;2显示星期;3显示年月日
unsigned char time_dog,dog_none;//time_dog:
unsigned char modify_state=0,modify_bit=0,modify_enter=0,modify_key=0;
#define rst PD0
#define clk PD1
#define dat PD2

void out_byte(char addr,char data)//向DS1302写一个数
	{
		unsigned char i,temp;
	DDRD|=(1<<rst);
	DDRD|=(1<<clk);
	DDRD|=(1<<dat);
	PORTD&=~(1<<rst);
	PORTD&=~(1<<clk);
	PORTD|=(1<<rst);
	for (i=0;i<8;i++)		//发送读命令
		{
		temp=addr;
		if((temp&(1<<i))!=0)
			PORTD|=(1<<dat);
		else
			PORTD&=~(1<<dat);
		PORTD|=(1<<clk);
		PORTD&=~(1<<clk);
		}
	for (i=0;i<8;i++)		//发送数据
		{
		temp=data;
		if((temp&(1<<i))!=0)
			PORTD|=(1<<dat);
		else
			PORTD&=~(1<<dat);
		PORTD|=(1<<clk);
		PORTD&=~(1<<clk);
		}
	PORTD&=~(1<<rst);
	}

void write_ds1302(char addr,char data)//修改DS1302的一个字节
	{
	out_byte(0x8e,0x00);
	out_byte(addr,data);
	out_byte(0x8f,0x80);
	}

char in_byte(char addr)	//从ds1302读入一个字节
	{
	unsigned char i,temp,temp1;
	DDRD|=(1<<rst);
	DDRD|=(1<<clk);
	DDRD|=(1<<dat);
	PORTD&=~(1<<rst);
	PORTD&=~(1<<clk);
	PORTD|=(1<<rst);
	for (i=0;i<8;i++)		//发送读命令
		{
		temp=addr;
		if((temp&(1<<i))!=0)
			PORTD|=(1<<dat);
		else
			PORTD&=~(1<<dat);
		PORTD|=(1<<clk);
		PORTD&=~(1<<clk);
		}
	DDRD&=~(1<<dat);
	temp=0;					//准备接收数据
	for (i=0;i<8;i++)		//接收一个字节数据
		{
		temp1=PIND;
		PORTD|=(1<<clk);
		temp1=(temp1>>2)&0x01;
		temp|=(temp1<<i);
		PORTD&=~(1<<clk);
		}
	PORTD&=~(1<<rst);
	return(temp);
	}


void bcd_change(void)		//三字节BCD码转换为六位led显示值
	{
	dsp[0]=led[bcd_dsp[0]>>4];
	dsp[1]=led[bcd_dsp[0]&0x0f];
	dsp[2]=led[bcd_dsp[1]>>4];
	dsp[3]=led[bcd_dsp[1]&0x0f];
	dsp[4]=led[bcd_dsp[2]>>4];
	dsp[5]=led[bcd_dsp[2]&0x0f];
	
	}

/*********************刷新数码管*********/	
void reflash(void)
	{
	char i,j,mark;
	DDRB=0xff;
	DDRC=0xff;
	mark=0;
	for(i=0;i<=5;i++)
		{
		if(dsp[i]!=0xc0)
			{
			mark=i;
			break;
			}
		}
		if(i==5)
			mark=6;
		if(dsp_state==0)			//修改数据时,在修改的位上显示一个点
			{
			for(i=0;i<=5;i++)
			dsp[i]|=0x80;
			dsp[modify_bit]&=0x7f;
			}
		if(dsp_state==1)			//显示时间时,在时分秒之间显示一个闪烁的点
			{
			time_dog++;
			if (time_dog<30)
				{
				dsp[1]&=0x7f;
				dsp[3]&=0x7f;
				}
			if (dsp[5]!=dog_none)
				{
				dog_none=dsp[5];
				time_dog=0;
				}
			}
		if(dsp_state==3)			//在显示年月日时,在年月日之间显示一个点
			{
			mark=0;
			dsp[1]&=0x7f;
			dsp[3]&=0x7f;
			}
		if(dsp_state==2)
			mark=5;
	for(j=0;j<2;j++)
		{
			while(mark<6)
			{	PORTC=0;
				PORTC=dig[mark];
			    PORTB=dsp[mark];
				_delay_ms(2);
				mark++;
			}
		}
	}
			
	
void main(void)
	{

/**********初始化int1中断及键盘*******************/
	DDRB=0xff;
	DDRD&=0x07;
	MCUCR|=(1<<ISC11);//下降沿触发
	MCUCR&=~(1<<ISC10);
	GIFR&=~(1<<INTF1);	//清中断标志
	SREG|=(1<<SREG_I);	//全局中断
	GICR|=(1<<INT1);	//int1开中断
/*************************************************/
	write_ds1302(0x90,0b10100101);	//写充电寄存器
	if ((in_byte(0x81)&0x80)!=0)	//如果没有启动时钟,则启动时钟
		write_ds1302(0x80,0x00);
	dsp_state=1;			//初始化显示时分秒
	DDRB=0xff;
	DDRC=0xff;
	while (1)
		{
		SREG&=~(1<<SREG_I);//显示时,关中断
		switch(dsp_state)
			{
			case 0:			//直接显示dsp的值
				break;
			case 1:			//显示时分秒
				bcd_dsp[0]=in_byte(0x85)&0x3f;
				bcd_dsp[1]=in_byte(0x83)&0x7f;
				bcd_dsp[2]=in_byte(0x81)&0x7f;
				bcd_change();
				break;
			case 2:			//显示星期
				bcd_dsp[0]=0;
				bcd_dsp[1]=0;
				bcd_dsp[2]=(in_byte(0x8b)&0x07)-1;
				bcd_change();
				break;
			case 3:			//显示年月日
				bcd_dsp[0]=in_byte(0x8d);
				bcd_dsp[1]=in_byte(0x89)&0x1f;
				bcd_dsp[2]=in_byte(0x87)&0x3f;
				bcd_change();
				break;
			default:
				break;
			}
		reflash();
		SREG|=(1<<SREG_I); //显示完毕,开中断
		}
	}

/******************键盘中断*************************/	
SIGNAL(SIG_INTERRUPT1)
	{
	char key,temp;
//	_delay_ms(1);	//此处为去抖动
	temp=PIND;
	if (temp&0xf0)	//键有效
		key=temp&0xf0;
	temp=PIND;
	while(temp&0xf0)//等待键释放
		temp=PIND;
	if (key==0x10&modify_state==0)//改变显示状态键:显示时分秒、年月日、星期
		{
		dsp_state++;
		if (dsp_state>3)
			dsp_state=1;
		}
	if (key==0x20&modify_state!=0)//数据加键
		{
		bcd_dsp[modify_bit]++;
		if(bcd_dsp[modify_bit]>9)bcd_dsp[modify_bit]=0;
		dsp[modify_bit]=led[bcd_dsp[modify_bit]];
		}
	if (key==0x40&modify_state!=0)//确认保存数据
		{
		if (modify_state==3)
			{
			write_ds1302(0x84,((bcd_dsp[0]<<4)|(bcd_dsp[1]&0xff)&0x3f));
			write_ds1302(0x82,((bcd_dsp[2]<<4)|(bcd_dsp[3]&0xff)&0x7F));
			write_ds1302(0x80,((bcd_dsp[4]<<4)|(bcd_dsp[5]&0xff)&0x7f));
			dsp_state=1;
			modify_state=0;
			modify_key=0;
			}
		if (modify_state==2)
			{
			write_ds1302(0x8a,(bcd_dsp[5]&0x07)+1);
			bcd_dsp[3]=in_byte(0x85)&0x3f;
			bcd_dsp[4]=in_byte(0x83)&0x7f;
			bcd_dsp[5]=in_byte(0x81)&0x7f;
			dsp[0]=led[bcd_dsp[3]>>4];
			dsp[1]=led[bcd_dsp[3]&0x0f];
			dsp[2]=led[bcd_dsp[4]>>4];
			dsp[3]=led[bcd_dsp[4]&0x0f];
			dsp[4]=led[bcd_dsp[5]>>4];
			dsp[5]=led[bcd_dsp[5]&0x0f];
			
			bcd_dsp[0]=bcd_dsp[3]>>4;
			bcd_dsp[1]=bcd_dsp[3]&0x0f;
			bcd_dsp[2]=bcd_dsp[4]>>4;
			bcd_dsp[3]=bcd_dsp[4]&0x0f;
			bcd_dsp[4]=bcd_dsp[5]>>4;
			bcd_dsp[5]=bcd_dsp[5]&0x0f;
			modify_state=3;
			modify_bit=0;
			}
		if (modify_state==1)
			{
			write_ds1302(0x8c,(bcd_dsp[0]<<4)|(bcd_dsp[1]&0xff));
			write_ds1302(0x88,((bcd_dsp[2]<<4)|(bcd_dsp[3]&0xff)&0x1F));
			write_ds1302(0x86,((bcd_dsp[4]<<4)|(bcd_dsp[5]&0xff)&0x3f));
			
			dsp[0]=0xff;
			dsp[1]=0xff;
			dsp[2]=0xff;
			dsp[3]=0xff;
			dsp[4]=0xff;
			dsp[5]=led[(in_byte(0x8b)&0x07)-1];
			
			bcd_dsp[0]=0;
			bcd_dsp[1]=0;
			bcd_dsp[2]=0;
			bcd_dsp[3]=0;
			bcd_dsp[4]=0;
			bcd_dsp[5]=(in_byte(0x8b)&0x07)-1;
			modify_state=2;
			modify_bit=5;
			}
		}
	if (key==0x80)//数据修改键
		{
		if (modify_state==0&modify_key==0)
			{
			bcd_dsp[3]=in_byte(0x8d)&0x3f;
			bcd_dsp[4]=in_byte(0x89)&0x1f;
			bcd_dsp[5]=in_byte(0x87)&0x3f;
			dsp[0]=led[bcd_dsp[3]>>4];
			dsp[1]=led[bcd_dsp[3]&0x0f];
			dsp[2]=led[bcd_dsp[4]>>4];
			dsp[3]=led[bcd_dsp[4]&0x0f];
			dsp[4]=led[bcd_dsp[5]>>4];
			dsp[5]=led[bcd_dsp[5]&0x0f];
			
			bcd_dsp[0]=bcd_dsp[3]>>4;
			bcd_dsp[1]=bcd_dsp[3]&0x0f;
			bcd_dsp[2]=bcd_dsp[4]>>4;
			bcd_dsp[3]=bcd_dsp[4]&0x0f;
			bcd_dsp[4]=bcd_dsp[5]>>4;
			bcd_dsp[5]=bcd_dsp[5]&0x0f;
			modify_state=1;
			dsp_state=0;
			modify_bit=0;
			}
		if (modify_state!=0&modify_key==1)
			{
			modify_bit++;
			if (modify_bit>5&modify_state==1)modify_bit=0;
			if (modify_bit>5&modify_state==2)modify_bit=5;
			if (modify_bit>5&modify_state==3)modify_bit=0;
			}
		modify_key=1;
		}
	}
	

⌨️ 快捷键说明

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