Микроконтроллеры

Часы на микроконтроллере ATMEGA16

В данном проекте мы разработаем и соберем цифровые часы на микроконтроллере. В качестве камня будем использовать  микроконтроллер ATMEGA16 и 6 семи сегментных индикатора (далее просто индикаторы или дисплеи). Код программы, разработанный под ATMEGA16, может с легкостью использоваться на других камнях, таких как ATMEGA32, ATMEGA8515 и другие.

Итак, наши цифровые  часы работают следующим образом. Когда напряжение подано индикаторы выставляются в нули следующего вида «00:00:00» соответственно часы, минуты и секунды. Для установки времени будем использовать два кнопочных выключателя. Кнопка S1 необходима для установки минут, при ее нажатии происходит инкремент переменной  содержащей минуты на 1, при достижении значения в 59, происходит ее сброс и отсчет начинается сначала, т.е. с нуля.

Аналогичным образом работает кнопка S2, только используется для установки переменной отвечающей за часы.

Схема часов на микроконтроллере

На рисунке ниже представлена наша схема, особенностью схемы является то, что управление всеми индикаторами осуществляется при помощи одного порта PORTB. С его помощью поочередно осуществляется запись одной цифры в индикатор. За поочередное включение,а именно за динамическую индикацию отвечает PORTC. Что такое динамическая индикация было сказано ранее.  Важно отметить что все дисплеи с общим катодом, поэтому для включения того или иного дисплея нужно подать на его общий вывод сигнал низкого состояния, или просто «0». 

Часы на микроконтроллере

Важно! Для правильной работы цифровых часов нужно чтобы внутренний генератор камня был настроен на частоту в 4 Мгц.

Код программы  часов

Ниже представлен код для часов на микроконтроллере ATMEGA16. Программа была написана с использованием среды AVR Studio 5. Еще раз повторю, что данные часы работают от внутреннего тактового генератора. Который имеет определённую погрешность, поэтому период одной секунды может меняться. И вешать их на стену или нет и сверять по ним время решайте сами. 

#define F_CPU	4000000UL
#include <avr/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
 
#define SegDataPort		PORTB
#define SegDataPin		PINB
#define SegDataDDR		DDRB
 
#define SegCntrlPort	PORTC
#define SegCntrlPin		PINC
#define SegCntrlDDR		DDRC
 
 
/*Global Variables Declarations*/
unsigned char hours = 0;
unsigned char minutes = 0;
unsigned char seconds = 0;
 
 
/*Function Declarations*/
/*****************************************************************************/
/*Decimal Digit (0-9) to Seven Segment Values Encoder*/
unsigned char DigitTo7SegEncoder(unsigned char digit, unsigned char common);
 
/*Timer Counter 1 Compare Match A Interrupt Service Routine/Interrupt Han-dler*/
ISR(TIMER1_COMPA_vect);
 
 
/*Main Program*/
/*****************************************************************************/
int main(void)
{
    SegDataDDR = 0xFF;
	SegCntrlDDR = 0x3F;
	SegCntrlPort = 0xFF;
 
	TCCR1B = (1<<CS12|1<<WGM12);
	OCR1A = 15625-1;
	TIMSK = 1<<OCIE1A;
	sei();
 
 
	while(1)
    {
        /* Set Minutes when SegCntrl Pin 6 Switch is Pressed*/
		if((SegCntrlPin & 0x40) == 0 )
		{	
			_delay_ms(200);
			if(minutes < 59)
				minutes++;
			else
				minutes = 0;
		}
        /* Set Hours when SegCntrl Pin 7 Switch is Pressed*/			
		if((SegCntrlPin & 0x80) == 0 )
		{	
			_delay_ms(200);
			if(hours < 23)
				hours++;
			else
				hours = 0;
		}			
 
		SegDataPort = DigitTo7SegEncoder(seconds%10,1);
		SegCntrlPort = ~0x01;
		SegDataPort = DigitTo7SegEncoder(seconds/10,1); 
		SegCntrlPort = ~0x02;
		SegDataPort = DigitTo7SegEncoder(minutes%10,1);
		SegCntrlPort = ~0x04;
		SegDataPort = DigitTo7SegEncoder(minutes/10,1); 
		SegCntrlPort = ~0x08;
		SegDataPort = DigitTo7SegEncoder(hours%10,1); 
		SegCntrlPort = ~0x10;
		SegDataPort = DigitTo7SegEncoder(hours/10,1);
		SegCntrlPort = ~0x20;
 
    }
	return 0;
}
 
