Você está na página 1de 15

ITAndroids Ser a melhor equipe de robtica do mundo

Tutorial de SPI

Autor: Igor Franzoni Okuyama T-16

Data: 12/12/2012

Pgina 1
ITAndroids Ser a melhor equipe de robtica do mundo

1. Introduo

O Serial Peripheral Interface (SPI) um protocolo de


comunicao sncrono que opera em modo duplex. Ele sncrono,
porque usa um clock externo para mandar informaes e duplex,
pois usa duas linhas de transmisso de dados, uma para enviar e
outra para receber dados.

Nesse protocolo, importante a distino entre Master e Slave.


O Master, ou mestre aquele que controla a comunicao. Ele que
decide quando o Slave (escravo) vai mandar ou receber algum dado.
No SPI, h apenas um Master, mas pode haver vrios Slaves.

Esse tutorial ser baseado no PIC16F877A, e usaremos o


compilador do MikroC.

2. Interface

O SPI usa basicamente 4 pinos:

Serial Data Out (SDO) RC5/SDO: Pino de sada de dados.


(OUTPUT);

Serial Data In (SDI) RC4/SDI/DAS: Pino de entrada de dados


(INPUT);

Serial Clock (SCK) RC3/SCK/SCL: Pino que envia ou recebe o


clock. (OUTPUT para Master e INPUT para Slave);

Slave Select (SS) RA5/AN4/SS/C2OUT: Pino usado para


ativar ou desligar um Slave e usado apenas nos Slaves.
0 (zero) significa que o Slave est ativo, e 1 significa inativo.
Os Slaves desligados no recebero dados do Master, ou
enviaro dados para ele. Use o Slave Select apenas quando
houver mais de um Slave. (INPUT para Slave somente. Master
controla o SS com um pino de output qualquer).

Pgina 2
ITAndroids Ser a melhor equipe de robtica do mundo

Veja um esquema da pinagem para 1 Master e 1 Slave:

Legenda:

SCLK: serial clock (sada do master, entrada no slave);

MOSI: master output, slave input (sada do master, entrada no


slave);

MISO: master input, slave output (sada no slave, entrada no


master);

SS: slave select (sada no master, entrada no slave).

Agora um esquema para 1 Master e 3 Slaves (independentes):

Pgina 3
ITAndroids Ser a melhor equipe de robtica do mundo

3. Registradores

Os registradores ligados ao SPI so 4:

SSPCON
SSPSTAT
SSPBUF
SSPRS

Olhe o datasheet do PIC16F877A para entender o que eles fazem.


Comentaremos um pouco sobre alguns no prximo item.

4. Operao

Aqui explicaremos como funciona o protocolo SPI no


PIC16F877A.

A figura a seguir ser usada na explicao:

Tudo comea com um dado (byte) sendo escrito no buffer


(SSPBUF) do Master. Esse byte copiado para o Shift Register
(SSPSR) e a transmisso comear. O clock inicia-se e a cada
mudana do clock (ver o bit 6 CKE do SSPSTAT) um bit enviado
para o Slave (do mais significativo para o menos significativo). Cada
bit enviado guardado no Shift Register do Slave at formar o byte
completo.

Pgina 4
ITAndroids Ser a melhor equipe de robtica do mundo

Quando o clock se inicia, o Slave tambm comea a enviar o


byte que foi colocado em seu buffer previamente. Assim, ao mesmo
tempo em que o Master envia um byte para o Slave, o Slave envia
um byte para o Master, caracterizando a transmisso duplex.

Quando um byte foi totalmente recebido pelo Master ou pelo


Slave o flag SSPSTAT.BF (Buffer Status bit) fica com estado alto e
ocorre a interrupo do SPI (flag SSPIF). No usaremos a
interrupo nesse tutorial.

importante notar que a transmisso de um dado s


completada se a recepo de um dado for completada. Por isso, o flag
SSPSTAT.BF importante.

Quando o flag SSPSTAT.BF fica alto, deve-se ler o buffer para


que ele volte ao estado baixo. Se isso no for feito, o flag ficar
sempre alto e no poderemos detectar se o PIC recebeu algum dado.
Ler o buffer tambm importante para evitar overflow, isto , evitar
que um novo byte seja recebido, enquanto o buffer ainda guarda o
byte anterior que no foi lido.

OBS*: Comentaremos sobre os flags WCOL e SSPOV do


SSPCON1.

Se voc tentar transmitir um dado (escrever dado no buffer)


enquanto estiver transmitindo outro, o flag WCOL ficar alto e o novo
byte a ser enviado ser ignorado. Por isso, sempre verifique se o
WCOL est alto antes de enviar algum dado.

O flag SSPOV ficar alto se ocorrer overflow, como explicamos


