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

Считывание данных с DS1307


Электронщик

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

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

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


uint8_t data5;
/*Функция чтения данных из DS1307*/
uint8_t read_DS1307 (uint8_t reg ) /*Передаем адрес регистра*/
{
       uint8_t time2;
      /*формируем состояние СТАРТ*/
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));

/*выдаем на шину пакет SLA-W  */  
TWDR = 0xD0;
TWCR = (1<<TWINT)|(1<<TWEN); 
while(!(TWCR & (1<<TWINT)));    
                  
/*передаем адрес управляемого устройства*/

TWDR = 0x68;

TWCR = (1<<TWINT)|(1<<TWEN); 
while(!(TWCR & (1<<TWINT)));
   


       TWDR = reg;   /*Адрес регистра*/
       TWCR = (1<<TWINT)|(1<<TWEN);
       while (!(TWCR & (1<<TWINT)));
      /*формируем состояние ПОВСТАР*/
       TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
       while (!(TWCR & (1<<TWINT)));
       TWDR = 0xD1; /*Передаем адрес + бит чтения*/
       TWCR = (1<<TWINT)|(1<<TWEN);
       while (!(TWCR & (1<<TWINT)));

       TWDR = 0x68;

TWCR = (1<<TWINT)|(1<<TWEN); 
while(!(TWCR & (1<<TWINT)));


data5=TWDR;

TWCR = (1<<TWINT)|(1<<TWEN); 
while(!(TWCR & (1<<TWINT)));


    
     /*формируем состояние СТОП*/
      TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
      return time2;
}




void write_DS1307 (uint8_t reg, uint8_t time2) /*передаем два параметра: адрес регистра, к которому будем обращаться и передаваемую информацию*/
{
/*формируем состояние СТАРТ*/
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));

/*выдаем на шину пакет SLA-W  */  
TWDR = 0xD0;
TWCR = (1<<TWINT)|(1<<TWEN); 
while(!(TWCR & (1<<TWINT)));    
                  
/*передаем адрес управляемого устройства*/

TWDR = 0x68;

TWCR = (1<<TWINT)|(1<<TWEN); 
while(!(TWCR & (1<<TWINT)));
   
   TWDR =reg; /*передаем  данные*/    // Передача адреса регистра
     
      TWCR = (1<<TWINT)|(1<<TWEN); 
      while(!(TWCR & (1<<TWINT)));

 TWDR =time2; /*передаем  данные*/    // Передача данных
     
      TWCR = (1<<TWINT)|(1<<TWEN); 
      while(!(TWCR & (1<<TWINT)));

 /*формируем состояние СТОП*/
  
  
TWCR = (1<<TWINT)|
(1<<TWEN)|(1<<TWSTO);

}

void initTWI(){ 
  TWSR = 0x00;
  TWBR = 72; //100kHz   

}


void nastr() {
  write_DS1307 (0x02, 14); /*Записываем необходимый час*/
  write_DS1307 (0x01, 15); /*Записываем необходимую минуту*/
  write_DS1307 (0x00, 0); /*Запускаем часы*/
 
}


void setup() {
  //DDRC = 0x00;  /*Выставляем порт как вход*/
 
 initTWI();
Serial.begin(9600); 
nastr();// настройка и запуск часов
}
void loop() {

read_DS1307(0x02);       /*Считываем час*/

Serial.print(data5);
Serial.print(':');
read_DS1307(0x02);       /*Считываем минуты*/
Serial.println(data5);
 delay(600);
   }
 

 

 

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

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

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

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

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

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

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

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

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

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

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

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

а что это за число?

5 часов назад, Электронщик сказал:

TWDR = 0x68;

у меня это выглядит так

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

//==============================================================================
// запись времени в DS1307
//==============================================================================
void DS1307_WriteDateTime(uint16_t date, uint16_t time)
{
  if(I2C_Start(DEV_DS1307 | I2C_WRITE));              // старт-условие
  {
    I2C_WriteInt8(0x00);                              // начальный адрес данных DS1307
    I2C_WriteInt8(0);                                 // сохраняем секунды
    I2C_WriteInt8(BinToBCD(time%60));                 // сохраняем минуты
    I2C_WriteInt8(BinToBCD(time/60));                 // сохраняем часы
    I2C_WriteInt8(1);                                 // сохраняем день недели
    I2C_WriteInt8(BinToBCD(date & 0x001F));           // сохраняем день
    I2C_WriteInt8(BinToBCD((date >> 5) & 0x000F));    // сохраняем месяц
    I2C_WriteInt8(BinToBCD((date >> 9) & 0x007F));    // сохраняем год
  }
  I2C_Stop();                                         // stop-условие
}

