mikrokontrolery.net

 

   

Część 4 - Magistrala I2C


W tym ćwiczeniu wykorzystamy dwa dodatkowe układy scalone typu PCF8574A produkcji firmy Philips. Układ ten jest 8-bitowym ekspanderem magistrali I2C. Linie SDA i SCL należy podłączyć odpowiednio do pinów P2.0 i P2.1 mikrokontrolera. Do wyjść pierwszego układu podłączamy diody LED, a do drugiego ukłądu naszą klawiaturę.

Ze względu na złożoność procedur obsługi magistrali I2C przygotowano dla języka asemblera i C oddzielne pliki zwierające podstawowe procedury obsługi tej magistrali. Ma to na celu uniknięcie ciągłego przepisywania stosunkowo dużego kodu zawierającego niezbędne procedury. Zamieszczone poniżej pliki zawierają procedury zapewniające:
- wygenerowanie sekwencji "START"
- wygenerowanie sekwencji "STOP"
- wysłanie na magistralę bajtu danych
- odczytanie z magistrali bajtu danych
Procedury te pozwalają na komunikację z większością typowych układów scalonych zawierających interfejs I2C pracujący w trybie "MASTER-SLAVE".

Plik I2C.ASM
;
; Procedura generująca sekwencję START
;

I2C_START:
SETB SDA
SETB SCL
ACALL DELAY
CLR SDA
ACALL DELAY
CLR SCL
RET

;
; Procedura generująca sekwencję STOP.
; Stan linii SDA zostaje zapamiętany po zakończeniu
; transmisji we wskaˇniku przeniesienia C.
;

I2C_STOP:
CLR SDA
ACALL DELAY
SETB SCL
ACALL DELAY
SETB SDA
ACALL DELAY
MOV C,SDA
RET

;
; Procedura odczytująca bajt z magistrali I2C.
; Wartość bitu ACK należy przekazać do procedury poprzez
; wskaˇnik przeniesienia C.
; Odczytany bajt jest umieszczany w akumulatorze.
;

I2C_READ:
MOV ACK,C
SETB SDA
MOV R0,#8
L0: ACALL DELAY
SETB SCL
ACALL DELAY
MOV C,SDA
RLC A
CLR SCL
DJNZ R0,L0

MOV C,ACK
MOV SDA,C
ACALL DELAY
CLR SCL
RET

;
; Procedura wysyłająca bajt na magistralę I2C.
; Stan bitu ACK jest zwracany poprzez wskaˇnik przeniesienia C.
; Bajt do wysłania należy umieścić w akumulatorze.
;

I2C_WRITE:
MOV R0,#9
SETB C
L1: CLR SCL
RLC A
MOV SDA,C
ACALL DELAY
SETB SCL
ACALL DELAY
DJNZ R0,L1
MOV C,SDA
CLR SCL
RET

DELAY:
NOP
NOP
RET

Plik I2C.C
void delay(void)
{
asm{0x00};
asm{0x00};
}


void I2C_START(void)
{
SDA = SCL = 1;
delay();
SDA = 0;
delay();
SCL = 0;
}

bit I2C_STOP(void)
{
SDA = 0;
delay();
SCL = 1;
delay();
SDA = 1;
delay();
return (~SDA);
}

unsigned char I2C_READ(bit ACK)
{
unsigned char bitCount = 8, temp;

SDA = 1;
do
{
delay();
SCL = 1;
delay();
temp <<= 1;
if (SDA) temp++;
SCL = 0;
} while (--bitCount);
SDA = ACK;
delay();
SCL = 1;
delay();
SCL = 0;
return (temp);
}

bit I2C_WRITE(unsigned char byte)
{
unsigned char bitCount = 9;
bit temp;

do
{
SCL = 0;
SDA = byte & 0x80;
byte = (byte << 1) + 1;
delay();
SCL = 1;
delay();
}while(--bitCount);
temp = SDA;
SCL = 0;
return(temp);
}

Przykład 4.1
Przykład 4.1.ASM
NAME P04_01_ASM_SRC

$INCLUDE (ATMEL/REG8252.INC)

P04_01_ASM SEGMENT CODE

RSEG P04_01_ASM

SDA EQU P2.0
SCL EQU P2.1
ACK EQU 00h

ACALL I2C_START
MOV A, #70h
ACALL I2C_WRITE
MOV A, #254
ACALL I2C_WRITE
ACALL I2C_STOP
SJMP $

$INCLUDE (I2C.ASM)
END

Przykład 4.1.C
#include <ATMEL/REG8252.H>
#include "I2C.H"

