Работа с часами реального времени DS3231


• О проекте
• Обратная связь
• Полезные ссылки
• Полезные программы
• Друзья сайта


Последние комментарии

Сергей: Работа с часами реального времени DS3231
Извините что проп...

Алексей: Осваиваем PCAD с нуля. Вывод на печать
Пикад уже умер. Я...




           

Библиотека для AVR





AXLIB Генератор





Помощь сайту


   
				

Работа с часами реального времени DS3231

	
	
	

Дата: 29 Апреля 2015. Автор: Алексей

	
	
В библиотеке AXLIB есть набор функций для работы с данными часами.

Немного лирики. Микросхема DS3231 является часами реального времени с температурной компенсацией TCXO. Погрешность составляет ±2 минуты за год при температуре окружающей среды от -40°С до +85°С. TCXO дает возможность получать на выходе микросхемы 32кГц во всем температурном диапазоне. Так же микросхема содержит два будильника которые могут генерить прерывания и выводить данное событие на один из выводов микросхемы.

Схема включения микросхемы.

Схема включения DS3231

Для тех кто не хочет колупаться с пайкой, можно купить готовый модуль в магазине Чип Резистор.

Давайте разбираться с выводами.

VCC, GND – это питание.
SDA, SCL – это шина I2C (с ней мы уже знакомились, кто не в курсе что это, идет сюда)
RST – это сброс микросхемы (Reset)
N.C. – это неиспользуемые выводы. Судя по документации нужно прицепить к GND.
Vbat – это батарейка. Если батарейка не используется, та вывод нужно посадить на GND.
32kHz – это вывод с открытым стоком. При использовании требует подтягивающий резистор к питанию. На выходе генерится меандр с частотой 32 кГц. Вывод может быть включен или выключен. Если не используется, то можно его никуда не подключать.
INT/SQW - Пин на котором возможен либо меандр с частотой настроенной в RS1 RS0, либо выход прерывания при совпадении любого из будильников. Настройка производится установкой разряда INTCH в регистре контроля по адресу 0EН. При логическом уровне 0 вывод выдает меандр, при логическом уровне 1 прижимает вывод к нулю при совпадении хронометра и любого из будильников. При использовании этого вывода его необходимо подтянуть к питанию резистором, так как он реализован с открытым стоком и в неактивном состоянии будет висеть в воздухе. Если данный вывод не используется, то его можно никуда не подключать.

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

Карта памяти

Как видно из таблицы в памяти расположены 19 регистров. Разберем их по очереди.

00Н – регистр содержит текущие секунды. Возможно чтение и запись. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы секунд от 0 до 9. В разрядах BIT4…BIT6 записываются десятки секунд от 0 до 6.

01Н – регистр минут содержит текущие минуты. Возможно чтение и запись. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы минут от 0 до 9. В разрядах BIT4…BIT6 записываются десятки минут от 0 до 6.

02Н – регистр часов. Возможно чтение и запись. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы часов от 0 до 9. В разряде BIT6 расположен вариант вывода часов. Если в этом разряде 0, то вывод будет в 24 часовом формате. При этом разряды BIT4 и BIT5 будут содержать десятки от 0 до 2. Если в разряде BIT6 записан лог 1, то вывод будет осуществляться в 12 часовом режиме. В этом режиме разряд BIT5 будет содержать значения суток, если присутствует лог 0, то это до полудня, а если лог 1, то после полудня. BIT4 выводит десятую часть часов, либо 0, либо 1.

03Н – регистр дня недели. Возможно чтение и запись. Три младших разряда принимают значения от 1 до 7. (с понедельника до воскресения).

04Н – регистр дней. Возможно чтение и запись. чтение и запись. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы дней от 0 до 9. В разрядах BIT4…BIT5 записываются десятки дней от 0 до 3.

05Н – регистр месяцев. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы месяцев от 0 до 9. В разряде BIT4 записываются десятки месяца, либо 0, либо 1. Также в данном регистре есть разряд Century BIT7. Данный разряд переключается при переполнении регистра годов. То есть данный разряд переключится когда регистр годов перейдет с 99 на 00. (например с 1999 на 2000) Указывает на изменения века.

06Н – регистр годов. Возможно чтение и запись. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы годов от 0 до 9. В разрядах BIT4…BIT7 записываются десятки годов от 0 до 9.

07Н – регистр секунд будильника 1. Возможно чтение и запись. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы секунд от 0 до 9. В разрядах BIT4…BIT6 записываются десятки секунд от 0 до 6.

08Н – регистр минут будильника 1. Возможно чтение и запись. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы минут от 0 до 9. В разрядах BIT4…BIT6 записываются десятки минут от 0 до 6.

09Н – регистр часов будильника 1. Возможно чтение и запись. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы часов от 0 до 9. В разряде BIT6 расположен вариант ввода часов. Если в этом разряде 0, то ввод должен быть в 24 часовом формате. При этом разряды BIT4 и BIT5 должны содержать десятки от 0 до 2. Если в разряде BIT6 записан лог 1, то ввод должен осуществляться в 12 часовом режиме. В этом режиме разряд BIT5 должен содержать значения суток, если записать лог 0, то это до полудня, а если лог 1, то после полудня. BIT4 должен содержать десятую часть часов, либо 0, либо 1.

0AН - регистр дней или дней недели будильника 1. Возможно чтение и запись. Структура данных в регистре следующая. В разряды BIT0…BIT3 записываются, либо единицы дней, либо единицы дней недели. Диапазон соответственно, либо от 0 до 9, либо от 1 до 7. В разряды BIT4 и BIT5 записываются только десятки дней от 0 до 3. Разряд BIT6 указывает на вариант данных. Если 0, то записаны дни, а если 1, то дни недели.

