вівторок, 13 січня 2015 р.

Годинник на Atmega8 + DS1302


Схема годинника на DS1302 в Proteus




#asm // Асемблерна вставка ініціалізації підключення мікросхеми DS1302 до Atmega8
  .equ __DS1302_port=0x15;//Подключаем DS1302 к PORTС(0x15-адреса регістра порта)
  .equ __DS1302_io=2 ;//Другий пін для io
  .equ __DS1302_sclk=1 ;//Перший пін для sclk
  .equ __DS1302_rst=0 ;//Нульовий пін для rst
  #endasm
#include <bcd.h>
#include <mega8.h>
#include <delay.h>
#include <DS1302.h>

#define DIGITS 6   // Кількість розрядів індикатора
unsigned char chislo[DIGITS]; //масив чисел, що відповідають кожному розряду
unsigned char numder[]= //масив, в якому індексу будут відповідати біти на порту D для кожної цифри
{ 
0b00111111, //цифра 0
0b00000110, //цифра 1
0b01011011, //цифра 2
0b01001111, //цифра 3
0b01100110, //цифра 4
0b01101101, //цифра 5
0b01111101, //цифра 6
0b00000111, //цифра 7
0b01111111, //цифра 8
0b01101111, //цифра 9
0b00000000, //пусто
}; 
unsigned char hour_1, minute_1;//години та хвилини для наведення
unsigned char second, minute, hour, date, month, year;// змінні часу та дати
bit Button_1_state, Button_2_state;
unsigned short i=0; // змінна, що визначає номер розряду який виводиться
unsigned short k, dp; // змінні для крапки
//*****************************************************************************
// преривання по переповненню timer0
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTB=0x3f; // погасимо індикатор
    if (i==2||i==4) dp=k;//виводимо крапку на 2 та 4 індикатор
    else  dp=0;
PORTD=((numder[ chislo[i]])|dp); // виведем поточне число    
PORTB=~(1<<i); // вмикаємо відповідний розряд індикатора
if (i++>DIGITS) i=0; // якшо не дійшли до старшого розряду готуєм виведення наступного
  }                    // якшо дійшли до старшого розряду готуєм виведення нульового
//*****************************************************************************
void out_1(unsigned short num)//виведення першої пари знаків (для секунд)
{   chislo[0]=num%10; //одиниці секунд
    chislo[1]=num/10; // десятки
    k=(~k)&0b10000000;// крапка засвічується та гасне кожну секунду
    }
      
void out_2(unsigned short num)//виведення другої пари знаків (для хвилин)
{   chislo[2]=num%10; //одиниці хвилин
    chislo[3]=num/10; // десятки
    }  
void out_3(unsigned short num)//виведення третьої пари знаків (для годин)
{   chislo[4]=num%10; //одиниці годин
    chislo[5]=num/10; // десятки
    }
//****************************************************************************
void main(void)
{
//Порт В
    PORTB=0x00;
    DDRB=0b00111111; //PB0-3 виходи (розряди)
//Порт С
    PORTC=0b00111111;      //включимо підтягуючі резистори на PС0-5
    DDRC=0b00000000; //PС0-3 входи (кнопки + DS1302)
//Порт Д
    PORTD=0b0000000;
    DDRD=0b11111111; //PD0-PD6 виходи (сегменти) 

    TCCR0=0x03; //встановлюємо подільник таймера 64
    rtc_init(0,0,0);//Ініціалізація DS1302 
            // кожне перерив приблизно 2 мс
    rtc_set_date(13,01,15);//встановлюємо дату 13.01.15         

    TIMSK=0x01;// переривання по переповненню таймера 0   
    #asm("sei")// глобальний дозвіл перерывання
//***************************************************************************
while (1) //основний цикл
{ 
rtc_get_time(&hour,&minute,&second);//зчитуємо години, хвилини, секунди
                                    // у відповідні змінні
    out_1(second);    //виводимо на індикатор секунди
    out_2(minute);    //хвилини
    out_3(hour);     // години    
   
 while (PINC.3==0){   //Поки натиснена кнопка збільшення хвилин
      k=0x80;// крапки засвічуються
  minute++;         // збільшуємо хвилини кожні 300мс в діапазоні 0-60
  if(minute==60)minute=0;
  minute_1 = bin2bcd(minute);// перетворюємо двійкове число в двійково-десяткове
  out_2(minute);//виводимо на індикатор хвилини які наводимо
  delay_ms(300);
  Button_1_state = 1;
      
  }
 while (PINC.4==0){ //Поки натиснена кнопка збільшення годин
      k=0x80;// крапки засвічуються
  hour++;      // збільшуємо години кожні 300мс в діапазоні 0-24
  if(hour==24)hour=0;
  hour_1 = bin2bcd(hour);
  out_3(hour);    //виводимо на індикатор
  delay_ms(300);
  Button_2_state = 1;
    }
    delay_ms(500);
    if (Button_1_state && PINC.3){// Якщо кнопка наведення хвилин була натиснена і її тільки що відпустили 
        ds1302_write(0b10000010, minute_1);//Записуємо нове виставлене значення хвилин в 1302
        ds1302_write(0b10000000, 0);//Скидаємо секунди в 0 в 1302
        Button_1_state = 0;// скидаємо фіксатор
        }
    if (Button_2_state && PINC.4){// Якщо кнопка наведення годин була натиснена і її тільки що відпустили 
        ds1302_write(0b10000100, hour_1);//Записуємо нове виставлене значення годин в 1302
        Button_2_state = 0;
        }
    while (PINC.5==0){ // Поки кнопка дати натиснена 
    k=0;// розділові крапки засвічуються
    rtc_get_date(&date, &month, &year); // зчитується дата
    out_1(year);    //виводимо на індикатор рік
    out_2(month);    //місяць
    out_3(date);     //число 
    delay_ms(500);
 }  
 }   
}

Sourse_file (Proteus in folder EXE)








Немає коментарів :

Дописати коментар