Часы на ATmega8 и LCD 16x2 Мой Проект

Обсуждаем контроллеры компании Atmel.
Ответить
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение RGB »

Доброго времени суток МНОГОУВАЖАЕМЫЕ КОТЫ !
Нуждаюсь в вашей помощи.
Решил я наконец-то создать что то своё, для начало подумал сделать свои "сообственные" ЧАСЫ на микроконтроллере ATmega8. Подключённая переферия следующая: дисплей (WH1602L), микросхема времени RTC (DS1307), датчик температуры (DS1820), 4 тактовых кнопки, 4 светодиода над кнопками (сигнализирующие какую кнопку нужно нажать ( если не очень понятно, то смотреть видео)), 2 реле управление нагрузками, и один Spiker (хотелось бы что бы Spiker дублировал сигналом нажатие кнопки) а так он для будильника.
Вообщем начял я паять, моделировать ( в Proteus'e ), писать программу ( в CVAVR ), как через некоторое время полезли вопросы (ну это и нормальное явление, ибо без них ни куда) но как оказалось что вопросы я такие не одалею "ОДИН" вот и прощу помощи у знающих КОТОВ :
1. Как правильно организовать "МЕНЮ" Т.Е. как сделать так что бы при входе к примеру в "подменю Настройка часов" кнопки те которые отвечали за перелистывание меню, теперь работали как перелистывание часов и минут.

2. Помогите решить проблемму задержки программы по функции delay.h ( к примеру в моём случае при нажатии на кнопку программа как бы "не мгновенно" переключается по меню а с некой задержкой

Код: Выделить всё

     LED_LEFT = 1; 
     LED_RIHT = 1;
       wait (3000);
     LED_LEFT = 0; 
     LED_RIHT = 0;
       wait (3000);
это кусок из всей программы которую я написал. В этом куске (как видно на видео) выполняется работа мигания "сигнальных светодиодов" ( wait (3000); это задержка от таймера_1

Код: Выделить всё

void wait (unsigned int time)         
{
   TCNT1 = 0;
   while (TCNT1<time){}
}
Функция delay.h давала не выносимые задержки в работе, решено было попробывать так. Ситуация более менее улучшилась, но всё равно не то. Как заставить моргать светодиод без задержки?)

3. Как сделать дублирование "звукавым сигналом" Spiker'a нажатие кнопки? ( В моём проекти пока нет Spiker'a поскольку я пока разбираюсь с меню. Но он будет, и хотелось бы по мимо того что он выполнял роль будильника ещё и дублировал нажатие кнопок "звукавым сигналом").

4. Очень не обычный факт обнаружен: не ужели подсветка LCD кушает так много тоака? Моя микросхема стабилизатора 78L05 ну уж очень сильно греется. решил разобраться от чего так греется, выяснелось что дело в подсветки LCD (сам в шоке) У меня есть лабороторный блок питания, я решил пдключить саму подсветку LCD на прямую к блоку питания, и чуть не поседел от увиденного. Амперметр показывал около 1 Ампера. Такое реально?
Ну вроде пока всё! Но вопросы ещё предстоят 8)

И в заключении вот моё видео http://www.youtube.com/watch?v=VFGObn8zSs4&feature=plcp
И вот файлы проекта
Часы.rar
(97.43 КБ) 428 скачиваний
Помогите пожалуйста!!!
Реклама
Аватара пользователя
ILYAUL
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение ILYAUL »

1. Как правильно организовать "МЕНЮ" Т.Е. как сделать так что бы при входе к примеру в "подменю Настройка часов" кнопки те которые отвечали за перелистывание меню, теперь работали как перелистывание часов и минут.
Переопределить их функцию.
3. Как сделать дублирование "звукОвым сигналом" Spiker'a нажатие кнопки? ( В моём проекти пока нет Spiker'a поскольку я пока разбираюсь с меню. Но он будет, и хотелось бы по мимо того что он выполнял роль будильника ещё и дублировал нажатие кнопок "звукОвым сигналом").
Знаете , что такое ноты и чем они характеризуются? В общем случае - два таймера , один генерит частоту , другой длительность звучания
Реклама
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение RGB »

