Teman-teman dari Jam Real-Time PCF8563 dari Arduino ke I2C

Hai, Habr. Saya kebetulan menggunakan RTC pada chip PCF 8563 menggunakan I2C, karena saya tidak menemukan fungsi normal untuk pekerjaan yang lebih nyaman dengan Arduino, saya harus bekerja secara langsung melalui I2C. Saya menemukan tutorial penjelasan di Internet Bahasa Inggris dengan deskripsi terperinci tentang prosesnya . Artikel ini sebagian merupakan terjemahan dari sebagian pengalamannya sendiri dengan RTC ini.



Tetapkan tanggal dan waktu


Hal pertama yang kami naiki ke manual ( ada di sini ) dan mencari daftar organisasi mendaftar di sana.



Untuk mengatur tanggal dan waktu, kita perlu register dari 02h hingga 08h. Data dalam register ini disimpan dalam format desimal biner (BCD), oleh karena itu, untuk merekam detik, menit, dll. pertama kita mengimplementasikan fungsi terjemahan (dari format desimal ke BCD dan sebaliknya) dan kemudian dengan perintah Wire.write () kita menuliskannya dalam register mulai dari 02h. Kami membaca dengan cara yang sama, mentransfer dari BCD kembali ke sistem desimal, mulai dari register 02h yang sama. Seperti yang dapat Anda lihat dari tabel, bit tidak digunakan di beberapa register (ditunjukkan oleh huruf x), agar tidak membebani informasi saat membaca, kami akan menggunakan operasi bitwise AND (logis "DAN") yang akan mengatur ulang bit yang tidak kami butuhkan. Sebagai contoh, hari-hari dalam sebulan (Days), kita membutuhkan bit 0 hingga 5, menggunakan operasi (dayOfMonth & B00111111) kita mereset 6 dan 7 bit, semua yang lain tetap tidak tersentuh.

Langsung kode itu sendiri dengan output informasi pada monitor serial:

#include "Wire.h" #define PCF8563address 0x51 //     byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; String days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; //     -    . byte bcdToDec(byte value) { return ((value / 16) * 10 + value % 16); } //   byte decToBcd(byte value){ return (value / 10 * 16 + value % 10); } //       PCF8563 void setPCF8563() { Wire.beginTransmission(PCF8563address); Wire.write(0x02); Wire.write(decToBcd(second)); Wire.write(decToBcd(minute)); Wire.write(decToBcd(hour)); Wire.write(decToBcd(dayOfMonth)); Wire.write(decToBcd(dayOfWeek)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.endTransmission(); } //       PCF8563 void readPCF8563() { Wire.beginTransmission(PCF8563address); Wire.write(0x02); Wire.endTransmission(); Wire.requestFrom(PCF8563address, 7); second = bcdToDec(Wire.read() & B01111111); //      minute = bcdToDec(Wire.read() & B01111111); hour = bcdToDec(Wire.read() & B00111111); dayOfMonth = bcdToDec(Wire.read() & B00111111); dayOfWeek = bcdToDec(Wire.read() & B00000111); month = bcdToDec(Wire.read() & B00011111); year = bcdToDec(Wire.read()); } void setup() { Wire.begin(); Serial.begin(9600); //     second = 0; minute = 28; hour = 9; dayOfWeek = 2; dayOfMonth = 13; month = 8; year = 13; setPCF8563(); } void loop() { readPCF8563(); Serial.print(days[dayOfWeek]); Serial.print(" "); Serial.print(dayOfMonth, DEC); Serial.print("/"); Serial.print(month, DEC); Serial.print("/20"); Serial.print(year, DEC); Serial.print(" - "); Serial.print(hour, DEC); Serial.print(":"); if (minute < 10) { Serial.print("0"); } Serial.print(minute, DEC); Serial.print(":"); if (second < 10) { Serial.print("0"); } Serial.println(second, DEC); delay(1000); } 


Mengatur alarm


Dalam PCF 8563, Anda dapat mengaktifkan alarm dan mengaturnya untuk waktu tertentu, hari dalam seminggu atau sebulan. Pengaturan alarm terletak di register dari 09h ke 0h dalam format desimal biner.



Untuk mengaktifkan alarm dengan beberapa pengaturan, misalnya, menit dan jam, Anda perlu mengatur bit ke-7 (memungkinkan bit) menjadi satu. Untuk ini, gunakan operasi logis OR (OR) dan nilai B10000000.

Memeriksa pengoperasian alarm dapat dilakukan dengan 2 cara: keras dan lunak. Menggunakan metode lunak, kami memeriksa bit ke-3 dari register 0x01 (bit bendera alarm AF). Ketika dipicu, itu sama dengan satu, mengaturnya ke 0, alarm berbunyi.



Untuk verifikasi yang sulit, Anda perlu menerjemahkan 1 bit dalam register yang sama (AIE) menjadi satu. Ketika alarm berbunyi, pin INT (interrupt) di papan masuk ke posisi penghantar, menjadi keluaran saluran terbuka, jadi Anda dapat dengan aman menyolder LED dengan resistor, misalnya, dan menghubungkan semuanya ke 5 volt.

Sekarang sketsa itu sendiri:

daftar
 #include "Wire.h" #define PCF8563address 0x51 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; byte alarmMinute, alarmHour, alarmDay, alarmDayOfWeek; String days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; byte bcdToDec(byte value) { return ((value / 16) * 10 + value % 16); } byte decToBcd(byte value){ return (value / 10 * 16 + value % 10); } //        void setPCF8563alarm() { byte am, ah, ad, adow; am = decToBcd(alarmMinute); am = am | 100000000; //       ah = decToBcd(alarmHour); ah = ah | 100000000; //       ad = decToBcd(alarmDay); ad = ad | 100000000; //        adow = decToBcd(alarmDayOfWeek); adow = ad | 100000000; //       //        PCF8563 Wire.beginTransmission(PCF8563address); Wire.write(0x09); Wire.write(am); Wire.write(ah); // .         /* Wire.write(ad); Wire.write(adow); */ Wire.endTransmission(); //  .  INT     //     PCF8563alarmOff() Wire.beginTransmission(PCF8563address); Wire.write(0x01); Wire.write(B00000010); Wire.endTransmission(); } void PCF8563alarmOff() //      . { byte test; //    0x01h Wire.beginTransmission(PCF8563address); Wire.write(0x01); Wire.endTransmission(); Wire.requestFrom(PCF8563address, 1); test = Wire.read(); //  3    0 test = test - B00001000; //      0x01h Wire.beginTransmission(PCF8563address); Wire.write(0x01); Wire.write(test); Wire.endTransmission(); } void checkPCF8563alarm() //    { byte test; //    0x01h     test Wire.beginTransmission(PCF8563address); Wire.write(0x01); Wire.endTransmission(); Wire.requestFrom(PCF8563address, 1); test = Wire.read(); test = test & B00001000; if (test == B00001000) //    { Serial.println("** alarm **"); delay(2000); //     PCF8563alarmOff(); } } void setPCF8563() { Wire.beginTransmission(PCF8563address); Wire.write(0x02); Wire.write(decToBcd(second)); Wire.write(decToBcd(minute)); Wire.write(decToBcd(hour)); Wire.write(decToBcd(dayOfMonth)); Wire.write(decToBcd(dayOfWeek)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.endTransmission(); } void readPCF8563() { Wire.beginTransmission(PCF8563address); Wire.write(0x02); Wire.endTransmission(); Wire.requestFrom(PCF8563address, 7); second = bcdToDec(Wire.read() & B01111111); minute = bcdToDec(Wire.read() & B01111111); hour = bcdToDec(Wire.read() & B00111111); dayOfMonth = bcdToDec(Wire.read() & B00111111); dayOfWeek = bcdToDec(Wire.read() & B00000111); month = bcdToDec(Wire.read() & B00011111); year = bcdToDec(Wire.read()); } void setup() { Wire.begin(); Serial.begin(9600); second = 50; minute = 44; hour = 13; dayOfWeek = 1; dayOfMonth = 19; month = 8; year = 13; setPCF8563(); //       alarmMinute = 45; alarmHour = 13; setPCF8563alarm(); } void loop() { readPCF8563(); Serial.print(days[dayOfWeek]); Serial.print(" "); Serial.print(dayOfMonth, DEC); Serial.print("/"); Serial.print(month, DEC); Serial.print("/20"); Serial.print(year, DEC); Serial.print(" - "); Serial.print(hour, DEC); Serial.print(":"); if (minute < 10) { Serial.print("0"); } Serial.print(minute, DEC); Serial.print(":"); if (second < 10) { Serial.print("0"); } Serial.println(second, DEC); delay(1000); //  checkPCF8563alarm(); } 


Gunakan sebagai generator


Seperti banyak RTC, PCF8563 dapat digunakan sebagai generator sinyal. Pin COT (pin 7 dari rangkaian mikro) adalah saluran terbuka, sehingga Anda dapat mengedipkan LED melalui pin ini dengan frekuensi yang berbeda. Daftar 0x0D sesuai dengan parameter frekuensi.



Bit ketujuh register ini (FE) menyalakan generator. Bit 0 dan 1 mengatur frekuensi yang diinginkan. Bit 6 hingga 2 tidak digunakan.

Menulis nilai-nilai berikut ke dalam register, Anda bisa mendapatkan frekuensi yang diinginkan:

  • 10000000 - 32.768 kHz;
  • 10000001 - 1.024 kHz;
  • 10000010 - 32 Hz;
  • 10000011 - 1 Hz;
  • 0 - nonaktifkan output;

Contoh sketsa:

 #include "Wire.h" #define PCF8563address 0x51 void PCF8563oscOFF() //   { Wire.beginTransmission(PCF8563address); Wire.write(0x0D); Wire.write(0); Wire.endTransmission(); } void PCF8563osc1Hz() //    1 Hz { Wire.beginTransmission(PCF8563address); Wire.write(0x0D); Wire.write(B10000011); Wire.endTransmission(); } void PCF8563osc32Hz() //    32 Hz { Wire.beginTransmission(PCF8563address); Wire.write(0x0D); Wire.write(B10000010); Wire.endTransmission(); } void PCF8563osc1024kHz() //    1.024 kHz { Wire.beginTransmission(PCF8563address); Wire.write(0x0D); Wire.write(B10000001); Wire.endTransmission(); } void PCF8563osc32768kHz() //    32.768 kHz { Wire.beginTransmission(PCF8563address); Wire.write(0x0D); Wire.write(B10000000); Wire.endTransmission(); } void setup() { Wire.begin(); } void loop() { PCF8563osc1Hz(); delay(2000); PCF8563osc32Hz(); delay(2000); PCF8563osc1024kHz(); delay(2000); PCF8563osc32768kHz(); delay(2000); PCF8563oscOFF(); delay(2000); } 


Contoh bentuk gelombang yang diambil dari LED

1 Hz



32 Hz



1,024 kHz



32,768 kHz

Source: https://habr.com/ru/post/id463265/


All Articles