| Ваш IP: 100.26.179.251 | Online(29) - гости: 5, боты: 24 | Загрузка сервера: 0.19 ::::::::::::

Простые часы на ATtiny2313 (Arduino IDE)

На микроконтроллере ATtiny2313 можно собрать простые часы, в качестве индикатора часов будет использоваться модуль TM1637, который представляет собой 4-х разрядный семисегментный дисплей на базе драйвера TM1637 с двоеточием для индикации такта секунд.

Схема часов очень простая, а использование модуля TM1637 упрощает сборку часов. Для коррекции времени служат две кнопки (для минут и часов).

Перед загрузкой скетча рекомендую ознакомится со статьей — ATtiny2313 + Arduino IDE

// tm1637 PB0 === CLK
// tm1637 PB1 === DIO
 
int i,i1,hh,mm,bb;
 
void setup() {
  DDRB = 0b00000000; 
  PORTB |= (1 << 2) | (1 << 3);
   cli();  
  TCCR1A = 0;   
  TCCR1B = 0;   
  OCR1A = 18750; // 0.1 s
  TCCR1B |= (1 << WGM12); 
  TCCR1B |= (1 << CS11) | (1 << CS10);  // 64  
  TIMSK |= (1 << OCIE1A);  
   sei(); 
}
 
void loop() {
  print_time(hh * 100 + mm, bb, 7);// int число выводимое на индикатор, двоеточие, яркость от 0 до 7
  if(i1 <= 5){bb = 1;}else{bb = 0;}
 
  if(((PINB >> 2) & 1) == 0){mm++; if(mm>59){mm = 0;} delay(200);}
  if(((PINB >> 3) & 1) == 0){hh++; if(hh>23){hh = 0;} delay(200);}
}
 
void tm_dec(byte dig){
       for(int i = 0; i < 8; i++) {
         DDRB |= (1 << 0);del();
       if (dig & 0x01)
         DDRB &= ~(1 << 1);
       else
         DDRB |= (1 << 1);del();
         DDRB &= ~(1 << 0);del();
         dig = dig >> 1;
  }
         DDRB |= (1 << 0);
         DDRB &= ~(1 << 1);del();
         DDRB &= ~(1 << 0);del();
 
       if (((PINB >> 1) & 1) == 0)
         DDRB |= (1 << 1);del();
         DDRB |= (1 << 0);del();
  }  
 
void tm_stop(){
         DDRB |= (1 << 1);del();
         DDRB &= ~(1 << 0);del();
         DDRB &= ~(1 << 1);del();
  }  
 
void tm_start(){
         DDRB |= (1 << 1);del();
  }
 
void print_time(int t, bool pd_t, int br){
        tm_start();tm_dec(0b10001000 + br);//tm_stop();tm_start();
        tm_dec(0x40);tm_stop();tm_start();
 
        int data0 = t / 1000;
        int data1 = t / 100 % 10;
        int data2 = t / 10 % 10;
        int data3 = t % 10;
 
      for(byte n = 0; n < 4; n++){
        int data;
      switch(n){
        case 0: data = data0;break;
        case 1: data = data1;break;
        case 2: data = data2;break;
        case 3: data = data3;break;
        }
 
      switch(data){  // XGFEDCBA
        case 0:  data = 0b00111111;break;     // 0
        case 1:  data = 0b00000110;break;     // 1
        case 2:  data = 0b01011011;break;     // 2
        case 3:  data = 0b01001111;break;     // 3
        case 4:  data = 0b01100110;break;     // 4
        case 5:  data = 0b01101101;break;     // 5
        case 6:  data = 0b01111101;break;     // 6
        case 7:  data = 0b00000111;break;     // 7
        case 8:  data = 0b01111111;break;     // 8
        case 9:  data = 0b01101111;break;     // 9
        }
 
        if(n == 0){data0 = data;}
        if(n == 1){data1 = data;}
        if(n == 2){data2 = data;}
        if(n == 3){data3 = data;}
        }
      if(pd_t == 1){data1+= 0b10000000;}
      tm_dec(0xC0);tm_dec(data0);tm_dec(data1);tm_dec(data2);tm_dec(data3);tm_stop();
}  
 
void del(){delayMicroseconds(100);}
 
ISR(TIMER1_COMPA_vect){
     i++;i1++;
     if(i1 > 9){i1 = 0;}
     if(i > 599){mm++;i = 0;}
     if(mm > 59){hh++;mm = 0;}
     if(hh > 23){hh = 0;}
     }

Скетч использует 1330 байт (64%) памяти устройства. Всего доступно 2048 байт.
Глобальные переменные используют 19 байт (14%) динамической памяти, оставляя 109 байт для локальных переменных. Максимум: 128 байт.