/*
* Function Description:
* Encode a Decimal Digit 0-9 to its Seven Segment Equivalent.
*
* Function Arguments:
* digit - Decimal Digit to be Encoded
* common - Common Anode (0), Common Cathode(1)
* SegVal - Encoded Seven Segment Value 
*
* Connections:
* Encoded SegVal is return in the other G-F-E-D-C-B-A that is A is the least
* significant bit (bit 0) and G bit 6.
*/
unsigned char DigitTo7SegEncoder(unsigned char digit, unsigned char common)
{
	unsigned char SegVal;
 
	switch(digit)	
	{	
		case 0:	if(common == 1)	SegVal = 0b00111111;
				else			SegVal = ~0b00111111;
				break;
		case 1:	if(common == 1)	SegVal = 0b00000110;
				else			SegVal = ~0b00000110;
				break;
		case 2:	if(common == 1)	SegVal = 0b01011011;
				else			SegVal = ~0b01011011;
				break;
		case 3:	if(common == 1)	SegVal = 0b01001111;
				else			SegVal = ~0b01001111;
				break;
		case 4:	if(common == 1)	SegVal = 0b01100110;
				else			SegVal = ~0b01100110;
				break;
		case 5:	if(common == 1)	SegVal = 0b01101101;
				else			SegVal = ~0b01101101;
				break;
		case 6:	if(common == 1)	SegVal = 0b01111101;
				else			SegVal = ~0b01111101;
				break;
		case 7:	if(common == 1)	SegVal = 0b00000111;
				else			SegVal = ~0b00000111;
				break;
		case 8:	if(common == 1)	SegVal = 0b01111111;
				else			SegVal = ~0b01111111;
				break;
		case 9:	if(common == 1)	SegVal = 0b01101111;
				else			SegVal = ~0b01101111;		
	}		
	return SegVal;
}
 
/*Timer Counter 1 Compare Match A Interrupt Service Routine/Interrupt Han-dler*/
ISR(TIMER1_COMPA_vect)
{
	seconds++;
 
	if(seconds == 60)
	{
		seconds = 0;
		minutes++;
	}
	if(minutes == 60)
	{
		minutes = 0;
		hours++;		
	}
	if(hours > 23)
		hours = 0;
}

Комментарии  

 
#1 Варгорий 29.11.2014 12:50
Извините за возможно глупый вопрос... А можно стабилизировать внутренний генератор внешним кварцевым резонатором?
Цитировать
 
 
#2 Фархат 08.01.2015 13:26
Здравствуйте, а можно ли в этой схеме использовать микроконтроллер AtMega16l-8AU ?
Цитировать
 
 
#3 Anrew 16.01.2015 10:10
Цитирую Варгорий:
Извините за возможно глупый вопрос... А можно стабилизировать внутренний генератор внешним кварцевым резонатором?

Странный вопрос))Можно использовать либо внешний генератор на кварце либо внутренний. Кварц намного стабильнее чем внутренний.
Цитировать
 
 
#4 Сергей 20.05.2015 09:08
Цитирую Варгорий:
Извините за возможно глупый вопрос... А можно стабилизировать внутренний генератор внешним кварцевым резонатором?

Можно конечно! Только фьюз выставить соответствующий .
Цитировать
 
 
#5 Сергей 20.05.2015 09:20
Цитирую Фархат:
Здравствуйте, а можно ли в этой схеме использовать микроконтроллер AtMega16l-8AU ?

Думаю, что можно - частота работы схемы 4 Мгц, а этот МК тянет до 8, в реальности даже больше... Правда, у меня есть некоторые сомнения по поводу самой схемы - нет токоограничител ьных резисторов и транзисторных ключей...
Цитировать
 
 
#6 Сергей 20.05.2015 09:25
Цитирую Сергей:
Цитирую Фархат:
Здравствуйте, а можно ли в этой схеме использовать микроконтроллер AtMega16l-8AU ?

Думаю, что можно - частота работы схемы 4 Мгц, а этот МК тянет до 8, в реальности даже больше... Правда, у меня есть некоторые сомнения по поводу самой схемы - нет токоограничительных резисторов и транзисторных ключей...

Поправочка - в цепи питания виден резистор 1К, но вряд ли он полноценно заменит все вышеперечисленн ое, скорее всего будет заметна разность яркости индикаторов, да и номинал самого резистора великоват ...
Цитировать
 
 
#7 Михан 20.05.2015 10:03
Ток в 5 мА получается, маловато будет)
Цитировать
 
 
#8 Сергей 20.05.2015 13:43
Цитирую Михан:
Ток в 5 мА получается, маловато будет)

Даже меньше - прямое падение напряжения на ключах МК и индикаторе будет составлять не менее половины питания, как мне видится. В теории можно обойтись без всех резисторов, если точно подобрать напряжение питания (2,5-3,5В) примерно. Лучше всего подбирать лабораторным БП с ограничением тока по минимально приемлемому свечению индикатора, и потом изготовить БП с точно таким напряжением. Важно! БП должен быть стабилен! Даже незначительное повышение напряжения вызовет резкий прирост тока и может вывести из строя и МК и индикатор. Возможно придется заменить МК на более низковольтный AtMega16l-8AU, но это вряд ли.
Цитировать
 
 
#9 Сергей 20.05.2015 13:45
Цитирую Михан:
Ток в 5 мА получается, маловато будет)

Лучше все же в цепи выводов 1-7 МК установить резисторы 470 ом, в цепи выводов 22-27 транзисторные ключи (с вывода МК через резистор 1К-10К к базе, коллектор к индикатору, а эммитер к 0 раз индикатор ОК ) соответственно и транзистор должен быть n-p-n. Резистор 1К из питания исключить. Установить керамический конденсатор 0.1 мкф и оксидный 100-500 мкф в питание.
Цитировать
 
 
#10 Алексей 26.04.2018 09:56
Что нужно изменить в программе если скажем.. pc6 и pc5 поменять местами?
Цитировать
 

Добавить комментарий


Защитный код
Обновить

Последние комментарии

Последнии темы форума

  • Нет сообщений для показа