|
| |||||||
|
Опубликовано 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)
Добавить комментарийДля отправки комментария вы должны авторизоваться. |
|||||||