acima: se voc tem um byte no lido no buffer e receber outro,
acontece overflow. Se SSPOV ficar alto, significa que voc no leu o
buffer. Sempre leia o buffer, mesmo que ele seja no seja importante.

5. Implementao

Mos obra!

5.1. 1 Master e 1 Slave:

O primeiro circuito que iremos fazer ter apenas um Master e


um Slave, trocando informao entre si. O Master enviar potncias

Pgina 5
ITAndroids Ser a melhor equipe de robtica do mundo

de 2 para o Slave, e o Slave enviar um contador binrio para o


Master =D. Veja os cdigos:

Cdigo do Master:

//ITAndroids

//1 Master e 1 Slave

//Cdigo para o Master

//Compilado em MikroC 5.3

//by Igor Franzoni Okuyama T-16

char rec;

char x = 0b00000001;

char SPI(char buf)

while(SSPCON.WCOL); //Esperar para no haver coliso de dados (Esperar a transmisso


anterior se completar)

SSPBUF = buf; //Carrega o dado a ser enviado no buffer (A transmisso ir comear)

while(!SSPSTAT.BF); //Esperar o recebimento de dados ser completado

return SSPBUF; //Retornar o dado recebido do slave

void init()

//Configurao do SPI

//SSPSTAT:

SSPSTAT.SMP = 0; //Input data sampled at middle of data output time

SSPSTAT.CKE = 0; //Transmit occurs on transition from Idle to active clock state

//SSPCON:

Pgina 6
ITAndroids Ser a melhor equipe de robtica do mundo

SSPCON.SSPEN = 1; //Enables serial port and configures SCK, SDO, SDI, and SS as serial
port pins

SSPCON.CKP = 0; //Idle state for clock is a low level

SSPCON.SSPM3 = 0;

SSPCON.SSPM2 = 0; //SPI Master mode, clock = FOSC/4

SSPCON.SSPM1 = 0;

SSPCON.SSPM0 = 0;

//Configurando portas

TRISC.F3 = 0; //SCK, Pino de clock, Master output

TRISC.F4 = 1; //SDI, Pino de entrada de dados, Master input

TRISC.F5 = 0; //SDO, Pino de sada de dados, Master output

TRISD = 0b00000000; //A porta D ser usada para vermos o que o Master est recebendo

void main()

init();

while(1)

delay_ms(10); //Espera Slave carregar buffer. IMPORTANTE! O Slave tem que carregar
seu buffer antes de o Master carregar! Teste comentar essa

//linha. O Master recebe a mesma coisa que ele enviou, pois no d tempo de o Slave
carregar seu buffer.

rec = SPI(x); //Enviar byte x

PORTD = rec;

delay_ms(1000); //Esperar para transmitir dado novamente

x = x << 1; //Operao shift para esquerda. O bit 1 vai andando

if(x == 0b00000000)

x = 0b00000001;

Pgina 7
ITAndroids Ser a melhor equipe de robtica do mundo

Cdigo do Slave:

//ITAndroids

//1 Master e 1 Slave

//Cdigo para o Slave

//Compilado em MikroC 5.3

//by Igor Franzoni Okuyama T-16

char rec;

int cont = 0;

char SPI(char buf)

while(SSPCON.WCOL); //Esperar no haver coliso de dados (Esperar a transmisso


anterior se completar)

SSPBUF = buf; //Carrega o dado a ser enviado no buffer (A transmisso ir comear)

while(!SSPSTAT.BF); //Esperar o recebimento de dados ser completado

return SSPBUF; //Retornar o dado recebido do slave

void init()

//Configurao do SPI

//SSPSTAT:

SSPSTAT.SMP = 0; //Input data sampled at middle of data output time

SSPSTAT.CKE = 0; //Transmit occurs on transition from Idle to active clock state

//SSPCON:

Pgina 8
ITAndroids Ser a melhor equipe de robtica do mundo

SSPCON.SSPEN = 1; //Enables serial port and configures SCK, SDO, SDI, and SS as serial
port pins

SSPCON.CKP = 0; //Idle state for clock is a low level

SSPCON.SSPM3 = 0;

SSPCON.SSPM2 = 1; //SPI Slave mode, clock = SCK pin. SS pin control disabled. SS can
be used as I/O pin.

SSPCON.SSPM1 = 0;

SSPCON.SSPM0 = 1;

//Configurando portas

TRISC.F3 = 1; //SCK, Pino de clock, Slave input

TRISC.F4 = 1; //SDI, Pino de entrada de dados, Slave input

TRISC.F5 = 0; //SDO, Pino de sada de dados, Slave output

TRISD = 0b00000000; //A porta D ser usada para vermos o que o Slave est recebendo

void main()

init();

while(1)

rec = SPI(cont); //Enviar cont

PORTD = rec; //Escrever o que foi recebido na porta D

delay_ms(100); //Esperar para transmitir dado novamente