Хорошо! зайдём с другой стороны.
Начнём всё по порядку:
1. Значит имеются 3 переменных которые инкрементируются при нажатии той или иной кнопки. В моём случаи это menu, set, enter;
При нажатии на кнопку "menu" мы пибавляем еденичку к переменной menu;
В вечном цикле сравниваем значение menu, если оно равно 0 то отображаем "главный экран время и дата" если равно 1 то входим в меню и отображаем "настройка часов"
К кнопкам "<<<" ">>>" (влево и вправо) присвоена переменная set; Она инкрементируются или декрементируются в зависимости от нажатой кнопки. Это своего рода перелистывания меню, её мы тоже проверяем в вечном цикле
если 0 то "настойка часов" если 1 то "настройка даты" если 2 то "настройка будильника" ( но здесь есть тоже свои подводные камни; как остановить декремент переменной когда она достигла 0? Инкремент переменной обнуляю с помощю функции if(set == 3) set = 0; а вот как быть с декрементом?)
Так вот: нужно кнопкой "ENTER" войти в выбранный пункт подменю ( к примеру "настройка часов" и отобразить на дисплее в верхней строчки "НАСТОЙКА ЧАСОВ" а в нижней часы и минуты. А кнопками "<<<" ">>>" (влево и вправо) двигать курсор под часами и минутами и кнопкой "ENTER" увиличивать значение часов или минут ( по достежению часов 23 обнулить их, и по достижению минут 59 обнулить их) а кнопкой "MENU" выйти из подменю "настройки часов"

Код: Выделить всё

//..........//
               if (menu == 0) {
              //Вывести главный экран 
                                      }   
               if (menu == 1) {
                     if (set == 0) {
              //Войти в меню "настройка часов"
                                         }
                      if (set == 1) {
              //Войти в меню "настройка даты"
                                          }
                      if (set == 2) {
              //Войти в меню "настройка будильника"
                                          }
                                  } 
 //........//
Уважаемые КОТЫ! помогите реализовать это!
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение shads »

Не знаю..... поможет тебе это или нет, но глянь как я реализовал настройку часов у себя.

Приборчик типа токого, только на MEGA8, с 4-х разрядным семисегментником. Пишу в AVRStudio.
Спойлер

Код: Выделить всё

//-----------------------------------------------------------------------------------------------------------------------
//МЕНЮ ПРОГРАММИРОВАНИЯ ЧАСОВ
//вправо\влево - переход к следующим\предыдущим полям редактирования
//вверх\вниз - изменение значения сегмента
//удержание вправо - запомнить данные
//удержание влево - выход без сохранения
//ClockData [7]; глобальный массив данных часов ([0] секунды, [1] минуты, [2] часы, [3] день, [4] дата, [5] месяц, [6] год

void MenuSetupClock (void)
{
	//step - номер редактируемой ступени: 
	//0,1-год, 2,3-месяц, 4,5-день, 6,7-часы, 8,9-минуты, 10-вых без прогр, 11-вых с прогр.
	char step = 0;	
	char BtnMask;

	char minute = 	ClockData[1];					//временная переменная минут
	char hour = 	ClockData[2];					//временная переменная часов
	char day = 		ClockData[4];					//временная переменная дня
	char month = 	ClockData[5];					//временная переменная месяца
	char year = 	ClockData[6];					//временная переменная года

	while (1){

		if ((step == 0) || (step == 1)){			//редактирование года		
			DispMessageShow (TxtYear);				//вывести на дисплей "year"
			BtnPressWait1Sec (); 					//в течение 1 сек ожидаем нажатия кнопки					

			while (1){
				DispSimbShow ('2',0);				//выводим на дисплей тысячи 
				DispSimbShow ('0',1);				//сотни
				DispSimbShow ((year >> 4),2);		//десятки
				DispSimbShow ((year & 0x0f),3);		//единицы
	
				BtnMask = FlashSeg (2 + step); 		//мигаем соответствующим сегментом, ожидаем нажатия кнопки
				char TempYear = year;

				if (BtnMask == ShortRight){			//нажата кнопка "влево"
					DispFlashCoun = 50;				//моргнуть соответствующим сегментом
					if (++ step == 2)				//если >= 2, переходим к редактированию даты
						break;
				}

				if (BtnMask == ShortLeft){			//нажата кнопка "вправо"
					DispFlashCoun = 50;
					if (step ==1)
						step --;
				}
	
				if (BtnMask == LongLeft){			//выход из настройки без сохранения
					step = 10;
					break; 
				}
	
				if (BtnMask == LongRight){			//выход из настройки с сохранением 
					step = 11;
					break; 
				}
				
				if (BtnMask == ShortUp){			//увеличить значение сегмента
					if (step)	year ++;
					else		year += 0x10;
				}

				if (BtnMask == ShortDown){			//уменьшить значение сегмента
					if 	(step)	year --;
					else		year -= 0x10;
				}
				
				year = VrfClockInpData (TempYear, year, 0,99);//проверить корректность ввода года
			}
		}

		if ((step >= 2) && (step <= 5)){			//редактирование числа и месяца			
			DispMessageShow (TxtDate);
			BtnPressWait1Sec (); 					//в течение 1 сек ожидаем нажатия кнопки					

			while (1){
				DispSimbShow ((day >> 4),0);		//выводим на дисплей число и месяц
				DispSimbShow ((day & 0x0f),1);
				DispSimbShow ((month >> 4),2);		
				DispSimbShow ((month & 0x0f),3);
				DispData [1] |= SegH;				//допечатать точку
	
				BtnMask = FlashSeg (step - 2); 		//мигаем сегментом, ожидаем нажатия кнопки
				char TempDay = day; 
				char TempMonth = month;

				if (BtnMask == ShortUp){			//увеличить значение сегмента
					if 	(step == 2)					//десятки дня
						day += 0x10;

					if 	(step == 3)					//единицы дня
						day ++;

					if 	(step == 4)					//десятки месяца
						month += 0x10;

					if 	(step == 5)					//единицы месяца
						month ++;
				}

				if (BtnMask == ShortDown){			//уменьшить значение сегмента
					if 	(step == 2)					//десятки дня
						day -= 0x10;

					if 	(step == 3)					//единицы дня
						day --;

					if 	(step == 4)					//десятки месяца
						month -= 0x10;

					if 	(step == 5)					//единицы месяца
						month --;
				}

				day =   VrfClockInpData 	(TempDay, 	day, 	1, 31);//проверка корректности ввода дня
				month = VrfClockInpData 	(TempMonth, month, 	1, 12);//проверка корректности ввода месяца

				if (BtnMask == ShortRight){
					DispFlashCoun = 50;
					if (++ step > 5)
						break;
				}

				if (BtnMask == ShortLeft){
					DispFlashCoun = 50;
					if (-- step < 2)
						break;
				}
	
				if (BtnMask == LongLeft){
					step = 10;
					break; 
				}
	
				if (BtnMask == LongRight){
					step = 11;
					break; 
				}
			}
		}
	
		if ((step >= 6) && (step <= 9)){			//редактирование часов и минут			
			DispMessageShow (TxtCloc);
			BtnPressWait1Sec (); 					//в течение 1 сек ожидаем нажатия кнопки					

			while (1){
				DispSimbShow ((hour >> 4),0);		//выводим на дисплей часы и минуты
				DispSimbShow ((hour & 0x0f),1);
				DispSimbShow ((minute >> 4),2);		
				DispSimbShow ((minute & 0x0f),3);
				DispData [1] |= SegH;				//допечатать точку
	
				BtnMask = FlashSeg (step - 6); 		//мигаем сегментом, ожидаем нажатия кнопки
				char TempHour = hour; 
				char TempMinute = minute;

				if (BtnMask == ShortUp){			//увеличить значение сегмента
					if 	(step == 6)					//десятки часов
						hour += 0x10;

					if 	(step == 7)					//единицы часов
						hour ++;

					if 	(step == 8)					//десятки минут
						minute += 0x10;

					if 	(step == 9)					//единицы минут
						minute ++;
				}

				if (BtnMask == ShortDown){			//уменьшить значение сегмента
					if 	(step == 6)					//десятки часов
						hour -= 0x10;

					if 	(step == 7)					//единицы часов
						hour --;

					if 	(step == 8)					//десятки минут
						minute -= 0x10;

					if 	(step == 9)					//единицы минут
						minute --;
				}
			
				hour = 	 VrfClockInpData (TempHour, 	hour, 	0, 23);	//проверка корректности ввода часа
				minute = VrfClockInpData (TempMinute,	minute, 0, 59);	//проверка корректности ввода минуты

				if (BtnMask == ShortRight){
					DispFlashCoun = 50;
					if (step < 9)
						step ++;
				}

				if (BtnMask == ShortLeft){
					DispFlashCoun = 50;
					if (-- step < 6)
						break;
				}

				if (BtnMask == LongLeft){
					step = 10;
					break; 
				}
	
				if (BtnMask == LongRight){
					step = 11;
					break; 
				}
			}
		}

		if (step == 10){
			DispMessageShow (TxtRet);				//выход без сохранения
			BtnPressWait2Sec (); 					//в течение 1 сек ожидаем нажатия кнопки					
			return;
		}

		if (step == 11){

			IICStart();
			IICByteWrite (0xD0);					//запись данных в DS1307
			IICByteWrite (0x00);					//сбросить указатель адреса DS1307 на 0 

			IICByteWrite (0);						//записать секунды
			IICByteWrite (minute);					//минуты
			IICByteWrite (hour);					//часы
			IICByteWrite (0);						//день
			IICByteWrite (day);						//дата 
			IICByteWrite (month);					//месяц
			IICByteWrite (year);					//год
			IICStop();

			StructEEWrite ();						

			DispMessageShow (TxtDone);
			BtnPressWait2Sec (); 					//в течение 1 сек ожидаем нажатия кнопки					
			return;
		}
	}
}


//ФУНКЦИЯ МИГАНИЯ СЕГМЕНТА И ОЖИДАНИЕ НАЖАТИЯ КНОПКИ (исп-ся в меню настройки часов)
//АРГУМЕНТ - номер мигающего сегмента 0-3
//ЗНАЧЕНИЕ - нажатая клавиша (если 0 - выход по timeout)
char FlashSeg (unsigned char seg)
{
    BtnTimeOutCoun = TimeOutConst;
    char* pDispSeg = &DispData [seg];
    char SegVal = *pDispSeg;

    while (1){                                    //крутимся    
        if (DispFlashCoun < 50)
            *pDispSeg = SegVal;
        else
            *pDispSeg = 0;
                                        
        if (BtnFlags){
            char temp = BtnFlags;                //кнопка нажата
            BtnFlags = 0;
            return temp;                        //возвращаем маску нажатой кнопки
        }

        if (! BtnTimeOutCoun)
            return 0;
    }
}


//ФУНКЦИЯ ПРОВЕРКИ ВВЕДЕННЫХ ДАННЫХ 
//АРГУМЕНТ_1 - исходное значение (в двоично-десятичном виде)
//АРГУМЕНТ_2 - измененное значение (в двоично-десятичном виде)
//АРГУМЕНТ_3 - минимально возможное значение (в шестнадцатеричном виде)
//АРГУМЕНТ_4 - максимально возможное значение
//ЗНАЧЕНИЕ - возвращаем корректное значение
char VrfClockInpData (char mem, char change, char min, char max)
{
    if (((change >> 4) >= 10)
    || ((change & 0x0f) >= 10))
        return mem;
        
    char temp = ConvBinDecToHex (change);
    if ((temp < min) || (temp > max))
        return mem;

    return change;
}
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
C@at
Вымогатель припоя
Сообщения: 652
Зарегистрирован: Вс ноя 13, 2011 16:42:05
Откуда: Украина

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение C@at »

Особой небходимости комплимировть проект на 8мгц нет, а отладку в протеусе это сильно тормозит и это еще датчик температуры там не подключен.
RGB писал(а):а вот как быть с декрементом?)
обычно так
Спойлер

