0% acharam este documento útil (0 voto)
14 visualizações15 páginas

Tutorial de SPI com PIC16F877A

Enviado por

Eduardo Pinheiro
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato DOCX, PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
14 visualizações15 páginas

Tutorial de SPI com PIC16F877A

Enviado por

Eduardo Pinheiro
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato DOCX, PDF, TXT ou leia on-line no Scribd

ITAndroids “Ser a melhor equipe de robótica do mundo”

Tutorial de SPI

Autor: Igor Franzoni Okuyama T-16

Data: 12/12/2012

Pá gina 1
ITAndroids “Ser a melhor equipe de robótica do mundo”

1. Introdução

O Serial Peripheral Interface (SPI) é um protocolo de


comunicação síncrono que opera em modo duplex. Ele é síncrono,
porque usa um clock externo para mandar informações e é duplex,
pois usa duas linhas de transmissão de dados, uma para enviar e
outra para receber dados.

Nesse protocolo, é importante a distinção entre Master e Slave.


O Master, ou mestre é aquele que controla a comunicação. Ele é que
decide quando o Slave (escravo) vai mandar ou receber algum dado.
No SPI, há apenas um Master, mas pode haver vários 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 saída 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 não receberão dados do Master, ou
enviarão 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).

Pá gina 2
ITAndroids “Ser a melhor equipe de robótica do mundo”

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

Legenda:

 SCLK: serial clock (saída do master, entrada no slave);


 MOSI: master output, slave input (saída do master, entrada no
slave);
 MISO: master input, slave output (saída no slave, entrada no
master);
 SS: slave select (saída no master, entrada no slave).

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

Pá gina 3
ITAndroids “Ser a melhor equipe de robótica do mundo”

3. Registradores

Os registradores ligados ao SPI são 4:

 SSPCON
 SSPSTAT
 SSPBUF
 SSPRS

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


Comentaremos um pouco sobre alguns no próximo item.

4. Operação

Aqui explicaremos como funciona o protocolo SPI no


PIC16F877A.

A figura a seguir será usada na explicação:

Tudo começa com um dado (byte) sendo escrito no buffer


(SSPBUF) do Master. Esse byte é copiado para o Shift Register
(SSPSR) e a transmissão começará. O clock inicia-se e a cada
mudança 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.

Quando o clock se inicia, o Slave também começa a enviar o


byte que foi colocado em seu buffer previamente. Assim, ao mesmo

Pá gina 4
ITAndroids “Ser a melhor equipe de robótica do mundo”

tempo em que o Master envia um byte para o Slave, o Slave envia


um byte para o Master, caracterizando a transmissão duplex.

Quando um byte foi totalmente recebido pelo Master ou pelo


Slave o flag [Link] (Buffer Status bit) fica com estado alto e
ocorre a interrupção do SPI (flag SSPIF). Não usaremos a
interrupção nesse tutorial.

É importante notar que a transmissão de um dado só é


completada se a recepção de um dado for completada. Por isso, o
flag [Link] é importante.

Quando o flag [Link] fica alto, deve-se ler o buffer para


que ele volte ao estado baixo. Se isso não for feito, o flag ficará
sempre alto e não poderemos detectar se o PIC recebeu algum dado.
Ler o buffer também é importante para evitar overflow, isto é, evitar
que um novo byte seja recebido, enquanto o buffer ainda guarda o
byte anterior que não 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 não lido no buffer e receber outro,
acontece overflow. Se SSPOV ficar alto, significa que você não leu o
buffer. Sempre leia o buffer, mesmo que ele seja não seja
importante.

5. Implementação

Mãos à obra!

5.1. 1 Master e 1 Slave:

O primeiro circuito que iremos fazer terá apenas um Master e


um Slave, trocando informação entre si. O Master enviará potências

Pá gina 5
ITAndroids “Ser a melhor equipe de robótica do mundo”

de 2 para o Slave, e o Slave enviará um contador binário para o


Master =D. Veja os códigos:

Código do Master:

//ITAndroids

//1 Master e 1 Slave

//Código para o Master

//Compilado em MikroC 5.3

//by Igor Franzoni Okuyama T-16

char rec;

char x = 0b00000001;

char SPI(char buf)

while([Link]); //Esperar para não haver colisão de dados (Esperar a transmissão


anterior se completar)

SSPBUF = buf; //Carrega o dado a ser enviado no buffer (A transmissão irá começar)

while(![Link]); //Esperar o recebimento de dados ser completado

