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

📄 clock.c

📁 用单片机和数码管
💻 C
字号:

#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))

#include<avr/interrupt.h>
#include<inttypes.h>
#include<util/delay.h>

#include<avr/io.h>

uint8_t Second=50, Minute=59, Hour=20;
uint8_t key;
uint8_t AMinute=0, AHour=0, AE=0, telltime=0, Hour_format=0;
uint8_t dis[]=
{ 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f };
uint8_t disp[6];

void dispro(uint8_t s) //计算每个数码管所显示的数值
{
	
	uint8_t Hour_D;
	Hour_D=Hour;
	
		
	
	
	if ((Hour_format==1)&(Hour_D>=12)) // 时制转换
	{
		switch (Hour_D)
		{
		case 12:
			Hour_D=12;
			break; 
		case 24:
			Hour_D=0;
			break; //闹钟时显示
		default:
		{
			Hour_D-=12;
		}
			break;
		}

	}	
	
	if (s==0) // 正常时间
	{
		disp[0]=Hour_D/10;
		disp[1]=Hour_D-disp[0]*10;

		disp[2]=Minute/10;
		disp[3]=Minute-disp[2]*10;

		disp[4]=Second/10;
		disp[5]=Second-disp[4]*10;
	}

	if (s==1) // 闹钟时间
	{
		disp[0]=AHour/10;
		disp[1]=AHour-disp[0]*10;

		disp[2]=AMinute/10;
		disp[3]=AMinute-disp[2]*10;

		disp[4]=0;
		disp[5]=AE;
	}
	
}

void delay(uint8_t m) //延时子函数
{
	uint16_t j;
	for (; m!=0; m--)
	{
		for (j=8000; j!=0; j--)
		{
			;
		}
	}
}

void display(uint8_t a, uint8_t b, uint8_t c, uint8_t d) //显示函数  
{
	dispro(d);
	uint8_t i, sel;
	sel=c;
	for (i=a; i<b; i++)
	{
		PORTA=0x00;
		PORTC=~sel;

		PORTA=dis[disp[i]];

		_delay_us(100);
		sel=sel<<1; //移位,扫描下一个数码管
	}
}

void getkey(uint8_t n) //获取键盘输入
{

	uint8_t qut=0;

	key=0;
	while (qut==0)
	{
		if ((PINB&0xA0)!=0xA0)
			_delay_ms(8);
		if ((PINB&0xA0)!=0xA0)
		
			{
				
				switch ((PINB&0xA0))
				//读端口电平,并忽略闹钟口
				{

				case 0x80:
					key=5;
					while ((PINB&0xA0)==0x80)
						;
					qut=1;
					break;
				case 0x20:
					key=7;
					while ((PINB&0xA0)==0x20)
						;
					qut=1;
					break;
				default:
				{
				}
					break;
				}
			}

		switch (n)
		{
		case 0:
			display(0, 2, 0x01, 0);
			break; //时显示
		case 2:
			display(0, 2, 0x01, 1);
			break; //闹钟时显示
		case 1:
			display(2, 4, 0x04, 0);
			break; //分显示
		case 3:
			display(2, 4, 0x04, 1);
			break; //闹钟分显示
		case 4:
			display(4, 6, 0x10, 1);
			break; //闹钟使能显示
		default:
		{
		}
			break;
		}

	}
}

SIGNAL(SIG_OVERFLOW1)
//一秒基准与时分进位,未完成

{
	TCNT1H=0Xfc;
	TCNT1L=0X30;

	if (Second==59)
	{
		Second=0;
		if (Minute==59)
		{
			Minute=0;
			if(Hour==23) Hour=0;
			else Hour++;
			telltime=1;
		}
		else Minute++;
	}
	else Second++;

	if ((Hour==AHour)&(Minute==AMinute)&(AE==1)) //  判断是否闹钟时刻
	sbi (PORTB,3); //如果闹钟时刻,响一分钟

	else
	cbi (PORTB,3);

	if (telltime==1)
	{
		sbi (PORTB,3);

		if ((Second>3))
		{
			cbi (PORTB,3);
			telltime=0;
		}
	}

}

void Init_Device(void) //初始化函数
{
	DDRB=0x0F; //B口前四位输出,后四位输入
	DDRC=0xFF; //C口输出
	PORTC=0xFF;
	DDRA=0xFF; //A口输出
	//DDRD=0xFF; //D口输出   
	//PORTD=0xFF;
	TCCR1A=0;
	TCCR1B=5;
	TCNT1H=0Xfc;
	TCNT1L=0X30;
	TIMSK=(1<<TOIE1); //开中断

	MCUCSR |= (1<<7);
	MCUCSR |= (1<<7);
}

void adjtime(void) //调时子函数
{
	TIMSK=(0<<TOIE1); //停止计时中断

	getkey(0);

	while (key==7)
	{
		if (Hour==23)
			Hour=0;
		else
			Hour++;
		getkey(0);
	}
	getkey(1);
	while (key==7)
	{
		if (Minute==59)
			Minute=0;
		else
			Minute++;
		getkey(1);
	}
	Second=0;

	TIMSK=(1<<TOIE1); //重新开始计时


}

void adjalm(void) //调闹钟
{

	getkey(2);
	while (key==7)
	{
		if (AHour==23)
			AHour=0;
		else
			AHour++;
		getkey(2);
	}
	getkey(3);
	while (key==7)
	{
		if (AMinute==59)
			AMinute=0;
		else
			AMinute++;
		getkey(3);
	}
	getkey(4);
	while (key==7)
	{
		if (AE==1)
			AE=0; //AE为闹钟使能(alarm enable)
		else
			AE++;
		getkey(4);
	}
}

int main(void)
{
	Init_Device();
sei	();
	for(;;)
	{

		display (0,6,0x01,0);

		key=0;
		if ((PINB&0xF0)!=0xF0)
			_delay_ms(8);
		if ((PINB&0xF0)!=0xF0)
		{
			switch ((PINB&0xF0))
			{
				case 0xE0: key=4;break;
				case 0xB0: key=6;break;
				case 0x70: key=7;while ((PINB&0xF0)==0x70);break;

				default :
				{}break;
			}
		}
		if (key==4)
		adjtime();
		if (key==6)
		adjalm();
		if (key==7)
		Hour_format=!Hour_format;
		

	}
}






/*#include <avr/io.h>
#include <util/delay.h>

int main (void)
{
	DDRA=0xFF;
	DDRC=0xFF;
	while(1)
	{	
		uint8_t i, sel=0x01;
		for (i=0; i<5; i++)
			{
				PORTA=0x00;
				PORTC=~sel;

				PORTA=0x06;

				_delay_us(100);
				sel=sel<<1; //移位,扫描下一个数码管
			}
	}		
}*/

⌨️ 快捷键说明

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