Код: Выделить всё

                 if (menu>=1) {  
                     if (PIND.4==0){  //  плюс       
                          
                             if (set==1)  {   min++; if(min>= 60)  {   min=0; }; };  //        минуты   
                             if (set==2)  {  hour++; if(hour>= 24)  {   hour=0;   };};   //        часы
                              rtc_set_time(hour,min,sek); //  
                            delay_ms(250);
                              }; //    

                     if (PIND.7==0){  //  минус  

                             if (set==1)  {   min--; if(min>= 255) { min=59; }; };    // минуты        
                             if (set==2)  {  hour--; if(hour>= 255){ hour=23; };};   //        часы
                              rtc_set_time(hour,min,sek); // 
                            delay_ms(250); //    
                        }; 

            }; 
Реклама
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение RGB »

Всем огромное СПАСИБО кто откликнулся, и помогает!!!
Я решил поступить следующим образом:
Нарисовал меню на бумажке, стрелочками всё это соединил, куда что нужно, и как должно работать))) типо блок схема получилась!!! Сейчас вот меню наченает преображаться, сижу по блок схеме пишу программу!!! Всё красиво, но вот дошёл до меню "настройки часов" теперь загвоздка, нужно кнопкой "ENTER" выбирать что настраивать часы или минуты. Сообственно к кнопки "ENTER" хочу привязать мигание курсора под выбранным изменяемым эллементом, а вот как сделать мигающий курсор под часами или минутами ума не приложу.