//==============================================================================
// чтение времени из DS1307
//==============================================================================
uint8_t DS1307_ReadDateTime(uint16_t *const date, uint16_t *const time)
{
  uint8_t state;
 
  state = I2C_Start(DEV_DS1307 | I2C_WRITE);            // старт-условие
  if(!state)                                            // если DS1307 не отвечает
  {                                                     // то
    I2C_Stop();                                         // stop-условие
    *time = ERROR_DATETIME;                             // время недостоверное
    *date = ERROR_DATETIME;                             // дата не достоверная
  }
  else
  {
    I2C_WriteInt8(0x00);                                 // начальный адрес данных DS1307
    I2C_RepStart(DEV_DS1307 | I2C_READ);                 // команда на чтение
    I2C_ReadInt8(NOLAST);                                // считываем секунды
    uint8_t minutes = I2C_ReadInt8(NOLAST) & 0x7F;       // считываем минуты
    uint8_t hours = I2C_ReadInt8(NOLAST) & 0x3F;         // считываем часы
    I2C_ReadInt8(NOLAST);                                // день недели
    uint8_t day = I2C_ReadInt8(NOLAST) & 0x3F;           // считываем день
    uint8_t month = I2C_ReadInt8(NOLAST) & 0x1F;         // считываем месяц
    uint8_t year = I2C_ReadInt8(LAST);                   // считываем год
    I2C_Stop();                                          // stop-условие
    *date = (BCDToBin(year) <<  9) | (BCDToBin(month) << 5) | BCDToBin(day);
    *time = BCDToBin(hours) * 60 + BCDToBin(minutes);
  }
  return(state);
}

 

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

TWDR = 0x68; - это адрес часов, без режима передачи или записи, то есть реальный их адрес, без этого у меня TWI не работает.

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

Часы запустил, спасибо, видимо первый раз что-то не так сделал, хотя ж делал, так само, чудеса, теперь осталась проблема,  ставлю допустим 55 минут, они идут и когда стает 58 минут, раз и резко становится 64 минуты, это особенность формата часов? Или их нужно обнулять по минутам, и при этом плюсовать  час? 

Изменено пользователем Электронщик
Ссылка на комментарий
Поделиться на другие сайты

Два варианта работы с часами.

Считывание времени.

Опрос выхода микросхемы, микросхему настраиваем на 1 Гц.

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

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

15 часов назад, Электронщик сказал:

когда стает 58 минут, раз и резко становится 64 минуты

Время, хранятся в формате BCD.
Т.е., например, единицы минут хранятся в младших 4 битах, а десятки минут хранятся в старших 3 битах.

Необходим перевод числа и BCD в BIN при чтении, ну и при записи из BIN в BCD.

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

1 час назад, dm37 сказал:

Необходим перевод числа и BCD в BIN при чтении, ну и при записи из BIN в BCD.

//========================================================================
void RTC_Get_Time (void)
{
   u08 temp = I2C_ReadRegister (RTC_ADDR, HOURS_REGISTER);

   if (temp & (1<<AMPM)) // 12-часовой режим.
      temp &= 0x1F;
   else
      temp &= 0x3F; // 24-часовой режим.

   set_hours (bcd_hex_time (temp));

   temp = I2C_ReadRegister (RTC_ADDR, MINUTES_REGISTER);
   set_minutes (bcd_hex_time (temp));

   temp = I2C_ReadRegister (RTC_ADDR, SECONDS_REGISTER);
   set_seconds (bcd_hex_time (temp));
}

void RTC_Set_Time (u08 hours, u08 minutes, u08 seconds)
{
   I2C_WriteRegister (RTC_ADDR, HOURS_REGISTER, hex_bcd_time (hours));
   I2C_WriteRegister (RTC_ADDR, MINUTES_REGISTER, hex_bcd_time (minutes));
   I2C_WriteRegister (RTC_ADDR, SECONDS_REGISTER, hex_bcd_time (seconds));
}

u08 bcd_hex_time (u08 a)
{
   return (((a >> 4) * 10)) + (a & 0x0F); //    return (((a >> 4) * 10)) | (a & 0x0F); // однокуйственно...
}

