Meranie teploty pomocou LM92: Rozdiel medzi revíziami

Z Kiwiki
Skočit na navigaci Skočit na vyhledávání
d
 
(17 medziľahlých úprav od 2 ďalších používateľov nie je zobrazených)
Riadok 1: Riadok 1:
 +
[[Kategória:Konfigurovateľné mikroprocesorové systémy]]
 +
[[Kategória:Sériové komunikačné zbernice]]
 +
{{sablona_mikroprocoserove_systemy|Sériové komunikačné zbernice|Synchrónna komunikácia I2C|Meranie teploty pomocou LM92|Hodiny reálneho času|Synchrónna komunikácia SPI|Distribuovaný systém zber dát 1-Wire|Protokol 1-Wire|Meranie teploty pomocou teplomera DS18S20}}
 
== Teplotný snímač LM92 ==
 
== Teplotný snímač LM92 ==
  
Riadok 8: Riadok 11:
  
 
'''Charakteristické znaky'''
 
'''Charakteristické znaky'''
 +
* jednoduchý dizajn
 +
* zaznamenávanie a kontrola teploty
 +
* sériové rozhranie
 +
* výstup pre vypnutie systému pri kritickej teplote
 +
* minimálna spotreba energie pri Shut-down móde
 +
* až 4 teplotné snímače LM92 je možné pripojiť na jednu zbernicu
 +
* 12 bitový znamienkový výstup
 +
* Operuje až do 150 ºC
  
- jednoduchý dizajn
 
  
- zaznamenávanie a kontrola teploty
+
'''Špecifikácie'''
 +
 
 +
* napájanie 2,7V až 5,5V
 +
* spotreba počas behu 350 μA
 +
*      spotreba počas shut-down 5 μA
 +
* Rozlíšenie 0,0625 ºC
 +
 
 +
 
 +
[[Súbor:Popis pinov LM92.jpg|center|thumb|400px|Obr. 2. Popis pinov]]
 +
 
 +
;SDA : sériová obojsmerná dátová linka
 +
;SCL : hodinový vstup
 +
;T_CRIT_A : výstup alarmu pri kritickej teplote
 +
;INT : výstup pre prerušenie
 +
;GND : zem
 +
;+Vs : napájanie
 +
;A0 – A1 : nastavenie adresy
 +
 
 +
'''Dátový formát teploty'''
 +
 
 +
Teplotné dáta môžu byť čítané z teplomera alebo z registrov pre SetPointy; a zapisované do Setpoint registrov. Teplotné dáta môžu byť čítané kedykoľvek. Ak bude frekvencia čítania dát vysoká, dáta v teplomery sa nestihnú obnoviť. Teplotné dáta sú reprezentované 13-bitovým binárnym číslom s LSB. Jeden bit je rovný 0, 0625 ºC.
 +
 
 +
[[Súbor:Teplotný register LM92.jpg|center|thumb|600px|Obr. 3. Teplotný register]]
 +
 
 +
Ako vidíme na obr. 3, bity D0 až D2 sú stavové bity. Teplota je na D3 až D14 a D15 je znamienko. Ak D15 je 1, znamienko je -. Príklady reprezentácie teploty sú na obr. 4. Treba si uvedomiť, že ak prečítame tento register získame 16 bitov, čo nie je hneď konkrétna nameraná teplota. Ak chceme získať teplotu, musíme sa zbaviť stavových bitov D0 až D2.
 +
 
 +
[[Súbor:Digitálny vystup LM92.jpg|center|thumb|400px|Obr. 4. Digitálny výstup z teplomera]]
 +
 
 +
 
 +
== Spojenie LM92 s mikrokontrolérom Cypress ==
 +
 
 +
Pre spojenie potrebujeme sériové rozhranie I2C, ktoré slúži na komunikáciu mikrokontroléra s teplomerom a napríklad RS232 rozhranie pre komunikáciu mikrokontroléra s počítačom, kde môžme získané informácie ďalej spracovávať a vyhodnocovať.
 +
 
 +
 
 +
== RS232 ==
 +
 
 +
Toto rozhranie zavedieme použitím hardvérového bloku UART, ktorý Cypress obsahuje. Rýchlosť komunikácie bude 19200Bd, čo znamená frekvenciu 153kHz. Keď chceme nastaviť túto frekvenciu, musíme deliť základnú frekvenciu Cypress 24Mhz/156. Použijeme delič frekvencie VC3, ktorý bude následne zdroj frekvencie pre UART. Pre príjímané dáta použijeme pin P0_4 a pre odosielané dáta použijeme pin P0_2. Konkrétne nastavenia bloku UART priamo v PSoC dizajneri sú na obr. 5. Na obr.6. je vidieť umiestnenie blokov UART s schéme zapojenia.
 +
 
 +
[[Súbor:nastavenia UART.jpg|center|thumb|400px|Obr. 5. Konkrétne nastavenia bloku UART]]
 +
 
 +
[[Súbor:Umiestnenie UART.jpg|center|thumb|400px|Obr. 6. Umiestnenie bloku UART v schéme zapojenia]]
 +
 
 +
== I2C ==
 +
 
 +