И ещё вопросик: можно ли в программе сделать функцию проверки отсутствия или неисправности микросхемы RTC-DS1307 ? И при её отсутствии или неисправности вывести сообщение на LCD типо "ОШИБКА_1"
Эта микросхема общается с МК по протоколу I2C. Тоесть мне нужно сделать некую проверку на опрос этого протокола? или что?

Подскажите Пожалуйста!
Реклама
Аватара пользователя
dracon
Грызет канифоль
Сообщения: 259
Зарегистрирован: Пт авг 10, 2012 21:44:55
Откуда: Moskow
Контактная информация:

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение dracon »

А мигание всего блока часы\минуты при его выборе уже не подходит? Вроде проще чем курсор заморачивать и информативнее намного. сразу видно чего за блок настраиваем.
MAXимки, мои любимые микрушки....
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение RGB »

А мигание всего блока часы\минуты при его выборе уже не подходит? Вроде проще чем курсор заморачивать и информативнее намного. сразу видно чего за блок настраиваем.
Точно!!! но как очищать и записывать с некой задержкой к примеру часы?

Код: Выделить всё

           lcd_gotoxy(0,0);
           lcd_putsf("НАСТРОЙКА  ЧАСОВ");
            
             if (enter == 1){
           lcd_gotoxy(6,1);
           lcd_putchar(hour/10+0x30);
           lcd_putchar(hour%10+0x30); 
               
                            }
           lcd_putchar(':');
           lcd_putchar(min/10+0x30);
           lcd_putchar(min%10+0x30);  
           LED_BLUE = 0;
           LED_RIHT = 1;
           LED_LEFT = 1;
           LED_RED  = 0; 
             wait (3000); 
           LED_BLUE = 1;
           LED_RIHT = 0;
           LED_LEFT = 0;
           LED_RED  = 1; 
             wait (3000); 
             rtc_set_time(hour,min,sek); // óñòàíîâêà âðåìåíè 

