S35390A driver for 8051 part 2

Posted by: 邱小新 at 下午4:11 in ,
原始碼下載

● 警報中斷 alarm interrupt

  1. alarm 的設置很簡單,只要先設置好警報時間,再設置中斷模式即可。
  2. 中斷模式有很多種,主要使用 alarm interrupt 模式,即 INT1AE=1,INT1ME=0,INT1FE=0。
  3. 當警報觸發時,INT1 pin 會從 HIGH 變成 LOW,直到設置 INT1AE=0,INT1 pin 才又恢復成 HIGH。
  4. 當警報觸發時,register status1 中的 INT1 會變成 1,只要讀取 status1 後自動變成 0,即下次再讀取 INT1 的值為 0。
  5. 當警報觸發時,而且 INT1AE=1,每隔一秒就會重置 status1(INT1=1)。也就是讀取完 status1 後,再次讀取 INT1 的值為 0,但是在下一秒再次讀取 status1,則 INT1 又會變成 1,每隔一秒就再次變成 1,除非當 INT1AE=0,則此動作就取消。
  6. 手動設定連接 INT1 pin 的 port 是沒有作用的,也就是手動設定 INT1 並不會觸發中斷。
  7. S35390A 的 alarm interrupt 剛好符合 8051 的 external interrupt,可以直接用 external interrupt 來偵測。如果沒有多餘的腳位,則可改成讀取 status1 來判斷 interrupt。
  8. 如果一開始就把 INT1 pin 拉 LOW,就會造成當 alarm interrupt 發生後要取消回 HIGH 時,不會自動回復成 HIGH,而是一直呈現在 LOW 的狀態下。

void s35390a_write_alarm1(unsigned char xdata *value) { unsigned char i=10, j; while (--i) { // set alarm time i2c_start(); if(i2c_write(ADDR_INT1 | I2C_WRITE)) continue; for (j=0; j<RTC_ALARM_LENGTH; j++) { if(i2c_write(value[j])) break; } if (j<RTC_ALARM_LENGTH) continue; i2c_stop(); // start alarm j = s35390a_read_status_2(); j = j & INT1_MASK | INT1AE; s35390a_write_status_2(j); break; } }

● free SRAM register

  1. S35390A 可使用的 SRAM 只有二個 bytes,一個是完整的 Free register,一個是分散在各地的 Scratch bits。
  2. Scratch bits 中的 SC0/SC1 存在 status1,所以任意時間都可以用。而 SC2~SC7 存在 INTx register,只有當 INTxME=0 and INTxFE=1,才可以使用。

bin2bcd bcd2bin

Posted by: 邱小新 at 下午4:49 in
int bin2bcd (int x) { return (x%10) | ((x/10) << 4); } int bcd2bin (int x) { return (x >> 4) * 10 + (x & 0x0f); }

S35390A driver for 8051 part 1

Posted by: 邱小新 at 下午1:34 in ,
原始碼下載

● 簡介

S35390A 是由精工電子有限公司開發製造,Seiko Instruments Inc. 是一家日本公司,台灣也有子公司,網址為 http://www.sii.com.tw/

datasheet 下載點: 簡體中文版英文版日文版

● 電源 Power Supply

  1. 一般來說 S35390A 的電源是由鈕扣電池(CR2032 3V)所提供,一開始我還以為是由主板上的電源所提供,害我一直誤解為啥 Power-on 就要重置時間。原來是說當電池沒電或換了新電池時,才會有 power-on detection。
  2. BLD 為電壓降低偵測旗標,S35390A 一秒才會做一次電壓降低偵測,所以只要電池拔掉再裝回去的時間在一秒內都不會引起 BLD。
  3. POC 為 Power-on Detection,只要把電池拔掉約五秒,再次裝上電池就會觸發POC。
  4. 當 POC or BLD 被設置,都需要做一次 chip reset。

● 協定 protocol

  1. S35390A 是使用 I2C protocol,在 1.5V 有 100kHz 速度,在 3.0V 有 400kHz 速度,算是快速的 I2C chip。
  2. 在早期的 datasheet 裏跟現在的 datasheet(Rev.2.5_00) 對於經由 command 所取的 data 描述大不同。主要是早期接收 bit 時,是從 LSB 到 MSB,剛好跟 command 的傳送方式相反,造成一些問題。而新的 datasheet 就把 data 的描述顛倒過來,使得 command 跟 data 的 bit order 剛好一致,但本質是不變的。
  3. 參數設定 command 對於 bit order 不同是沒有差異的,主要是時間 command 對於 bit order 是很敏感的。由於 bit order 接收是 little endian 而非普遍的 big endian,所以對於 I2C protocol 必須重新設計,不能使用舊的方法。
  4. 如果是按照新的 datasheet 來說,是不用重新設計 protocol,但是由於接收下來的時間卻 little endian,所以必須另外寫一個轉換函數把 little endian 轉換成 big endian。
  5. 執行 command(Real-time data 1 access),照原始 I2C protocol 來說,讀取最後一個 byte 回傳 ack=1,讀取中間的 bytes 一律回傳 ack=0。當然 S35390A datasheet 也是如此寫,沒有錯誤。但是實際上在 coding 的過程中卻發現完全相反,讀取中間的 bytes 必須回傳 ack=1,才能得到正確值;如果回傳 ack=0,傳回值卻都是 0。真是奇也怪哉,莫名奇妙,害我玩了好多天才找到問題所在。
  6. 在設定時間時,必須一次寫入完整 7 bytes,如果漏了一個 byte 就執行 i2c_stop, S35390A 則不會存入這次寫入的時間。

● slave address

S35390A 的 slave address 為 7-bit addressing 變化型,也就是把前 4 bits 固定,後 3 bits 來當做 command。因此在 I2C bus 上的 chip,前 4 bits 不能為 0110,也就是不能為 0x6? 的 slave address,否則會跟 S35390A 相衝突。

● chip init

按照 datasheet 所陳述的初始化流程圖,有下列需要注意的事項。

  1. 當電源接上時(也就是裝上電池),會設置 POC=1;在此時需要設置 RESET=1,讓 chip reset。
  2. 當電源拔掉時(也就是突然接觸不良),會設置 BLD=1;在此時需要設置 RESET=1,讓 chip reset。
  3. 當有不明原因讓 chip 進入 test mode 時,會設置 TEST=1;在此時需要設置 RESET=1,讓 chip reset。
  4. chip reset 完之後,必需再次檢查上述三項條件。
void s35390a_init(void) { unsigned char tmp; while (1) { // check status 1 tmp = s35390a_read_status_1(); if ((tmp & (POC | BLD)) || ((tmp & H24) == 0)) { s35390a_reset(); continue; } // check status 2 tmp = s35390a_read_status_2(); if (tmp & TEST) { s35390a_reset(); continue; } break; } // read datetime s35390a_read_data1(rtc_data); }

to be continue...