| Ваш IP: 52.23.219.12 | Online(54) - гости: 27, боты: 27 | Загрузка сервера: 0.31 ::::::::::::

ATtiny2313 + DS3231 (Arduino IDE)

Модуль часов реального времени DS3231 (ZS-042) построен на микросхеме DS3231SNкоторая является часами реального времени. В отличии от старой модели часов, например на микросхеме DS1307, эти часы содержат внутренний кварцевый резонатор, благодаря чему часы имеют точный ход.

Микросхема RTC DS3231 отсчитывает секунды, минуты, часы, день недели, даты месяца, месяцы, годы. Дата по окончании месяца автоматически подстраивается для месяцев, у которых дней меньше 31, включая учет февраля и коррекцию дней для високосного года (до 2100 года). Часы работают либо в 24-часовом, либо в 12-часовом формате с индикатором ~AM/PM. Предоставляется два программируемых по времени дня будильника, и программируемый выход прямоугольного сигнала. Адрес и данные передаются последовательно через двунаправленную шину I2C.

Основные возможности микросхемы DS3231:

  • Очень точная система RTC, которая полностью обслуживают все функции отсчета времени.
  • Точность ±2 ppm в диапазоне 0°..+40°C.
  • Точность ±3.5 ppm в диапазоне -40°..+85°C.
  • Выход цифрового датчика температуры с точностью ±3°C.
  • Регистр учета старения (Aging Trim).
  • Система входа/выхода для генерации сброса микроконтроллера с подавлением дребезга (RST Output/Pushbutton Reset Debounce Input).
  • Два программируемых по времени дня будильника (Time-of-Day Alarm).
  • Programmable Square-Wave Output Signal.
  • Простой последовательный интерфейс I2C, позволяющий подключить микросхему к любому микроконтроллеру. Скорость работы интерфейса до 400 кГц.
  • Вход резервного питания для подключения батареи с очень низким потреблением энергии.
  • Работа от уровня напряжения 3.3V.

 

Установка и считывание времени производится при помощи регистров согласно следующей таблице:

Для работы с модулем DS3231 под управлением Arduino существуют несколько библиотек, но при использовании  микроконтроллера ATtiny2313 использование библиотек не целесообразно из-за малого объема памяти (2 кБ). Следующий пример скетча не использует библиотек, что позволило оптимально использовать память ATtiny2313. Так же хочу отметить, что скетч не поддерживает изменение и считывание данных регистров отвечающих за управление будильниками (регистры с 0x07 по 0x0D), поддерживаются только регистры отвечающие за хранение времени и температурного датчика.

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

Схема часов

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

Часы работают следующим образом — с 0 по 25 и с 30 по 50 секунду индикатор показывает время, точка мигает в такт секундам, далее с 25 по 30 секунду индикатор показывает число и месяц, потом  с 50 по 55 выводится показания датчика температуры, а с 55 до 59 секунды индикатор показывает ход секунд.

Температура представлена 10-битным кодом с разрешающей способностью 0.25°C, и она доступна по в регистрах по адресам 11h и 12h, поэтому на индикатор часов выводятся сотые доги градуса кратные 0,25 °С.

Корректировка времени

// set_time(21,2,3,8,14,20,0);// год 00-99, ДН 1-7 (1=ВС), месяц 1-12, дата 1-31, час 0-23, минуты 0-59, секунды 0-59

Для корректировки времени раскомментируйте эту сроку, загрузите скетч, а затем закомментируйте сроку и снова загрузите скетч.

Если необходимо скорректировать только один параметр времени, то в тех параметрах которые Вы не хотите менять укажите число 255.

// set_time(255,255,3,9,255,255,255);// год 00-99, ДН 1-7 (1=ВС), месяц 1-12, дата 1-31, час 0-23, минуты 0-59, секунды 0-59

После применения этой функции будет скорректировано только дата и месяц.

#define SDA 2 // PB3
#define SCL 3 // PB2
#define SQW 4 // PB4
 
byte bb;
 
void setup(){
  DDRB &= ~(1 << SQW);PORTB |= (1 << SQW);
 //  set_time(21,3,3,9,22,02,0);// год 00-99, ДН 1-7 (1=ВС), месяц 1-12, дата 1-31, час 0-23, минуты 0-59, секунды 0-59
   ds_write(0x0E, 0b00000000); // выход SQW, частота 1 Гц
 
   delay(500);
}
 
