Я использую Arduino и DS1307 для создания RTC, но мой код имеет некоторые проблемы

Я не получаю никаких ошибок, но значения, которые должны отображаться в RTC_read, по какой-то причине не отображаются. Первоначально я думал, что это может быть связано с тем, что код перехватывается где-то в цикле, но это не так. случай. Странно, когда я использую Serial.print() для некоторого значения, все значение не отображается

#include<avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>

void i2c_init() 
{
  TWSR=0x00;
  TWBR=0x47;
  TWCR=(1<<TWEN);
}

void i2c_start()  
{
  TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
  while(!(TWCR&(1<<TWINT)));
}

void i2c_end() 
{
  TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
  while(!(TWCR&(1<<TWSTO))); 
}

void i2c_write(uint8_t data) 
{
  TWDR=data;
  TWCR=(1<<TWINT)|(1<<TWEN);
  while(!(TWCR&(1<<TWINT)));
}

uint8_t i2c_read(int ack_val) 
{
  TWCR=(1<<TWINT)|(1<<TWEN)|(ack_val<<TWEA);
  while(!(TWCR&(1<<TWINT)));
  return TWDR;
}

void RTC_init()
{
  i2c_init();
  i2c_start();
  i2c_write(11010000);
  i2c_write(00000111);
  i2c_write(00000000);
  i2c_end();
}

void RTC_set_time_date(uint8_t second,uint8_t minute,uint8_t hour,uint8_t day,uint8_t month,uint8_t year) 
{
  i2c_start();
  i2c_write(11010000);
  i2c_write(00000000);
  i2c_write(second);
  i2c_write(minute);
  i2c_write(hour);
  i2c_write(day);
  i2c_write(month);
  i2c_write(year);
  i2c_end();  
}

void RTC_read()
{
  char second,minute,hour,day,month,year;  
  i2c_start();
  i2c_write(11010000);
  i2c_write(00000000);
  i2c_end();

  i2c_start();
  i2c_write(11010001);
  second=i2c_read(1);
  minute=i2c_read(1);
  hour=i2c_read(1);
  day=i2c_read(1);
  month=i2c_read(1);
  year=i2c_read(0);
  i2c_end();
  Serial.println(second);
  Serial.println(minute);
  Serial.println(hour);
  Serial.println(day);
  Serial.println(month);
  Serial.println(year);
  Serial.println("Recieving data");
}

int main()
{
  Serial.begin(9600);
  uint8_t second,minute,hour,day,month,year;
  second=00000000;
  minute=01000000;
  hour=00100011;
  day=00000011;
  month=00000111;
  year=00011001;
  Serial.write("abcd");
  RTC_init();
  RTC_set_time_date(second,minute,hour,day,month,year);  
  RTC_read();
  return 0;
}

, 👍0

Обсуждение

это не скетч ардуино, @Juraj

присвоение чисел в main() не является двоичным... это восьмеричное присвоение... minute=01000000; равно 262144 минутам.... но загруженное в uint8_t оно равно нулю минут, @jsotola

На самом деле значения, записанные (или прочитанные) в устройство, имеют формат BCD, а не двоичный и не восьмеричный., @user3629249

вы пытаетесь запустить RTC в 12- или 24-часовом режиме?, @user3629249

с учетом регистра минут. 0x00 - 0 минут. 0x59 составляет 59 минут. Самый значащий полубайт имеет допустимый диапазон 0...5, младший значащий полубайт имеет допустимый диапазон 0...9., @user3629249

в функции: i2c_start() делает: TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) включает часы и устанавливает линию данных для изменения с низкого уровня на высокий во время высокая часть такта? Т.Е. управляющая последовательность «СТАРТ»?, @user3629249


1 ответ


1

Начнем с порядка регистров:

seconds  -- bit 7 is clock start/stop bit, 0 = enabled
minutes
hours    -- bit 6 is selector 12/24 hour, 
         -- when in 12 hour, bit 5 is am/pm, 1=pm 
         -- When in 24 hour, bit 5 indicates in hour 20...23
day      -- week day 1...7
date     -- day of month 1...31 
         -- where the most significant nibble can contain the values
         -- 0, 1, 2, 3
         -- where the least significant nibble can contain the values
         -- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
month    -- 0x1x indicates in upper 10 months
year
control
<other ram>

При записи этих регистров предыдущее время переносится на фон/изображение основных регистров.

Ключевое значение имеет бит подтверждения, который отображается в конце каждого передаваемого байта. Вот подробности:

DS13077 of 12Acknowledge: Каждое принимающее устройство при обращении к нему обязано генерировать подтверждение после приема каждого байта. Ведущее устройство должно генерировать дополнительный тактовый импульс, который связан с этим битом подтверждения. Устройство, которое подтверждает, должно опустить линию SDA во время тактового импульса подтверждения таким образом, чтобы линия SDA была стабильно НИЗКОЙ в течение ВЫСОКОГО периода времени, связанного с подтверждением. часовой пульс. Конечно, необходимо учитывать время установки и удержания. Ведущее устройство должно сигнализировать подчиненному об окончании данных, не генерируя бит подтверждения в последнем байте, который был тактирован из подчиненного устройства. В этом случае ведомое устройство должно оставить линию данных ВЫСОКОЙ, чтобы ведущее устройство могло сгенерировать условие СТОП

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

вторая проблема, которую я вижу, это то, что биту ACK присваивается неправильное значение

,