Так как в ATtiny2313 еще остается немного памяти и я решил дополнить часы будильником.

Управление часами осуществляется при помощи 4-х кнопок, кнопки НН и ММ для корректировки часов и минут, кнопка SET ALARM служит для установки времени срабатывания будильника, при нажатии на кнопку SET ALARM мигание двоеточия прекращается, что свидетельствует о активации режима корректировки времени будильника, кнопками НН и ММ устанавливается время будильника. При повторном нажатии кнопки SET ALARM происходит переход в режим часов. Кнопка ALARM ON/OFF предназначена для активации режима будильника, при нажатии на кнопку загорается светодиод и при совпадении времени часов и времени будильника будет слышен прерывисты звуковой сигнал, который будет звучать в течении 1 минуты, прервать сигнал можно нажав на кнопку ALARM ON/OFF.

Время будильника сохраняется в энергонезависимой памяти.

// tm1637       PB0 === CLK
// tm1637       PB1 === DIO
// zummer       PD5
// MM+          PB2
// HH+          PB3
// ALARM/TIME   PB4
// ALARM ON/OFF PD4
// led ALARM    PD3
 
int i,i1,hh,mm,bb,b_hh,b_mm,bud,blok;
 
void setup() {
  DDRB = 0b00000000; 
  DDRD = 0b00101000;
  PORTB |= (1 << 2) | (1 << 3) | (1 << 4);
  PORTD |= (1 << 4);
   cli();  
  TCCR1A = 0;   
  TCCR1B = 0;   
  OCR1A = 18750; // 0.1 s
  TCCR1B |= (1 << WGM12); 
  TCCR1B |= (1 << CS11) | (1 << CS10);  // 64  
  TIMSK |= (1 << OCIE1A);  
   sei(); 
   b_hh = EEPROM_read(1);
   b_mm = EEPROM_read(0);
}
 
void loop() {
  if(bud == 0){print_time(hh * 100 + mm, bb, 7);}// int число выводимое на индикатор, двоеточие, яркость от 0 до 7
  if(bud == 1){print_time(b_hh * 100 + b_mm, bb, 7);}// int число выводимое на индикатор, двоеточие, яркость от 0 до 7
  if(i1 <= 5){bb = 1;}else{bb = 0;} 
  if(bud == 1){bb = 1;}
  // button set time
  if(((PINB >> 2) & 1) == 0 && bud == 0){mm++; if(mm>59){mm = 0;} delay(200);}
  if(((PINB >> 3) & 1) == 0 && bud == 0){hh++; if(hh>23){hh = 0;} delay(200);}
  // button set alarm
  if(((PINB >> 4) & 1) == 0 && bud == 0){bud = 1; delay(200);}
  if(((PINB >> 4) & 1) == 0 && bud == 1){bud = 0; delay(200);}
  // button set time alarm
  if(((PINB >> 2) & 1) == 0 && bud == 1){b_mm++;  if(b_mm>59){b_mm = 0;}EEPROM_write(0,b_mm); delay(200);}
  if(((PINB >> 3) & 1) == 0 && bud == 1){b_hh++;  if(b_hh>23){b_hh = 0;}EEPROM_write(1,b_hh); delay(200);}
  // led alarm | button on/off
  if(((PIND >> 4) & 1) == 0 && blok == 1){blok = 0; delay(200);}
  if(((PIND >> 4) & 1) == 0 && blok == 0){blok = 1; delay(200);}
  if(blok == 1){PORTD &= ~(1 << 3);}else{PORTD |= (1 << 3);}
  // zummer
  if((hh * 100 + mm) == (b_hh * 100 + b_mm) && blok == 0){if(i1 <= 5){DDRD |= (1 << 5);pic();} else {DDRD &= ~(1 << 5);}}  
} // loop
 
void pic(){
  for(int g=0;g<1000;g++){
  PORTD |= (1 << 5);
  delayMicroseconds(150);
  PORTD &= ~(1 << 5);
  delayMicroseconds(100);}
  }
 
void tm_dec(byte dig){
       for(int i = 0; i < 8; i++) {
         DDRB |= (1 << 0);del();
       if (dig & 0x01)
         DDRB &= ~(1 << 1);
       else
         DDRB |= (1 << 1);del();
         DDRB &= ~(1 << 0);del();
         dig = dig >> 1;
  }
         DDRB |= (1 << 0);
         DDRB &= ~(1 << 1);del();
         DDRB &= ~(1 << 0);del();
 
       if (((PINB >> 1) & 1) == 0)
         DDRB |= (1 << 1);del();
         DDRB |= (1 << 0);del();
  }  
 
void tm_stop(){
         DDRB |= (1 << 1);del();
         DDRB &= ~(1 << 0);del();
         DDRB &= ~(1 << 1);del();
  }  
 