void loop() {
  byte sec =  (ds_read(0) & 0x0F) + (((ds_read(0) & 0x70) >> 4) * 10);
  byte min =  (ds_read(1) & 0x0F) + (((ds_read(1) & 0x70) >> 4) * 10);
  byte hour = ((ds_read(2) & 0x0F) + ((ds_read(2) & 0x70) >> 4) * 10);
  byte day =  (ds_read(3) & 0x0F);
  byte datat = ((ds_read(4) & 0x0F) + ((ds_read(4) & 0x70) >> 4) * 10);
  byte mont = ((ds_read(5) & 0x0F) + ((ds_read(5) & 0x70) >> 4) * 10);
  byte year = ((ds_read(6) & 0x0F) + ((ds_read(7) & 0x70) >> 4) * 10);
  int temper = (ds_read(0x11)*100 + ((ds_read(0x12) & 0b11000000) >> 6)*25) ;
 
  if(((PINB >> SQW) & 1)==1){bb = 0;}else{bb = 2;}
 
  if(sec >= 0 && sec <= 25){print_time(hour *100 + min, bb, 7, 0);}
  if(sec > 25 && sec <= 30){print_time(datat *100 + mont, 0, 7, 0);}
  if(sec > 30 && sec <= 50){print_time(hour *100 + min, bb, 7, 0);}
  if(sec > 50 && sec <= 55){print_time(temper, 2, 7, 0);}
  if(sec > 55){print_time(sec, 0, 7, 1);}
 
}
 
 
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, byte pd_t, int br, bool mn) {
  tm_start(); tm_dec(0b10001000 + br); //tm_stop();tm_start();
  tm_dec(0x40); tm_stop(); tm_start();
 
  int data0,data1;
  if(mn==1){data0 = 10;data1 = 10;}
  else{data0 = t / 1000;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
      case 10: data = 0b00000000; break;    // пусто
    }
 
    if (n == 0) {data0 = data;}
    if (n == 1) {data1 = data;}
    if (n == 2) {data2 = data;}
    if (n == 3) {data3 = data;}
  }
  switch (pd_t) {
    case 1 : data2 = data2 + 0b10000000; break;
    case 2 : data1 = data1 + 0b10000000; break;
    case 3 : data0 = data0 + 0b10000000; break;
  }
  tm_dec(0xC0); tm_dec(data0); tm_dec(data1); tm_dec(data2); tm_dec(data3); tm_stop();
}
 
void del() {delayMicroseconds(200);}
 
bool i2c_read_bit() {
    bool i2c_bit = 1;        
    DDRB &= ~(1 << SDA);            
    delayMicroseconds(10); 
    DDRB &= ~(1 << SCL);                
    if((PINB >> SDA) & 1) i2c_bit=0;                            
    delayMicroseconds(10);  
    DDRB |= (1 << SCL);              
    return i2c_bit;  
}
 
byte i2c_write_byte(byte data){
    for (byte i=0; i<8; i++){i2c_write_bit((data&0x80)==0);data<<=1;}    
    return i2c_read_bit(); 
}
 
byte i2c_read_byte(byte a){
    byte i, data=0;                
    for(i=0; i<8; i++){if (!i2c_read_bit()) data++;if(i!=7) data<<=1;}        
    i2c_write_bit(a);return data;  
}
 
void i2c_write_bit(byte b){
    delayMicroseconds(5);
    if(b){DDRB |= (1 << SDA);}else{DDRB &= ~(1 << SDA);}
    delayMicroseconds(5);
    DDRB &= ~(1 << SCL);       
    delayMicroseconds(10);
    DDRB |= (1 << SCL);
}
 
void i2c_start(){
     delayMicroseconds(10);  
     DDRB &= ~(1 << SDA); DDRB &= ~(1 << SCL); 
     delayMicroseconds(10); 
     DDRB |= (1 << SDA);  PORTB &= ~(1 << SDA);
     delayMicroseconds(10); 
     DDRB |= (1 << SCL);  PORTB &= ~(1 << SCL);   
     delayMicroseconds(10);
}
 