0BН – регистр минут будильника 2. Возможно чтение и запись. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы минут от 0 до 9. В разрядах BIT4…BIT6 записываются десятки минут от 0 до 6.

0CН – регистр часов будильника 2. Возможно чтение и запись. Структура данных в регистре следующая. В разрядах BIT0…BIT3 записываются единицы часов от 0 до 9. В разряде BIT6 расположен вариант ввода часов. Если в этом разряде 0, то ввод должен быть в 24 часовом формате. При этом разряды BIT4 и BIT5 должны содержать десятки от 0 до 2. Если в разряде BIT6 записан лог 1, то ввод должен осуществляться в 12 часовом режиме. В этом режиме разряд BIT5 должен содержать значения суток, если записать лог 0, то это до полудня, а если лог 1, то после полудня. BIT4 должен содержать десятую часть часов, либо 0, либо 1.

0DН - регистр дней или дней недели будильника 2. Возможно чтение и запись. Структура данных в регистре следующая. В разряды BIT0…BIT3 записываются, либо единицы дней, либо единицы дней недели. Диапазон соответственно, либо от 0 до 9, либо от 1 до 7. В разряды BIT4 и BIT5 записываются только десятки дней от 0 до 3. Разряд BIT6 указывает на вариант данных. Если 0, то записаны дни, а если 1, то дни недели.

0EН – регистр контроля. Возможно чтение и запись.

BIT0 A1IE - Разрешает/запрещает прерывания от будильника 1.
BIT1 A2IE - Разрешает/запрещает прерывания от будильника 2.
BIT2 INTCN - Разрешает/запрещает прерывания на выводе INT/SQW микросхемы.
BIT3, BIT4 RS1, RS2 - Задают частоту меандра выводимого на выводе INT/SQW микросхемы.
BIT5 CONV - Заставляем микросхему начать преобразование температуры. Запись в этот разряд возможно только тогда, когда бит занятости BSY сброшен.
BIT6 BBSQW - Если в этот разряд записать 1, то при работе от батарейки и отсутствующем питании на выводе INT/SQW будут продолжать выходить импульсы. При логическом 0 в данном разряде переведет вывод INT/SQW в высокоимпедансное состояние.
BIT7 EOSC - Разряд управления генератором. Если установлен логический 0, генератор включен. Если работа осуществляется только от батарейки, то логическая 1 отключает генератор. При подаче внешнего питания в этот разряд автоматически записывается логический 0 и генератор включается.

Немного о разрядах BIT7 в будильниках. Данные разряды дают возможность генерить сигнал раз в секунду, минуту, час, день или день недели. Это зависит от того что будет записано в эти разряды. Для наглядности вот таблички для обоих будильников. Я думаю посмотрев на них сразу станет все понятно.

Биты будильников

Так же вот таблица для задачи выходной частоты на выводе INT/SQW микросхемы.

Биты настройки частоты вывода INT/SQW

0FН – регистр контроля/статуса. Возможна запись и чтение.

BIT0 A1F - Флаг прерывания при совпадении значения будильника 1 и хронометра. Для сброса флага необходимо записать 0. Флаг принимает на запись только 0, при записи 1 ничего не происходит. Так же если установлен бит INTCN, то будет сгенерировано прерывание на выводе INT/SQW микросхемы.
BIT1 A2F - Флаг прерывания при совпадении значения будильника 2 и хронометра. Для сброса флага необходимо записать 0. Флаг принимает на запись только 0, при записи 1 ничего не происходит. Так же если установлен бит INTCN, то будет сгенерировано прерывание на выводе INT/SQW микросхемы.
BIT2 BSY – Флаг занятости. Взводится при преобразовании температуры. После преобразования сбрасывается и находится в покое в течение 1 минуты.
BIT3 EN32kHz – Бит разрешения вывода меандра с частотой 32кГц на выводе 32kHz микросхемы. При 1 разрешено, при 0 запрещено. По умолчанию при подаче питания установлена 1.
BIT7 OSF – Флаг контроля работы генератора. Логическая 1 указывает, что генератор остановлен. Условия возникновения 1 в этом флаге. 1. При первом включении питания (Тут я могу ошибиться, кто знает пусть поправит)
2. Напряжения на внешнем питание и на батарейке ниже нормы для тактирования схемы.
3. Сброшен бит EOSC при питании микросхемы от батарейки.
4. Внешние факторы влияющие на работу кристалла. Шумы, помехи и т. д.

10Н – Регистр хранит данные для правки частоты работы кристалла.

11Н – Регистр хранит данные температуры измеренной последний раз. (старший байт)

12Н – Регистр хранит данные температуры измеренной последний раз. (младший байт)

Так, с кишками микросхемы разобрались, теперь давайте все это запишем в виде библиотеки. Первая функция которая нам понадобится, будет называться DS_BYTE ds3231_byte(DS_BYTE data); Эта функция получает байт в десятиричном формате, а после преобразования возвращает в удобочитаемом виде для часов.

DS_BYTE ds3231_byte(DS_BYTE data)
{
	DS_BYTE temp = 0;
	
	while(data > 9)
		{
			data -= 10;
			temp++;
		}
	
	return (data | (temp << 4));
}

Суть ее проста. Мы просто в цикле вычитаем десятку до тех пор, пока не останутся только единицы. При каждом вычитании увеличиваем счетчик десяток. Как только десятки закончились, возвращаем наш байт предварительно собрав его. Десятки в старшие четыре бита, а единицы в младшие.
Следующая функция записывает время в регистры часов.

void ds3231_write_time(DS_BYTE hour, DS_BYTE min, DS_BYTE sec)
{	
	i2c_start();
	i2c_send_byte(0xD0);
	i2c_send_byte(0x00);
	i2c_send_byte(ds3231_byte(sec));
	i2c_send_byte(ds3231_byte(min));
	i2c_send_byte(ds3231_byte(hour));
	i2c_stop();
	
}

