DS1307 RTC entegresi 00 çıktısı döndürme sorunu

Başlatan istinaf duvarı, 17 Şubat 2024, 17:54:43

istinaf duvarı

Merhabalar. CCS ile hazırladığım DS1307 saat programında DS1307 entegresi 00 verisi döndürmekte. Devreyi Proteus'ta çalıştırdığımda tarih ve saat yerine 00'lar görüyorum.




İlk denemede DS1307 ve I2C LCD'yi bus topolojisinde PIC'e bağlamıştım. İkisinin çakışma yaptığını düşünüp I2C yerine normal LCD ile denedim. Onda da aynı şekilde 00'lar döndürmeye devam ediyor.

Anladığım kadarıyla yurtdışında da bu sorundan muzdarip olan çok sayıda geliştirici var. Bir çözüm bulabilene denk gelmedim.

Nerede hata yapıyoruz?

Ana program bu şekilde:
#include <i2c_rtc.h>
/*
#define LCD_ADDR 0x40
#define lcd_total_rows 2
#define lcd_total_columns 16
#include <i2c_lcd.h>
*/
//Normal LCD'ye geçildiği için iptal edildi. 
#include <ds1307.c>
#define LCD_ENABLE_PIN  PIN_C0                                    ////
#define LCD_RS_PIN      PIN_C1                                    ////
#define LCD_RW_PIN      PIN_C2                                    ////
#define LCD_DATA4       PIN_C4                                    ////
#define LCD_DATA5       PIN_C5                                    ////
#define LCD_DATA6       PIN_C6                                    ////
#define LCD_DATA7       PIN_C7
#include <lcd.c>


void main()
{
BYTE sec;
  BYTE min;
  BYTE hrs;
  BYTE day;
  BYTE month;
  BYTE yr;
  BYTE dow;
 
  ds1307_init();
  
  // Set date for -> 15 June 2005 Tuesday
  // Set time for -> 15:20:55
  ds1307_set_date_time(15,6,5,2,15,20,55);
   lcd_init();
  //lcd_clear();        //Normal LCD'ye geçerken iptal edildi.
  lcd_putc( "   Initing...   ");
  delay_ms(500);
  //lcd_clear();        //Normal LCD'ye geçerken iptal edildi. 
  lcd_putc("\f");
  
  
   while(TRUE)
   {
     delay_ms(1000);
   
    ds1307_get_date(day,month,yr,dow);
    ds1307_get_time(hrs,min,sec);
    i2c_read(0);
    //delay_ms(100);
     
    printf(lcd_putc, "\f\%02d/\%02d/\%02d\r\n",day,month,yr);
    printf(lcd_putc, "\%02d:\%02d:\%02d", hrs,min,sec); //TODO: User Code
   }

}

Sigortaların olduğu başlık dosyası bu şekilde:
#include <18F2455.h>
#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(clock=48MHz,crystal=20MHz)
#use i2c(Master,Slow=100000,sda=PIN_B0,scl=PIN_B1,force_hw)

RTC sürücü dosyası:
////////////////////////////////////////////////////////////////////////////////
///                               DS1307.C                                   ///
///                     Driver for Real Time Clock                           ///
///                                                                          ///
/// ds1307_init() - Enable oscillator without clearing the seconds register -///
///                 used when PIC loses power and DS1307 run from 3V BAT     ///
///               - Disable squarewave output                                ///
///                                                                          ///
/// ds1307_set_date_time(day,mth,year,dow,hour,min,sec)  Set the date/time   ///
///                                                                          ///
/// ds1307_get_date(day,mth,year,dow)               Get the date             ///
///                                                                          ///
/// ds1307_get_time(hr,min,sec)                     Get the time             ///
///                                                                          ///
////////////////////////////////////////////////////////////////////////////////

/*
#define RTC_SDA  PIN_C4
#define RTC_SCL  PIN_C3

#use i2c(master, sda=RTC_SDA, scl=RTC_SCL) 
*/
// Sürücü içerisinde yer alan I2C yapılandırma kodunu ana programa aktardığımdan burayı iptal ettim. I2c ayarlaması ana programda yapılıyor. 


BYTE bin2bcd(BYTE binary_value);
BYTE bcd2bin(BYTE bcd_value);

void ds1307_init(void)
{
   BYTE seconds = 0;

   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x00);      // REG 0
   i2c_start();
   i2c_write(0xD1);      // RD from RTC
   seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307
   i2c_stop();
   seconds &= 0x7F;

   delay_us(3);

   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x00);      // REG 0
   i2c_write(bin2bcd(seconds));     // Start oscillator with current "seconds value
   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x07);      // Control Register
   i2c_write(0x80);     // Disable squarewave output pin
   i2c_stop();

}