Aj keď aj pre toto sériové rozhranie existuje hardéverový blok, rozhodli sme sa, že si naprogramujeme vlastný softvér pre implementáciu tohto rozhrania. Toto naše rozhranie nebude potrebovať vonkajšie PULL-UP rezistory.
 +
 
 +
Ako prvé vytvoríme súbor napr. ''i2c.inc'', v ktorom sa nachádzajú deklarácie pre rozhranie I2C. Jeho obsah je nasledovný:
 +
 
 +
<source lang="asm">
 +
; Definicia portu a pinov
 +
; upravit podla aktualneho nastavenia
 +
 
 +
PORT: equ PORT_1         ; PORT_0, PORT_1, PORT_2
 +
SDA: equ P_5 ; P_0, P_1, ... P_7
 +
SCL: equ P_4 ; P_0, P_1, ... P_7
 +
 
 +
;=============================================================================
 +
; Globalne definicie
 +
I2C_WRITE: equ %00000000
 +
I2C_READ: equ %00000001
 +
I2C_ACK: equ %00000010
 +
I2C_NOACK: equ %00000100
 +
 
 +
PORT_2: equ PRT2DR
 +
PORT_1: equ PRT1DR
 +
PORT_0: equ PRT0DR
 +
P_7: equ %10000000
 +
P_6: equ %01000000
 +
P_5: equ %00100000
 +
P_4: equ %00010000
 +
P_3: equ %00001000
 +
P_2: equ %00000100
 +
P_1: equ %00000010
 +
P_0: equ %00000001
 +
;-----------------------------------------------------------------------------
 +
; Makra pre set/clear pinov SDA, SCL
 +
MACRO SET_SDA
 +
mov A, reg[PORT]
 +
or A, SDA
 +
mov reg[PORT],A
 +
call BitDly
 +
ENDM
 +
 
 +
MACRO CLR_SDA
 +
mov A, reg[PORT]
 +
xor A, 0xFF
 +
or A, SDA
 +
xor A, 0xFF
 +
mov reg[PORT],A
 +
call BitDly
 +
ENDM
 +
 
 +
MACRO SET_SCL
 +
mov A, reg[PORT]
 +
or A, SCL
 +
mov reg[PORT],A
 +
call BitDly
 +
ENDM
 +
 
 +
MACRO CLR_SCL
 +
mov A, reg[PORT]
 +
xor A, 0xFF
 +
or A, SCL
 +
xor A, 0xFF
 +
mov reg[PORT],A
 +
call BitDly
 +
ENDM
 +
; Makra pre nastavenie priznakov premennej [Flag]
 +
MACRO SET_NO_ACK
 +
mov [Flag], 0x80
 +
ENDM
 +
 
 +
MACRO CLR_NO_ACK
 +
mov [Flag], 0x00
 +
ENDM
 +
 
 +
MACRO BIT_DELAY
 +
call  BitDly
 +
ENDM
 +
</source>
 +
 
 +
Potom vytvoríme súbor napr. ''i2c.asm'', ktorý obsahuje konkrétne funkcie pre I2C rozhranie. Program zaberá cca 770 Byte v ROM. Hlavným účelom bolo minimalizovať počet premenných v RAM, zrušiť [Flag] a [BitCnt] nahradiť registrom X. Jeho obsah je nasledovný:
 +
 
 +
<source lang="asm">
 +
include "m8c.inc"
 +
include "i2c_sw.inc"
 +
 
 +
export I2C_Init
 +
export I2C_Start
 +
export I2C_Stop
 +
export I2C_Send
 +
export I2C_Recv
 +
 
 +
;=============================================================================
 +
; Premenne pre I2C
 +
area bss(RAM)
 +
BitCnt: BLK 1 ; pocitadlo pre pocet bitov
 +
SlvAdr: BLK 1 ; adresa slave
 +
RcvDat: BLK 1 ; prijate data
 +
Flag: BLK 1 ; priznak
 +
Temp: BLK 1 ; pomocna premenna
 +
;=============================================================================
 +
 
 +
area text
 +
;-----------------------------------------------------------------------------
 +
; BitDly zakladny delay
 +
BitDly: nop ; delay 4x sysclk, upravit podla hodin procesora
 +
; v pripade potreby nizsej prenosovej rychlosti
 +
; sem doplnte casovy slucku
 +
ret
 +
;-----------------------------------------------------------------------------
 +
; I2C_Init inicializacia pinov rozhrania na uroven H
 +
; a reset rozhrania
 +
; Vstup
 +
; -
 +
; Vystup
 +
; -
 +
I2C_Init:
 +
SET_SDA
 +
SET_SCL
 +
call I2C_Stop
 +
ret
 +
;-----------------------------------------------------------------------------
 +
; SendStart vysle I2C start a adresu slave
 +
; nastavuje priznak premennej [Flag] NO_ACK, ak slave nepotvrdil
 +
; prijem znaku
 +
; Vstup
 +
; A - adresa slave
 +
; X - mod (I2C_READ, I2C_WRITE)
 +
; Vystup
 +
; -
 +
I2C_Start: asl A ; posun adrsy
 +
mov [SlvAdr],A ; odlozenie adresy
 +
swap A,X ; maska modu
 +
or [SlvAdr],A
 +
CLR_SDA
 +
CLR_SCL
 +
mov A, [SlvAdr]
 +