Как видно из названия переменных передаваемых функции, мы будем записывать время в виде часы, минуты и секунды. Сразу оговорюсь, я живу в России и у нас время имеет 24 часовой формат. Поэтому данная функция записывает время в этом формате. И так, как она работает. Сначала мы выдаем условие старта на шину. (Кто не в курсе откуда взялась эта функция, идут сюда и читают.) Затем передаем адрес микросхемы, за ним адрес первого регистра со временем, а у нас это секунды. За ним по очереди закидываем значения времени, предварительно преобразовав данные в часовой вид. После выдаем условие стопа и отпускаем шину.
Следующая функция будет записывать дату в память часов.

void ds3231_write_date(DS_BYTE year, DS_BYTE month, DS_BYTE date, DS_BYTE day)
{
	i2c_start();
	i2c_send_byte(0xD0);
	i2c_send_byte(0x03);
	i2c_send_byte(ds3231_byte(day));
	i2c_send_byte(ds3231_byte(date));
	i2c_send_byte(ds3231_byte(month));
	i2c_send_byte(ds3231_byte(year));
	i2c_stop();
}

Эта функция мало чем отличается от предыдущей, поэтому я надеюсь на вашу сообразительность и понимание как она работает)). А теперь самое интересное, читаем из микросхемы.
Функция чтения времени.

void ds3231_read_time(DS_BYTE *str)
{
	DS_BYTE temp[3];
	int i = 0;
	
	i2c_start();
	i2c_send_byte(0xD0);
	i2c_send_byte(0x00);
	i2c_restart();
	i2c_send_byte(0xD1);
	temp[0] = i2c_read_byte(ACK);
	temp[1] = i2c_read_byte(ACK);
	temp[2] = i2c_read_byte(NACK);
	i2c_stop();
	
	while(i < 3)
		{
			*str = ((temp[i] & 0x0F)+((temp[i] >> 4) * 10));
			str++;
			i++;
		}
}

Что здесь происходит. Сначала как всегда условие старта, затем передаем адрес микросхемы и адрес первого регистра. Затем даем повстарт и снова адрес микросхемы с одним но. Меняем последний бит записи на чтение. Это видно как адрес с 0xD0 поменялся на 0xD1. Затем в массив записываем три параметра, сначала секунды, затем минуты и в конце часы. Такой порядок выбран из-за адресации памяти часов. Если кто не понимает, смотрите карту памяти, таблица выше. Да, вот еще, обратите внимание на то, что первые два байта читаются, а в ответ посылается ACK, а в последнем NACK. Это говорит о том, что пока мы читаем, то отсылаем ACK, а когда мы читаем последний байт и больше читать не будем, то шлем NACK и кидаем условие стоп. Все, данные прочитаны. Теперь нам надо их как-то вернуть. Функция возвращает только одно переменные, а вот массивы возвращать не может. Как быть? Да очень просто. Создаем массив нужной длинны и передаем функции указатель на адрес первой ячейки. А так как мы знаем длину массива, то просто сдвигаемся по ячейкам увеличивая адрес на единицу, не забывая по этим адресам записывать данные. Вот этим и занимается цикл. Сначала мы по первому адресу записываем значение первой ячейки массива с секундами предварительно обнулив старшие четыре бита. Таким образом мы записали единицы, а потом прибавляем десятки. Для этого сдвигаем байт вправо на четыре бита. Таким образом мы получим десятки и умножаем их на десять. Вот и все. После вызова данной функции у нас в массиве окажутся значения времени.
Следующая функция чтения даты.

void ds3231_read_date(DS_BYTE *str)
{
	DS_BYTE temp[4];
	int i = 1;
	
	i2c_start();
	i2c_send_byte(0xD0);
	i2c_send_byte(0x03);
	i2c_restart();
	i2c_send_byte(0xD1);
	*str = i2c_read_byte(ACK);
	temp[1] = i2c_read_byte(ACK);
	temp[2] = i2c_read_byte(ACK);
	temp[3] = i2c_read_byte(NACK);
	i2c_stop();
	
	str++;
	while(i < 3)
	{
		*str = ((temp[i] & 0x0F)+(((temp[i] >> 4) & 0x07) * 10));
		str++;
		i++;
	}	
	*str = ((temp[3] & 0x0F)+((temp[3] >> 4) * 10));
}

Тут немного по замороченее с преобразованием. Первым байтом идет день недели, а так как он может принимать значение от 1 до 7, то его можно сразу записать в массив. Далее как и с временем, пишем год, месяц, число. В связи с тем что наше устройство врятли доживет до 2099 года, нам не нужен седьмой бит Century. Для этого чтобы он не мешался, мы накладываем маску 0x07 и обнуляем 7 бит. Все бы хорошо, но год все таки возможно дойдет до значения 99. А вдруг доживет до 99 года)) И наложение такой маски не приемлемо. Поэтому мы преобразования числа и месяца делаем в цикле, а год уже преобразуем отдельно. И последняя функция на сегодня, это чтение температуры. Микросхема, то с температурной компенсацией, значит имеет температуру. Расположена она в двух регистрах, но для наглядности я буду дергать только из первого, без десятых и не буду проверять на минус. Все таки часы висят чаще в помещении. Если все таки приспичит полный диапазон температур, то вычислять их можно по той же схеме что я описывал в статье по работе с датчиком DS18B20. Алгоритм такой же.

DS_BYTE ds3231_read_temp(void)
{
	DS_BYTE MSB = 0;
	
	i2c_start();
	i2c_send_byte(0xD0);
	i2c_send_byte(0x11);
	i2c_restart();
	i2c_send_byte(0xD1);
	MSB = i2c_read_byte(NACK);
	i2c_stop();
	
	return MSB;
}