void ds1307_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec)
{
  sec &= 0x7F;
  hr &= 0x3F;

  i2c_start();
  i2c_write(0xD0);            // I2C write address
  i2c_write(0x00);            // Start at REG 0 - Seconds
  i2c_write(bin2bcd(sec));      // REG 0
  i2c_write(bin2bcd(min));      // REG 1
  i2c_write(bin2bcd(hr));      // REG 2
  i2c_write(bin2bcd(dow));      // REG 3
  i2c_write(bin2bcd(day));      // REG 4
  i2c_write(bin2bcd(mth));      // REG 5
  i2c_write(bin2bcd(year));      // REG 6
  i2c_write(0x80);            // REG 7 - Disable squarewave output pin
  i2c_stop();
}

void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow)
{
  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x03);            // Start at REG 3 - Day of week
  i2c_start();
  i2c_write(0xD1);
  dow  = bcd2bin(i2c_read() & 0x7f);   // REG 3
  day  = bcd2bin(i2c_read() & 0x3f);   // REG 4
  mth  = bcd2bin(i2c_read() & 0x1f);   // REG 5
  year = bcd2bin(i2c_read(0));            // REG 6
  i2c_stop();
}

void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec)
{
  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);            // Start at REG 0 - Seconds
  i2c_start();
  i2c_write(0xD1);
  sec = bcd2bin(i2c_read() & 0x7f);
  min = bcd2bin(i2c_read() & 0x7f);
  hr  = bcd2bin(i2c_read(0) & 0x3f);
  i2c_stop();

}

BYTE bin2bcd(BYTE binary_value)
{
  BYTE temp;
  BYTE retval;

  temp = binary_value;
  retval = 0;

  while(1)
  {
    // Get the tens digit by doing multiple subtraction
    // of 10 from the binary value.
    if(temp >= 10)
    {
      temp -= 10;
      retval += 0x10;
    }
    else // Get the ones digit by adding the remainder.
    {
      retval += temp;
      break;
    }
  }

  return(retval);
}


// Input range - 00 to 99.
BYTE bcd2bin(BYTE bcd_value)
{
  BYTE temp;

  temp = bcd_value;
  // Shifting upper digit right by 1 is same as multiplying by 8.
  temp >>= 1;
  // Isolate the bits for the upper digit.
  temp &= 0x78;

  // Now return: (Tens * 8) + (Tens * 2) + Ones

  return(temp + (temp >> 2) + (bcd_value & 0x0f));
} 



mehmet

Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
http://www.mehmetbilgi.net.tr
CC BY

istinaf duvarı

#2
Pull up ile de denendi. Yine çalışmıyor.

Simülasyon kaynaklı bir hata da olabilir. Elinde gerçek DS1307 olan varsa deneyebilir mi?

ete

Buraya Çalışma dosyalarını (hex dahil) koysaydınbelki birisi deneme yapardı.
Ancak 18F2455 'in ellerinde olma ihtimali az gibi görünüyor.

Diğer taraftan programa bakınca;
#use delay(clock=48MHz,crystal=20MHz)
satırı bana ilginiç geldi. Zira bu satır PLL kullanıldığını gösteriyor. Ancak 48Mhz PLL frekansı elde etmek için 20Mhz kullanılması bence yanlış. Yada 2,4Mhz lik bir kristal kullanman gerekir ki pek standart kristal gibi gelmedi bana.

Programda ayrıca PLL kullanılacağını gösteren bir ibare de göremedim. Şayet bu yazılan satır bunu otomatik ayarlıyor ise sorun yok.

Ekranda her şeyin 00 göükmesi RTC ile haberleşmenin yapılamadığını gösteriyor bana kalırsa. İşin bu kısmına odaklanman gerekiyor. Ya, sürücü dosyası düzgün değil yada program düzgün değil. Bu ikisinden birisi. Simulasyonun bir kusuru var ise başka bir programla aynı devre test edilebilir. Bunu sağlamak için aynı programı yazmayı deneyeceğim (Basic ile).

Ekrana değerler en azından çıktığına göre program çalışıyor demektir bir şekilde. Ama haberleşme olmuyor. Bu arada I2C için Pullup mutlaka olması gereken bir husus dur. Sanırım PORTB de dahili pullup ları kullandın.

Diğer bir dikkat edilecek husus ise bu işlemcide Çıkış portları LATA , LATB, LATC LATD şeklinde, ve giriş portlarıda port isimleri ile PORTA, PORTB,PORTC PORTD şeklinde kullanılıyor.
Acaba bu iş CCSC de nasıl yapılıyor ? zira programda bu ifadeleri göremedim.

