http://my-avr.at.ua/publ/1-1-0-22 спаял такие часы (в машине сломались). сделал по статье, но индикатор с общим анодом (код переделал под общ анод). Но часы не пошли. Переделал прогу - часы пошли. Но как зажечь точку секундную в разряде единиц часов - пока не въехал. Код пока без учета кнопок управления и интервал секунд составляет 0,1сек для проверки работы чтоб не ждать долго. Не нашел как вставить сюда файлы, а то б выложил схему , печатку и фото.
/***************************************************** CodeWizardAVR V2.05.0 Advanced Project : Version : Date : 02-02-2012 Author : Belazov Company : Comments: часы на Мега8 Chip type : ATmega8 Program type : Application AVR Core Clock frequency: 8,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/
#include <mega8.h> #include <delay.h>
#define digit0 PORTB.0 //анод 1 цифры - десятки минут #define digit1 PORTB.1 //анод 2 цифры - единицы минут #define digit2 PORTB.2 //анод 3 цифры - десятки часов #define digit3 PORTB.3 //анод 4 цифры - единицы часов
unsigned char sek; // переменная сек. unsigned char min; // пересенная мин. unsigned char hour; // переменная часов char digit_out[4], ; //массив для работы с LED, сюда для соответствующего разряда индикатора (0,1,2,3) //заносим цифру от 0 до 9 которое соотв индексу //массива digits[] для отображения этой цифры в знакоместе char cur_dig; //переменная для работы с LED для смены знакоместа для динамической индикации unsigned char indication_min; //для декодирования минут unsigned char indication_hour;//для декодирования часов
//PORTD= 0-E, 1-F, 2-A, 3-B, 4-C, 5-G, 6-D, 7-Dp соответствие порта сегментам индикатора flash char digits[]= { // Сейчас у нас схема с общим анодом - управление сегментом подачей 0 на вывод порта 0b10100000, //индекс массива соответствует цифре, которой он соответствует 0b11100111, //а двоичное число в этом месте - кодировка вывода порта 0b10010010, //для отображения этой цифры на индикаторе 0b10000011, //1 в разряде 7 - потушенная точка DP 0b11000101, 0b10001001, 0b10001000, 0b11100011, 0b10000000, 0b10000001,}; //после массива ставить ; !!!
void recoding_min(void) //функция для перекодировки из dec в десятки +единицы { if (indication_min<60) //начинаем преобразование если число < 60 так как { //2-разрядный LED digit_out[0]=indication_min%10; //Делим на 10 остаток в масив 1-разряд десятки минут indication_min=indication_min/10; //Оставляем 2 разряда digit_out[1]=indication_min%10; //Делим на 10 остаток в масив 2-разряд единицы минут }; }
void recoding_hour(void) //функция для перекодировки изdec в десятки +единицы { if (indication_hour<24) //начинаем преобразование если число < 24 так как { //2-разрядный LED digit_out[2]=indication_hour%10; //Делим на 10 остаток в масив 1-разряд десятки часов indication_hour=indication_hour/10; //Оставляем 2 разряда digit_out[3]=indication_hour%10; //Делим на 10 остаток в масив 2-разряд единицы часов } }
void start(void) //описываю ф-цию start { TCCR1B=0x00; //остановка таймера Т1-cчетчик времени минут TCCR1B=0x0D; //запуск Т1 делитель 977Гц и режим прерыв при совпадении с А
}
// Timer 0 overflow interrupt service routine //это прерывание для органицации динамической индикации interrupt [TIM0_OVF] void timer0_ovf_isr(void) { TCNT0=0xBF; // Reinitialize Timer 0 value, частота прерываний 77Гц PORTB=0xFF ; //чтобы предотвратить эффект “тени” на соседних индикаторах switch (cur_dig) { case 0:{digit3=0; digit2=1;digit1=1;digit0=1; break;}; //подаём питание на разряд 3 case 1:{digit2=0; digit3=1;digit1=1;digit0=1; break;}; //подаём питание на разряд 2 case 2:{digit1=0; digit3=1;digit2=1;digit0=1; break;}; //подаём питание на разряд 1 case 3:{digit0=0; digit3=1;digit2=1;digit1=1; break;}; //подаём питание на разряд 0
} //ОА на digit->0, OK->1 PORTD=digits[digit_out[cur_dig]]; //выводим с каждым срабатыванием таймера число из //мaссива digits[] в порт D, но не для всех разрядов сразу cur_dig++; //а с каждым срабатыванием таймера, увеличиваем //переменную cur_dig на 1 if(cur_dig==4) cur_dig=0; //если cur_dig = 4 обнуляем }
// Timer1 output compare A interrupt service routine //это прерывание для счета секунд ( минуты и часы считаются в main) interrupt [TIM1_COMPA] void timer1_compa_isr(void) { sek++; // инкрементируем секунду }
// Global enable interrupts #asm("sei") start(); while (1) { switch (sek) { case 60:{min++; //min инкремент if (min==60) //если минут 60 {hour++; //часов инкремент и min=0; //обнуление минут }; if (hour==24) //проверка если часов 24 {hour=0; //то обнулить часы }; sek=0; break;}; } indication_hour = hour; //перем для вывода часов indication_hour присваиваю значение hour indication_min = min; //перем для вывода минут indication_min присваиваю значение min recoding_min (); //вызов функции для извлечения единиц-десятков минут recoding_hour (); //вызов функции для извлечения единиц-десятков часов
} }
Сообщение отредактировал belazov - Четверг, 02.02.2012, 18:50
void recoding_hour(void) //функция для перекодировки в десятки +единицы { if (indication_hour<24) //начинаем преобразование если число < 24 т.к. 2-разрядный LED { digit_out[2]=(indication_hour%10)&0b01111111; //Делим на 10 остаток в масив 1-разряд десятки часов и обнуляю разряд7 (Dp) indication_hour=indication_hour/10; //Оставляем 2 разряда digit_out[3]=indication_hour%10; //Делим на 10 остаток в масив 2-разряд единицы часов } }
проштудировал. вроде бы так же? но точка не горит зараза. И еще, чтобы в обработке прерывания инвертировать бит, так получится?
Добавлено (04.02.2012, 00:22) --------------------------------------------- Сделал с подсказки форумчан. Мигает такой вариант
Code
// Timer 0 overflow interrupt service routine //это прерывание для органицации динамической индикации interrupt [TIM0_OVF] void timer0_ovf_isr(void) { TCNT0=0xBF; // Reinitialize Timer 0 value, частота прерываний 77Гц PORTB=0xFF ; //чтобы предотвратить эффект “тени” на соседних индикаторах switch (cur_dig) { case 0:{digit3=0; digit2=1;digit1=1;digit0=1; break;}; //подаём питание на разряд 3 case 1:{digit2=0; digit3=1;digit1=1;digit0=1; break;}; //подаём питание на разряд 2 case 2:{digit1=0; digit3=1;digit2=1;digit0=1; break;}; //подаём питание на разряд 1 case 3:{digit0=0; digit3=1;digit2=1;digit1=1; break;}; //подаём питание на разряд 0
} //ОА на digit->0, OK->1 PORTD=digits[digit_out[cur_dig]]; //выводим с каждым срабатыванием таймера число из //мaссива digits[] в порт D, но не для всех разрядов сразу cur_dig++; //а с каждым срабатыванием таймера, увеличиваем //переменную cur_dig на 1 if ((cur_dig == 3) && (dot==1)){ // если текущий отображаемый разряд - единицы часов и включено отображение точки PORTD =PORTD ^ 0b10000000; // то добавляем в вывод запятую }; if(cur_dig==4) cur_dig=0; //если cur_dig = 4 обнуляем }
Я не в том месте проги поджигал точку.
Сообщение отредактировал belazov - Пятница, 03.02.2012, 23:30