Вот и все пока. В будильники я еще пока не вкурил, как разберусь потом выложу. Пару фоток, модуль и то как он выводит на экран.

Модуль с микросхемой DS3231

Вывод данных на экран

В библиотеке AXLIB есть набор функций для работы с данными часами.



Миша    22.06.15 21:09

Уважаемый Алексей! Прекрасно, что Вы расписали теорию. Но, с моими 8_ю классами и возрастом, хотелось бы поближе к практике. Не могли бы Вы выложить готовую схему, скетч (и, желательно, библиотеки) для сборки Ваших часов вживую. Все прибамбасы есть, а собрать ничего толком не могу. В инете ничего толком нет, а собрать хочется, в программировании полный 0, надеюсь на понимание.

Алексей    23.06.15 11:13

Уважаемый Миша. Первое что я хочу Вам сказать: не публикуйте свой адрес почты в комментариях. Это может привести к заваливанию спамом. По поводу схемы. Данная микросхема установлена на готовой плате в виде конечного модуля, поэтому так таковой схемы у меня нет. Если хочется самому спаять, то в документации на микросхему есть схема или можно посмотреть в начале статьи. Скетча у меня нет, так как программа была написана на чистом С в IDE AtmelStudio 6.2. Библиотеку для работы с шиной i2c можно взять тут. Исходный код для часов можно скопировать прямо из данной статьи. Или можно немного подождать и я добавлю библиотеку для работы с этими часами в свою библиотеку axlib. Если можно, то расскажите по подробнее что у Вас есть из железа.

Сергей    11.11.15 21:36

Как видно из названия переменных передаваемых функции, мы будем записывать время в виде часы, минуты и секунды. Сразу оговорюсь, я живу в России и у нас время имеет 34 часовой формат. Поэтому данная функция записывает время в этом формат. Поправьте.

Алексей    11.11.15 21:45

Упс. Да, косячек. Поправил, спасибо.

Виталий    17.12.15 12:34

Может быть, все-таки, не десятые (секунд, минут, часов и т.д.) а десятки???

Алексей    17.12.15 16:42

Да, как-то не по русски получилось.

Виталий    07.02.16 18:13

Не проверяли, что будет, если принудительно записать в регистры заведомо бОльшие значения (больше 59 секунд или минут, больше 24 часов и пр.)? Есть защита от дурака или нет?

Алексей    07.02.16 20:46

Нет. Данная проверка должна заботить программиста. Если делать все проверки в библиотечных функциях, то библиотека будет очень много весть. Проверка данных должна проводиться до передачи их функции.

Виталий    10.02.16 09:58

При чем здесь библиотечные функции? Я спрашивал про саму микруху, как она воспринимает передачу ей времени 72 часа 68 минут, к примеру.

Алексей    10.02.16 10:14

А. Не, я не пробовал. Сегодня вечером попробую. Даже интересно стало.

Алексей    10.02.16 21:40

Лучше один раз увидеть, чем сто раз прочитать. Видео записи бреда в часы.

Андрей    15.02.16 08:25

Я так понимаю, что в этом часовом модуле выходы уже подтянуты к питанию через резисторы 4.7к ?

Алексей    15.02.16 09:11

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

Андрей    19.02.16 20:56

Возможно ли установить в микросхеме дату не передавая туда день недели? Он автоматически не вычисляется?

Алексей    19.02.16 21:03

Интересно, а как она узнает день недели если эта микросхема по сути простой счетчик. Конечно нужно день недели записывать самому. А в чем проблема?

Андрей    19.02.16 21:25

У меня была библиотека для 1307, там день недели в функции записи даты вообще не использовался, а считывался нормально. Буду разбираться, может он где-то вычислялся перед записью.

Алексей    19.02.16 21:38

А в чем сложность записать день недели? Или это принципиально?

Андрей    20.02.16 08:38

Ничего сложного, но когда в установках выставляется дата, как-то непривычно выставлять день недели )). Уже нашел функцию: int what_day(short day, short month, short year) { int a = (14 - month) / 12; int y = year - a; int m = month + 12 * a - 2; return (7000 + (day + y + y / 4 - y / 100 + y / 400 + (31 * m) / 12)) % 7; }

Андрей    20.02.16 08:58

Только надо учесть, что в этой функции воскр=0, а не 7.

Алексей    20.02.16 08:59

Ну если это криьично, то можно добавить в axlib

Андрей    20.02.16 09:25

Кому надо - тот сам может добавить. Может это только у меня тараканы в голове))) Отличная библиотека, спасибо.

АНОНИМ    20.02.16 09:28

Кстати, а какой адрес у микросхемы памяти - 0x50? Или надо перемычки А0-А2 распаивать?

Алексей    20.02.16 09:45

Если голая микросхема, то 0х50, а если на китайском модуле то без перемычек 0х57.

Дмитрий    29.02.16 13:15

Подскажите почему не обновляются показания температуры при работе, обновление происходит только при включении питания

Алексей    29.02.16 15:09

Потому что нужно смотреть бит занятости и давать команду на оцифровку температуры когда он снят. И только после этого читать текущую температуру.

Дмитрий    29.02.16 16:04

так и делаю но самое интересное что бит занятости всегда снят

Алексей    29.02.16 16:13

А точно адрес регистра 0x0F?

Сергей    14.04.16 17:46

Здравствуйте Алексей. Подскажите есть ли какие то условия что бы в DS3231 не обнулялось время после откл. питания ?

Алексей    14.04.16 18:50

Установка батарейки.

Сергей    15.04.16 15:01

ау

АНОНИМ    15.04.16 15:12

Какой из черпающий ответ, прямо америку открыл!!!

Алексей    15.04.16 20:07

Других вариантов нет. Так гласит документация на микросхему. К сожалению батарейка это единственный вариант сохранению значения даты и время. Если обесточивание происходит кратковременно, то можно поставить конденсатор эдак на 1000мкф.