Ete

NOT: Sorunun büyük ihtimal ile haberleşme pinlerine haricen bir pullup direnci bağlamamış olmandan kaynaklandığını düşünüyorum. Biliyorsun dahili pullup direncinin aktif olabilmesi için öncelikli şart o pinin giriş pini olması gerekir. Halbuki haberleşme pinlerinin hiç birisi giriş pini değil. CLK zaten hiç değil ama DTA pini çift yönlü çalışan bir pin ve sürücü bunu ayarlaması gerekir. Ama programda tanımlanırkan çıkış pini olarak tanımlıyoruz. BU nedenle dahili pulluplar bu sistemde iş görmezler.

ete

İlişikte yazdığım programı veriyorum. Ekran görüntülerini ve işlemci ayarı vs hepsi ilgili dosyalarda gözüküyor.
Sİmulasyon dosyasını veremedim nedense kayıt etmedi. Ama sizin devre ve kendi dosyanızı benim ayarlarımla kullanabilirsiniz. İşlemci frekansı 48Mhz olmalı simulasyonda.

Ben pullup direnci bağladım RTC haberleşme hatlarına daili pulluplar da kullanılabilir.

Deneyin bakalım simulasyondamı hata yoksa derleyicinizdemi anlayalım.

Ete

istinaf duvarı

Alıntı yapılan: ete - 18 Şubat 2024, 14:52:11İlişikte yazdığım programı veriyorum. Ekran görüntülerini ve işlemci ayarı vs hepsi ilgili dosyalarda gözüküyor.
Sİmulasyon dosyasını veremedim nedense kayıt etmedi. Ama sizin devre ve kendi dosyanızı benim ayarlarımla kullanabilirsiniz. İşlemci frekansı 48Mhz olmalı simulasyonda.

Ben pullup direnci bağladım RTC haberleşme hatlarına dahili pulluplar da kullanılabilir.

Deneyin bakalım simulasyondamı hata yoksa derleyicinizdemi anlayalım.

Ete


Sizinki çalışıyor. Ekrana saat datası geliyor.

CCS-C PLL çarpanını kendi otomatik ayarlıyor. 2550 serisi 20MHz kristalle 48MHz çalışabiliyor. Datasheette bu bilgi var.
Pull-Up dirençleri kadraj dışında kaldığından resimde çıkmadı. Dirençler bahsettiğim I2C LCD'nin yanındaydı.  Onları PIC'e yaklaştırdım yine aynı. 

PLL kullanmadan çarpanı 1:1 yapıp 20MHz çalıştırdım. Aynı sorun devam ediyor. PIC18F2455'i PIC18F2550 ile değiştirerek derleme yaptım. 2455  herkeste olmayabilir.