call I2C_Send
 +
ret
 +
;-----------------------------------------------------------------------------
 +
; SendStop vysle stop na I2C a uvolni linku
 +
; Vstup
 +
; -
 +
; Vystup
 +
; -
 +
I2C_Stop: CLR_SDA
 +
SET_SCL
 +
SET_SDA
 +
ret
 +
;-----------------------------------------------------------------------------
 +
; SendByte vysle znak
 +
; nastavuje priznak NO_ACK v premennej [Flag]
 +
; Vstup
 +
; A - znak
 +
; Vystup
 +
; -
 +
I2C_Send: CLR_NO_ACK
 +
mov [BitCnt],0x08
 +
sbLoop: asl A ; nastavenie SDA podla rotovaneho bitu v CY
 +
 +
push A
 +
jnc sb_low ; ? CY == 0
 +
SET_SDA ; CY = 1, SDA -> 1
 +
jmp sb_end
 +
sb_low: CLR_SDA ; CY = 0, SDA -> 0
 +
sb_end: SET_SCL ;
 +
CLR_SCL ;
 +
pop A
 +
 +
dec [BitCnt]
 +
jnz sbLoop ; podmienka cyklu
 +
 +
SET_SDA ; uvolnenie datovej linky pre ACK
 +
SET_SCL ; vyslanie clocku pre ACK
 +
 +
mov A, reg[PORT] ; kontrola na potvrdenia ACK od slave
 +
and A, SDA
 +
jnz sb_ex ; SDA = 1, slave potvrdil
 +
SET_NO_ACK ; nastavenie priznaku NoACK
 +
 +
sb_ex: CLR_SCL
 +
ret
 +
;-----------------------------------------------------------------------------
 +
; RecvByte - nacitanie byte z I2C
 +
; Vstup
 +
; A  - priznak potvrdenia nacitaneho znaku (I2C_ACK, I2C_NO_ACK)
 +
; Vystup
 +
; A - nacitany znak
 +
I2C_Recv: push A
 +
mov [BitCnt],0x08
 +
mov [RcvDat],0x00
 +
 +
rbLoop: SET_SDA ; ***** doplnene
 +
SET_SCL ; clock pre nacitanie bitu
 +
 
 +
mov A,reg[PORT] ; nacitanie a ulozenie bitu
 +
 
 +
mov [Temp],0x80 ; nasada pre rotaciu
 +
and A,SDA ; kontrola na stav bitu SDA
 +
jnz rb_H ;
 +
asl [Temp] ; nastavenie CY bitu
 +
rb_H: asl [Temp] ; 1x rotacia - set CY, 2x rotacia - clear CY
 +
rb_set: mov A,[RcvDat]
 +
rlc A ; presun CY do dat
 +
mov [RcvDat],A
 +
 
 +
CLR_SCL
 +
dec [BitCnt]
 +
jnz rbLoop ; koniec cyklu
 +
 +
pop A ; vytiahnutie priznaku zo stacku
 +
 +
cmp A, I2C_ACK
 +
jnz rb_noack
 +
CLR_SDA ; ack by master
 +
jmp rb_ex
 +
 +
rb_noack:
 +
SET_SDA ; no ack by master, last byte
 +
 +
rb_ex: SET_SCL
 +
CLR_SCL ; ***** doplnene
 +
SET_SDA
 +
mov A,[RcvDat]
 +
ret
 +
</source>
 +
 
 +
== Konečne reálna komunikácia s LM92 ==
 +
 
 +
Po všetkých týchto krokoch sa môžme vrhnúť do vytvorenia programu, ktorý bude pomocou vyššie uvedeného rozhrania získavať informácie z teplomera a posielať ich cez sériové rozhranie RS232 do počítača. Pre príjem a odosielanie informácií môžme použiť program terminál.
 +
 
 +
<source lang="asm">
 +
include "m8c.inc"      ; part specific constants and macros
 +
include "memory.inc"    ; Constants & macros for SMM/LMM and Compiler
 +
include "PSoCAPI.inc"  ; PSoC API definitions for all User Modules
 +
include "i2c.inc" ; deklaracie a premenne pre I2C
 +
include "i2c.asm"
 +
 
 +
export _main
 +
 
 +
LM92_ADR: equ 0x4B ; adresa teplomera
  
- sériové rozhranie
+
; registre teplomera (konstatnty)
  
- výstup pre vypnutie systému pri kritickej teplote
+
LM92_T_TEMP: equ 0x00         ; aktualna teplota
 +
LM92_CONFIG: equ    0x01         ; konfiguracny register
 +
LM92_T_HYST: equ    0x02         ; hystereza
 +
LM92_T_CRIT: equ 0x03         ; kriticka teplota (80 stupnov)
 +
LM92_T_LOW:    equ    0x04         ; dolna hranica termostatu
 +
LM92_T_HIGH: equ    0x05         ; horna hranica termostatu
 +
LM92_MIR: equ    0x07         ; manufacturer identification register (MIR)
 +
;-----------------------------------------------------------------------------
 +
area lit
 +
text:
 +
DS "Komunikacia OK" ; kontrola komunikacie
 +
DB 0x00
  
- minimálna spotreba energie pri Shut-down móde
+
area bss(RAM) ; premenne
 +
