| |||||||
Опубликовано 2013-05-23 09:25:41 автором MRS Электронное реле времени на микроконтроллереВ предыдущих уроках я рассказывал, как к микроконтроллеру подключить семисегментный индикатор, кнопки и как управлять нагрузкой постоянного и переменного тока. Давайте все это материализуем в какое-нибудь полезное устройство, например часовой таймер.Таймер должен отсчитывать какое-то время и по истечении включать или отключать полезную нагрузку, например светодиод.Скажу честно, собирал я его по просьбе друга, ему нужно было включать глушылку вай фай. Схема электронного реле времени выглядит так #include <mega8.h> #include <delay.h> struct Stime { unsigned char second; unsigned char minute; unsigned char hour; } time[3]; void TimerEvent() { PORTB.4=1; } unsigned char Zminute=0,Zhour=0; unsigned char chislo[4]; //определяем массив из двух элементов типа char беззнаковый(unsigned) unsigned char numder[]= //определяем массив, в котором индексу будут соответствовать бити на порте D { 0b11111100, //цифра 0 0b01100000, //цифра 1 0b11011010, //цифра 2 0b11110010, //цифра 3 0b01100110, //цифра 4 0b10110110, //цифра 5 0b10111110, //цифра 6 0b11100000, //цифра 7 0b11111110, //цифра 8 0b11110110, //цифра 9 }; void out(unsigned char hour,unsigned char minute) { /*сначала нам нужно определить, из скольких десятков и единиц состоит выводимое число. Например, передали мы "45", нам надо его разложить на 4 и 5, чтобы на первый разряд семисегментника вывести цифру 4, а на второй - 5 */ chislo[1]=hour%10; //оператор % дает остаток от целочисленного деления, например 34%10 будет 4 chislo[0]=hour/10; // узнаем, сколько десятков в числе chislo[3]=minute%10; chislo[2]=minute/10; } unsigned char i=0; // переменная для определения, на какой разряд семисегментника выводить число // прерывания по переполнению timer0 interrupt [TIM0_OVF] void timer0_ovf_isr(void) { PORTD=numder[ chislo[i] ]; if (i==1) PORTD.0=1; else PORTD.0=0; //включаем/выключаем точку PORTB = ( (PORTB & 0b11110000) | ( (~(1 <<i)) & 0b00001111 ) ); //включаем определённый разряд семисегментника if (++i>3) i=0; } /* прерывания таймера2 вызывается 1 раз в секунду, потому что таймер2 тактирует от часового кварца на 32768 герц и в таймере установлен предделитель частоты 128, ето значит что 128 тактов считаются как один тоэсть кварц в нас 32768 таймер в нас 8 битный максимальноэ число 255 мы выбераем пределитель 128 получается 32768/128=255, это значит что за секунду пременная щета таймера (TCNT2) дойдет до 255 и таймер згенерирует прерывания по переполнению переменной */ unsigned char outMenu=0; interrupt [TIM2_OVF] void timer2_ovf_isr(void) { if (time[0].second++==60) { time[0].second=0; if (time[0].minute++==60) { time[0].minute=0; if (time[0].hour++==24) { time[0].hour=0; } } out(time[outMenu].hour,time[outMenu].minute); if ( (time[0].minute==Zminute) && (time[0].hour==Zhour) ) TimerEvent(); //если минуты и секунды равны заданым вызываем функцию TimerEvent } } void main(void) { PORTB=0x00; DDRB=0x1F; PORTD=0x00; DDRD=0b11111111; TCCR0=0x00; TCNT0=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 0,977 kHz TCCR0=0x04; TCNT0=0x00; // Timer/Counter 2 initialization // Clock source: TOSC1 pin // Clock value: PCK2/128 // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x08; TCCR2=0x05; TCNT2=0x00; OCR2=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x41; // Global enable interrupts #asm("sei") while (1) { if (!(PINC & 0b00000001) && outMenu>0 ) // проверяем нажата ли кнопка 1 { if (regim=true) time[outMenu].hour++; else time[outMenu].minute++; } if (!(PINC & 0b00000010)) // проверяем нажата ли кнопка 2 { if (++outMenu>2) outMenu=0; } if (!(PINC & 0b00000100) && outMenu>0 ) // проверяем нажата ли кнопка 3 { if (regim=true) time[outMenu].hour--; else time[outMenu].minute--; } delay_ms(200); out(time[outMenu].hour,time[outMenu].minute); }; } Файлы к проекту в архиве Timer.zip Комментарии - (5)
Добавить комментарийДля отправки комментария вы должны авторизоваться. |