Електронні шаховий годинник. Найпростіший варіант такого годинника, являє собою, просто два поперемінно включаються секундоміра.
Матеріал статті може бути, корисний тим, кт про починає освоювати 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.
Ось вихідний код вийшов в результаті.
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 ( "
<
lcd_putsf ( "
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)
if (min_A == 60)
if (hour_A == 96)
if (sek_B == 60)
if (min_B == 60)
if (hour_B == 96)
#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 ( "
<
lcd_putsf ( "
>;
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)
if (min_A == 60)
if (hour_A == 96)
if (sek_AA == 60)
if (min_AA == 60)
if (hour_AA == 24)
if (sek_B == 60)
if (min_B == 60)
if (hour_B == 96)