MICE-5103, software Sigma-Delta ADC experiment


http://wp.me/ph3BR-Ni

過了一個多月, 終於有空完成了實驗, 但是沒有用 AT89C2051, 因為沒有 DEBUGGER, 也沒有 IC, 兼除錯麻煩, 所以改了一下, 用普通的 INTEL P8051AH 加上一個外置的比較器 LM311.
nEO_IMG_MICE-5103-8051-ADC-config

.

.

LM311 比較器

nEO_IMG_LM311-comparator

原理應該是一樣, 實驗的目的 –

1) 驗證程序的真實可用性.

2) 徹底了解這個 Sigma-Delta ADC 方法的利弊和原理, 因為經驗告訴俺們, 抄來的東西, 沒有親自驗證過, 可靠度是 50%, 果然, 又再次證實, 原來的源碼是有些小問題的, 實際在板上運行就馬上察覺. 那些 SIMULATOR 也是一樣, 直到真實在 MCU 上執行的結果才可考/可靠.

3) 套用到其他的CPU

結果 –

修改了一些小小的細節後, 順利完成也理解了一些小問題, 例如, ADC 的範圍和速度限制, 解析度和速度的關係.

因為要顯示 ADC的值, 也懶惰再去做其他, 所以直接用 MICE-5103 的 7劃管 (7-segment LED) 的内置程序, 顯示 ADC 結果, 16 BIT, 4個管, 4位數, HEX 碼. 因為 ADC 過程不能開中斷, 所以是 ADC 轉換好後, 一次過把4個字位的數據存到 DSIPLAY BUFFER, 再呼叫 ROM 的顯示常式做顯示, 因此短片內看到的結果顯示在閃爍, 每次黑屏的時間就是 ADC 的過程和延時的片段, 每秒大概顯示3次. 聽說有的體重秤的設計就是這樣, 最便宜的硬件, 沒用ADC, 沒有專用的CPU, 靠軟件達成 12 BIT 以上的 ADC 解析度, 原來就是這樣做的, 因為量體重, 不需要很快, 也不需要高速的機器. 當然, 這個試驗的源碼稍加修改, 就會變成實用的源碼, 很多東西就是這樣, 都是說穿了不值錢.

這個題目大概就這樣, 俺學會了臨摹, 以後就是自己創作了, 不過, 現在看來這個還是很神奇的方法.

途中看了 INTEL 8051 INSTRUCTION 的資料, 用了 SWAP A 這個指令, 源碼裡面有註明和解說

http://www.win.tue.nl/~aeb/comp/8051/set8051.html#51anl

還有 LM311 DATASHEET / AT89C2051 DATASHEET 等等.

.
.
test video clip

h_ttp://youtu.be/M3MggAz8DmE

.

.
sigma-delta-adc-8051-LM311.asm


;************************************************
;* Sigma-Delta ADC experiment with generic 8051 core and LM311 comparator
;* author: xiao_laba@yahoo.com.cn
; reading and learning, include more comments for better understanding
; 2012-DEC-07
; 2013-JAN-27, test rig setup for 8051 test and debug
; last modification : 2013-JAN-27
; assembler : ASEMW-51, http://plit.de/cgi-bin/asem-51/wwwasem.cgi
; how to assemble the code,
;    asemw sigma-delta-adc-8051-LM311.asm

;************************************************

; reference and the orginal idea of code:
; software Sigma-Delta ADC for AT89C2051
; http://5.13.blog.163.com/blog/static/335445652007929113450285/
; Sigma-Delta ADC Version 1.0a *
; 作者: jimweaver@nbip.net *
; 測量範圍: DC 18V~30V *
; 最近修改: 2003-12-29 *
;************************************************

; this for 89c2051 only, as it has internal comparator
;ADC_CON BIT P3.7 ; RC 充電引腳
;COM_OUT BIT P3.6 ; AT89C2051特有的, P3.6無外接引腳, P1.0/P1.1兩腳接內部比
; 較器, 比較輸出在P3.6讀取
; 當P3.6 = 1, 跳回上面Precharge:, 繼續充電
; 當P3.6 = 0, Vc > Vin, 表示AIN-的電壓高於AIN+, 執行下面
; 一行指令, 開始 ADC

; my confiiguration, for Intel P8051AH and it should be in general
; no internal comparator, use LM311 instead external
ADC_CON BIT P1.0 ; RC 充電引腳, P1.0 must set to outpout pin
COM_OUT BIT P1.6 ; LM311 COMparator OUTput connect to P1.6 (input pin)

; MICE-5103 8051 emualator definnation
PORT_A EQU 0CF01H ;8155 port define, should be no uses
PORT_B EQU 0CF02H ;8155 port define, should be no uses
PORT_C EQU 0CF03H ;8155 port define, should be no uses
display_ADC_result EQU 0DE00H ; 7-SEG LED display subroutine, put bytes at
; 0x3EH-0x39H to LED, each byte for each LED

;ISEG AT 60H ;堆棧起始
;Stack: DS 20H ;堆棧大小