Код: Выделить всё

if (enter == 1){
           lcd_gotoxy(6,1);
           lcd_putchar(hour/10+0x30);
           lcd_putchar(hour%10+0x30); 
// теперь как очистить только часы не трогая всё остальное? а потом записать? что бы получился эффект мигания?
               
                            }
Аватара пользователя
C@at
Вымогатель припоя
Сообщения: 652
Зарегистрирован: Вс ноя 13, 2011 16:42:05
Откуда: Украина

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение C@at »

Код: Выделить всё

unsigned char  drygalka=0;
////////////////////////////////////////////////////////////    
                                       drygalka++;  
                                    if (drygalka>=130)     //   значение зависит от быстродействия программы в основном цикле
                                            {    
                                               drygalka=0;  
                                            };   
    if (enter == 1){
           lcd_gotoxy(6,1);  
        if (drygalka>=65){   
           lcd_putchar(hour/10+0x30);
           lcd_putchar(hour%10+0x30);   
               } else { 
                lcd_putsf("\x20\x20"); 
                 }  
           
// теперь как очистить только часы не трогая всё остальное? а потом записать? что бы получился эффект мигания?
               
                            }
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение RGB »

Спасибо!
Вот только одного не пойму толи у меня CVAVR тупит толи Я
Он у меня выполняет условие только после "else" хотя компилирует нориально без ошибок
А то что до "else" вообще как будто не видет. :shock:
Аватара пользователя
C@at
Вымогатель припоя
Сообщения: 652
Зарегистрирован: Вс ноя 13, 2011 16:42:05
Откуда: Украина

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение C@at »

тогда так
Спойлер

Код: Выделить всё

 drygalka++;  
                                    if (drygalka>=40)     //   значение зависит от быстродействия программы в основном цикле
                                            {    
                                               drygalka=0;  
                                            };   
    if (enter == 1){
           lcd_gotoxy(6,1);  
        if (drygalka<=20){   
           lcd_putchar(hour/10+0x30);
           lcd_putchar(hour%10+0x30);   
               } else { 
                lcd_putsf("\x20\x20"); 
                 } 
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение Goodefine »

RGB писал(а):... Моя микросхема стабилизатора 78L05 ну уж очень сильно греется. решил разобраться от чего так греется, выяснелось что дело в подсветки LCD (сам в шоке) У меня есть лабороторный блок питания, я решил пдключить саму подсветку LCD на прямую к блоку питания, и чуть не поседел от увиденного. Амперметр показывал около 1 Ампера. Такое реально?...
Резистор в цепь подсветки ставить надо, Семен Семеныч. Как она еще живая до сих пор...
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Аватара пользователя
RGB
Родился
Сообщения: 17
Зарегистрирован: Пт ноя 09, 2012 17:22:37
Откуда: Москва
Контактная информация:

Re: Часы на ATmega8 и LCD 16x2 Мой Проект

Сообщение RGB »

Уважаемый C@at и так и сяк пробовал, ни выходит ни как. на отрез отказывается работать с блоком if только видет else.

Goodefine
Резистор в цепь подсветки ставить надо, Семен Семеныч. Как она еще живая до сих пор...
ставил я сопротевление в цепь, но у меня lcd еле тускло светит! ставил ещё в самом начале когда распаивал макетку и на 330 Ом, и на 68 Ом, и на 47 Ом. эффекта ноль!!!
Ответить

Вернуться в «AVR»