lm92_temp: BLK 2 ; namerana teplota (rezervované 2 bajty v RAM)
 +
;-----------------------------------------------------------------------------
 +
area text
 +
_main:
 +
mov  A,UART_PARITY_NONE 
 +
        call  UART_Start              ; UART 19200bd, 8bit,1,N
 +
M8C_EnableGInt   
 +
call I2C_Init ; inicializacia I2C zbernice
 +
WaitForData:                      ; cakanie na povel z RS232   
 +
        call  UART_bReadRxStatus   
 +
        and  A, UART_RX_COMPLETE      ;ak nebol prijaty ziadny znak,   
 +
        jz    WaitForData              ;vrati sa na WaitForData
 +
        call  UART_bReadRxData          ; cita data   
 +
        call  UART_SendData            ; prenasa data
  
- až 4 teplotné snímače LM92 je možné pripojiť na jednu zbernicu
+
cmp A,'q' ; kontrola komunikacie (v kazdom z nasledujucich krokov sa prijate data porovnavaju s danym znakom, napr.q)
 +
jz state_q                      ; ak nastane zhoda zero flag ZF sa nastavi na 1 a program prejde do prislusnej casi, napr. state_q
  
- 12 bitový znamienkový výstup
+
cmp A,'w' ; vycitanie prednastaveneho registra (T_TEMP - default)
 +
jz state_w
  
- Operuje až do 150 ºC
+
cmp A,'a' ; nastavenie registra T_TEMP
 +
jz state_a
  
 +
        cmp A,'s' ; nastavenie registra T_CONFIG
 +
jz state_s
  
'''Špecifikácie'''
+
cmp A,'d' ; nastavenie registra T_HYST
 +
jz state_d
 +
 
 +
        cmp A,'f' ; nastavenie registra T_CRIT
 +
jz state_f
 +
 
 +
cmp A,'g' ; nastavenie registra T_LOW
 +
jz state_g
 +
 
 +
        cmp A,'h' ; nastavenie registra T_HIGH
 +
jz state_h
 +
 
 +
cmp A,'j' ; nastavenie registra MIR
 +
jz state_j
 +
 
 +
    jmp  WaitForData              ; navrat do zakladnej slucky
 +
;-------------------------------------------------------------------------------
 +
 
 +
state_q: ; kontrola komunikacie
 +
        call UART_PutCRLF              ; odriadkovanie
 +
        mov A, >text                    ; do A sa ulozi prvy znak retazca text                 
 +
mov X, <text                    ; do X sa ulozi posledny znak retazca text
 +
call UART_CPutString            ; vytlaci sa retazec text
 +
        call UART_PutCRLF              ; odriadkovanie
 +
 
 +
    jmp  WaitForData                  ; navrat do zakladnej slucky
 +
;-------------------------------------------------------------------------------- 
 +
 
 +
state_w: ; vycitanie obsahu nastaveneho registra teplomera
 +
 
 +
mov A, LM92_ADR                ; nastavenie adresy slave, resp. LM92 pre I2C
 +
mov X, I2C_READ ; nastavenie komunikacie na citanie
 +
call I2C_Start ; zaciatok komunikacie
 +
mov A, I2C_ACK ; nacitanie prveho byte
 +
call I2C_Recv
 +
mov [lm92_temp],A
 +
mov A, I2C_NOACK ; nacitanie druheho (posledneho) byte
 +
call I2C_Recv
 +
mov [lm92_temp+1],A
 +
call I2C_Stop ; ukoncenie komunikacie
 +
call UART_PutCRLF ; odriadkovanie terminalu
 +
mov A,[lm92_temp] ; vypis udaju teploty na terminal (prvy byte)
 +
call UART_PutSHexByte          ; v hexadecimalnom tvare
 +
mov A,[lm92_temp+1] ; vypis udaju teploty na terminal (druhy byte)
 +
call UART_PutSHexByte          ; v hexadecimalnom tvare
 +
;----------------------------------------------------------------------------------
 +
 
 +
state_a:
 +
 
 +
mov A, LM92_T_TEMP              ; do A sa presunie adresa registra T_TEMP
 +
call set_register         ; zavola sa funkcia set_register
 +
jmp  WaitForData              ; navrat do zakladnej slucky
 +
;----------------------------------------------------------------------------------
 +
 
 +
state_s:
 +
 
 +
mov A, LM92_CONFIG         ; rovnaky postup ako pri state_a
 +
call set_register ; len pre ine registre
 +
jmp  WaitForData
 +
 
 +
;----------------------------------------------------------------------------------
 +
 
 +
state_d:
 +
 
 +
mov A, LM92_T_HYST
 +
call set_register
 +
jmp  WaitForData
 +
 
 +
;----------------------------------------------------------------------------------
 +
 
 +
state_f:
 +
 
 +
mov A, LM92_T_CRIT
 +
call set_register
 +
jmp  WaitForData
 +
 
 +
;----------------------------------------------------------------------------------
 +
 
 +
state_g:
 +
 
 +
mov A, LM92_T_LOW
 +
call set_register
 +
jmp  WaitForData
  
- napájanie 2,7V až 5,5V
+
;----------------------------------------------------------------------------------
  
- spotreba počas behu 350 μA
+
state_h:
  