:1000000077EF02F0F76A140FF66E000EF722090080
:10001000F5501200280C0106202020496E697469F1
:100020006E672E2E2E20202000000C00C69E9E966D
:1000300014C0C9FF020EC6BE05D09EA6FED7000E94
:10004000C5BC010E016E1200C69CC586C5B6FED7A2
:1000500000B0C59A00A0C58AC588C5B8FED7C9CF6B
:1000600001F0120011C012F0D8901232780E121660
:100070001230006E00323F0E001600501224136E34
:1000800011500F0B1324016E120013C014F0156AE7
:100090001450090805E20A0E145E100E152603D04E
:1000A0001450152601D0F4D715C001F012000C6AC7
:1000B000C580C5B0FED7D00E146EB8DF146AB6DFA7
:1000C000C582C5B2FED7D10E146EB0DF006ABCDFA8
:1000D00001C00DF001C011F0C5DF01C00CF0C584F6
:1000E000C5B4FED70C9E040E006E002EFED700D0C5
:1000F000C580C5B0FED7D00E146E98DF146A96DFA7
:100100000CC013F0C2DF01C00DF001C014F08EDF8F
:10011000C582C5B2FED7D00E146E88DF070E146EEE
:1001200085DF800E146E82DFC584C5B4FED788EFEC
:1001300002F0129E3F0E1016C580C5B0FED7D00E3D
:10014000146E74DF146A72DF12C013F09EDF01C0F8
:1001500013F001C014F06ADF11C013F096DF01C084
:1001600013F001C014F062DF10C013F08EDF01C085
:1001700013F001C014F05ADF0FC013F086DF01C086
:1001800013F001C014F052DF0CC013F07EDF01C089
:1001900013F001C014F04ADF0DC013F076DF01C088
:1001A00013F001C014F042DF0EC013F06EDF01C087
:1001B00013F001C014F03ADF800E146E37DFC584EF
:1001C000C5B4FED797EF02F0EA6A130EE96EEF505E
:1001D0000DE0060E016E006A002EFED7012EFBD741
:1001E0007B0E006E002EFED7EF2EF3D712001AB052
:1001F00002D08B9801D08B8894981AB202D08B9A37
:1002000001D08B8A949A1AB402D08B9C01D08B8C2B
:10021000949C1AB602D08B9E01D08B8E949E0000C7
:100220008B809490020E006E002EFED700D000004E
:100230008B90949012001B6A9488000E82B8010E75
:100240001B12948A000E82BA010E006ED8900036FE
:1002500000501B12948C000E82BC010E006E003602
:100260000036FC0E001600501B12948E000E82BE4B
:10027000010E006E003600360036F80E00160050F3
:100280001B121BC001F012009488948A948C948EE7
:100290008B84949400008B8094900000CCDF01C08C
:1002A0001AF08B90949000008B80949000D000D036
:1002B0000000C1DF01C019F08B9094909498949A3B
:1002C000949C949E1A38006EF00E0016005019107F
:1002D000016E71EF01F09490949294948B929492A9
:1002E000D3D701C019F001BEFBD7175202E18B92A0
:1002F00001D08B82949200008B94949400008B9098
:1003000094901838196E0F0E191619C01AF06FDF75
:1003100018500F0B196E1A6E6ADF12009498949A97
:10032000949C949E9490949294948B9294928B9497
:1003300094948B9094900F0E136E46DF010E0C6E0A
:100340000C50030808E3030E1A6E51DF050E136EFE
:100350003BDF0C2AF5D7020E1A6E49DF050E136E2D
:1003600033DF0C6A0C5003080EE3036A0C50F2CF23
:100370000DF0F29E47DE0DBEF28E0D6E176A186EFE
:10038000AADF0C2AEFD798EF02F0142C01D003D08B
:10039000400E156E01D0156A010E135C152615501E
:1003A0008009166E176A186E96DF12001250070A3F
:1003B00007E00B0A0AE0060A10E0020A14E018D06F
:1003C000010E136E146EE1DF18D0176A010E186E5D
:1003D00082DF020E136EF8DE10D0010E136E020ED5
:1003E000146ED3DF0AD0176A100E186E74DF05D0B2
:1003F000010E176E12C018F06EDF12000900F552E0
:100400000CE0F6CF0CF0F7CF0DF0F5CF12F0CEDF09
:100410000CC0F6FF0DC0F7FFF1D712001350016AB0
:10042000125C03E212C000F00CD0006A080E146ED9
:10043000123600361350005CD8B0006E0136142E10
:10044000F7D71200200E0DA8300E0E6E0CC000F073
:100450000CAE08D0001E002A00C00CF02D0E0E6E4F
:100460000D8E0D8001500CC012F0640E136ED6DF9D
:1004700000C00CF0300E01240F6E0CC012F00A0EFA
:10048000136ECCDF300E0024116E300E0124106E7E
:100490000EC000F0300E0F5C04E00D820DBE0D8426
:1004A00012D00DB410D00EC00FF00DB204D0300E2B
:1004B000105C04E00D800DBE0D8205D0D8A40D8027
:1004C000D8B40FC010F00DB405D00DB206D00DB0E9
:1004D00007D009D00EC012F069DF0FC012F066DF3E
:1004E00010C012F063DF11C012F060DF1200F86A72
:1004F000D09E93829380310EC86E280EC66EC78E32
:10050000C79CC150C00B0F09C16E070EB46ECFD58A
:100510000F0E0C6E060E0D6E050E0E6E020E0F6E99
:100520000F0E106E140E116E370E126E02D6F6D626
:10053000180EF66E000EF76E61DF020E0C6EFA0EEC
:10054000136E42DE0C2EFBD72A0EF66E000EF76EEF
:1005500055DF040E0C6EFA0E136E36DE0C2EFBD732
:10056000C580C5B0FED7D00E146E60DD030E146ECC
:100570005DDDC582C5B2FED7D10E146E57DD010E0A
:10058000006E62DD01507F0B0C6E116E6BDD01C0E1
:100590000BF0010E006E58DD01503F0B0C6E116E1A
:1005A00061DD01C008F0010E006E4EDD01501F0B31
:1005B0000C6E116E57DD01C009F0006A45DD01C007
:1005C0000CF001C011F04EDD01C00AF0C584C5B4C5
:1005D000FED7C580C5B0FED7D00E146E27DD146AD5
:1005E00025DDC582C5B2FED7D10E146E1FDD010E0A
:1005F000006E2ADD01507F0B0C6E116E33DD01C0E1
:1006000005F0010E006E20DD01507F0B0C6E116EA7
:1006100029DD01C006F0006A17DD01503F0B0C6EAA
:10062000116E20DD01C007F0C584C5B4FED7006A95
:100630000BDD0C0E126EBADE08C00CF0010E0D6E52
:1006400001DF2F0E126EB2DE09C00CF0010E0D6E2E
:10065000F9DE2F0E126EAADE0AC00CF0010E0D6E2E
:10066000F1DE0D0E126EA2DE0A0E126E9FDE07C0C4
:100670000CF0010E0D6EE6DE3A0E126E97DE06C02D
:100680000CF0010E0D6EDEDE3A0E126E8FDE05C02E
:0C0690000CF0010E0D6ED6DE5CD70300EE
:020000040030CA
:0E00000004CC380E008781000FC00FE00F40C7
:00000001FF
;PIC18F2550
;CRC=A0AA  CREATED="18-Şub-24 15:33"

