日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

树莓派——实时时钟模块(RTC)

發布時間:2023/12/10 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 树莓派——实时时钟模块(RTC) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 RTC介紹

樹莓派為了節約成本以及減小體積,沒有板載的實時時鐘(real-time clock,RTC),或者叫作硬件時鐘。
在某些場合下,如果樹莓派無法聯網,但是它上面運行的程序又和時間緊密相關,要求系統時間是正確的,在這種情況下,我們就可以為樹莓派添加一個外部的RTC,使之重啟之后也能保持時間正確。
此實驗以DS1302為例

2 DS1302

2.1 模塊簡介

DS1302模塊自帶一塊CR2032紐扣電池,電池使用時間至少應該有一年以上。
DS1302與單片機之間能簡單地采用同步串行的方式進行通信,僅需用到三個口線:

  • RST復位
  • I/O數據線
  • SCLK串行時鐘
    DS1302工作時功耗很低保持數據和時鐘信息時功率小于1mW。

2.2 模塊參數

  • PCB為單面板,尺寸:44mm23mm1.6mm;
  • 帶4個定位孔,直徑3.1mm;
  • 備用電池為正品天球CR2032,電壓3V,電流260mAh,非可充電電池。理論數據保持時間大于10年;
  • 晶振32.768KHz,日本原裝進口晶振,匹配電容為6pF,尺寸2*6mm;
  • DS1302為8腳直插國產大芯片,芯片下面有IC座,方便更換及插拔芯片;
  • 模塊工作電壓兼容3.3V/5V,可與5V及3.3V單片機連接;
  • 工作溫度:0°—70°。

2.3 接線

DS1302樹莓派wiringPi引腳編號
VCC3.3V輸出3.3V輸出
GNDGround(地)Ground(地)
CLKSCLK14
DATSDA030
RSTCEO10

2.4 寄存器簡介

讀寄存器地址:81h~8Dh
寫寄存器地址:80h~8Ch

2.5 控制字簡介

3 代碼塊

通過對寄存器的操作來讀寫時間,代碼(參考wiringPi自帶示例代碼)如下:

#include<stdio.h> #include<stdlib.h> #include<stdint.h> #include<string.h> #include<time.h>#include<wiringPi.h>//---------------------------------------------------#define RTC_SECS 0 #define RTC_MINS 1 #define RTC_HOURS 2 #define RTC_DATE 3 #define RTC_MONTH 4 #define RTC_DAY 5 #define RTC_YEAR 6 #define RTC_WP 7 #define RTC_TC 8 #define RTC_BM 31static int dPin, cPin, sPin; static unsigned int masks[] = { 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x07, 0xFF }; /*0x7F 011111110x3F 001111110x1F 000111110x07 000001110xFF 11111111 *///--------------------------------------------------- void ds1302Setup(const int clockPin, const int dataPin, const int csPin); void ds1302rtcWrite(int reg, unsigned int data); void ds1302regWrite(const int reg, const unsigned int data); void dsShiftOut(unsigned int data); int setLinuxClock(); void ds1302clockRead(int clockdata[8]); int dsShiftIn(); int bcdToD(unsigned int byte, unsigned int mask); int setDSClock(); int dToBcd(int tmp); void ds1302clockWrite(int clock[8]);int main(int argc, char *argv[]) {int i;int clock[8];wiringPiSetup();ds1302Setup(14, 30, 10);if (argc == 2) {if (strcmp(argv[1], "-slc") == 0) {return setLinuxClock();//讀取DS1302內的時間來設置Linux的時間}else if (strcmp(argv[1], "-sdsc") == 0) {return setDSClock();//讀取Linux的時間來設置DS1302的時間}/*else if (strcmp(argv[1], "-rtest") == 0) {return ramtest();//進行ram測試,此處因為當時覺得沒必要所以沒有寫,具體可以參考wiringPi示例程序}*/else {printf("Usage: ds1302 [-slc | -sdsc | -rtest]\n");return EXIT_FAILURE;}}i = 0;while (true) {printf("%5d: ", i);ds1302clockRead(clock);//讀取DS1302內的時間//由于DS1302內的數據是BCD編碼,所以需要轉化為十進制后才能輸出printf(" %2d:%02d:%02d", bcdToD(clock[2], masks[2]), bcdToD(clock[1], masks[1]), bcdToD(clock[0], masks[0]));printf(" %2d/%02d/%04d", bcdToD(clock[3], masks[3]), bcdToD(clock[4], masks[4]), bcdToD(clock[6], masks[6]) + 2000);printf("\n");delay(200);i++;}return 0; }void ds1302Setup(const int clockPin, const int dataPin, const int csPin) {dPin = dataPin;//30cPin = clockPin;//14sPin = csPin;//10digitalWrite(dPin, LOW);digitalWrite(cPin, LOW);digitalWrite(sPin, LOW);pinMode(dPin, OUTPUT);pinMode(cPin, OUTPUT);pinMode(sPin, OUTPUT);ds1302rtcWrite(RTC_WP, 0);//關閉寫保護 }void ds1302rtcWrite(int reg, unsigned int data) {ds1302regWrite(0x80 | ((reg & 0x1f) << 1), data);//將reg轉化為寫寄存器的實際地址 }void ds1302regWrite(const int reg, const unsigned int data) {digitalWrite(sPin, HIGH);delayMicroseconds(1);dsShiftOut(reg);dsShiftOut(data);digitalWrite(sPin, LOW);delayMicroseconds(1); }void dsShiftOut(unsigned int data) {pinMode(dPin, OUTPUT);for (int i = 0; i < 8; i++) {digitalWrite(dPin, (data&(1 << i))); delayMicroseconds(1);//LSB優先,從低位開始傳輸digitalWrite(cPin, HIGH); delayMicroseconds(1);digitalWrite(cPin, LOW); delayMicroseconds(1);} }int setLinuxClock() {char dateTime[20];char command[64];int clock[8];printf("Setting the Linux Clock from the DS1302... ");fflush(stdout);//沖洗流中的信息ds1302clockRead(clock);// [MMDDhhmm[[CC]YY][.ss]]// 輸出格式sprintf(dateTime, "%02d%02d%02d%02d%02d%02d.%02d",bcdToD(clock[RTC_MONTH], masks[RTC_MONTH]),bcdToD(clock[RTC_DATE], masks[RTC_DATE]),bcdToD(clock[RTC_HOURS], masks[RTC_HOURS]),bcdToD(clock[RTC_MINS], masks[RTC_MINS]),20,bcdToD(clock[RTC_YEAR], masks[RTC_YEAR]),bcdToD(clock[RTC_SECS], masks[RTC_SECS]));sprintf(command, "/bin/date %s", dateTime);//字符串格式化system(command);//向Linux輸出命令return 0; }void ds1302clockRead(int clockdata[8]) {int i;unsigned int regVal = 0x81 | ((RTC_BM & 0x1F) << 1);digitalWrite(sPin, HIGH); delayMicroseconds(1);dsShiftOut(regVal);//控制字for (i = 0; i < 8; i++) {clockdata[i] = dsShiftIn();//讀取時鐘數據//printf("%d %d\n", i, clockdata[i]);}digitalWrite(sPin, LOW); delayMicroseconds(1); }int dsShiftIn() {uint8_t value = 0;pinMode(dPin, INPUT);delayMicroseconds(1);for (int i = 0; i < 8; i++) {value |= (digitalRead(dPin) << i);digitalWrite(cPin, HIGH); delayMicroseconds(1);digitalWrite(cPin, LOW); delayMicroseconds(1);}return value; }int bcdToD(unsigned int byte, unsigned int mask) {byte &= mask;int b1 = (byte & 0xF0) >> 4;//取高四位作為十進制的十位數int b2 = byte & 0x0F;//取低四位作為十進制的個位數return b1 * 10 + b2; }int setDSClock() {struct tm t;//Linux時間結構體time_t now;int clock[8];printf("Setting the clock in the DS1302 from Linux time... ");now = time(NULL);//取得當前時間UTC秒數,無時區轉換gmtime_r(&now, &t);//獲取當前時間結構,UTC時間,無時區轉換//DS1302內數據采用BCD編碼,故需轉化clock[0] = dToBcd(t.tm_sec); // secondsclock[1] = dToBcd(t.tm_min); // minsclock[2] = dToBcd(t.tm_hour); // hoursclock[3] = dToBcd(t.tm_mday); // dateclock[4] = dToBcd(t.tm_mon + 1); // months 0-11 --> 1-12clock[5] = dToBcd(t.tm_wday + 1); // weekdays (sun 0)clock[6] = dToBcd(t.tm_year - 100); // yearsclock[7] = 0; // W-Protect offds1302clockWrite(clock);printf("OK\n");return 0; }int dToBcd(int tmp) {return ((tmp / 10) << 4) + tmp % 10; }void ds1302clockWrite(int clock[8]) {unsigned int regVal = 0x80 | ((RTC_BM & 0x1f) << 1);digitalWrite(sPin, HIGH); delayMicroseconds(1);dsShiftOut(regVal);for (int i = 0; i < 8; i++) {dsShiftOut(clock[i]);}digitalWrite(sPin, LOW); delayMicroseconds(1); }

4 注意之處

  • 如果要使用wiringPi自帶的那個示例程序ds1302.c文件,編譯命令可用:
    gcc -Wall -o ds1302 ds1302.c -lwiringPi -lwiringPiDev
    -o 表示自命名生成的文件
    -l 表示需要連接到哪些庫
  • ds1302內的數據是用BCD編碼的,讀取和存儲都需要先進行轉化
  • ds1302是LSB優先的
  • 以上博客有什么問題,請在評論區聯系博主

總結

以上是生活随笔為你收集整理的树莓派——实时时钟模块(RTC)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。