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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

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

1 RTC介紹

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

2 DS1302

2.1 模塊簡(jiǎn)介

DS1302模塊自帶一塊CR2032紐扣電池,電池使用時(shí)間至少應(yīng)該有一年以上。
DS1302與單片機(jī)之間能簡(jiǎn)單地采用同步串行的方式進(jìn)行通信,僅需用到三個(gè)口線:

  • RST復(fù)位
  • I/O數(shù)據(jù)線
  • SCLK串行時(shí)鐘
    DS1302工作時(shí)功耗很低保持?jǐn)?shù)據(jù)和時(shí)鐘信息時(shí)功率小于1mW。

2.2 模塊參數(shù)

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

2.3 接線

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

2.4 寄存器簡(jiǎn)介

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

2.5 控制字簡(jiǎn)介

3 代碼塊

通過(guò)對(duì)寄存器的操作來(lái)讀寫時(shí)間,代碼(參考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內(nèi)的時(shí)間來(lái)設(shè)置Linux的時(shí)間}else if (strcmp(argv[1], "-sdsc") == 0) {return setDSClock();//讀取Linux的時(shí)間來(lái)設(shè)置DS1302的時(shí)間}/*else if (strcmp(argv[1], "-rtest") == 0) {return ramtest();//進(jìn)行ram測(cè)試,此處因?yàn)楫?dāng)時(shí)覺得沒必要所以沒有寫,具體可以參考wiringPi示例程序}*/else {printf("Usage: ds1302 [-slc | -sdsc | -rtest]\n");return EXIT_FAILURE;}}i = 0;while (true) {printf("%5d: ", i);ds1302clockRead(clock);//讀取DS1302內(nèi)的時(shí)間//由于DS1302內(nèi)的數(shù)據(jù)是BCD編碼,所以需要轉(zhuǎn)化為十進(jìn)制后才能輸出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);//關(guān)閉寫保護(hù) }void ds1302rtcWrite(int reg, unsigned int data) {ds1302regWrite(0x80 | ((reg & 0x1f) << 1), data);//將reg轉(zhuǎn)化為寫寄存器的實(shí)際地址 }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優(yōu)先,從低位開始傳輸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();//讀取時(shí)鐘數(shù)據(jù)//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;//取高四位作為十進(jìn)制的十位數(shù)int b2 = byte & 0x0F;//取低四位作為十進(jìn)制的個(gè)位數(shù)return b1 * 10 + b2; }int setDSClock() {struct tm t;//Linux時(shí)間結(jié)構(gòu)體time_t now;int clock[8];printf("Setting the clock in the DS1302 from Linux time... ");now = time(NULL);//取得當(dāng)前時(shí)間UTC秒數(shù),無(wú)時(shí)區(qū)轉(zhuǎn)換gmtime_r(&now, &t);//獲取當(dāng)前時(shí)間結(jié)構(gòu),UTC時(shí)間,無(wú)時(shí)區(qū)轉(zhuǎn)換//DS1302內(nèi)數(shù)據(jù)采用BCD編碼,故需轉(zhuǎn)化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自帶的那個(gè)示例程序ds1302.c文件,編譯命令可用:
    gcc -Wall -o ds1302 ds1302.c -lwiringPi -lwiringPiDev
    -o 表示自命名生成的文件
    -l 表示需要連接到哪些庫(kù)
  • ds1302內(nèi)的數(shù)據(jù)是用BCD編碼的,讀取和存儲(chǔ)都需要先進(jìn)行轉(zhuǎn)化
  • ds1302是LSB優(yōu)先的
  • 以上博客有什么問題,請(qǐng)?jiān)谠u(píng)論區(qū)聯(lián)系博主

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。