ete

Data sheet den benim anladığım şöyle. Bu işlemcide ki PLL yi aktif ettiğin zaman 4Mhz OSC frekansından sabit 96Mhz elde ediyor.
Bu nedenle kullandığın kristale bağlı olarak işlemciye 4Mhz gitmesini PLL_Presecaler ile ayarlaman gerekiyor. Dİyelimki 20Mhz Kristal kullandın. Bu durumda 4Mhz elde etmen için onu 5'e bölmen gerekir ki bunun için Config ayrlarında;
_PLLDIV_5_1L         EQU  H'FC'; Divide by 5 (20 MHz oscillator input) seçeneği seçilmeli.
Kısaca presclaer seçimi kullandığın kristalden 4 Mhz elde etmek için kaça bölümnmesi gerektiğini belirliyor.
Birde Postscaler var ki oda 96Mhz PLL frekasnından işlemciye hangi frekansı vereceksin onu belirliyor. 48 Mhz olsun diyorsan bu durumda ;
_CPUDIV_OSC2_PLL3_1L EQU  H'EF'; [Primary Oscillator Src: /2][96 MHz PLL Src: /3]
seçeneği seçilerek 96Mhz/2=48 Mhz elde etmiş oluyorsun.

Bu seçenekler tabiiki gerçek devrede etkin olacak. Simulasyonda ekrandaki işlemci frekansını  48Mhz (Manuel)olarak belirlediğimiz için bunların bize etkisi olmuyor.

Buda gösteriyorki asıl sorunun config yada işlemci frekansı değil. Bana kalırsa sürücü üzerine odaklan. O sürücü üniversalmidir yani yeni nesil işlemcilerde LATX registeri devreye giriyor eskilerde bu yok. Eskilere göre yazılmış ise sorun olacaktır.

Dikkatimi çeken bir başka husus da senin devrende resimden görüldüğü kadarı ile DS1307 nin SDA hattı HIGH da SCL hattı ise LOW da gözüküyor. Benim devrede her ikisi HIGH da gözüküyor. SCL elbette arada bir LOW oluyordur ama beklemede HIGH da kalıyor. Sende yine pullup sorunu var gibi geliyor bana.

Ete

istinaf duvarı

#7
Alıntı yapılan: ete - 18 Şubat 2024, 18:25:21Data sheet den benim anladığım şöyle. Bu işlemcide ki PLL yi aktif ettiğin zaman 4Mhz OSC frekansından sabit 96Mhz elde ediyor.
Bu nedenle kullandığın kristale bağlı olarak işlemciye 4Mhz gitmesini PLL_Presecaler ile ayarlaman gerekiyor. Dİyelimki 20Mhz Kristal kullandın. Bu durumda 4Mhz elde etmen için onu 5'e bölmen gerekir ki bunun için Config ayrlarında;
_PLLDIV_5_1L         EQU  H'FC'; Divide by 5 (20 MHz oscillator input) seçeneği seçilmeli.
Kısaca presclaer seçimi kullandığın kristalden 4 Mhz elde etmek için kaça bölümnmesi gerektiğini belirliyor.
Birde Postscaler var ki oda 96Mhz PLL frekasnından işlemciye hangi frekansı vereceksin onu belirliyor. 48 Mhz olsun diyorsan bu durumda ;
_CPUDIV_OSC2_PLL3_1L EQU  H'EF'; [Primary Oscillator Src: /2][96 MHz PLL Src: /3]
seçeneği seçilerek 96Mhz/2=48 Mhz elde etmiş oluyorsun.

Bu seçenekler tabiiki gerçek devrede etkin olacak. Simulasyonda ekrandaki işlemci frekansını  48Mhz (Manuel)olarak belirlediğimiz için bunların bize etkisi olmuyor.