;CSEG
ORG 0000H
SJMP On_Reset

ORG 0003H ;外部中斷 INT0
RETI

ORG 000BH ;TIMER 0 溢出中斷
AJMP Timer0Handler

;USING 0 ;使用Register bank 0

On_Reset:
;    MOV SP,#(Stack-1) ;初始化堆棧指針
;    MOV SP,#5f ;初始化堆棧指針

mov P1,#0f0h  ; p1.0 output, p1.6 input
CLR ADC_CON       ;ADC_CON=0, C5 discharging; ADC_CON拉低,電容放電

MainLOOP:
ACALL SigmaDeltaADC

;call many times, then naked eyes can visual the digits of 7-seg LED
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result
LCALL display_ADC_result

SJMP MainLOOP

; add this to a compilation success
Timer0Handler:
ret

;************************************************
;* 名稱:SigmaDeltaADC *
;* 功能:測量電池電壓 *
;* 參數:無 *
;* 返回:R0R1: 電池電壓 *
;* 影響:A,PSW,R0,R1,R6,R7 *
;************************************************

SigmaDeltaADC:
;ADC過程不允許中斷,所以要關中斷
CLR EA ;屏蔽所有中斷

Precharge: ;預充電,令Vc=Vin, Vc = 電容C5的電壓, Vin=待測的電壓
SETB ADC_CON      ; 設定 ADC_CON 輸出 HIGH 大約電壓為 VCC(+5V), 透過 R9 (100K)
; 對 C5 (104, 0.1UF) 充電, 此為 Vc, 並進入比較器 AIN-

;     JB P3.6,Precharge ; AT89C2051特有的, P3.6無外接引腳, P1.0/P1.1兩腳接內部比
; 較器, 比較輸出在P3.6讀取
; 當P3.6 = 1, Vin > Vc, 跳回上面Precharge:, 繼續充電
; 當P3.6 = 0, Vc > Vin, 表示AIN-的電壓高於AIN+, 執行下面
; 一行指令, 開始 ADC

; 8051AH, no internal comparator, use LM311, comparator connects to P1.6
; 8051AH, 沒有內置比較器, 用LM311輸出接到P1.6
JB COM_OUT,Precharge ; when COM_OUT = 1, means Vin > Vc, go back, keep charging
; when COM_OUT = 0, means Vc > Vin, AIN- > AN+,
; go to next instruction, start ADC comversion

ADC_Start:
;每次轉換時間=5000*11us=55ms
;each ADC is about 5000*11us=55ms

; intial ADC result, set to 00:00
CLR A
MOV R0,A   ;high byte;高字節, R0:R1 (16bit) to store ADC value
MOV R1,A   ;low byte; 低字節

;load counter
;   MOV R6,#20 ;20x250 = 5000 sampling; 5000次ADC採樣, 5000 loops
MOV R6,#66 ;66x250 = 165000 sampling is about 2^17, over sampling technique
ADC_Loop1:
;   MOV R7,#250    ;R6=20, R7=250, total loop count = 20x250 = 5000 loops
MOV R7,#250    ;R6=20, R7=250, total loop count = 20x250 = 5000 loops

ADC_Loop2:
;   MOV C,P3.6     ; 取比較器輸出, 存入 Carry bit (Cy)
MOV C,COM_OUT  ; comparator output, save to carry bit (Cy), 取比較器輸出, 存入 Carry bit (Cy)
MOV ADC_CON,C  ; if Cy =1, Vin >= Vc, ADC_CON = high, keep charging; 若Cy=1, 說明 Vc 等於或小於 Vin, ADC_CON (P1.0) = 1, 繼續充電
; if Cy =0, Vin < Vc, 若Cy=0, 說明 Vc > Vin, ADC_CON = low, around 0V; 此時 ADC_CON (P1.0) = 0, 大約 0V,
; C5 is discharging; C5 開始被放電
; 下面繼續 ADC value 累計, 加上 Cy (0 或 1), 累計比較器輸出的
; 高電平個數
CLR A     ;1C (1 CPU cycle time, 6MHZ Xtal = 0.5MHZ CPU speed ?!)
ADDC A,R1 ;1C, low byte 低字節
MOV R1,A  ;1C
CLR A     ;1C
ADDC A,R0 ;1C, high byte 高字節
MOV R0,A  ;1C
DJNZ R7,ADC_Loop2 ; loop 循環
DJNZ R6,ADC_Loop1   ; ADC value, accumualted xxx000 times, 連續累計 xxx000, 得到 ADC value 累計總值

;ADC completed 結束
SETB EA ; enable all interrupt 開放所有中斷
CLR ADC_CON ; discharge Capacitor, prepare for next ADc, 電容放電,為下一次測量做準備

;R0:R1, 16 bit ADC value, save this result to 7-SEG LED buffer for display & debug purpose
;0X3E, 0X3D, 0X3C, 0X3B = 7-SEG LED BUFFER
;R0-H, R0-L, R1-H, R1-l = 16 bit ADC result, R0:R1
MOV A,R0  ; HIGH BYTE, HIGH NIBBLE
swap a    ; ACC = hhhhllll, after swap, ACC = llllhhhh, 4bit:4bit swapped
anl A,#0fh; filter out ACC = 0000hhhh
mov 03eh,a; first digit, R0 high nibble