-      spotreba počas shut-down 5 μA
+
mov A, LM92_T_HIGH
 +
call set_register
 +
jmp  WaitForData
  
- Rozlíšenie 0,0625 ºC
+
;----------------------------------------------------------------------------------
 +
state_j:
  
 +
mov A, LM92_MIR
 +
call set_register
 +
        jmp  WaitForData
  
[[Súbor:Popis pinov LM92.jpg|center|thumb|400px|Obr. 2. Popis pinov]]
+
;----------------------------------------------------------------------------------
 +
; set_register nastavenie aktualneho registra LM92
  
SDA – sériová obojsmerná dátová linka
+
; Vstup
  
SCL – hodinový vstup
+
; A - cislo registra
  
T_CRIT_A – výstup alarmu pri kritickej teplote
+
; Vystup
  
INT – výstup pre prerušenie
+
; -
  
GND – zem
+
set_register:
  
+Vs – napájanie
+
push A                            ; hodnota A sa zapise na vrch zasobnika, resp. SP
 +
mov A, LM92_ADR                  ; do A sa presunie adresa LM92
 +
mov X, I2C_WRITE   ; nastavenie komunikacie na zapis
 +
call I2C_Start   ; zaciatok komunikacie
 +
pop A                            ; posledny byte zo zasobnika sa vymaze a zapise sa do A
 +
call I2C_Send                    ; hodnota A,t.j. cislo registra sa posle
 +
call I2C_Stop   ; ukoncenie komunikacie
  
A0 – A1 – nastavenie adresy
+
jmp  WaitForData           ; navrat do zakladnej slucky
 +
ret                              ; PC register sa zameni za prve dva byty v SP
 +
</source>
  
'''Dátový formát teploty'''
+
Keď toto všetko dáme dokopy, môžme si vyskúšať komunikáciu s teplomerom LM92. Na ilustráciu uvediem aj hardvérové zapojenie, ktoré je možné vidieť na obr. 7.
  
Teplotné dáta môžu byť čítané z teplomera alebo z registrov pre SetPointy; a zapisované do Setpoint registrov. Teplotné dáta môžu byť čítané kedykoľvek. Ak bude frekvencia čítania dát vysoká, dáta v teplomery sa nestihnú obnoviť. Teplotné dáta sú reprezentované 13-bitovým binárnym číslom s LSB. Jeden bit je rovný 0, 0625 ºC.
+
[[Súbor:Zapojenie s LM92.jpg|center|thumb|400px|Obr. 7. Hardvérové zapojenie]]

Aktuálna revízia z 09:59, 21. marec 2013

Predmet

Konfigurovateľné mikroprocesorové systémy
Tématická časť:
Sériové komunikačné zbernice

Teplotný snímač LM92

Všeobecný popis

LM92 je digitálny teplomer a tepelný komparátor s I2C rozhraním, jeho presnosť je ±0.33ºC. Môže byť napájaný v rozsahu napätí 2,7V až 5,5V. Sériová zbernica, 12-bitový znamienkový výstup a rozsah 128 ºC je ideálny pre široký rozsah aplikácií, napr. teplotný manažment a ochrana aplikácií v PC, elektronické testovacie náradie, kancelárska technika, elektronika, automobilové a medicínske aplikácie.

Obr. 1. Bloková schéma

Charakteristické znaky

  • jednoduchý dizajn
  • zaznamenávanie a kontrola teploty
  • sériové rozhranie
  • výstup pre vypnutie systému pri kritickej teplote
  • minimálna spotreba energie pri Shut-down móde
  • až 4 teplotné snímače LM92 je možné pripojiť na jednu zbernicu
  • 12 bitový znamienkový výstup
  • Operuje až do 150 ºC


Špecifikácie

  • napájanie 2,7V až 5,5V
  • spotreba počas behu 350 μA
  • spotreba počas shut-down 5 μA
  • Rozlíšenie 0,0625 ºC


Obr. 2. Popis pinov
SDA 
sériová obojsmerná dátová linka
SCL 
hodinový vstup
T_CRIT_A 
výstup alarmu pri kritickej teplote
INT 
výstup pre prerušenie
GND 
zem
+Vs 
napájanie
A0 – A1 
nastavenie adresy

Dátový formát teploty

Teplotné dáta môžu byť čítané z teplomera alebo z registrov pre SetPointy; a zapisované do Setpoint registrov. Teplotné dáta môžu byť čítané kedykoľvek. Ak bude frekvencia čítania dát vysoká, dáta v teplomery sa nestihnú obnoviť. Teplotné dáta sú reprezentované 13-bitovým binárnym číslom s LSB. Jeden bit je rovný 0, 0625 ºC.

Obr. 3. Teplotný register

Ako vidíme na obr. 3, bity D0 až D2 sú stavové bity. Teplota je na D3 až D14 a D15 je znamienko. Ak D15 je 1, znamienko je -. Príklady reprezentácie teploty sú na obr. 4. Treba si uvedomiť, že ak prečítame tento register získame 16 bitov, čo nie je hneď konkrétna nameraná teplota. Ak chceme získať teplotu, musíme sa zbaviť stavových bitov D0 až D2.

Obr. 4. Digitálny výstup z teplomera