void tm_start(){
         DDRB |= (1 << 1);del();
  }
 
void print_time(int t, bool pd_t, int br){
        tm_start();tm_dec(0b10001000 + br);//tm_stop();tm_start();
        tm_dec(0x40);tm_stop();tm_start();
 
        int data0 = t / 1000;
        int data1 = t / 100 % 10;
        int data2 = t / 10 % 10;
        int data3 = t % 10;
 
      for(byte n = 0; n < 4; n++){
        int data;
      switch(n){
        case 0: data = data0;break;
        case 1: data = data1;break;
        case 2: data = data2;break;
        case 3: data = data3;break;
        }
 
      switch(data){  // XGFEDCBA
        case 0:  data = 0b00111111;break;     // 0
        case 1:  data = 0b00000110;break;     // 1
        case 2:  data = 0b01011011;break;     // 2
        case 3:  data = 0b01001111;break;     // 3
        case 4:  data = 0b01100110;break;     // 4
        case 5:  data = 0b01101101;break;     // 5
        case 6:  data = 0b01111101;break;     // 6
        case 7:  data = 0b00000111;break;     // 7
        case 8:  data = 0b01111111;break;     // 8
        case 9:  data = 0b01101111;break;     // 9
        }
 
        if(n == 0){data0 = data;}
        if(n == 1){data1 = data;}
        if(n == 2){data2 = data;}
        if(n == 3){data3 = data;}
        }
      if(pd_t == 1){data1+= 0b10000000;}
      tm_dec(0xC0);tm_dec(data0);tm_dec(data1);tm_dec(data2);tm_dec(data3);tm_stop();
}  
 
void del(){delayMicroseconds(100);}
 
ISR(TIMER1_COMPA_vect){
     i++;i1++;
     if(i1 > 9){i1 = 0;}
     if(i > 599){mm++;i = 0;}
     if(mm > 59){hh++;mm = 0;}
     if(hh > 23){hh = 0;}
     }
 
unsigned char EEPROM_read(unsigned int uiAddress){
  while(EECR & (1<<EEPE));
    EEAR = uiAddress;
    EECR |= (1<<EERE);
    return EEDR;
}
 
void EEPROM_write(unsigned int uiAddress, unsigned char ucData){
    while(EECR & (1<<EEPE));
      EEAR = uiAddress;
      EEDR = ucData;
      EECR |= (1<<EEMPE);
      EECR |= (1<<EEPE);
}

Следующая версия часов аналогична первым часам, но в них в качестве индикатора используется LCD1602.

// ATTINY2313 V1.25
// D4 = PB0
// D5 = PB1
// D6 = PB2
// D7 = PB3
// E  = PB4
// RS = PD6
// button HH = PD3
// button MM = PD4
 
int i,hh,mm,ss;
int a[8];
 
void setup() {
    DDRB = 0b00011111;
    DDRD = 0b01000000;
    PORTD |= (1 << 4) | (1 << 3);
    cli();  
    TCCR1A = 0;   
    TCCR1B = 0;   
    OCR1A = 18750; // 0.1 s
    TCCR1B |= (1 << WGM12); 
    TCCR1B |= (1 << CS11) | (1 << CS10);  // 64  
    TIMSK |= (1 << OCIE1A);  
    sei();
         delay(100);
    lcd(0x03);delayMicroseconds(4500);
    lcd(0x03);delayMicroseconds(4500);
    lcd(0x03);delayMicroseconds(200);
    
    lcd(0b00000010);del();
    lcd(0b00001100);del();
    lcd(0b00000001);
}
 
void loop() {    
  if(((PIND >> 4) & 1) == 0){mm++; if(mm>59){mm = 0;}}
  if(((PIND >> 3) & 1) == 0){hh++; if(hh>23){hh = 0;}}
    a[0] = hh/10+48;
    a[1] = hh%10+48;
    a[2] = mm/10+48;
    a[3] = mm%10+48;
    a[4] = ss/10+48;
    a[5] = ss%10+48;
 
    lcd(0b10000000+6); // 0
    lcdString("TIME");
    lcd(0b11000000+4); // 1
    lcdChar(a[0]);lcdChar(a[1]);lcdString(":");lcdChar(a[2]);lcdChar(a[3]);lcdString(":");lcdChar(a[4]);lcdChar(a[5]);
 
    delay(100);
}
 