MOV A,R0  ; HIGH BYTE, LOW NIBBLE
anl A,#0fh
mov 03dh,a

MOV A,R1  ; LOW BYTE, HIGH NIBBLE
swap a
anl A,#0fh
mov 03ch,a

MOV A,R1  ; LOW BYTE, LOW NIBBLE
anl A,#0fh
mov 03bh,a

; MICE-5103 have 6 digits of 7-SEG LED, this last two have no used, masked to
; no display, show 'space' of off, LED table, see MICE-5103 manual, page 21
; LED_table @ 0xFD80, "space" is at index = 0x10h, so load ACC=0x10h, put
;them to display buffer
;   ORG 0DF80H
; LED_TB:
;   db 3FH ; "0"
;   db 06H ; "1"
;   db 5BH ; "2"
;.. so on
mov a,#010h ; space
mov 03ah,a
mov 039h,a

; now, ADC result is already at display buffer, let us go back to caller
; ready to display this ADC result
RET

END

.
.
.
sigma-delta-adc-8051-LM311.hex

:02000000800B73
:0100030032CA
:10000B0001617590F0C290116212DE0012DE0012D7
:10001B00DE0012DE0012DE0012DE0012DE0012DE47
:10002B000012DE0012DE0012DE0012DE0012DE0015
:10003B0012DE0012DE0012DE0012DE0012DE0012F3
:10004B00DE0012DE0012DE0012DE0012DE0012DE17
:10005B000012DE0080B122C2AFD2902096FBE4F8F2
:10006B00F97E427FFAA2969290E439F9E438F8DFF0
:10007B00F4DEF0D2AFC290E8C4540FF53EE8540F53
:10008B00F53DE9C4540FF53CE9540FF53B7410F5FD
:04009B003AF53922D7
:00000001FF

.
.
.
.
sechematic and design plan
nEO_IMG_8051-ADC-design-plan_Page_1

nEO_IMG_8051-ADC-design-plan_Page_2

nEO_IMG_8051-ADC-design-plan_Page_3

.

nEO_IMG_MICE-5103 manual013
.

REF:
AT89C2051, software Sigma-Delta ADC
.
https://xiaolaba.wordpress.com/2012/12/06/at89c2051-software-sigma-delta-adc/
.
.
MICE-5103_7-seg.asm, test MICE-5103 LED display and routine call


;************************************************
;* author: xiao_laba@yahoo.com.cn
; test MICE-5103 7-seg LED display
; 2013-JAN-27
; tested
; assembler : ASEMW-51, http://plit.de/cgi-bin/asem-51/wwwasem.cgi
; how to assemble the code,
;    asemw MICE-5103_7-seg.asm
;************************************************

PORT_A EQU 0CF01H
PORT_B EQU 0CF02H
PORT_C EQU 0CF03H

display_buffer EQU 0DE00H

ORG 0000H
SJMP On_Reset

ORG 0003H ;外部中斷 INT0
RETI

ORG 000BH ;TIMER 0 溢出中斷
AJMP Timer0Handler

;USING 0 ;使用Register bank 0

On_Reset:

MainLOOP:
MOV A,#0H
MOV 03EH,A

MOV A,#1H
MOV 03DH,A

MOV A,#2H
MOV 03CH,A

MOV A,#3H
MOV 03BH,A

MOV A,#4H
MOV 03AH,A

MOV A,#5H
MOV 039H,A

LCALL display_buffer
LCALL display_buffer
LCALL display_buffer
LCALL display_buffer
LCALL display_buffer
LCALL display_buffer
LCALL display_buffer
LCALL display_buffer
LCALL display_buffer
LCALL display_buffer

ACALL DELAY
ACALL DELAY
ACALL DELAY
ACALL DELAY
ACALL DELAY
ACALL DELAY
ACALL DELAY
ACALL DELAY
ACALL DELAY
ACALL DELAY
ACALL DELAY

AJMP MainLOOP

delay:
mov R1,#010h  ; initialize the R1 register with an immediate value 10h = 16d
mov R0,#0FFh  ; load R0 with FFh value to repeat the loop for 256 times
back:
DJNZ R0, back   ;internal loop repeates 256 times
DJNZ R1, back   ;external loop repeates 16 times
RET

; add this to a compilation success
Timer0Handler:
ret

END

.
.
MICE-5103_7-seg.hex

:02000000800B73
:0100030032CA
:10000B0001647400F53E7401F53D7402F53C740314
:10001B00F53B7404F53A7405F53912DE0012DE0077
:10002B0012DE0012DE0012DE0012DE0012DE001203
:10003B00DE0012DE0012DE00115B115B115B115B47
:10004B00115B115B115B115B115B115B115B010DA3
:0A005B00791078FFD8FED9FC2222AC
:00000001FF

END-of-article

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s