顯示具有 W77E352 標籤的文章。 顯示所有文章

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,才可以使用。

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...

winbond reset status

Posted by: 邱小新 at 上午10:08 in ,

記錄一下系統開機或是被 reset 時的一些旗標狀態。

旗標狀態

resetWTRFPOREWTWDCON判斷
power-on reset01001000000bPOR=1
external resetxxx0x0x0xx0bEWT=1*
POR=0#
watchdog reset1xx0x0x01x0bWTRF=1

註解

  1. x: 保留原值,不會變更。
  2. *: 系統如果有開啟 watchdog 功能,在發生 external reset 時,EWT 一定是 1。
  3. #: 一開機時 POR=1,此時把 POR 設成 0,下次發生 external reset 時,POR 一定是 0,以此來區分。適合沒有開啟 watchdog 功能的系統。

判斷順序

  1. 開啟 watchdog: WTRF=1(watchdog) -> EWT=1(external) -> POR=1(power-on)。
  2. 關閉 watchdog: POR=1(power-on) -> POR=0(external),watchdog 不用判斷。

reset 開機狀態

  1. Program Counter 強制跳回 0000h,也就是從頭開始執行。
  2. SFR 都會返回 reset value,datasheet 有一張表。
  3. stack point 會變成 07h。
  4. Vdd 小於 2V 時,RAM 資料會遺失;反之則會保存。

好用的 STATUS register

Posted by: 邱小新 at 上午10:47 in

以往在寫 uart 的 putchar 函數時,都是用下列方式來寫。在初始化時還要先把 TI 設成 1。但是如此會造成 ES 中斷一直發生。只適合沒有開啟 ES 中斷程序來用。

void putchar(char value) { while (!TI); TI = 0; SBUF = value; }

若是改用下列方式來寫,初始化時不用把 TI 設成 1,ES 中斷就不會一直發生。但是如此會被 block,等到傳送完才繼續其它工作,對效能來說不是很好。適合需要開啟 ES 中斷程序來用。

void putchar(char value) { SBUF = value; while (!TI); TI = 0; }

W77E352 有一個 register 叫 STATUS(0xC5),它的 SPTA0 位元為 uart 傳送忙碌指標,當 TI 為 1 時,自動清成 0。在 W79E632 也有 STATUS register,但是卻沒有 SPTA0 位元,不知是否可用?

void putchar(char value) { while (STATUS & SPTA0); SBUF = value; } void uart_isr(void) interrupt (4) { if (TI) TI = 0; }

W77E352 interrupt

Posted by: 邱小新 at 下午1:51 in

W77E352 可以算是 winbond 系列中中斷最多的一個,而像之前我使用的 W79E632 的中斷似乎也是跟 W77E352 系出同門。比如 watchdog timer 的中斷號碼都是 12,而 W79E632 的中斷就少了中間的 7~11,現在終於在 W77E352 看到影子了。但是奇怪的是 6 號中斷不知是那一個?


priority /
interrupt number
sourceflagaddr
0external interrupt 0IE00003h
1timer 0 overflowTF0000bh
2external interrupt 1IE10013h
3timer 1 overflowTF1001bh
4serial portRI+TI0023h
5timer 2 overflowTF2+EXF2002bh
6????0033h
7serial port 1RI_1+TI_1003bh
8external interrupt 2IE20043h
9external interrupt 3IE3004bh
10external interrupt 4IE40053h
11external interrupt 5IE5005bh
12watchdog timerWDIF0063h

  1. INT0,INT1 根據標準的 8051,是可以設定成 edge trigger 或 level trigger,但是由 winbond 提供的 INT2~INT5 卻只能是 edge trigger,而且還各有不同的 edge。
  2. INT2 is raising edge triggered.
  3. INT3 is falling edge triggered.
  4. INT4 is raising edge triggered.
  5. INT5 is falling edge triggered.
  6. INT2~INT5 需手動清除中斷旗標,但可以經由設定 T2MOD 的 HCx,變成自動清除。
  7. INT2~INT5 如果沒有清除中斷旗標,會造成中斷一直重覆,切記。由於 INT0~INT1 會自動清除,所以沒有這個問題。

SDCC Bankswitching (code banking)

Posted by: 邱小新 at 下午5:23 in ,
範例下載, 使用 winbond w77e532, uart output "010hello test".

要做 SDCC code banking 真是有夠麻煩,找不到有人分享成功案例就算了,sdccman.pdf 竟然也只提到一頁而已,完全沒法子去了解如此實做。最後靠著不斷的試驗,總算完成這一件不可能的任務。

  1. 修改 C:\Program Files\SDCC\lib\src\mcs51\crtbank.asm 來達成 bankswitching 的函數。
  2. 重新建立 mcs51.lib,把修改好的 crtbank.asm 置換掉舊的 mcs51.lib。
  3. Project Properties → C/C++ Build → Settings → Tool Settings → SDCC Linker → Command 輸入 sdcc -Wl-r "-Wl-b BANK1=0x18000",千萬不要輸入 sdcc "-Wl-r -Wl-b BANK1=0x18000",為此我花了半天找問題,真是 ooxx。
  4. 建立一個 c source file,開頭輸入 #pragma codeseg BANK1。
  5. 建立一個函數 void test1(void) banked { ... },要記得加上 banked。
  6. 轉換 ihx 成 bin,makebin.exe < test.ihx > test.bin
  7. 產生出來的 bin,裏面有 common/bank0/bank1,但是在 bank1 裏沒有 common 存在,需要手動加進去,而且也要手動分開這個 bin,才方便 winbond isp writer 燒錄。
  8. 大功告成,真是幸苦啊,花了一天才完成。

to be continue.... 後面有空再來補一些說明及範例吧。

SDCC Bankswitching (code banking) part 2。

W77E352 雜記

Posted by: 邱小新 at 下午4:35 in

從今天開始又要開始玩 8051 了,在公司裏被丟來丟去,如浮萍一般飄泊不定,真是可憐啊。
BTW 有人要挖角嗎?歡迎來電喔。

  1. W77E352 內含二個 serial port,port 0 可以使用 timer 1/2 做 baudreate generator,而 port 1 只能使用 timer1。所以只要設定好 T2CON,port0 就會使用 timer2;如果只有設定 timer1 則 port 0/1 就會共用 timer1。
  2. W77E352 有 1K 的 On-chip SRAM,使用 xdata(MOVX) 來存取,位置在 0x0000~0x03FF。使用前需把 PMR 的 DME0 開啟,就是 PMR |= 1。
  3. to be continue....