Электронные "шахматные" часы.

Автор: с2. Опубліковано в Початківцям з CV AVR


 Электронные шахматные часы. Простейший вариант таких часов,  представляет собой, просто два попеременно включаемых секундомера.

Материал статьи может быть, полезен тем, кто начинает осваивать CodeVisionAVR.

Как ни велик интернет, однако простых и интересных схем не так уж просто и найти.

Вот, например часы типа шахматных, погуглил и мне не встретилась подобная схема, а ведь сделать самому такую схему на МК, это несложно.

Определение: «Часы для шахмат» называют часы с двумя устройствами индикации времени, соединенными друг с другом таким образом, что только одно из них может работать в одно и то же время. 

 

Приведу Вам простой пример таких шахматных часов (вообще-то это прототип в виде секундомера , а не таймера обратного отсчета, да еще и упрощенной версии без дополнительных функций, но это дело поправимо :))  исходник прилагается). 

 

Схема:

 

 

Функции: Управление происходит просто, при нажатой кнопке Кн-1 идет счет 1-го секундомера, при нажатой кнопке Кн-3 идет счет 2-го секундомера, кнопкой Кн-2 (сброс) обнуляем показания счета.

 

Если в управлении включения секундомеров использовать переключатель П2К или обыкновенный перекидной, это и будет примерно соответствовать нужной функциональности схемы.

 

 

В данном проекте основное, это  использование двух секундомеров, при желании их число можно увеличить, что может оказаться полезно и для других схем,  на примере этого проекта создаем его начало в CodeVisionAVR.

 

Сначала выберем МК и частоту.

 

подключим LCD к   PORTB

 


а порт  PORTD  делаем  управление кнопок на вход с подтяжкой внутренними резисторами к +.




Самое интересное это сконфигурировать таймер на точный счет секунд.

Как это делается, мне очень доходчиво в свое время, помогла информация с сайта my-avr.at.uа.

В параметрах таймера выберем Timer 1, Clock Value 7,813 kHz, Interrupt on: Compare A Match, Comp. A = 1e85 (это чисто обозначает что он будет тактироваться с частотой в 1 секунду)
clock value - частота счета
Interrupt on Compare A match - прерывание по совпадению с регистром А



Здесь мы немного остановимся. Что это за число 1е85? Почему решили взять именно это число?

Итак, чтобы правильно посчитать какова частота работы таймера нужно открыть инженерный калькулятор. Число 1e85 (оно в 16-чной системе счисления) =7813 в 10ситичной с/ч. С этого следует что 7813(частота прерывания = 1 Гц)*5(сек)=39065 и перевести это в 16чную с/ч тогда мы получим 9899, вот это число вставляем в Comp. A и наш таймер будет работать с частотой 0,2 Гц то есть 1раз в 5секунд.
Генерируем код и сохраняем.

В коде таймера: (TIM1_COMPA)
Нужно вставить в середину следующие строки кода:
TCNT1H=0;
TCNT1L=0;
Для корректной работы таймера этим регистрам присваивается  0.
Вот исходный код получился в итоге.

 

 

Code
/*****************************************************
CodeWizardAVR V2.04.4a Advanced
Project : Shahmaty
Version : 1
Date : 13.05.2012
Company : c2.at.ua
Chip type : ATtiny2313
AVR Core Clock frequency: 8,000000 MHz
*****************************************************/
#include <tiny2313.h>
#asm
.equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>
#include <delay.h>
unsigned char sek_B, min_B, hour_B;
unsigned char sek_A, min_A, hour_A;

    interrupt [TIM1_COMPA] void timer1_compa_isr(void)
   {
   TCNT1H=0;
   TCNT1L=0;  
   if (PIND.2==0) { // Секундомер №1 разрешено
   sek_A ++ ; // инкрементирруем
   };
   if (PIND.4==0) { // Секундомер №2 разрешено
   sek_B ++ ; // инкрементирруем
   };  
  }

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTD=0x1C;
DDRD=0x00;

TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x1E;
OCR1AL=0x85;
OCR1BH=0x00;
OCR1BL=0x00;
TIMSK=0x40;
USICR=0x00;
ACSR=0x80;
lcd_init(16);
#asm("sei")

while (1)
{
lcd_gotoxy(0,0); // Место на дисплее
lcd_putchar(hour_A/10+0x30);
lcd_putchar(hour_A%10+0x30);
lcd_putchar(':');
lcd_putchar(min_A/10+0x30);
lcd_putchar(min_A%10+0x30);
lcd_putchar(':');
lcd_putchar(sek_A/10+0x30);
lcd_putchar(sek_A%10+0x30);
if (PIND.2==0) // на экране состояние 1-го секундомера
lcd_putsf(" <start1");
else
{
lcd_putsf(" < payza");
};
lcd_gotoxy(0,1); // Место на дисплее
if (PIND.4==0) // на экране состояние 2-го секундомера
lcd_putsf("start2> ");
else
{
lcd_putsf("payza > ");
};
lcd_putchar(hour_B/10+0x30);
lcd_putchar(hour_B%10+0x30);
lcd_putchar(':');
lcd_putchar(min_B/10+0x30);
lcd_putchar(min_B%10+0x30);
lcd_putchar(':');
lcd_putchar(sek_B/10+0x30);
lcd_putchar(sek_B%10+0x30);

if (sek_A==60) { min_A++, sek_A=0; }; // Условие работы секунд
if (min_A==60) { hour_A++, min_A=0; }; // Условие работы минут
if (hour_A==96) { hour_A=0; } ; // Условие работы часов в формате 4х суток

if (sek_B==60) { min_B++, sek_B=0; }; // Условие работы секунд
if (min_B==60) { hour_B++, min_B=0; }; // Условие работы минут
if (hour_B==96) { hour_B=0; } ; // Условие работы часов в формате 4х суток

if (PIND.3==0) { //общий сброс
hour_A=0;
min_A=0;
sek_A=0;
hour_B=0;
min_B=0;
sek_B=0;
};
};
}

 

 

Фьюзы для работы схемы с внешним кварцем нужно выставить так:

Проект в протеусе

Архив проекта 16х2; исходник, протеус, (прошивка, в папке проекта ЕХЕ.).

Это конечно интересно, но это просто два секундомера с накоплением отсчитанного времени, дальше все можно делать гораздо функциональней, вся фантазия в этой схеме может быть затруднена, только тем, как вывести на экран в 16 символов все функции и всю информацию, и что бы она там , была логически понятна, любому пользователю....

В общем arbeiten (продолжаем работать:)))) Пока на факт с количеством символов не обращаем внимание берем "пожирнее" индикатор, и добавляем в программу учет текущего времени.

Теперь схема становится гораздо интересней, так как,  мы видим на экране для каждого секундомера не только накопленное время , но и текущий отрезок времени , от начала нажатия кнопки пуск.

Код теперь имеет такой вид: 

 

Code
/*****************************************************
CodeWizardAVR V2.04.4a Advanced
Project : Shahmaty
Version : 1
Date : 13.05.2012
Author : C@at
Company : c2.at.ua
Chip type : ATtiny2313
AVR Core Clock frequency: 8,000000 MHz
*****************************************************/
#include <tiny2313.h>
#asm
.equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>
#include <delay.h>
unsigned char sek_A, min_A, hour_A;
unsigned char sek_AA, min_AA, hour_AA;
unsigned char sek_B, min_B, hour_B;
unsigned char sek_BB, min_BB, hour_BB;

interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
TCNT1H=0;
TCNT1L=0;
if (PIND.2==0) { // Секундомер №1 разрешено
sek_A ++ ; // инкрементирруем
sek_AA ++ ; //
};
if (PIND.4==0) { // Секундомер №2 разрешено
sek_B ++ ; // инкрементирруем
sek_BB ++ ; //
};
}