Spojenie LM92 s mikrokontrolérom Cypress

Pre spojenie potrebujeme sériové rozhranie I2C, ktoré slúži na komunikáciu mikrokontroléra s teplomerom a napríklad RS232 rozhranie pre komunikáciu mikrokontroléra s počítačom, kde môžme získané informácie ďalej spracovávať a vyhodnocovať.


RS232

Toto rozhranie zavedieme použitím hardvérového bloku UART, ktorý Cypress obsahuje. Rýchlosť komunikácie bude 19200Bd, čo znamená frekvenciu 153kHz. Keď chceme nastaviť túto frekvenciu, musíme deliť základnú frekvenciu Cypress 24Mhz/156. Použijeme delič frekvencie VC3, ktorý bude následne zdroj frekvencie pre UART. Pre príjímané dáta použijeme pin P0_4 a pre odosielané dáta použijeme pin P0_2. Konkrétne nastavenia bloku UART priamo v PSoC dizajneri sú na obr. 5. Na obr.6. je vidieť umiestnenie blokov UART s schéme zapojenia.

Obr. 5. Konkrétne nastavenia bloku UART
Obr. 6. Umiestnenie bloku UART v schéme zapojenia

I2C

Aj keď aj pre toto sériové rozhranie existuje hardéverový blok, rozhodli sme sa, že si naprogramujeme vlastný softvér pre implementáciu tohto rozhrania. Toto naše rozhranie nebude potrebovať vonkajšie PULL-UP rezistory.

Ako prvé vytvoríme súbor napr. i2c.inc, v ktorom sa nachádzajú deklarácie pre rozhranie I2C. Jeho obsah je nasledovný:

; Definicia portu a pinov 
; upravit podla aktualneho nastavenia

PORT:		equ		PORT_1	        ; PORT_0, PORT_1, PORT_2
SDA:		equ		P_5		; P_0, P_1, ... P_7
SCL:		equ		P_4		; P_0, P_1, ... P_7

;=============================================================================
; Globalne definicie
I2C_WRITE:	equ		%00000000
I2C_READ:	equ		%00000001	
I2C_ACK:	equ		%00000010
I2C_NOACK:	equ		%00000100

PORT_2:		equ 	PRT2DR
PORT_1:		equ 	PRT1DR
PORT_0:		equ 	PRT0DR
P_7:		equ		%10000000
P_6:		equ		%01000000
P_5:		equ		%00100000
P_4:		equ		%00010000
P_3:		equ		%00001000
P_2:		equ		%00000100
P_1:		equ		%00000010
P_0:		equ		%00000001
;-----------------------------------------------------------------------------
; Makra pre set/clear pinov SDA, SCL
MACRO SET_SDA
	mov A, reg[PORT]
	or A, SDA
	mov reg[PORT],A
	call BitDly
ENDM

MACRO CLR_SDA
	mov A, reg[PORT]
	xor A, 0xFF
	or A, SDA
	xor A, 0xFF
	mov reg[PORT],A
	call BitDly
ENDM

MACRO SET_SCL
	mov A, reg[PORT]
	or A, SCL
	mov reg[PORT],A
	call BitDly
ENDM

MACRO CLR_SCL
	mov A, reg[PORT]
	xor A, 0xFF
	or A, SCL
	xor A, 0xFF
	mov reg[PORT],A
	call BitDly
ENDM
; Makra pre nastavenie priznakov premennej [Flag]
MACRO SET_NO_ACK
	mov [Flag], 0x80
ENDM

MACRO CLR_NO_ACK
	mov [Flag], 0x00
ENDM

MACRO BIT_DELAY
	call  BitDly
ENDM

Potom vytvoríme súbor napr. i2c.asm, ktorý obsahuje konkrétne funkcie pre I2C rozhranie. Program zaberá cca 770 Byte v ROM. Hlavným účelom bolo minimalizovať počet premenných v RAM, zrušiť [Flag] a [BitCnt] nahradiť registrom X. Jeho obsah je nasledovný:

include "m8c.inc"
include "i2c_sw.inc"

export I2C_Init
export I2C_Start
export I2C_Stop
export I2C_Send
export I2C_Recv

;=============================================================================
; Premenne pre I2C
area bss(RAM)
	BitCnt:		BLK 1		; pocitadlo pre pocet bitov
	SlvAdr:		BLK 1		; adresa slave
	RcvDat:		BLK 1		; prijate data
	Flag:		BLK 1		; priznak
	Temp:		BLK 1		; pomocna premenna
;=============================================================================

area text
;-----------------------------------------------------------------------------
; BitDly	zakladny delay 
BitDly:		nop			; delay 4x sysclk, upravit podla hodin procesora
						; v pripade potreby nizsej prenosovej rychlosti 
						; sem doplnte casovy slucku 
			ret
;-----------------------------------------------------------------------------
; I2C_Init	inicializacia pinov rozhrania na uroven H
;			a reset rozhrania
; Vstup
;	-
; Vystup
;	-
I2C_Init:
			SET_SDA
 			SET_SCL
 			call I2C_Stop
 			ret