cont++; //Aumentar cont para fazer um contador binrio na porta D do Master

if(cont > 255)

cont = 0;

Pgina 9
ITAndroids Ser a melhor equipe de robtica do mundo

Veja um vdeo do funcionamento do circuito no Proteus:

1 Master 1 Slave.avi

5.2 1 Master e 2 Slaves:

Agora faremos um circuito com 1 Master controlando 2 Slaves.


Sendo assim, precisaremos mudar uma configurao nos Slaves.
Precisamos ativar o pino Slave Select (RA5). Para isso, configure os 4
primeiros bits do registrador SSPCON1. Alm disso, precisamos
configurar o pino SS como input. Para isso, alm de fazer TRISA.F5 =
1, devemos desativar os conversores analgicos configurando o
registrador ADCON1.

No Master, devemos usar dois pinos quaisquer como output


para controlar os Slaves. 0 (zero) significa que o Slave est ativo e 1
significa inativo.

Nesse exemplo, os Slaves enviam uma informao qualquer


para o Master, pois o foco est no envio de informao do Master para
os Slaves.

Seguem os cdigos do Master e dos Slaves:

Cdigo do Master:

//ITAndroids

//1 Master e 2 Slaves

//Cdigo para o Master

//Compilado em MikroC 5.3

//by Igor Franzoni Okuyama T-16

#define SS1 PORTB.F6

#define SS2 PORTB.F7

Pgina 10
ITAndroids Ser a melhor equipe de robtica do mundo

char rec;

char x = 0b00000001;

char y = 0b10000000;

char SPI(char buf)

while(SSPCON.WCOL);

SSPBUF = buf;

while(!SSPSTAT.BF);

return SSPBUF;

void init()

//Configurao do SPI

//SSPSTAT:

SSPSTAT.SMP = 0;

SSPSTAT.CKE = 0;

//SSPCON:

SSPCON.SSPEN = 1;

SSPCON.CKP = 0;

SSPCON.SSPM3 = 0;

SSPCON.SSPM2 = 0;

SSPCON.SSPM1 = 0;

SSPCON.SSPM0 = 0;

//Configurando portas

TRISB.F6 = 0;

Pgina 11
ITAndroids Ser a melhor equipe de robtica do mundo

TRISB.F7 = 0;

TRISC.F3 = 0;

TRISC.F4 = 1;

TRISC.F5 = 0;

void main()

init();

while(1)

SS1 = 0; //Slave 1 ativo

SS2 = 1; //Slave 2 inativo

delay_ms(1);

rec = SPI(x);

delay_ms(500);

x = x << 1;

if(x == 0b00000000)

x = 0b00000001;

SS1 = 1; //Slave 1 inativo

SS2 = 0; //Slave 2 ativo

delay_ms(1);

rec = SPI(y);

delay_ms(500);

y = y >> 1;

if(y == 0b00000000)

Pgina 12
ITAndroids Ser a melhor equipe de robtica do mundo

y = 0b10000000;

Cdigo para os Slaves:

//ITAndroids

//1 Master e 2 Slaves

//Cdigo para os Slaves

//Compilado em MikroC 5.3

//by Igor Franzoni Okuyama T-16

char rec;

char SPI(char buf)

while(SSPCON.WCOL);

SSPBUF = buf;

while(!SSPSTAT.BF);

return SSPBUF;

void init()

//Configurao do SPI

//SSPSTAT:

SSPSTAT.SMP = 0;

SSPSTAT.CKE = 0;

//SSPCON:

SSPCON.SSPEN = 1;

Pgina 13
ITAndroids Ser a melhor equipe de robtica do mundo

SSPCON.CKP = 0;

SSPCON.SSPM3 = 0;

SSPCON.SSPM2 = 1; //SPI Slave mode, clock = SCK pin. SS pin control enabled.

SSPCON.SSPM1 = 0;

SSPCON.SSPM0 = 0;

//Configurando portas

ADCON1.PCFG3 = 0;

ADCON1.PCFG3 = 1; //Todo o port A digital

ADCON1.PCFG3 = 1;

ADCON1.PCFG3 = 0;

TRISA.F5 = 1; //Slave Select

TRISC.F3 = 1;

TRISC.F4 = 1;

TRISC.F5 = 0;

TRISD = 0b00000000;

void main()

init();

while(1)

rec = SPI(0);

PORTD = rec;

delay_ms(1);

Pgina 14
ITAndroids Ser a melhor equipe de robtica do mundo

Vdeo do funcionamento:

1 Master e 2 Slaves.avi

6. Bibliografia:

http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus

Datasheet pic 16F877A

Escreva aqui sua opinio sobre o tutorial. O que podemos melhorar?


Alguma parte no est clara? Sugestes?

Pgina 15

Você também pode gostar