void i2c_stop()  {
     DDRB |= (1 << SDA);            
     delayMicroseconds(10);
     DDRB &= ~(1 << SCL);               
     delayMicroseconds(10); 
     DDRB &= ~(1 << SDA);             
}
 
byte ds_read(byte reg){
     byte data = 0;
     i2c_start();
     i2c_write_byte(0b11010000);
     i2c_write_byte(reg);
     i2c_start(); 
     i2c_write_byte(0b11010001); 
     data = i2c_read_byte(0);
     i2c_stop();
     return data;
  }
 
void ds_write(byte reg, byte data){
     i2c_start();
     i2c_write_byte(0b11010000);
     i2c_write_byte(reg);
     i2c_write_byte(data);
     i2c_stop();
  }  
 
void set_time(byte years, byte days, byte monts, byte datas, byte hours ,byte minute, byte second){
    if(second < 255){ds_write(0x00,(second/10<<4)+second%10);}
    if(minute < 255){ds_write(0x01,(minute/10<<4)+minute%10);} 
    if(hours < 255){ds_write(0x02,(hours/10<<4)+hours%10);}
    if(days < 255){ds_write(0x03,days);}
    if(datas < 255){ds_write(0x04,(datas/10<<4)+datas%10);}
    if(monts < 255){ds_write(0x05,(monts/10<<4)+monts%10);}
    if(years < 255)ds_write(0x06,(years/10<<4)+years%10);
  }  

Скетч использует 1638 байт (79%) памяти устройства. Всего доступно 2048 байт.
Глобальные переменные используют 10 байт (7%) динамической памяти, оставляя 118 байт для локальных переменных. Максимум: 128 байт.

Arduino IDE 1.8.9 | Плата для прошивки версии 1.2.5 (выбрать в менеджере плат)

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

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

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

  • Автомобильный регулятор освещения

    В темное время суток иногда необходимо дополнительное освещения в автомобиле (для ремонта, регулировка двигателя и др), предложенная схема позволяет плавно регулировать осветительную 12В/2А лампу от 5% до 90% ее яркости при помощи ШИМ регулятора. Регулятор предназначен для автомобилей с отрицательной массой. Конструкция регулятора основана на микросхеме 40106 которая работает как …Подробнее...
  • Удвоитель напряжения на микросхеме NE555

    Описание. Схема простейшего удвоителя напряжения использованием микросхемы NE555 показана на рисунке. Здесь IC NE555 подключен в схеме как нестабильный мультивибратор с частотой генерации около 9KHz. Базы двух транзисторов (Q1 и Q2) подключены напрямую к выходу мультивибратора (контакт 3). При выходе сигнала из мультивибратора в первый момент Q1 будет OFF и …Подробнее...
  • Микрофонный усилитель на К153УД2

    Входное напряжение номинальное 1,5мВ максимальное 3000мВ Выходное напряжение номинальное 220мВ максимальное 9000мВ Перегрузочная способность не менее 66дБ Отношение сиг\шум -55дБ Коэф. гармоник 0,08% Номинальный диапазон частот 20…20000Гц Напряжение питания ±15В Ток потребления 12 мА Усилитель включен по схеме инвертирующего усилителя. Неинвертирующий вод DA1 подключен к общему проводу, а на инвертирующий …Подробнее...
  • Запись String в энергонезависимую память EEPROM

    Запись String в энергонезависимую память EEPROM

    EEPROM.put()  функция записывает данные любого стандартного типа или произвольную структуру в энергонезависимую память EEPROM, иначе говоря если размер данных превышает 1 байт, нужно использовать функцию EEPROM.put(). При записи данных в EEPROM размер которых превышает 1 байт, необходимо корректный расчет адресов по которым будет производится запись, для расчета адресов используется функция sizeof(). Для чтения …Подробнее...
  • Блок питания с защитой от КЗ

    Практически каждый начинающий радиолюбитель стремится вначале своего творчества сконструировать сетевой блок питания (БП), чтобы впоследствии использовать его для питания различных экспериментальных устройств. И конечно, хотелось бы, чтобы этот БП «подсказывал» об опасности выхода из строя отдельных узлов при ошибках или неисправностях монтажа. На сегодняшний день существует множество схем, в том …Подробнее...