return SSPBUF; //Retornar o dado recebido do slave

void init()

//Configuração do SPI

//SSPSTAT:

[Link] = 0; //Input data sampled at middle of data output time

[Link] = 0; //Transmit occurs on transition from Idle to active clock state

//SSPCON:

Pá gina 6
ITAndroids “Ser a melhor equipe de robótica do mundo”

[Link] = 1; //Enables serial port and configures SCK, SDO, SDI, and SS as serial
port pins

[Link] = 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 saída 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 não 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; //Operação shift para esquerda. O bit 1 vai andando

if(x == 0b00000000)

x = 0b00000001;

Pá gina 7
ITAndroids “Ser a melhor equipe de robótica do mundo”

Código do Slave:

//ITAndroids

//1 Master e 1 Slave

//Código para o Slave

//Compilado em MikroC 5.3

//by Igor Franzoni Okuyama T-16

char rec;

int cont = 0;

char SPI(char buf)

while([Link]); //Esperar não haver colisão de dados (Esperar a transmissão


anterior se completar)

SSPBUF = buf; //Carrega o dado a ser enviado no buffer (A transmissão irá começar)

while(![Link]); //Esperar o recebimento de dados ser completado

return SSPBUF; //Retornar o dado recebido do slave

void init()

//Configuração do SPI

//SSPSTAT:

[Link] = 0; //Input data sampled at middle of data output time

[Link] = 0; //Transmit occurs on transition from Idle to active clock state

//SSPCON:

Pá gina 8
ITAndroids “Ser a melhor equipe de robótica do mundo”

[Link] = 1; //Enables serial port and configures SCK, SDO, SDI, and SS as serial
port pins

[Link] = 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 saída 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 binário na porta D do Master

if(cont > 255)

cont = 0;

Pá gina 9
ITAndroids “Ser a melhor equipe de robótica do mundo”

Veja um vídeo do funcionamento do circuito no Proteus:

5.2 1 Master e 2 Slaves:

Agora faremos um circuito com 1 Master controlando 2 Slaves.


Sendo assim, precisaremos mudar uma configuração nos Slaves.
Precisamos ativar o pino Slave Select (RA5). Para isso, configure os 4
primeiros bits do registrador SSPCON1. Além disso, precisamos
configurar o pino SS como input. Para isso, além de fazer TRISA.F5 =
1, devemos desativar os conversores analógicos 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 informação qualquer


para o Master, pois o foco está no envio de informação do Master
para os Slaves.

Seguem os códigos do Master e dos Slaves:

Código do Master:

//ITAndroids

//1 Master e 2 Slaves

//Código para o Master

//Compilado em MikroC 5.3

//by Igor Franzoni Okuyama T-16

#define SS1 PORTB.F6

#define SS2 PORTB.F7

Pá gina 10
ITAndroids “Ser a melhor equipe de robótica do mundo”

char rec;

char x = 0b00000001;

char y = 0b10000000;

char SPI(char buf)

while([Link]);

SSPBUF = buf;

while(![Link]);

return SSPBUF;

void init()

//Configuração do SPI

//SSPSTAT:

[Link] = 0;

[Link] = 0;

//SSPCON:

[Link] = 1;

[Link] = 0;

SSPCON.SSPM3 = 0;

SSPCON.SSPM2 = 0;

SSPCON.SSPM1 = 0;

SSPCON.SSPM0 = 0;

//Configurando portas

TRISB.F6 = 0;

Pá gina 11
ITAndroids “Ser a melhor equipe de robótica 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)

Pá gina 12
ITAndroids “Ser a melhor equipe de robótica do mundo”

y = 0b10000000;

Código para os Slaves:

//ITAndroids

//1 Master e 2 Slaves

//Código para os Slaves

//Compilado em MikroC 5.3

//by Igor Franzoni Okuyama T-16

char rec;

char SPI(char buf)

while([Link]);

SSPBUF = buf;

while(![Link]);

return SSPBUF;

void init()

//Configuração do SPI

//SSPSTAT:

[Link] = 0;

[Link] = 0;

//SSPCON:

[Link] = 1;

Pá gina 13
ITAndroids “Ser a melhor equipe de robótica do mundo”

[Link] = 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);

Pá gina 14
ITAndroids “Ser a melhor equipe de robótica do mundo”

Vídeo do funcionamento:

6. Bibliografia:

[Link]

Datasheet pic 16F877A

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


Alguma parte não está clara? Sugestões?

Pá gina 15

Você também pode gostar