Max    11.06.16 23:09

Добрый день. Подскажите как можно вывести время как на фото автора?? У меня какой-то бред все время выводит

Алексей    12.06.16 10:20

А какой бред именно?

Max    12.06.16 12:39

выводится 1, левый, символ. не получается преобразовать число в текст.

Алексей    12.06.16 13:28

Скачайте генератор кода AXLIB и попробуйте создать проект в нем. Там есть и часы и ЖК дисплей. Это исключит ошибки инициализации.

Max    12.06.16 16:39

Я так и сделал. У меня не получается конвертануть время считанное из ds3231 в надпись для дисплея, выводится символ код которого соответствует числу часов/минут/секунд. может я не той функцией пользуюсь??

Алексей    12.06.16 19:00

Нужно код посмотреть. Так сложновато что-то решить.

Max    12.06.16 19:09

SBYTE temp0; BYTE tt; BYTE vrem[3" target="_blank" style="padding-left:0px; color:#CC0000;">; int main(void) { DDRC=0x0f; PORTC=0x0f; lcd_init(0); lcd_gotoxy(0,0); lcd_str_out("LOADING."); ds3231_init(); ds3231_sqw_on(0); ds3231_en32khz(0); temp0=ds3231_read_temp(); tt=ds3231_read_time(vrem); lcd_clear(); lcd_gotoxy(0,1); lcd_char_out(temp0); lcd_str_out("C."); lcd_gotoxy(0,0); lcd_char_out(vrem[0" target="_blank" style="padding-left:0px; color:#CC0000;">); lcd_str_out(":"); lcd_char_out(vrem[1" target="_blank" style="padding-left:0px; color:#CC0000;">); lcd_str_out(":"); lcd_char_out(vrem[2" target="_blank" style="padding-left:0px; color:#CC0000;">); sei(); while (1) { PORTC=0x05; _delay_ms(500); PORTC=0x0a; _delay_ms(500); } }

Max    12.06.16 19:19

SBYTE temp0; BYTE tt; BYTE vrem(-3-); int main(void) { DDRC=0x0f; PORTC=0x0f; lcd_init(0); lcd_gotoxy(0,0); lcd_str_out("LOADING."); ds3231_init(); ds3231_sqw_on(0); ds3231_en32khz(0); temp0=ds3231_read_temp(); tt=ds3231_read_time(vrem); lcd_clear(); lcd_gotoxy(0,1); lcd_char_out(temp0); lcd_str_out("C."); lcd_gotoxy(0,0); lcd_char_out(vrem(-0-)); lcd_str_out(":"); lcd_char_out(vrem(-1-)); lcd_str_out(":"); lcd_char_out(vrem(-2-)); sei(); while (1) { PORTC=0x05; _delay_ms(500); PORTC=0x0a; _delay_ms(500); } } (- и -) квадратные скобки

Алексей    12.06.16 19:19

Лучше перейти на форум. Здесь какая-то каша с кодом получается.

Max    12.06.16 21:07

Всего то надо было обучалку почитать)) Еще есть вопрос, как читать 2 датчика ds1820 подключенных к соседним ногам??

Алексей    13.06.16 08:49

Что значит к соседним? DS1820 общается по шине 1W и может тянуть несколько штук на шине. Обращение к устройству происходит по его адресу.

АНОНИМ    13.06.16 22:23

У меня 2 шины 1W, так проще, чем разбираться с адресами и угадывать где какой, и в плане ремонта/модернизации тоже удобнее. #define PORT_W C #define PIN_W 0 на сколько я понимаю можно править когда надо и опрашивать несколько 1W шин по очереди.

Алексей    13.06.16 23:48

Теоретически можно менять программно пины без использования дефайнов и инициализировать постоянно шину. Но в любом случае в данный момент будет работать только один датчик. И мне непонятно, в чем проблема опрашивать датчики по адресу. Тем более есть готовая функция для этого.

Max    18.06.16 20:28

Пытался понять, что за бред выводит DS1820. особенно тут temper = (((WORD)temp(_1_) << 8) | (WORD)(temp(_0_) * 5)); из всей ds1820.h понадобилась только 1 функция и та оказалась не рабочей. Почитал пдфку по датчику и понял в чем прикол. В обще датчик прочитать можно так(конец функчии): temper=owire_read(); temper|=(owire_read()<<8); temper=temper*10; //чтобы точность 1/10 была temper=(temper>>4); // типо разделили на 16 ну и чтобы вывести на ЖК экран: lcd_gotoxy(4,1); sprintf(string, "%04d", temper); lcd_str_out(string);

Max    18.06.16 20:34


Max    18.06.16 21:19

Переместил код функции чтения 1 бита с 1W в функцию чтения всего байта - сэкономил 0,1% ПЗУ контроллера. А почему для I2C используется програмная реализация?? ведь есть аппаратный блок который может сам все обрабатывать.

Алексей    18.06.16 22:18

Чтобы были развязаны руки. Аппаратный I2C имеет фиксированное располодение выводов. Датчики DS1820 и DS18B20 имеют в корне разные функции вычисления температуры. Отсюда рекомендую не переписывать функции, а опрашивать датчики по РОМ коду.

Max    18.06.16 22:51

Ну так и питание у микрухи тоже имеет фиксированные выводы. Это уже проблемы разводки платы а не ПО. Криворукожоп не доведет проект до конца))). Немного модернезировал 1W библиотеку, теперь она 2-х канальная))). единственно так и не понял для чего куча циклов в функции owire_init, заменил ото все на _delay_us(300); все равно статус наличия датчика нигде не используется.

Алексей    19.06.16 10:08

