W pewnych modelach komputerów PC, ich płyty główne zawierały pamięć podręczną zbudowaną w oparciu o szybkie pamięci statyczne. W większości przypadków jest to typowa pamięć statyczna RAM o czasie dostępu od 10 ns do 25 ns (w zależności od płyty głównej) i pojemności 32k * 8 bitów. Wiele mikrokontrolerów ma możliwość przyłączenia dodatkowej pamięci RAM, czyli jest konstrukcyjnie przewidziana możliwość takiego rozszerzenia oraz istnieją instrukcje pozwalające zapisać oraz odczytać dane do/z pamięci. Przykładem takiego mikrokontrolera jest 80C51 (tu użyty jest mikrokontroler ATMEL 89C51, oraz instrukcja MOVX). Biorąc pod uwagę, że w/w mikrokontroler posiada 128 bajtów wewnętrznej pamięci danych, to dołączenie jednego układu pamięci RAM zwiększa zasoby kilkaset razy. Przestrzeń adresowa mikrokontrolera z rodziny C51 pozwala na przyłączenie dwóch układów pamięci RAM dając łącznie 64k bajtów pamięci danych, czyli w przypadku 89C51 jest to “niewyobrażalnie duża pamięć”.
Interfejs obsługujący zewnętrzną pamięć RAM wymaga użycia dodatkowych układów oraz absorbuje w samym mikrokontrolerze w całości port P0 i P2 oraz dwa wyprowadzenia portu P3. Port P0 spełnia podwójną rolę: szyny danych oraz część szyny adresowej. Port P2 pełni funkcję szyny adresowej oraz dwa wyprowadzenia portu P3 pełnią funkcję sygnałów strobu zapisu danych oraz odczytu danych do/z zewnętrznej pamięci RAM. Sposób przyłączenia pamięci przedstawia ilustracja 2. Układ U2 (74xx573) pełni rolę zatrzasku szyny adresowej, układ U4 (74xx08) jest odpowiedzialny za wygenerowanie sygnału wyboru do pamięci RAM.
Powyższy układ jest rozbudowany o interfejs szeregowy pozwalający na komunikację z systemem mikroprocesorowym. Schemat interfejsu szeregowego jest następujący: Odpowiadający powyższym schematom układ testowy przedstawia się następująco:
Program zawarty w mikrokontrolerze realizuje prosty test pamięci, który polega na wypełnieniu całej dostępnej przestrzeni zewnętrznej pamięci RAM i następnie sprawdzeniu (odczytaniu pamięci), czy we wszystkich zapisanych komórkach pamięci znajdują się właściwe dane. Jeżeli w wyniku wykonanych operacji nie zostaną wykryte różnice, to program przesyła na ekran terminala (emulatora terminala) poprzez łącze szeregowe komunikat o pozytywnym zakończeniu testu pamięci oraz w przypadku wypadku wysyłany jest komunikat zawierający adres komórki w pamięci, która zawiera inne dane niż oczekiwane.
Po uruchomieniu systemu testowego na ekran programu “Hyper Terminal” wyświetlany jest komunikat (program po wykonaniu testu pamięci odczekuje pewien interwał czasu i ponownie realizuje test pamięci):
Jeżeli w trakcie pracy “dokonamy uszkodzenia” (została rozłączona jedna z linii szyny danych), to efekt testu pamięci RAM jest następujący: Adres komórki pamięci jest przypadkowy (rozłączenie było wykonane na “żywym organizmie”).
Program mikrokontrolera jest następujący:
Kod: Zaznacz cały
;
; ****************************************************************************
; ****************************************************************************
; *** ***
; *** http://microgeek.eu ***
; *** ***
; *** BIALYSTOK 2017 ***
; *** ***
; *** Static RAM Test ***
; *** ***
; ****************************************************************************
; ****************************************************************************
;
$mod51
;
$NODEBUG
$LIST
$OBJECT
;
;-----------------------------------------------------------------------------
;
ExtRAMStart EQU 00000H
ExtRAMStop EQU 07FFFH
REG0 EQU 0
REG1 EQU 1
REG2 EQU 2
REG3 EQU 3
REG4 EQU 4
REG5 EQU 5
REG6 EQU 6
REG7 EQU 7
;
Cr EQU 0DH ;
Lf EQU 0AH ;
;
RESET EQU 00H
EXTI0 EQU 03H
TIMER0 EQU 0BH
EXTI1 EQU 13H
TIMER1 EQU 1BH
SINT EQU 23H
;
;-----------------------------------------------------------------------------
DSEG
;-----------------------------------------------------------------------------
ORG 8
STACKDATA: DS 40H ;
MemAdr: DS 2 ;
RlData: DS 1 ;
RqData: DS 1 ;
;
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
;
CSEG
;-----------------------------------------------------------------------------
ORG RESET ;
LJMP RESET_SERVICE ;
;-----------------------------------------------------------------------------
ORG EXTI0 ; EXT. INT. 0 SERVICE
RETI ;
;-----------------------------------------------------------------------------
ORG TIMER0 ; TIMER/COUNTER. INT. 0 SERVICE
RETI ;
;-----------------------------------------------------------------------------
ORG EXTI1 ; EXT. INT. 1 SERVICE
RETI ;
;-----------------------------------------------------------------------------
ORG TIMER1 ; TIMER/COUNTER. INT. 1 SERVICE
RETI ;
;-----------------------------------------------------------------------------
ORG SINT ; SERIAL INT. SERVICE
RETI ;
;-----------------------------------------------------------------------------
HexConv: DB '0123456789ABCDEF'
;-----------------------------------------------------------------------------
Conv: ;PROCEDURE Conv ( VAR R0 : CHAR ;
;**************** VAR R1 : CHAR ;
; A : BYTE ) ;
; BEGIN (* Conv *)
PUSH DPH ;
PUSH DPL ;
PUSH ACC ;
RR A ; R0 := HexConv [ A MOD 16 ] ;
RR A ;
RR A ;
RR A ;
ANL A , # 0FH ;
MOV DPTR , # HexConv ;
MOVC A , @ A + DPTR ;
MOV R0 , A ;
POP ACC ; R1 := HexConv [ A DIV 16 ] ;
ANL A , # 0FH ;
MOVC A , @ A + DPTR ;
MOV R1 , A ;
POP DPL ;
POP DPH ;
RET ;END (* Conv *) ;
;-----------------------------------------------------------------------------
SendSerialPool: ;PROCEDURE SendSerialPool ( A : BYTE ) ;
;****************** ;BEGIN (* SendSerialPool *)
CLR TI ; [TI] := 0 ;
MOV SBUF , A ; [SBUF] := A ;
SeCh_2: ;
JB TI , SeCh_1 ; WHILE NOT [TI] DO
SJMP SeCh_2 ;
SeCh_1: ; END (* WHILE *) ;
RET ;END (* SendSerialPool *) ;
;-----------------------------------------------------------------------------
SendSerialPoolTxt: ;PROCEDURE SendSerialPoolTxt ( DPTR : ADDRESS ) ;
;***************** ;BEGIN (* SendSerialPoolTxt *)
PUSH ACC ;
SendPool_3: ; LOOP
CLR A ; A := DPTR ^ ;
MOVC A , @ A + DPTR ;
CJNE A , # 0 , SendPool_1 ; IF A = 0 THEN
POP ACC ;
RET ; RETURN ;
SendPool_1: ; END (* IF *) ;
LCALL SendSerialPool ; SendSerialPool ( A ) ;
INC DPTR ; INC ( DPTR ) ;
LJMP SendPool_3 ; END (* LOOP *) ;
;END (* SendSerialPoolTxt *) ;
;-----------------------------------------------------------------------------
SendR0R1Pool: ;PROCEDURE SendR0R1Pool ( R0R1 : WORD ) ;
;**************** BEGIN (* SendR0R1Pool *)
PUSH REG1 ;
MOV A , R0 ; SendSerialPool ( R0 ) ;
LCALL SendSerialPool ;
POP ACC ; SendSerialPool ( R1 ) ;
LCALL SendSerialPool ;
RET ;END (* SendR0R1Pool *) ;
;-----------------------------------------------------------------------------
ClearRam: ;PROCEDURE ClearRam ;
;*************** ;BEGIN (* ClearRam *)
MOV DPTR , # ExtRAMStart ;
ClrR2: ;
CLR A ;
MOVX @ DPTR , A ;
MOV A , DPL ;
CJNE A , # LOW ( ExtRAMStop ) , ClrR1
MOV A , DPH ;
CJNE A , # HIGH ( ExtRAMStop ) , ClrR1
RET ;
ClrR1: ;
INC DPTR ;
LJMP ClrR2 ;
;END (* ClearRam *) ;
;-----------------------------------------------------------------------------
RAMTest: ;PROCEDURE RAMTest ;
;**************** ;BEGIN (* RAMTest *)
MOV R0 , # 0 ;
MOV DPTR , # ExtRAMStart ;
RamT3: ;
MOV A , R0 ;
CPL A ;
RL A ;
RL A ;
RL A ;
RL A ;
ANL A , # 0F0H ;
ORL A , R0 ;
MOVX @ DPTR , A ;
MOV A , DPL ;
CJNE A , # LOW ( ExtRAMStop ) , RamT1
MOV A , DPH ;
CJNE A , # HIGH ( ExtRAMStop ) , RamT1
LJMP RamT2 ;
RamT1: ;
INC DPTR ;
INC R0 ;
MOV A , R0 ;
CJNE A , # 0CH , RamT3 ;
MOV R0 , # 0 ;
LJMP RamT3 ;
RamT2: ;
MOV R0 , # 0 ;
MOV DPTR , # ExtRAMStart ;
RamT6: ;
MOV A , R0 ;
CPL A ;
RL A ;
RL A ;
RL A ;
RL A ;
ANL A , # 0F0H ;
ORL A , R0 ;
MOV B , A ;
MOVX A , @ DPTR ;
CJNE A , B , RamT7 ;
MOV A , DPL ;
CJNE A , # LOW ( ExtRAMStop ) , RamT4
MOV A , DPH ;
CJNE A , # HIGH ( ExtRAMStop ) , RamT4
LJMP RamT5 ;
RamT7: ; DPTR - fail address
CLR C ; A - real data
RET ; B - req. data
RamT4: ;
INC DPTR ;
INC R0 ;
MOV A , R0 ;
CJNE A , # 0CH , RamT6 ;
MOV R0 , # 0 ;
LJMP RamT6 ;
RamT5: ;
SETB C ;
RET ;END (* RAMTest *) ;
;-----------------------------------------------------------------------------
RAMFailMessage: ;PROCEDURE RAMFailMessage ( ) ;
;*************** ;BEGIN (* RAMFailMessage *)
MOV DPTR , # RamFailTxt ; SendSerialPoolTxt ( RamFailTxt ) ;
LCALL SendSerialPoolTxt ;
MOV A , LOW ( MemAdr + 1 ) ; Conv ( R0R1 , HIGH ( MemAdr ) ) ;
LCALL Conv ;
LCALL SendR0R1Pool ; SendR0R1Pool ( R0R1 ) ;
MOV A , LOW ( MemAdr ) ; Conv ( R0R1 , LOW ( MemAdr ) ) ;
LCALL Conv ;
LCALL SendR0R1Pool ; SendR0R1Pool ( R0R1 ) ;
MOV DPTR , # RamFailTxt2 ; SendSerialPoolTxt ( RamFailTxt2 ) ;
LCALL SendSerialPoolTxt ;
MOV A , LOW ( RlData ) ; Conv ( R0R1 , RealData ) ;
LCALL Conv ;
LCALL SendR0R1Pool ; SendR0R1Pool ( R0R1 ) ;
MOV A , # '/' ; SendSerialPool ( '/' ) ;
LCALL SendSerialPool ;
MOV A , LOW ( RqData ) ; Conv ( R0R1 , ReqData ) ;
LCALL Conv ;
LCALL SendR0R1Pool ; SendR0R1Pool ( R0R1 ) ;
MOV DPTR , # RamFailTxt3 ; SendSerialPoolTxt ( RamFailTxt3 ) ;
LCALL SendSerialPoolTxt ;
RET ;END (* RAMFailMessage *)
;-----------------------------------------------------------------------------
SendRAMOkMessage: ;PROCEDURE SendRAMOkMessage ;
;*************** ;BEGIN (* SendRAMOkMessage *)
MOV DPTR , # RamOKTxt ; SendSerialPoolTxt ( RamOKTxt ) ;
LCALL SendSerialPoolTxt ;
RET ;END (* SendRAMOkMessage *) ;
;-----------------------------------------------------------------------------
SRAMDiagnostic: ;PROCEDURE SRAMDiagnostic ;
;**************** ;BEGIN (* SRAMDiagnostic *)
LCALL RAMTest ; IF NOT RAMTest ( A , B , DPTR ) THEN
JC SRDiag_0 ;
MOV LOW ( RlData ) , A ; RlData := A ;
MOV A , B ; RqData := B ;
MOV LOW ( RqData ) , A ;
MOV A , DPL ; MemAdr := DPTR ;
MOV LOW ( MemAdr ) , A ;
MOV A , DPH ;
MOV LOW ( MemAdr + 1 ) , A ;
LCALL RAMFailMessage ; RAMFailMessage ( ) ;
RET ; RETURN ;
SRDiag_0: ; END (* IF *) ;
LCALL SendRAMOkMessage ; SendRAMOkMessage ( ) ;
RET ;END (* SRAMDiagnostic *) ;
;-----------------------------------------------------------------------------
HardInit: ;PROCEDURE HardInit ;
;**************** ;BEGIN (* HardInit *)
MOV SCON , # 01010000B ; tryb 1 : transmisja asnynchr.
; 76543210 ; 8 bitow
; ; z szybk. okresl. program.
; ; odbiornik odblokowany
MOV TMOD , # 00100001B ;
MOV TCON , # 01010100B ;
MOV TH1 , # 0FDH ; 9600 bps ;
MOV TL1 , # 0FDH ;
RET ;END HardInit ;
;-----------------------------------------------------------------------------
Delay: ;PROCEDURE Delay ( ) ;
;**************** ;BEGIN (* Delay *)
MOV DPTR , # 0 ;
Dly_0: ;
INC DPTR ;
MOV A , DPL ;
ORL A , DPH ;
JNZ Dly_0 ;
RET ;END (* Delay *) ;
;-----------------------------------------------------------------------------
LongDelay: ;PROCEDURE LongDelay ;
;**************** ;BEGIN (* LongDelay *)
LCALL Delay ; Delay ;
LCALL Delay ; Delay ;
LCALL Delay ; Delay ;
LCALL Delay ; Delay ;
LCALL Delay ; Delay ;
LCALL Delay ; Delay ;
LCALL Delay ; Delay ;
LCALL Delay ; Delay ;
RET ;END (* LongDelay *) ;
;-----------------------------------------------------------------------------
RESET_SERVICE: ;BEGIN (* SRAM *)
MOV SP , # LOW(STACKDATA)-1 ;
MOV P3 , # 0FFH ;
MOV P1 , # 0FFH ;
LCALL HardInit ; HardInit ;
Main_0: ; LOOP
MOV DPTR , # StartTxt ; SendSerialPoolTxt(StartKxt);
LCALL SendSerialPoolTxt ;
LCALL SRAMDiagnostic ; SRAMDiagnostic ;
LCALL ClearRam ; ClearRam ;
LCALL LongDelay ; LongDelay ;
LJMP Main_0 ; END (* LOOP *) ;
;END (* SRAM *)
;-----------------------------------------------------------------------------
StartTxt: DB Cr , Lf , '**** Static RAM diagnostic program ***'
DB Cr , Lf , 0
RamOKTxt: DB 'RAM TEST O.K.' , Cr , Lf , 0
RamFailTxt: DB 'RAM TEST FAIL AT ADDRESS ' , 0
RamFailTxt2: DB ' RL/RQ ' , 0
RamFailTxt3: DB Cr , Lf , Cr , Lf , 0
;-----------------------------------------------------------------------------
END