Buda gösteriyorki asıl sorunun config yada işlemci frekansı değil. Bana kalırsa sürücü üzerine odaklan. O sürücü üniversalmidir yani yeni nesil işlemcilerde LATX registeri devreye giriyor eskilerde bu yok. Eskilere göre yazılmış ise sorun olacaktır.

Dikkatimi çeken bir başka husus da senin devrende resimden görüldüğü kadarı ile DS1307 nin SDA hattı HIGH da SCL hattı ise LOW da gözüküyor. Benim devrede her ikisi HIGH da gözüküyor. SCL elbette arada bir LOW oluyordur ama beklemede HIGH da kalıyor. Sende yine pullup sorunu var gibi geliyor bana.

Ete


Evet sürücüyü inceleyeyim.

CCS, seçilen kristal ve istenen saat frekansina göre prescalar ve postscalar değerlerini otomatik ayarlıyor. Elimdeki PIC18F2455 ile  Led yakıp söndürme devresi üzerinde kronometre ile ledin yanma sönme zamanını ölçerek bunun testini yaptım.

istinaf duvarı

Başka bir tane sürücü buldum. Onu inceledim. İ2c için Ds1307_stream diye bir akış tanımlamışlar. Bu şekilde çalışıyor. Ama anladığım kadarıyla bu sefer İ2c portunu sadece RTC kullanabiliyor. Aynı porta başka cihaz bağlayamıyoruz.

ete

Stream dediğin sistem mutlaka I2C hattı çok meşgul ediyordur yada çok sık okuma yapıyordur o yüzden kullanamıyorsundur. Yoksa I2C nin tekniğine aykırı bu söylediklerin.
ete

istinaf duvarı

#10
Alıntı yapılan: ete - 21 Şubat 2024, 18:55:17Stream dediğin sistem mutlaka I2C hattı çok meşgul ediyordur yada çok sık okuma yapıyordur o yüzden kullanamıyorsundur. Yoksa I2C nin tekniğine aykırı bu söylediklerin.
ete

Sürücüyü caliştırırken
#use I2C(MASTER, I2C1, SLOW = 100000, STREAM = DS1307_STREAM) şeklinde tanımlama yapılmış.

I2c'de stream parametresinin ne işe yaradığı konusunda pek bir kaynak bulamadım.

///////////////////////////////////////////////////////////////////////////
////                                                                   ////
////                             DS1307.c                              ////
////                                                                   ////
////                      Driver for CCS C compiler                    ////
////                                                                   ////
////     Driver for Maxim DS1307 serial I2C real-time clock (RTC).     ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
////                     https://simple-circuit.com/                   ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////


#if defined DS1307_I2C_NO_STREAM
  #define RTC_I2C_START()   i2c_start()
  #define RTC_I2C_STOP()    i2c_stop()
  #define RTC_I2C_WRITE(x)  i2c_write(x)
  #define RTC_I2C_READ(x)   i2c_read(x)
#elif defined DS1307_I2C_STREAM
  #define RTC_I2C_START()   i2c_start(DS1307_I2C_STREAM)
  #define RTC_I2C_STOP()    i2c_stop(DS1307_I2C_STREAM)
  #define RTC_I2C_WRITE(x)  i2c_write(DS1307_I2C_STREAM, x)
  #define RTC_I2C_READ(x)   i2c_read(DS1307_I2C_STREAM, x)
#else
  #define RTC_I2C_START()   i2c_start(DS1307_STREAM)
  #define RTC_I2C_STOP()    i2c_stop(DS1307_STREAM)
  #define RTC_I2C_WRITE(x)  i2c_write(DS1307_STREAM, x)
  #define RTC_I2C_READ(x)   i2c_read(DS1307_STREAM, x)
#endif

#include <stdint.h>

#define DS1307_ADDRESS      0xD0
#define DS1307_REG_SECONDS  0x00
#define DS1307_REG_CONTROL  0x07

enum SQWE
{
  OUT_OFF = 0x00,
  OUT_ON  = 0x80,
  OUT_1Hz = 0x10,
  OUT_4096Hz  = 0x11,
  OUT_8192Hz  = 0x12,
  OUT_32768Hz = 0x13
};

typedef enum
{
  SUNDAY = 1,
  MONDAY,
  TUESDAY,
  WEDNESDAY,
  THURSDAY,
  FRIDAY,
  SATURDAY
} RTC_DOW;

typedef enum
{
  JANUARY = 1,
  FEBRUARY,
  MARCH,
  APRIL,
  MAY,
  JUNE,
  JULY,
  AUGUST,
  SEPTEMBER,
  OCTOBER,
  NOVEMBER,
  DECEMBER
} RTC_Month;