А при чем здесь питание? На линиях аппаратного I2C также заведены два канала АЦП и если мне нужно снимать показания с 5 каналов, как быть? Так что пока у AVR не появится ремап как у STM32, I2C выгодней программный. Функция owire_init() предназначена исключительно для шины 1W, а не для датчика. Данная функция как раз и возвращает статус наличия хотя бы одного устройства на линии. Делать программные задержки такой величины на асинхронных шинах категорически запрещается. Этой проблемой как раз блещет CVAVR. Влечет за собой сбои передачи, так как шина 1W критична к тайм-слотам. Так как все функции 1W запрещают прерывания, то возникают проблемы с часовой собакой и реализацией динамической индикации на семисегментных светодиодных индикаторах. Там еще куча косяков вылезает, такие как сбои таймеров, ШИМ и т.д.

Сергей    28.06.16 10:16

Здравствуйте. Прочитал статью, но пока не все понял. Вопрос вот в чем: Пробую загрузить в Ардуино пример DS3231_Serial_Easy из библиотеки DS3231, но при компиляции в IDE выдает ошибку: Arduino: 1.6.10 Hourly Build 2016/06/06 08:34 (Windows XP), Плата:"Arduino Pro or Pro Mini, ATmega328 (5V, 16 MHz)" collect2.exe: error: ld returned 5 exit status exit status 1 Ошибка компиляции для платы Arduino Pro or Pro Mini. Т.К. в аглицком не силен и с AVR-ами только начал знакомство, не пойму в чем ошибка. Подскажите пожалуйста.

Алексей    28.06.16 14:22

Это пример из Ардуины или кем-то написанный?

АНОНИМ    28.06.16 17:20

Из ардуиновской стандартной библиотеки DS3231

Алексей    28.06.16 21:54

Тогда нужно смотреть скеч. Кидайте мне на почту, гляну.

Сергей    01.07.16 10:38

Отправил

Алексей    01.07.16 11:31

Ничего не пришло. avrki@avrki.ru

Алексей    01.07.16 11:40

К сожалению в базе ардуины я такую библиотеку DS3231.h не нашел. Есть только Sodaq_DS3231.h, но с ней нужно разбираться. Скорее всего то что у Вас самописное и проще попросить помощи у автора.

Сергей    01.07.16 15:09

Отправил по указанному адресу. До этого отправлял через "Обратную связь"

Varkus    03.07.16 08:08

Везунчики, на С++ пишете, а мне приходится на Bashe'е "ваять" свои либы под этот девайс. Подключил эту плату к gpio роутера mr3020, ОС Openwrt. Только вот сборщики пришивок по какой-то неведомой причине не стали в последнюю сборку включать драйвер RTC. Теперь приходиться колхозить, вроде этого: bsec=`$i2c_tools_path/i2cget -y $i2c_bus $i2c_addr 0x00` bsec="$(( $(( $bsec & 0x70 )) >> 4 ))$(( $bsec & 0x0f ))" echo "$bsec" exit 0 И тоже подбираюсь к будильникам, надеюсь можно подключить бузер к sqw, хотя бы через транзистор, тогда у роутера еще и звук появится :)

Алексей    03.07.16 16:02

А на кой леший его к роутер подключать?

Масон    10.09.16 18:47

Алексей, а можно пример, как смотреть бит занятости, и давать команду на оцифровку температуры, когда он снять, а после читать текущую температуру? Буду очень признателен любой информации С:

Алексей    11.09.16 09:16

А нужно скачать генератор кода библиотеки axlib и сгенерив проект с часами, глянуть функцию получения температуры. Там как раз проверяется бит занятости и после вызывается команда оцифровки температуры и получения ее.

Юрий    31.10.16 17:28

Кто может подсказать как изменить время если часы уже запущены?

Андрей    31.10.16 19:18

Очень просто. Например если нужно поменять минуты просто пишешь в ячейку 01h нужное количество минут и всё.

Алексей    31.10.16 21:49

Так есть же функция
void ds3231_write_time(DS_BYTE hour, DS_BYTE min, DS_BYTE sec)
Передали ей время и она записала его.

Юрий    01.11.16 10:19

Спасибо за подсказку, покачто
"variable or field 'ds3231_write_time' declared void".
Библиотека DS3231.h

Юрий    01.11.16 10:54

Я пытаюсь это сделать в Ардуино 1.0.6.

Алексей    01.11.16 11:18

В ардуино это не заработает. Данная библиотека рсчитана на AtmelStudio 6.x

Алексей    01.11.16 11:21

Чтобы эти функции заработали в ардуино, нужно вних вписать общение по шине I2C функциями от ардуины. Ну или самому их написать опираясь на мои функции. Ардуина использует тот же гцц что и студия, так что проблем не должнобыть.

Виктор    29.11.16 19:45

Здравствуйте, не могли бы Вы подсказать куда копать. Смысл в следующем, есть МК, который постоянно спит, часы DS3231 его должны будить каждые 2 часа, МК выполняет что ему нужно и снова спать. Собрал схему, выяснилось, что часы работают не так как мне нужно. А именно, после того, как МК засыпает, примерно через 45-60 сек. на выходе SQW появляется лог.0. Если не загонять МК в сон, то 0 появляется при срабатывании будильника. Экспериментальным путём выяснил, 0 на выводе SQW появляется примерно через минуту, после того, как шина i2c отключается. Помогите пожалуйста, с шиной i2c ранее сталкиваться не приходилось.

Алексей    29.11.16 21:16

Интересная проблема. Завтра попробую изобразить.

Валерий    05.01.17 13:48

Каким образом к модулю подключить контроллер ATtiny2313-20PU?

Алексей    05.01.17 14:36

Шина I2C.

Валерий    07.01.17 15:20

Здравствуйте!
С программатором Громова получится запрограммировать этот модуль?

Алексей    07.01.17 16:42