u08 hex_bcd_time (u08 a)
{
   u08 temp = a;

   u08 cnt = 0;

   while (1)
   {
      if (temp >= 10)
      {
         temp -= 10;
         cnt++;
      }
      else
         break;
   }

   return ((cnt << 4) | (temp & 0x0F));
}

 

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

//==============================================================================
// Преобразование из BCD в BIN
//==============================================================================
uint8_t BCDToBin(uint8_t byte)
{
  return((byte & 0x0F) + (byte >> 4) * 10);
}

//==============================================================================
// Преобразование из BIN в BCD
//==============================================================================
uint8_t BinToBCD(uint8_t byte)
{
  return(((byte / 10) << 4) + (byte % 10));
}

 

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

1 час назад, dm37 сказал:

 

Понимаете, в чем фишка написания программ на си для МК. Это на ассемблере можно меряться у кого короче. Но на си короче - не значит быстрее, компактнее по выхлопу. Это зависит от программиста и компилятора.

Берем TINY и MEGA. У Tiny нет команды умножения. На Mega умножение на 10 будет производиться аппаратно.

Поэтому:

//========================================================================
__C_task main (void)
{
   u08 a = 2;
   u08 b;
   u08 c;

   wdt_enable (WDTO_15_MS);

   sleep_mode_init ();

   init_soft_timers ();
   Init_Events ();
   __enable_interrupt ();

   while (1)
   {
      __watchdog_reset ();

      proc_device ();

      b = (a << 1);
      c = (a << 3);

      PORTA = b + c;

      Process_Events ();
   }
}
//========================================================================

И когда пишешь программу, учитываешь, какой МК используется. Как в том или ином случае компилятор скомпилирует код.

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

16 часов назад, Электронщик сказал:

ставлю допустим 55 минут, они идут и когда стает 58 минут, раз и резко становится 64 минуты

был у меня такой заплет с китайскими DS1307. Причина была в том, что почему то чтение по I2C происходило с ошибками. ХЗ почему. Поигрался с константами настройки интерфейса и кое как нашел устойчивый режим. До этого нервов убил ведро. С таймером 41T00 вообще никаких проблем небыло, а тут такая лажа.

/* I2C1 init function */
static void MX_I2C1_Init(void)
{

  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x2000090E;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  HAL_I2C_Init(&hi2c1);

    /**Configure Analogue filter 
    */
  HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE);

}

подбирал строчку hi2c1.Init.Timing = 0x2000090E;

почему именно 0x2000090E; даже не спрашивай, не вспомню уже. Но как то посчитал. У иебя скорее всего будет другое число, потому как каменьб другой. У меня был STM32F030F4P6 на частоте 8 мегагерц

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

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

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

аппаратный ессно

тупят эти 1307 бесчеловечно. Вообще самый говенный RTC с которым мне приходилось работать. 41T00 по сравнению с ним просто патек-филипп по сравнению с советским будильником

прасю пардон

тот код который я выложил выше, это был для нормального 1307, купленного в магазине и не вызывающего сомнений в подлинности. Он работал без всякого шаманства. А вот код для того же самого идентичного устройства (повтор) уже на китайских DS-ках

* I2C1 init function */
static void MX_I2C1_Init(void)
{
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x0000020B;//0x2000090E
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
	
  if (HAL_I2C_Init(&hi2c1) != HAL_OK) Error_Handler();
  //if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) Error_Handler();
}

 

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

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

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

1 час назад, mail_robot сказал:

 

А вот нечего гнаться за китайщиной и дешевизной. Попалась китайщина - в мусорку, продавца в бан или поставить на вид.

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

заработало же. С бубном конечно, но все же. Да и по 15 рублей за часики это не по 200. Я как бы сделал выводы, но выбрасывать не стал )

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

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

1 час назад, mail_robot сказал:

заработало же. С бубном конечно, но все же. Да и по 15 рублей за часики это не по 200. Я как бы сделал выводы, но выбрасывать не стал )

Я делаю на устройства на заказ. И мой принцип - сделал и забыл. Последние слова - ключевые. А это значит, что никакого контрафакта. Зато и сплю спокойно, с чистой совестью. Конечно бывают, ммм, нюансы... Но это - рабочие моменты, из которых делаются выводы.

Да, это значит, что комплектующие дороже. Но нервы и время мне дороже.

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

согласен. Но на тот момент ситуация была сложнее чем можно обьяснить словами. Даже сэкономленые 5 копеек играли роль

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

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

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

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

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

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

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

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

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

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

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

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