;-----------------------------------------------------------------------------
; SendStart vysle I2C start a adresu slave
;			nastavuje priznak premennej [Flag] NO_ACK, ak slave nepotvrdil 
;			prijem znaku
; Vstup
; 	A - adresa slave
;	X - mod (I2C_READ, I2C_WRITE)
; Vystup
; 	-
I2C_Start:	asl A				; posun adrsy
			mov [SlvAdr],A		; odlozenie adresy
			swap A,X			; maska modu
			or [SlvAdr],A	
			CLR_SDA			 
			CLR_SCL				
			mov A, [SlvAdr]
			call I2C_Send
			ret
;-----------------------------------------------------------------------------
; SendStop	vysle stop na I2C a uvolni linku
; Vstup
;	-
; Vystup
;	-
I2C_Stop:	CLR_SDA
			SET_SCL
			SET_SDA
			ret
;-----------------------------------------------------------------------------
; SendByte	vysle znak
;			nastavuje priznak NO_ACK v premennej [Flag]
; Vstup
;	A	- znak
; Vystup
; 	-
I2C_Send:	CLR_NO_ACK
			mov	[BitCnt],0x08
	sbLoop:	asl A				; nastavenie SDA podla rotovaneho bitu v CY
			
			push A
			jnc	sb_low			; ? CY == 0
			SET_SDA				; 	CY = 1, SDA -> 1	
			jmp sb_end
	sb_low:	CLR_SDA				;	CY = 0, SDA -> 0
	sb_end:	SET_SCL				;					 
			CLR_SCL				; 
			pop A
			
			dec [BitCnt]	
			jnz sbLoop			; podmienka cyklu
			
			SET_SDA				; uvolnenie datovej linky pre ACK 
			SET_SCL				; vyslanie clocku pre ACK
	
			mov A, reg[PORT]	; kontrola na potvrdenia ACK od slave
			and A, SDA
			jnz sb_ex			; SDA = 1, slave potvrdil
			SET_NO_ACK			; nastavenie priznaku NoACK
			
	sb_ex:	CLR_SCL
			ret
;-----------------------------------------------------------------------------
; RecvByte	- nacitanie byte z I2C
; Vstup
;	A  - priznak potvrdenia nacitaneho znaku (I2C_ACK, I2C_NO_ACK)
; Vystup
;	A - nacitany znak	 
I2C_Recv:	push A
			mov	[BitCnt],0x08
			mov [RcvDat],0x00
			
	rbLoop:	SET_SDA				; ***** doplnene
			SET_SCL				; clock pre nacitanie bitu 

			mov A,reg[PORT]		; nacitanie a ulozenie bitu

			mov [Temp],0x80		; nasada pre rotaciu
			and A,SDA			; kontrola na stav bitu SDA
			jnz rb_H			;
			asl [Temp]			; nastavenie CY bitu 
	rb_H:	asl [Temp]			; 1x rotacia - set CY, 2x rotacia - clear CY
	rb_set: mov A,[RcvDat] 
			rlc A				; presun CY do dat		
			mov [RcvDat],A

			CLR_SCL
			dec [BitCnt]
			jnz rbLoop			; koniec cyklu
			
			pop A				; vytiahnutie priznaku zo stacku
		
			cmp A, I2C_ACK
			jnz	rb_noack
			CLR_SDA				; ack by master
			jmp rb_ex
	
	rb_noack:
			SET_SDA				; no ack by master, last byte
			
	rb_ex:	SET_SCL
			CLR_SCL				; ***** doplnene
			SET_SDA
			mov A,[RcvDat]
			ret

Konečne reálna komunikácia s LM92

Po všetkých týchto krokoch sa môžme vrhnúť do vytvorenia programu, ktorý bude pomocou vyššie uvedeného rozhrania získavať informácie z teplomera a posielať ich cez sériové rozhranie RS232 do počítača. Pre príjem a odosielanie informácií môžme použiť program terminál.

include "m8c.inc"       	; part specific constants and macros
include "memory.inc"    	; Constants & macros for SMM/LMM and Compiler
include "PSoCAPI.inc"   	; PSoC API definitions for all User Modules
include "i2c.inc"		; deklaracie a premenne pre I2C
include "i2c.asm"

export _main

LM92_ADR:		equ	0x4B	; adresa teplomera	

; registre teplomera (konstatnty)

LM92_T_TEMP:	equ	0x00	        ; aktualna teplota
LM92_CONFIG:	equ     0x01	        ; konfiguracny register	
LM92_T_HYST:	equ     0x02	        ; hystereza
LM92_T_CRIT:	equ	0x03	        ; kriticka teplota (80 stupnov)
LM92_T_LOW:     equ     0x04	        ; dolna hranica termostatu
LM92_T_HIGH:	equ     0x05	        ; horna hranica termostatu
LM92_MIR:	equ     0x07	        ; manufacturer identification register (MIR)
;-----------------------------------------------------------------------------
area lit
	text:					
		DS "Komunikacia OK"	; kontrola komunikacie			
		DB 0x00

area bss(RAM)				; premenne
	lm92_temp:	BLK 2		; namerana teplota (rezervované 2 bajty v RAM)
;-----------------------------------------------------------------------------
area text
_main:	
	mov   A,UART_PARITY_NONE  
        call  UART_Start      	        ; UART 19200bd, 8bit,1,N
	M8C_EnableGInt    
	call I2C_Init			; inicializacia I2C zbernice