void main(void)
{
I2C_START();
I2C_WRITE(0x70);
I2C_WRITE(0xFE);
I2C_STOP();
while(1);
}

Przykład 4.1.BAS
Config Sda = P2.0
Config Scl = P2.1

I2cstart
I2cwbyte &H70
I2cwbyte &HFE
I2cstop
Do
Loop
End

Efektem działania tego programu jest włączenie diody LED D1. Trochę uwagi należy poświęcić programowi w asemblerze i języku C.
W asemblerze dołączenie wspomnianego wcześniej pliku z podstawowymi procedurami nastąpiło przy użyciu dyrektywy "$INCLUDE". Dyrektywa ta powoduje wstawianiu w jej miejsce przez kompilator asemblera zawartości pliku wskazanego tą dyrektywą. Tak więc dwa fizyczne pliki zawierające kod ˇródłowy w czasie kompilacji są łączone w jeden. Konsekwencją tego jest fakt, że cokolwiek zadeklarujemy w pliku pierwszym będzie to obowiązywało również w pliku drugim. Dlatego pomimo pozornego niewykorzystywania bitów SDA i SCL przez program w pliku P04_01_ASM_SRC.A51 umieszczona tam deklaracja jest konieczna do poprawnego działania procedur zawartych w pliku I2C.ASM.
Trochę inaczej ta sprawa przedstawia się w języku C. Plik I2C.C został dodany do projektu za pomocą polecenia "Add node Source / Application" z menu RIDE IDE. Pliku ˇródłowym naszego programu umieszczamy dyrektywę "#include "I2C.H"".Jest to dyrektywa preprocesora włączająca plik nagłówkowy do pliku ˇródłowego. ˇródłowego pliku nagłówkowym umieszczone są prototypy procedur zawartych w pliku I2C.C.
W Bascomie sprawa przedstawia się zupełnie prosto, ponieważ obsługa magistrali I2C jest wbudowana w kompilator i nie ma potrzeby zawracania sobie głowy dołączaniem jakichkolwiek dodatkowych plików a przede wszystkim samodzielnego oprogramowywania transmisji. W tym momencie przewaga Bascoma nad asemblerem i C jest najbardziej widoczna. Aby korzystać z magistrali I2C nie potrzebujemy znać dokładnie protokołu transmisji, wystarczy tylko podłączyć do procesora odpowiednio linie SDA i SCL i możemy w prosty sposób sterować układami przez I2C.

Przykład 4.2.ASM
NAME P04_02_ASM_SRC
$INCLUDE (ATMEL/REG8252.INC)
P04_02_ASM SEGMENT CODE
RSEG P04_02_ASM
SDA EQU P2.0
SCL EQU P2.1
ACK EQU 00h

START:
ACALL I2C_START
MOV A, #72h
ACALL I2C_WRITE
MOV A, #0FFh
ACALL I2C_WRITE
ACALL I2C_STOP

ACALL I2C_START
MOV A,#73h
ACALL I2C_WRITE
MOV A,#0
ACALL I2C_READ
ACALL I2C_STOP

MOV R4, A

ACALL I2C_START
MOV A,#70h
ACALL I2C_WRITE
MOV A,R4
ACALL I2C_WRITE
ACALL I2C_STOP

SJMP START
$INCLUDE (I2C.ASM)
END

Przykład 4.2.C
#include <ATMEL/REG8252.H>
#include "I2C.H"

void main(void)
{
unsigned char temp;

while(1)
{
I2C_START();
I2C_WRITE(0x72);
I2C_WRITE(0xFF);
I2C_STOP();

I2C_START();
I2C_WRITE(0x73);
temp = I2C_READ(1);
I2C_STOP();

I2C_START();
I2C_WRITE(0x70);
I2C_WRITE(temp);
I2C_STOP();
}
}

Przykład 4.2.BAS
Config Sda = P2.0
Config Scl = P2.1
Dim Temp As Byte

Do
I2cstart
I2cwbyte &H72
I2cwbyte &HFF
I2cstop

I2cstart
I2cwbyte &H73
I2crbyte Temp , 9
I2cstop

I2cstart
I2cwbyte &H70
I2cwbyte Temp
I2cstop

Loop
End

Powyższy program odczytuje stan klawiatury i zapala diodę LED o numerze odpowiadającym naciśniętemu przyciskowi klawiatury, czyli odczytuje stan wejść pierwszego układu PCF8574 i przesyła go na wyjścia drugiego układu PCF8574.

Ostatnio na forum:

 

 

 

 

 
 
 
 
 

(c) 2004-2008 Radosław Kwiecień
Polityka prywatności