Перейти к содержанию

Работа с DS1307


-=FISHER=-

Рекомендуемые сообщения

Здравствуйте!

 

Для работы с DS1307 я использовал следующую библиотеку I2C:

Скрытый текст

#include "twi.h"

void I2C_Init(void)
{
	TWBR=0x20; //скорость передачи (при 8 мГц получается 100 кГц)
}

void I2C_StartCondition(void)
{
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
	while(!(TWCR&(1<<TWINT)));//подождем пока установится TWIN
}

void I2C_StopCondition(void)
{
	TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}

void I2C_SendByte(unsigned char c)
{
	TWDR=c;//запишем байт в регистр данных
	TWCR = (1<<TWINT)|(1<<TWEN);//включим передачу данных
	while(!(TWCR&(1<<TWINT)));//подождем пока установится TWIN	
}

 

Я уже научился настраивать время в DS1307 программно. Делал я это следующим образом:

Скрытый текст

	I2C_Init();
	
	//Устанавливаем время
 	I2C_StartCondition();
 	I2C_SendByte(0b11010000);
 	I2C_SendByte(0);//Переходим на 0x00
 	I2C_SendByte(RTC_ConvertFromBinDec(0)); //секунды
 	I2C_SendByte(RTC_ConvertFromBinDec(31)); //минуты
 	I2C_SendByte(RTC_ConvertFromBinDec(20)); //часы
 	I2C_SendByte(RTC_ConvertFromBinDec(5)); //день недели
 	I2C_SendByte(RTC_ConvertFromBinDec(29)); //дата
 	I2C_SendByte(RTC_ConvertFromBinDec(1)); //месяц
 	I2C_SendByte(RTC_ConvertFromBinDec(16)); //год
 	I2C_StopCondition();

 

Теперь для приближения моих часов к реальности, необходимо добавить возможность установки времени с помощью трёхкнопочного интерфейса. В связи с чем у меня возникли вопросы, а именно:

  1. При первом включении или при включении после отключения аккумулятора, все регистры времени будут пусты и считать с часов вообще ничего не получится, как правильно будет отследить это первое включение и записать в регистры времени значения по умолчанию, предположим 12:00:00 ?
  2. Я планирую выводить на дисплей только часы, минуты и секунды. Значит остальные данные мне не нужны, могу ли настраивать только эти показатели? Будут ли идти часы после такой настройки?
    Скрытый текст
    
     	I2C_StartCondition(); //начало передачи
     	I2C_SendByte(0b11010000); //режим записи
     	I2C_SendByte(0x00);//Переходим на 0x00
    	I2C_SendByte(RTC_ConvertFromBinDec(0)); //устанавливаем секунды
     	I2C_StopCondition();
    
     	I2C_StartCondition(); //начало передачи
     	I2C_SendByte(0b11010000); //режим записи
     	I2C_SendByte(0x01);//Переходим на 0x01
    	I2C_SendByte(RTC_ConvertFromBinDec(0)); //устанавливаем минуты
     	I2C_StopCondition();
    
     	I2C_StartCondition(); //начало передачи
     	I2C_SendByte(0b11010000); //режим записи
     	I2C_SendByte(0x02);//Переходим на 0x02
    	I2C_SendByte(RTC_ConvertFromBinDec(12)); //устанавливаем часы
     	I2C_StopCondition();

     

     

Изменено пользователем -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

1. В DS1307 есть 56 байт RAM, при первом включении там будет не известно что, но вы можете записать туда что-то конкретное, например строку "CLOCK". В программе читаете RAM и смотрите - если там строка есть, значит, не первое включение, если нет - первое.

2. Часы идти будут, но содержимое "календаря" будет некорректным.

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

@ARV

  1. RAM есть энергонезависимая память? Просто если нет, то после отключения мое слово сотрется?...
  2. Так как я не буду читать содержимое календаря, можно считать что его некорректные значения никак не повлияют на работу моих часов ни через день ни через месяц?
Изменено пользователем -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

RAM - это ОЗУ, оно не сохраняет содержимое при снятии питания. В случае с DS1307 эта память питается от батарейки и будет хранить содержимое все время, пока батарейка подключена. При отключении батарейки, естественно, "слово" сотрется.

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

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

27 минут назад, ARV сказал:

что-то конкретное, например строку "CLOCK"

 

Ну или для упрощения какой-то определённый байт по адресу например 0x08?

 

Скрытый текст

	I2C_StartCondition(); //начало передачи
 	I2C_SendByte(0b11010000); //режим записи
 	I2C_SendByte(0x08);//Переходим на 0x08
	I2C_SendByte(0x05); //записываем определённый байт в ОЗУ DS1307
 	I2C_StopCondition();

 

Спасибо огромное, разобрался!

Изменено пользователем -=FISHER=-

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

1 байт может быть не очень удачным вариантом, т.к. в момент подачи питания содержимое ОЗУ может быть СЛУЧАЙНЫМ, а байт задает всего 256 комбинаций. Т.е. вероятность того, что случайно содержимое этого байта станет равно вами заданному 1/256. В случае со строкой вероятность кардинально меньше, и чем длиннее строка, тем выша гарантия, что ложных "срабатываний" не будет.

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

3 минуты назад, ARV сказал:

1 байт может быть не очень удачным вариантом

Значит мне нужно разбить слово на байты и побайтно зписать в ОЗУ?

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Да просто запишите набор байтов с разными значениями. Хоть все 56 байт - 1..2..3..4....
А то сейчас тема дойдёт до "Как записать строку побайтно ?" :)

Ссылка на комментарий
Поделиться на другие сайты

Только что, Alex сказал:

А то сейчас тема дойдёт до "Как записать строку побайтно ?"

Ну так вообще говоря, обмен с внешними устройствами обычно и делается при помощи функции типа write_block(void* data, int data_len) :) ну и чтение аналогично.

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

1 минуту назад, Alex сказал:

Ну, вообще, да. Но фразы :

Я не слишком опытен, вот и пишу всякую ахинею порой.

3 минуты назад, ARV сказал:

типа write_block(void* data, int data_len)

Описание это функции в какой библиотеке я могу найти, подскажите пожалуйста?

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Описание этой функции должно быть понятно из её названия и параметров: запись блока (указатель на записываемые данные и количество байтов этих данных).

Вы за 5 минут можете написать её самостоятельно из имеющихся у вас функций записи 1 байта и обычного цикла.

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

2 минуты назад, -=FISHER=- сказал:

Я не слишком опытен, вот и пишу всякую ахинею порой.

Ничего страшного, это всё пройдёт со временем :)

2 минуты назад, -=FISHER=- сказал:

Описание это функции в какой библиотеке я могу найти, подскажите пожалуйста?

Это был пример. Так сказать, некий шаблон, который обычно реализуют для передачи/приёма данных.

Ссылка на комментарий
Поделиться на другие сайты

Только что, Alex сказал:

Ну, вообще, да. Но фразы ... настораживают :)

Тут, скорее всего, речь не о машинном слове, а о "текстовом" слове :) 

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

7 минут назад, ARV сказал:

Тут, скорее всего, речь не о машинном слове

Ну вы же написали

55 минут назад, ARV сказал:

например строку "CLOCK"

Вот я и решил что имеется ввиду обычный текст)

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

@-=FISHER=-

Вот у Вас код :

	//Устанавливаем время
 	I2C_StartCondition();
 	I2C_SendByte(0b11010000);
 	I2C_SendByte(0);//Переходим на 0x00
 	I2C_SendByte(RTC_ConvertFromBinDec(0)); //секунды
 	I2C_SendByte(RTC_ConvertFromBinDec(31)); //минуты
 	I2C_SendByte(RTC_ConvertFromBinDec(20)); //часы
 	I2C_SendByte(RTC_ConvertFromBinDec(5)); //день недели
 	I2C_SendByte(RTC_ConvertFromBinDec(29)); //дата
 	I2C_SendByte(RTC_ConvertFromBinDec(1)); //месяц
 	I2C_SendByte(RTC_ConvertFromBinDec(16)); //год
 	I2C_StopCondition();

Создайте функцию , типа :

void DS_Write(uint8_t addrr, void* pData, uint8_t size){
	uint8_t * p= (uint8_t*)pData;
	I2C_StartCondition(); //начало передачи
	I2C_SendByte(0b11010000); //режим записи
	I2C_SendByte(addrr);//Переходим на addrr
	while(size--)	I2C_SendByte(RTC_ConvertFromBinDec(*p++));
	I2C_StopCondition();
}

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

Можно создать структуру, в которой будут хранится секунды всякие, минуты, ... И передавать адрес этой структуры в функцию.

Ссылка на комментарий
Поделиться на другие сайты

@Alex Мне очень понравилась Ваше предложение. Только пожалуйста сможете объяснить, желательно на моем уровне понимания, что конкретно делают эти строчки:

  1. void* pData

  2. uint8_t * p= (uint8_t*)pData;

  3. *p++

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Только что, Alex сказал:

Создайте функцию , типа

Ну так теперь можно и не создавать :)

 

Только что, -=FISHER=- сказал:

void* pData

указатель на какой-то участок памяти МК

Только что, -=FISHER=- сказал:

uint8_t * p= (uint8_t*)pData

значение указателя p сделать равным значению pData. Собственно говоря, это по сути лишнее, привести тип указателя можно было бы и сразу в месте, где эти данные требуются, без промежуточного указателя.

Только что, -=FISHER=- сказал:

*p++

Взять байт по указателю и увеличить указатель на 1. 

Вообще говоря, все вышесказанное - азы Си... без знаний этого в Си, как без рук.

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

9 минут назад, -=FISHER=- сказал:

void* pData

Это указатель на блок данных. void - чтобы можно было передавать указатель любого типа, не преобразовывая его явно к uint8_t при передачи в функцию.

9 минут назад, -=FISHER=- сказал:

uint8_t * p= (uint8_t*)pData;

Это обычное преобразование типа void к uint8_t

9 минут назад, -=FISHER=- сказал:

*p++

Это инкремент указателя, с взятием значения по нему.

Ссылка на комментарий
Поделиться на другие сайты

1 минуту назад, Alex сказал:

Это указатель

 

2 минуты назад, ARV сказал:

указатель на какой-то участок памяти МК

Короче я пошел читать про указатели))) До этого как-то обходился только переменными.

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

3 минуты назад, ARV сказал:

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

Помнится, у меня не получалось инкрементировать указатель на void. Может я что-то неправильно делал, но забил и просто создаю отдельный на uint8.

Ссылка на комментарий
Поделиться на другие сайты

Только что, -=FISHER=- сказал:

пошел читать про указатели

Указатели в Си - это та самая бритва, при помощи которой можно сделать шедевр или кровавое месиво :) 

 

Только что, Alex сказал:

Помнится, у меня не получалось инкрементировать указатель на void

Это да, приводить и тут надо. Собственно, ваш подход я и сам применяю, т.к. придерживаюсь принципа "лучше написать больше, но понятнее".

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

4 минуты назад, ARV сказал:

казатели в Си - это та самая бритва, при помощи которой можно сделать шедевр или

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

Мы все учились по-немногу, чему-нибудь и как-нибудь...

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...