Программатор Громова загружает прошивку во флеш память МК. Модуль часов это периферийное устройство. Сформулируйте нормальный вопрос, что вам нужно. На данный момент это звучит так. Как м
не соединить пакрышку с велосипедом? А гаячным ключем я надену покрышку?

Валерий    19.01.17 16:45

Здравствуйте Аексей!
В наличии имеются модуль с установленными DS3231N и 24c32n, контроллеры ATtiny2313-20PU и ATmega8515-16PU, К176ИД3, кварц 4МГц, индикаторы ИВ22. Есть программатор Громова.
Хочу собрать часы с динамической индикацией часов, минут и секунд. Остальные навороты мне не нужны.
В 1979 году я собирал себе часы на микросхемах 133 серии. Точность +1 секунда за 18 суток. Сейчас они меня перестали устраивать. Потребляемая мощность (это не так важно). Второе, из-за частых отключений электроэнергии, каждый раз приходиться устанавливать время. И, наконец, перестал работать один дешифратор. Достать не имею возможности.
Раньше я работал на оборонном предприятии на разработке аппаратуры. Не работаю с развала СССР.
С указанными выше контроллерами и часами точного времени никогда не работал. Их в те времена просто не было. Программированием никогда не занимался. Были программисты. Поэтому все для меня внове.

Алексей    19.01.17 17:32

Суть-то в чем? Собрать за вас или прошивку написать?

Валерий    20.01.17 10:34

Здравствуйте Алексей!
Пока ничего не надо. Попробую сам разобраться. Может в процессе возникнут вопросы.
Есть программы для прошивок Bascom-AVR, Uniprof, Atmel Studio.

Алексей    20.01.17 14:51

Так качайте Axlib-генератор и не мучайтесь. Там все для этих часов есть.

Игорь    16.02.17 12:55

Алексей, не подскажете в чем проблема может быть?
МК Atmega16, подключил часы, заюзал либу, часы все время показывают время 25 60 60, по подключению все как в мануале, куда копать?

Алексей    16.02.17 19:44

Проект в студию))) Наверняка что-то напутали.

Валерий    27.02.17 21:46

Здравствуйте, Алексей!
Просматривая различные схемы с модулем на базе ds3231, я обнаружил, что в некоторых схемах ставятся подтягивающие резисторы на выводы, а в некоторых нет. В схеме модуля к выводам уже подключены подтягивающие резисторы номиналом 4,7к. Выходит, правильно будет не ставить дополнительные подтягивающие резисторы.
Я не смог найти как программируются эти модули. Выходит прошивка их производится через микроконтроллер. Другого я не нашел. Или я не прав?
Заканчиваю разрабатывать схему часов.

Алексей    27.02.17 22:15

Микросхема ds3231 это просто часы. В ней нет никакой прошивки и она никак не программируются. Она как телевизор, включили смотрим, выключили не смотрим. Для общения с микросхемой используется шина I2C. По стандарту данной шины обе линии нужно подтянуть к плюсу питания резисторами 4,7К. Если поставить больше резисторов, то начнут заваливаться фронты и будут ошибки при передаче. Прошивку для общения с микросхемой нужно писать самому и заливать ее в МК или ПК, ну в любой девайс с возможностью программирования и поддержкой шины I2C.

Валерий    27.02.17 23:29

http://radiolaba.ru/microcotrollers/ds3231-podklyuchenie-chasov-realnogo-vremeni.html.
Схема модуля на этом сайте.

Алексей    28.02.17 08:04

А в чем вопрос?

Алексей    28.02.17 11:36

Вот видео, которое развеет все сомнения на тему данных часов.

АНОНИМ    09.03.17 13:07




#include <io.h>
#include <iom16.h>
#include <main_init.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <i2c.h>
#include <ds3231.h>
#include <delay.h>


// переменные времени
unsigned char hour ;
unsigned char minute ;
unsigned int sec ;
char time[2];
char* ukaz = &time[0];

// переменные даты
unsigned char day;
unsigned char wday;
unsigned char month;
unsigned char year;

unsigned char x=0;
unsigned char des = 0;
unsigned char edin = 0;

#include <avr/io.h>

int main(void)
{
DDRD = 0x00; // входы
PORTD = 0xFF;
DDRB = 0xFF; // выходы
PORTB = 0x00;
ds3231_init();



while(1)
{





if( bit_is_clear(PIND,PD5))//вписываю время
{

ds3231_write_time(DS3231_24, 13, 13, 13);
_delay_us(100);
lcd_init();
lcd_dat('z'); // Выводим символы на экран
lcd_dat('a');
lcd_dat('p');
lcd_dat('i');
lcd_dat('s');
lcd_dat('a');
lcd_dat('n');
lcd_dat('o');
_delay_us(100000);

}


ds3231_read_time(ukaz);
sec = time[0]; // 0 часы 1 минуты 2 секунды вроде бы

//далее время вывожу на жки, с этим проблем нет, часть кода вырезал.

}
}



перелопатил всю схему, сделал все заново, все равно показывает дичь, на этот раз 25 часов 0 минут 0 секунд

Алексей    09.03.17 14:47

char* ukaz = &time[0]; Что это за чудо???
А теперь подробно, что должна делать программа?
И еще рекомендую глянуть тут.

АНОНИМ    09.03.17 16:26

Не обращайте внимание -_-
Да, я видел видос, делал по вашему примеру, даже переменные так же называл, результат тот же. В схеме только МК, часы, регклятор на 3.3 вольта да пара кнопок. Все резисторы по даташиту распихал. не знаю где я мог ошибиться и почему такая дурь идет при чтении

Алексей    09.03.17 17:59

Так в видео показано как записать время и дату даже не написав ни одной строчки кода. Должно работать.

АНОНИМ    10.03.17 09:45

Эм, простите, я идиот, забыл вставить батарейку. Все работает. еще раз извините -_-

Алексей    10.03.17 09:56