typedef struct rtc_tm
{
  uint8_t seconds;
  uint8_t minutes;
  uint8_t hours;
  RTC_DOW dow;
  uint8_t day;
  RTC_Month month;
  uint8_t year;
} RTC_Time;

///////////////////////// All Functions /////////////////////////
                                                               //
uint8_t bcd_to_decimal(uint8_t number);                        //
uint8_t decimal_to_bcd(uint8_t number);                        //
void RTC_Set(RTC_Time *time_t);                                //
RTC_Time *RTC_Get();                                           //
void OSC_Enable();                                             //
void OSC_Disable();                                            //
uint8_t RTC_Read_Reg(uint8_t reg_address);                     //
void RTC_Write_Reg(uint8_t reg_address, uint8_t reg_value);    //
void SQWE_Set(SQWE pin_out);                                   //
                                                               //
/////////////////////////////////////////////////////////////////

// converts BCD to decimal
uint8_t bcd_to_decimal(uint8_t number)
{
  return ( (number >> 4) * 10 + (number & 0x0F) );
}

// converts decimal to BCD
uint8_t decimal_to_bcd(uint8_t number)
{
  return ( ((number / 10) << 4) + (number % 10) );
}

// sets time and date
void RTC_Set(RTC_Time *time_t)
{
  uint8_t sec_reg = RTC_Read_Reg(DS1307_REG_SECONDS);

  // convert decimal to BCD
  time_t->day     = decimal_to_bcd(time_t->day);
  time_t->month   = decimal_to_bcd(time_t->month);
  time_t->year    = decimal_to_bcd(time_t->year);
  time_t->hours   = decimal_to_bcd(time_t->hours);
  time_t->minutes = decimal_to_bcd(time_t->minutes);
  time_t->seconds = decimal_to_bcd(time_t->seconds);
  // end conversion
  
  // test if oscillator is disabled (CH bit = 1)
  if(sec_reg & 0x80)
    time_t->seconds |= 0x80;

  // write data to the RTC chip
  RTC_I2C_START();
  RTC_I2C_WRITE(DS1307_ADDRESS);
  RTC_I2C_WRITE(DS1307_REG_SECONDS);
  RTC_I2C_WRITE(time_t->seconds);
  RTC_I2C_WRITE(time_t->minutes);
  RTC_I2C_WRITE(time_t->hours);
  RTC_I2C_WRITE(time_t->dow);
  RTC_I2C_WRITE(time_t->day);
  RTC_I2C_WRITE(time_t->month);
  RTC_I2C_WRITE(time_t->year);
  RTC_I2C_STOP();
}

RTC_Time c_time;

// reads time and date
RTC_Time *RTC_Get()
{
  RTC_I2C_START();
  RTC_I2C_WRITE(DS1307_ADDRESS);
  RTC_I2C_WRITE(DS1307_REG_SECONDS);
  RTC_I2C_START();
  RTC_I2C_WRITE(DS1307_ADDRESS | 0x01);
  c_time.seconds = RTC_I2C_READ(1) & 0x7F;
  c_time.minutes = RTC_I2C_READ(1);
  c_time.hours   = RTC_I2C_READ(1);
  c_time.dow   = RTC_I2C_READ(1);
  c_time.day   = RTC_I2C_READ(1);
  c_time.month = RTC_I2C_READ(1);
  c_time.year  = RTC_I2C_READ(0);
  RTC_I2C_STOP();

  // convert BCD to decimal
  c_time.seconds = bcd_to_decimal(c_time.seconds);
  c_time.minutes = bcd_to_decimal(c_time.minutes);
  c_time.hours   = bcd_to_decimal(c_time.hours);
  c_time.day     = bcd_to_decimal(c_time.day);
  c_time.month   = bcd_to_decimal(c_time.month);
  c_time.year    = bcd_to_decimal(c_time.year);
  // end conversion

  return &c_time;
}

// writes 'reg_value' to register of address 'reg_address'
void RTC_Write_Reg(uint8_t reg_address, uint8_t reg_value)
{
  RTC_I2C_START();
  RTC_I2C_WRITE(DS1307_ADDRESS);
  RTC_I2C_WRITE(reg_address);
  RTC_I2C_WRITE(reg_value);
  RTC_I2C_STOP();
}

// returns the value stored in register of address 'reg_address'
uint8_t RTC_Read_Reg(uint8_t reg_address)
{
  uint8_t reg_data;

  RTC_I2C_START();
  RTC_I2C_WRITE(DS1307_ADDRESS);
  RTC_I2C_WRITE(reg_address);
  RTC_I2C_START();
  RTC_I2C_WRITE(DS1307_ADDRESS | 0x01);
  reg_data = RTC_I2C_READ(0);
  RTC_I2C_STOP();

  return reg_data;
}