void lcdSend(bool isCommand, uint8_t data) {
    if(isCommand==0){PORTD |= (1 << 6);}//RS
    if(isCommand==1){PORTD &= ~(1 << 6);}//RS
    del();
    if(((data >> 7) & 1) ==1){PORTB |= (1 << 3);}else{PORTB &= ~(1 << 3);}
    if(((data >> 6) & 1) ==1){PORTB |= (1 << 2);}else{PORTB &= ~(1 << 2);}
    if(((data >> 5) & 1) ==1){PORTB |= (1 << 1);}else{PORTB &= ~(1 << 1);}
    if(((data >> 4) & 1) ==1){PORTB |= (1 << 0);}else{PORTB &= ~(1 << 0);}
    rs();
    if(((data >> 3) & 1) ==1){PORTB |= (1 << 3);}else{PORTB &= ~(1 << 3);}
    if(((data >> 2) & 1) ==1){PORTB |= (1 << 2);}else{PORTB &= ~(1 << 2);}
    if(((data >> 1) & 1) ==1){PORTB |= (1 << 1);}else{PORTB &= ~(1 << 1);}
    if(((data >> 0) & 1) ==1){PORTB |= (1 << 0);}else{PORTB &= ~(1 << 0);}
    rs();
}
 
void lcd(uint8_t cmd) {lcdSend(true, cmd);}
void lcdChar(const char chr) {lcdSend(false, (uint8_t)chr);}
void lcdString(const char* str) {while(*str != '\0') {lcdChar(*str);str++;}}
void del(){delay(5);}
void rs(){PORTB |= (1 << 4);del();PORTB &= ~(1 << 4);}
ISR(TIMER1_COMPA_vect){
     i++;
     if(i > 9){ss++;i=0;}
     if(ss > 59){mm++;ss = 0;}
     if(mm > 59){hh++;mm = 0;}
     if(hh > 23){hh = 0;}
     }

Скетч использует 1316 байт (64%) памяти устройства. Всего доступно 2048 байт.
Глобальные переменные используют 41 байт (32%) динамической памяти, оставляя 87 байт для локальных переменных. Максимум: 128 байт.

Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=3185#p3185

Прошивка проводилась при помощи программатора USBasp в среде Arduino IDE 1.8.9, версия платы 1.25

Комментарии

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

Войти с помощью: 

Случайные статьи

  • TDA8924 — двух канальный усилитель мощности звуковой частоты класса D

    TDA8924 — двух канальный усилитель мощности звуковой частоты класса D

    TDA8924 — двух канальный усилитель мощности звуковой частоты класса D. Номинальная выходная мощность усилителя 120 Вт на канал. Микросхема TDA8924 поставляется в корпусе HSOP24 с малым внутренним радиатором и не требует внешнего радиатора. Напряжение питания микросхемы от ± 12,5 В до ± 30 В. КПД усилителя более 90%. Сопротивление нагрузки 2 Ом. Размер …Подробнее...
  • Двухтональный звонок

    Двухтональный звонок

    Двухтональный звонок содержит управляющий генератор на элементах D1.1 — D1.3 микросхемы К155ЛА, который вырабатывает управляющие импульсы, частота которых зависит от емкости С1 и сопротивления R1. При указанных на схеме элементах частота переключения генератора примерно 0,7…0,8 Гц. Импульсы управляющего генератора подаются на генератор тона и поочередно подключают их к усилителю звуковой …Подробнее...
  • УСТРОЙСТВО ПЛАВНОГО ПЕРЕКЛЮЧЕНИЯ ЕЛОЧНОЙ ГИРЛЯНДЫ

    Устройство предназначено для плавного переключения, сетевой елочной гирлянды с частотой 0,2…2 Гц. Яркость свечения ламп можно регулировать. Устройство рассчитано на подключение гирлянды напряжением 220 В, мощностью не более 100 Вт. Принципиальная схема устройства переключения изображена на рисунке. Частотой переключения управляет мультивибратор, собранный на элементах DD1.3, DD1.4. Сдвиг момента открывания тиристора …Подробнее...
  • Малогабаритная АС

    В статье описана АС объемом 12л. Выбор закрытого акустического оформления для НЧ головки обусловлен там, что АС рассчитаны на воспроизведение классических и традиционных джазовых музыкальных произведений. В этих жанрах исполнения АС закрытого типа звучат лучше. Так же малые габариты АС обладают малой неравномерностью АЧХ. Для малогабаритной АС была выбрана НЧ …Подробнее...
  • Мостовой двухтактный усилитель мощностью 25Вт

    Мостовой двухтактный усилитель мощностью 25Вт

    Входной каскад на лампе Л1.1 построен по схеме с общим катодом и особенностей не имеет. Его назначение это обеспечить необходимый уровень чувствительности. При входном сигнале не менее 4 В входной каскад можно исключить. Фазоинвертор построен на лампе Л2 и представляет собой балансный смеситель. Фазоинвертор обладает большим усилением и симметричностью разделенного …Подробнее...