Бывает. Почему сразу идиот.

АНОНИМ    15.03.17 11:50

Алексей, вопрос по часам DS1307: функция ds1307_read_time(time_r) выдаёт в массив уже готовые к выводу значения, т.е. их можно сразу отправлять на LCD? Например вот так:


sec = time_r[0];
min = time_r[1];
hour = time_r[2];
lcd_str_out(hour);
lcd_str_out (":");
lcd_str_out (min);
lcd_str_out (":");
lcd_str_out (sec);


Или нужны какие-то ещё преобразования.

Алексей    15.03.17 13:27

В комменте выше 09.03.17 14:47 есть ссылка на видео. Я там подробно рассказываю как общаться с часами.

Алексейbird    15.03.17 13:44

Видео это я смотрел, но там вывод через sprintf, который жрёт кучу памяти. Идея как раз и состоит в том, чтобы избавиться от него.

Алексей    15.03.17 15:18

И этот вопрос уже поднимался. Идем сюда и смотрим видео в комменте "Алексей 06.02.17 14:01"

Алексейbird    15.03.17 16:04

Алексей, эти видео уже просмотрены и если бы я смог по ним что-либо понять, то я бы не задавал вопросы. Я не могу понять требуется ли предварительная подготовка данных, которые считываются с часов. Ведь у меня при коде

sec = time_r[0];
min = time_r[1];
hour = time_r[2];
lcd_str_out(hour);
lcd_str_out (":");
lcd_str_out (min);
lcd_str_out (":");
lcd_str_out (sec);


на экране тишина, ну кроме двоеточий. А при коде


sec = time_r[0] + 0x30;
min = time_r[1] + 0x30;
hour = time_r[2] + 0x30;
lcd_str_out(hour);
lcd_str_out (":");
lcd_str_out (min);
lcd_str_out (":");
lcd_str_out (sec);


на строке происходит сумасшествие, т.е. выводятся символы, которые точно не относятся ко времени, хотя и меняются каждую секунду, но форматирование строки не сохраняется и эти символы гуляют по всей строке, я думаю гуляло бы и по всему дисплею, но на других строках другие данные постоянно обновляются.
Да если использовать sprintf, данные норм выходят, но и прошивка увеличивается почти на 1,5 кб, ИМХО это расточительно...

Алексей    15.03.17 18:34

Интересно, а как можно в ячейку однобайтового массмва положить отформатированные два символа к примеру 30 секунд. Символ 3 это 0х33, а символ 0 это 0х30. То есть нужно втиснуть два байта в однобайтную ячейку (попытка натянуть латексное изделие на глобус). Естественно количество минут, секунд и часов просто число и жаждит функции sprintf.

Алексейbird    15.03.17 20:30

Алексей, да я то понял уже, что в ячейке массива лежит две цифры, а выводить из массива можно только одну цифру. Вот код, в нем можно использовать и функцию sprintf и более экономную функцию time_format, сделанную по лекалам твоей функции temper_format. Размер отличается больше чем в 1кб. Но у моей есть косяк, что не работает измерение(или вывод) температуры DS18B20, т.е. если ресетнуть МК, то видно проскакивающее значение, но буквально через доли секунды устанавливается значение 00.0. А также после значений времени вылезают какие-то четыре символа. Хотя время и при моей функции и при твоей показывает и идёт верно.

Алексей    15.03.17 21:06

По хорошему нужен проект. Я его запущу и посмотрю что не так. Скинь его на почту.

Валерий    23.04.17 16:06

Здравствуйте Алексей!
Спасибо за подробное описание данной микросхемы. Мною собрано несколько часов, все работает отлично. За шесть месяцев уход составил несколько секунд. Считаю это неплохим результатом. Пишу программы на ассемблере. Всем удачи!

Сергей    25.07.17 12:17

Добрый день.Заинтересовался Ардуино. Первые шаги. Модуль, что и на фото выше ZS-042(с DS3231), ардуино UNO и ардуино pro MINI. Заливаю модуль, через UNO. Устанавливаю батарейку CR2032(аккумулятор не нашел). собираю схему с Mini. Схема модуль и mini отрабатывает, пока не отключиться внешний источник. Перебрасываю модуль на UNO, смотрю по COMпорту - время застыло. При подаче внешнего питания продолжает дальше отсчитывать. На просторах интернета, говорят из-за цепи зарядки аккумулятора(убрать и всё), но дело в том что модуль в одном экземпляре и экспериментировать не хочется. Просто у меня подозрение, что это программно. если можно,то попроще объясните пожалуйста.

Алексей    26.07.17 08:46

Причем здесь аккумулятор. Без внешнего питания шина данных не работает. После подачи питания часы должны ходить. Если ставится батарейка, то она должна быть развязана диодом с микросхемой часов. Программно можно только включать тактирование для чтения данных из микросхемы. Тактирование отключается при снятии внешнего питания. Скорее всего батарейка разряжена или на модуле каряво китайцы схему собрали. Это нормально, так как на моем модуле китайцы накосячили с линиями адреса еепром.

Сергей    07.08.17 20:00

Извините что пропал. Всё это время обкатывал схему. Я нашёл ошибку в скетче, это меня и сбило с толку. Исправив ошибку, всё отрабатывает как надо. Отключается и включается в требуемое время по часам, даже если пропадало питание на неопределённый срок. Но казус с переключением DS3231 c MINI на UNO был, часы показывали время пропадания питания. В общем я сделал с самого начала. Перепрошил часики, потом MINI, собрал схему и всё работает. Спасибо за помощь.




Чтобы вставить ссылку используйте форму вида[url]http://www.адрес.ru[/url][text]текст ссылки[/text]
Чтобы вставить код используйте форму вида[code]код[/code]

Имя:   





  







Рейтинг@Mail.ru Яндекс.Метрика