void main(void)
{

#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTD=0x1C;
DDRD=0x00;

TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x1E;
OCR1AL=0x85;
OCR1BH=0x00;
OCR1BL=0x00;
TIMSK=0x40;
USICR=0x00;
ACSR=0x80;
lcd_init(16);
#asm("sei")

while (1)
{
lcd_gotoxy(0,0); // Место на дисплее
lcd_putchar(hour_A/10+0x30);
lcd_putchar(hour_A%10+0x30);
lcd_putchar(':');
lcd_putchar(min_A/10+0x30);
lcd_putchar(min_A%10+0x30);
lcd_putchar(':');
lcd_putchar(sek_A/10+0x30);
lcd_putchar(sek_A%10+0x30);
if (PIND.2==0) // на экране состояние 1-го секундомера
lcd_putsf(" <start1");
else
{
lcd_putsf(" < payza");
hour_AA=0, min_AA=0, sek_AA=0; // сброс текущего времени
};
lcd_gotoxy(0,1); //
lcd_putchar(hour_AA/10+0x30);
lcd_putchar(hour_AA%10+0x30);
lcd_putchar(':');
lcd_putchar(min_AA/10+0x30);
lcd_putchar(min_AA%10+0x30);
lcd_putchar(':');
lcd_putchar(sek_AA/10+0x30);
lcd_putchar(sek_AA%10+0x30);

lcd_gotoxy(0,2); //
if (PIND.4==0) // на экране состояние 2-го секундомера
lcd_putsf("start2> ");
else
{
lcd_putsf("payza > ");
hour_BB=0, min_BB=0, sek_BB=0; // сброс текущего времени
};
lcd_putchar(hour_B/10+0x30);
lcd_putchar(hour_B%10+0x30);
lcd_putchar(':');
lcd_putchar(min_B/10+0x30);
lcd_putchar(min_B%10+0x30);
lcd_putchar(':');
lcd_putchar(sek_B/10+0x30);
lcd_putchar(sek_B%10+0x30);

lcd_gotoxy(8,3); //текущее время
lcd_putchar(hour_BB/10+0x30);
lcd_putchar(hour_BB%10+0x30);
lcd_putchar(':');
lcd_putchar(min_BB/10+0x30);
lcd_putchar(min_BB%10+0x30);
lcd_putchar(':');
lcd_putchar(sek_BB/10+0x30);
lcd_putchar(sek_BB%10+0x30);

if (PIND.3==0) { //общий сброс
hour_A=0, min_A=0, sek_A=0; // сброс времени
hour_AA=0, min_AA=0, sek_AA=0; // сброс текущего
hour_B=0, min_B=0, sek_B=0; // сброс времени
hour_BB=0, min_BB=0, sek_BB=0; // сброс текущего
};

if (sek_A==60) { min_A++, sek_A=0; }; // Условие работы секунд
if (min_A==60) { hour_A++, min_A=0; }; // Условие работы минут
if (hour_A==96) { hour_A=0; } ; // Условие работы часов в формате 4х суток

if (sek_AA==60) { min_AA++, sek_AA=0; }; // Условие работы секунд
if (min_AA==60) { hour_AA++, min_AA=0; }; // Условие работы минут
if (hour_AA==24) { hour_AA=0; } ; // Условие работы часов

if (sek_B==60) { min_B++, sek_B=0; }; // Условие работы секунд
if (min_B==60) { hour_B++, min_B=0; }; // Условие работы минут
if (hour_B==96) { hour_B=0; } ; // Условие работы часов в формате 4х суток

if (sek_BB==60) { min_BB++, sek_BB=0; }; // Условие работы секунд
if (min_BB==60) { hour_BB++, min_BB=0; }; // Условие работы минут
if (hour_BB==24) { hour_BB=0; } ; // Условие работы часов
};
}

 

 Кстати при  компиляции он занимает в МК  58,1%  FLASHа, и здесь  остаеется еще полно места для дальнейшего творчества в этом устройстве:)))))

 Архив проекта 16х4; исходник, протеус, прошивка

Еще  небольшие примеры, для интересующихся программированием на любительском уровне....