// sets SQWE pin output
void SQWE_Set(SQWE pin_out)
{
  RTC_I2C_START();
  RTC_I2C_WRITE(DS1307_ADDRESS);
  RTC_I2C_WRITE(DS1307_REG_CONTROL);
  RTC_I2C_WRITE(pin_out);
  RTC_I2C_STOP();
}

// enables RTC oscillator
void OSC_Enable()
{
  uint8_t sec_reg = RTC_Read_Reg(DS1307_REG_SECONDS);
  sec_reg &= 0x7F;
  RTC_Write_Reg(DS1307_REG_SECONDS, sec_reg);
}

// disables RTC oscillator
void OSC_Disable()
{
  uint8_t sec_reg = RTC_Read_Reg(DS1307_REG_SECONDS);
  sec_reg |= 0x80;
  RTC_Write_Reg(DS1307_REG_SECONDS, sec_reg);
}

/*
 * Interfacing PIC16F877A microcontroller with DS1307 RTC.
 * C Code for CCS C compiler.
 * Time and date are displayed on 16x2 LCD.
 * This is a free software with NO WARRANTY.
 * https://simple-circuit.com/
 */

// LCD module connections
#define LCD_RS_PIN      PIN_D0
#define LCD_RW_PIN      PIN_D1
#define LCD_ENABLE_PIN  PIN_D2
#define LCD_DATA4       PIN_D3
#define LCD_DATA5       PIN_D4
#define LCD_DATA6       PIN_D5
#define LCD_DATA7       PIN_D6
// end LCD module connections

#include <16F877A.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP                       
#use delay(clock = 8MHz)
#use I2C(MASTER, I2C1, SLOW = 100000, STREAM = DS1307_STREAM)
#include <lcd.c>     // include LCD driver source file
#include <DS1307.c>  // include DS1307 driver source file

// DS1307 library variable declaration
RTC_Time *mytime;

// function for printing time and date on LCD
void rtc_print()
{
  // print time
  lcd_gotoxy(1, 1);
  printf(lcd_putc, "TIME: %02u:%02u:%02u", mytime->hours, mytime->minutes, mytime->seconds);
  // print date
  lcd_gotoxy(1, 2);
  printf(lcd_putc, "DATE: %02u/%02u/20%02u", mytime->day, mytime->month, mytime->year);
}

// main function
void main()
{
  delay_ms(1000);  // wait a second
  lcd_init();
  lcd_putc('\f');

  // read current time and date from the RTC chip
  mytime = RTC_Get();
  // print them
  rtc_print();

  delay_ms(1000);  // wait a second

  // set RTC time to 15:43:12 (hh:mm:ss) and date to 25-12-18 (dd-mm-yy)
  mytime->hours   = 15;
  mytime->minutes = 43;
  mytime->seconds = 12;
  mytime->day   = 25;
  mytime->month = 12;
  mytime->year  = 18;
  // write time and date to the RTC chip
  RTC_Set(mytime);

  // enable RTC oscillator
  OSC_Enable();

  // enable SQWE output with frequency of 1Hz
  SQWE_Set(OUT_1Hz);

  while(TRUE)
  {
    // read current time and date from the RTC chip
    mytime = RTC_Get();
    // print them
    rtc_print();

    delay_ms(100);  // wait 100 ms

  }

}
// end of code.

istinaf duvarı

Çalıştı. Dün bulduğum sürücü işe yarıyor.
Stream, LCD'ye engel çıkarmadı. Hata LCD'nin adresini yanlış girmekten kaynaklı çıktı.
Aynı porttan LCD ve RTC'yi sürmeyi başardım.

ete

Stream bir tabir olsa gerek. Anlamı parça parça bilgi akışı sağlanacak anlamına geliyor sanırım.
Normalde RTC de bir sürü okunacak yada yazılacak register var (SN - DAK - SAAT - HAFTANIN_GUNU - AYIN_GUNU - AY - YIL ) ancak normal çalışma anında yalnızca bir kaçını okumak gerekiyor ve özellikle SN registeri sürekli okunmak zorunda. Sanırım stream konusu bununla ilgili bir terim olsa gerek. I2C_Stream diye aratınca bir şey bulunamıyor ama yalnızca Stream diye aratınca bir şeyler çıkıyor alakalı alakasız. En alakalısını aşağıdaki linkte gördüm.
https://www.cihanyakar.com/streamkavrami/

Sonuçta ilk sürücü bir şekilde hata yapıyordu ama ne olduğunu bilemiyoruz ama ikincisinin çalıştığına sevindim. Kolay gelsin.

Ete

Powered by EzPortal