WaitForData:               	        ; cakanie na povel z RS232     
        call  UART_bReadRxStatus    
        and   A, UART_RX_COMPLETE       ;ak nebol prijaty ziadny znak,    
        jz    WaitForData               ;vrati sa na WaitForData
        call  UART_bReadRxData          ; cita data    
        call  UART_SendData             ; prenasa data 

 	cmp A,'q'			; kontrola komunikacie (v kazdom z nasledujucich krokov sa prijate data porovnavaju s danym znakom, napr.q)
 	jz state_q                      ; ak nastane zhoda zero flag ZF sa nastavi na 1 a program prejde do prislusnej casi, napr. state_q 

 	cmp A,'w'			; vycitanie prednastaveneho registra (T_TEMP - default)
 	jz state_w

 	cmp A,'a'			; nastavenie registra T_TEMP
 	jz state_a

        cmp A,'s'			; nastavenie registra T_CONFIG
 	jz state_s

 	cmp A,'d'			; nastavenie registra T_HYST
 	jz state_d

        cmp A,'f'			; nastavenie registra T_CRIT
 	jz state_f

 	cmp A,'g'			; nastavenie registra T_LOW
 	jz state_g

        cmp A,'h'			; nastavenie registra T_HIGH
 	jz state_h

 	cmp A,'j'			; nastavenie registra MIR
 	jz state_j

    jmp   WaitForData      	        ; navrat do zakladnej slucky
;-------------------------------------------------------------------------------

state_q:				; kontrola komunikacie
        call UART_PutCRLF               ; odriadkovanie
        mov A, >text                    ; do A sa ulozi prvy znak retazca text                   
	mov X, <text                    ; do X sa ulozi posledny znak retazca text
	call UART_CPutString            ; vytlaci sa retazec text
        call UART_PutCRLF               ; odriadkovanie

    jmp   WaitForData                   ; navrat do zakladnej slucky
;--------------------------------------------------------------------------------   

state_w:				; vycitanie obsahu nastaveneho registra teplomera

	mov A, LM92_ADR                 ; nastavenie adresy slave, resp. LM92 pre I2C
	mov X, I2C_READ			; nastavenie komunikacie na citanie
	call I2C_Start			; zaciatok komunikacie
	mov A, I2C_ACK			; nacitanie prveho byte
	call I2C_Recv
	mov [lm92_temp],A
	mov A, I2C_NOACK		; nacitanie druheho (posledneho) byte
	call I2C_Recv
	mov [lm92_temp+1],A
	call I2C_Stop			; ukoncenie komunikacie
	call UART_PutCRLF		; odriadkovanie terminalu
	mov A,[lm92_temp] 		; vypis udaju teploty na terminal (prvy byte)
	call UART_PutSHexByte           ; v hexadecimalnom tvare
	mov A,[lm92_temp+1] 		; vypis udaju teploty na terminal (druhy byte)
	call UART_PutSHexByte           ; v hexadecimalnom tvare
;----------------------------------------------------------------------------------

state_a:				

	mov A, LM92_T_TEMP              ; do A sa presunie adresa registra T_TEMP		
	call set_register	        ; zavola sa funkcia set_register		
	jmp   WaitForData               ; navrat do zakladnej slucky
;----------------------------------------------------------------------------------

state_s:				

	mov A, LM92_CONFIG	        ; rovnaky postup ako pri state_a	
	call set_register		; len pre ine registre	
	jmp   WaitForData 

;----------------------------------------------------------------------------------

state_d:				

	mov A, LM92_T_HYST		
	call set_register			
	jmp   WaitForData 

;----------------------------------------------------------------------------------

state_f:				

	mov A, LM92_T_CRIT		
	call set_register			
	jmp   WaitForData 

;----------------------------------------------------------------------------------

state_g:				

	mov A, LM92_T_LOW		
	call set_register			
	jmp   WaitForData 

;----------------------------------------------------------------------------------

state_h:				

	mov A, LM92_T_HIGH		
	call set_register			
	jmp   WaitForData 

;----------------------------------------------------------------------------------
state_j:				

	mov A, LM92_MIR	
	call set_register			
        jmp   WaitForData 	

;----------------------------------------------------------------------------------
; set_register	nastavenie aktualneho registra LM92

; Vstup 

;	A - cislo registra

; Vystup

; -

set_register:

	push A                            ; hodnota A sa zapise na vrch zasobnika, resp. SP
	mov A, LM92_ADR                   ; do A sa presunie adresa LM92
	mov X, I2C_WRITE		  ; nastavenie komunikacie na zapis
	call I2C_Start			  ; zaciatok komunikacie
	pop A                             ; posledny byte zo zasobnika sa vymaze a zapise sa do A
	call I2C_Send                     ; hodnota A,t.j. cislo registra sa posle 
	call I2C_Stop			  ; ukoncenie komunikacie

	jmp   WaitForData	          ; navrat do zakladnej slucky
	ret                               ; PC register sa zameni za prve dva byty v SP

Keď toto všetko dáme dokopy, môžme si vyskúšať komunikáciu s teplomerom LM92. Na ilustráciu uvediem aj hardvérové zapojenie, ktoré je možné vidieť na obr. 7.

Obr. 7. Hardvérové zapojenie