树莓派——实时时钟模块(RTC)
生活随笔
收集整理的這篇文章主要介紹了
树莓派——实时时钟模块(RTC)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1 RTC介紹
樹莓派為了節(jié)約成本以及減小體積,沒有板載的實(shí)時(shí)時(shí)鐘(real-time clock,RTC),或者叫作硬件時(shí)鐘。
在某些場合下,如果樹莓派無法聯(lián)網(wǎng),但是它上面運(yùn)行的程序又和時(shí)間緊密相關(guān),要求系統(tǒng)時(shí)間是正確的,在這種情況下,我們就可以為樹莓派添加一個(gè)外部的RTC,使之重啟之后也能保持時(shí)間正確。
此實(shí)驗(yàn)以DS1302為例
2 DS1302
2.1 模塊簡介
DS1302模塊自帶一塊CR2032紐扣電池,電池使用時(shí)間至少應(yīng)該有一年以上。
DS1302與單片機(jī)之間能簡單地采用同步串行的方式進(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腳直插國產(chǎn)大芯片,芯片下面有IC座,方便更換及插拔芯片;
- 模塊工作電壓兼容3.3V/5V,可與5V及3.3V單片機(jī)連接;
- 工作溫度:0°—70°。
2.3 接線
| VCC | 3.3V輸出 | 3.3V輸出 |
| GND | Ground(地) | Ground(地) |
| CLK | SCLK | 14 |
| DAT | SDA0 | 30 |
| RST | CEO | 10 |
2.4 寄存器簡介
讀寄存器地址:81h~8Dh
寫寄存器地址:80h~8Ch
2.5 控制字簡介
3 代碼塊
通過對寄存器的操作來讀寫時(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í)間來設(shè)置Linux的時(shí)間}else if (strcmp(argv[1], "-sdsc") == 0) {return setDSClock();//讀取Linux的時(shí)間來設(shè)置DS1302的時(shí)間}/*else if (strcmp(argv[1], "-rtest") == 0) {return ramtest();//進(jìn)行ram測試,此處因?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ù),無時(shí)區(qū)轉(zhuǎn)換gmtime_r(&now, &t);//獲取當(dāng)前時(shí)間結(jié)構(gòu),UTC時(shí)間,無時(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 表示需要連接到哪些庫 - ds1302內(nèi)的數(shù)據(jù)是用BCD編碼的,讀取和存儲都需要先進(jìn)行轉(zhuǎn)化
- ds1302是LSB優(yōu)先的
- 以上博客有什么問題,請?jiān)谠u論區(qū)聯(lián)系博主
總結(jié)
以上是生活随笔為你收集整理的树莓派——实时时钟模块(RTC)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 织梦留言板guestbook.htm加入
- 下一篇: Cheat Enginee(CE)修改器