Источник материала сайт http://c2.at.ua.
Как ни велик интернет, однако простых и интересных схем не так уж просто и
найти.
Вот, например часы типа шахматных, погуглил и мне не встретилась подобная
схема, а ведь сделать самому такую схему на МК, это несложно.
Определение: «Часы для шахмат» называют часы с двумя устройствами индикации времени, соединенными друг с другом таким образом, что только одно из них может работать в одно и то же время.
Приведу Вам простой пример таких шахматных часов (вообще-то это прототип в виде секундомера , а не таймера обратного отсчета, да еще и упрощенной версии без
дополнительных функций, но это дело поправимо :)) исходник прилагается).
Схема:
Функции: Управление происходит просто, при нажатой кнопке Кн-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 : http://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 : http://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; исходник, протеус, прошивка.
Еще небольшие примеры, для интересующихся программированием на любительском уровне....
|