#include<reg51.h>
int sem_segment[16];			//Объявляем массив кодов семисегментных индикаторов
int tsifra;				//Объявляем переменную, в которую будем помещать цифру для вывода
int chislo[8];				//Объявляем массив цифр выводимого на индикатор числа
int mem [5];				//Объявляем массив памяти для хранения введенных с клавиатуры чисел				
int znakomesto,i,j=0,otp,razr=1;
int sec,min,chas,chas_cor,min_cor;
unsigned int vrem_sec;			//Счетчик времени в секундах
unsigned int vrem_cor;			//Откорректированное время в секундах
int temp,SkanCode;
char set=0;				//Признак входа в режим настройки
char mode=0;				//Режим настройки
char pm=0;				//Признак второй половины дня

void init (void)
{
sem_segment[0]=0xfc;			//Заносим в массив коды соответствующих цифр
sem_segment[1]=0x60;
sem_segment[2]=0xda;
sem_segment[3]=0xf2;
sem_segment[4]=0x66;
sem_segment[5]=0xb6;
sem_segment[6]=0xbe;
sem_segment[7]=0xe0;
sem_segment[8]=0xfe;
sem_segment[9]=0xf6;
sem_segment[10]=0x00;			//Ничего не выводится на индикатор
sem_segment[11]=0xee;			//Код символа "А"
sem_segment[12]=0x9c;			//Код символа "С"
sem_segment[13]=0x9e;			//Код символа "Е"
sem_segment[14]=0x1e;			//Код символа "t"
sem_segment[15]=0xce;			//Код символа "P"
SCON=0;					//Настраиваем последовательный порт на режим регистра сдвига
}

void vyvod (void)
{
P1=0xff;				//Все единицы на Р1 => дешифратор не включает ни одного индикатора
tsifra=chislo[znakomesto];		//Берем цифру для вывода 
TF0=0;					//Сбрасываем флаг окончания передачи
if ((znakomesto==1)||(znakomesto==3)) 
SBUF=sem_segment[tsifra]+1;
else SBUF=sem_segment[tsifra];		//Пересылаем код цифры для отображения
while(T1==0);
P1=znakomesto+0xf0;			//очередного знакоместа
temp=P1;				//Прочитать состояние кнопок в переменную временного хранения
for(i=7;i>0;i--);			//Задержка времени для индикации
if (temp==otp) razr=1;                  //Если предыдущая нажатая кнопка отпущена, разрешить считывание следующей

if((temp !=(znakomesto+0xf0))&&(razr==1))
{
SkanCode=temp;				//Если хоть одна кнопка нажата, запомнить скан-код 
otp=znakomesto+0xf0;                    //Заносим код кнопки, которую нужно проверить на отпускание
razr=0;                                 //запретить повторное считывание нажатой кнопки
}
}

void time (void)
{
if (vrem_cor>0) vrem_sec=vrem_cor;
vrem_cor=0;
sec=(vrem_sec%60);			//Получаем только секунды
chislo[5]=sec%10;                       //Получаем единицы секунд
chislo[4]=sec/10;                       //Получаем десятки секунд
min=(vrem_sec/60)%60;			//Получаем только минуты
chislo[3]=min%10;			//Получаем единицы минут
chislo[2]=min/10;			//Получаем десятки минут
chas=(vrem_sec/3600);			//Получаем только часы
if (pm==1) chas=chas+12;		//Если стоит флаг второй половины дня, добавляем еще 12 часов
chislo[1]=chas%10;			//Получаем единицы часов
chislo[0]=chas/10;                      //Получаем десятки часов
}

void obnul (void)
{
for(znakomesto=0;znakomesto<7;znakomesto++)//Забиваем все разряды пустыми ячейками
chislo[znakomesto]=10;
}

void time_correct (void)
{
chas_cor=(mem[0]*10+mem[1]);
if (chas_cor>12)
{
chas_cor=chas_cor-12;			//Если количество часов превышает 12, уменьшаем на 12
pm=1;                                   //и выставляем флаг второй половины дня
}
min_cor=(mem[2]*10+mem[3]);
vrem_cor=(chas_cor*60+min_cor)*60+sec;	//Подсчитываем время в секундах
}

void show_mem (void)
{
chislo[0]=0;
chislo[1]=mem[0];
chislo[2]=mem[1];
chislo[3]=mem[2];
chislo[4]=mem[3];
chislo[5]=0;
}

void form_OPT (void)
{
chislo[0]=10;                            //Выводим на индикатор "ОРТ" - заставку входа в режим настроек
chislo[1]=0;
chislo[2]=15;
chislo[3]=14;
chislo[4]=10;
chislo[5]=10;
}

void menu (void)
{
if ((set==1)&&(mode==0))
{
form_OPT();switch (SkanCode)
{
case 0xB3: {mode=1;obnul();SkanCode=0;} break;
case 0xB4: {mode=3;obnul();SkanCode=0;} break;
default: ;
}
}
}

void key_enter (void)
{
switch (SkanCode)
{
case 0xB3: {chislo[j+2]=1;mem[j]=1; j=j+1;SkanCode=0;} break;
case 0x73: {chislo[j+2]=2;mem[j]=2; j=j+1;SkanCode=0;} break;
case 0xB4: {chislo[j+2]=3;mem[j]=3; j=j+1;SkanCode=0;} break;
case 0x74: {chislo[j+2]=4;mem[j]=4; j=j+1;SkanCode=0;} break;
case 0xB5: {chislo[j+2]=5;mem[j]=5; j=j+1;SkanCode=0;} break;
case 0x75: {chislo[j+2]=6;mem[j]=6; j=j+1;SkanCode=0;} break;
case 0xB0: {chislo[j+2]=7;mem[j]=7; j=j+1;SkanCode=0;} break;
case 0x70: {chislo[j+2]=8;mem[j]=8; j=j+1;SkanCode=0;} break;
case 0xB1: {chislo[j+2]=9;mem[j]=9; j=j+1;SkanCode=0;} break;
case 0x71: {chislo[j+2]=0;mem[j]=0; j=j+1;SkanCode=0;} break;
default: ;
}
}

void setup_time (void)
{
chislo[0]=14;                                   //Выставляем в первом разряде признак установки времени
if (j<4) key_enter();				//Процедура ввода с клавиатуры
}

void setup (void)
{
switch (mode)
{
case 1: setup_time(); break;
case 3: show_mem(); break;
default : ;                                                  
}
}

void obrab (void)
{
if (SkanCode==0xb2) 
{
time_correct();
set=0;
}
if (SkanCode==0x72) 
{
set=1;
mode=0;
j=0;
}
menu();
setup();
}

void indikat (void)
{
for(znakomesto=0;znakomesto<7;znakomesto++)
vyvod();
}

void main (void)
{
init();					//Вызов функции init
for(;;)
{
if (set==0) time();
indikat();
obrab();
}
}


