Quando fiz este código-fonte meu intuito era montar uma comunicação entre os dois chips mas devido a limitação do hardware do pic não foi possível(a menos que fizesse isso de modo manual sem usar o buffer do SPI) , então fiz somente um exemplo que demonstra como enviar os dados do mestre para o escravo sem que haja comunicação do escravo para o mestre,quem sabe futuramente posto aqui um modo de fazer isso manualmente(veja que no avr ATmega328 isso é perfeitamente possível), para quem quiser saber mais sobre o protocolo SPI e I2C veja este link:
http://dev.emcelettronica.com/i2c-or-spi-serial-communication-which-one-to-go
Neste código já está pronto o modo mestre e escravo bastando apenas mudar o nível logico do pino RA0(5V - modo mestre e GND - modo escravo), então o microcontrolador no modo mestre envia um carácter para o microcontrolador que está configurado como escravo, e se for o carácter esperado ele acende um led por um tempo e então deslia o led. Deixei até uma função para ler dados pela SPI no modo mestre("embora não foi utilizado") .
O código - fonte:
/*
* usando SPI no MPlab XC8(modo mestre e escravo)
*
* Compilador : MPlabXC8
* Microcontrolador: 18F13K22
* Autor: aguivone
* Versão: 1
* Data : 17 de abril de 2013
*/
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 12000000 // cristal de 20 Mhz
#include <xc.h>
#define SPI_SLAVE_WRITE 0x00
#define SPI_SLAVE_READ 0x01
/////////////////////////////////////////////////////configuraçôes do pic //////////////////////////////////////////////////
// CONFIG1H
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config PLLEN = OFF // 4 X PLL Enable bit (PLL is under software control)
#pragma config PCLKEN = ON // Primary Clock Enable bit (Primary clock enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
// CONFIG2L
#pragma config PWRTEN = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 19 // Brown Out Reset Voltage bits (VBOR set to 1.9 V nominal)
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
// CONFIG3H
#pragma config HFOFST = ON // HFINTOSC Fast Start-up bit (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
#pragma config MCLRE = OFF // MCLR Pin Enable bit (RA3 input pin enabled; MCLR disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config BBSIZ = OFF // Boot Block Size Select bit (512W boot block size)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
// CONFIG5L
#pragma config CP0 = OFF // Code Protection bit (Block 0 not code-protected)
#pragma config CP1 = OFF // Code Protection bit (Block 1 not code-protected)
// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
// CONFIG6L
#pragma config WRT0 = OFF // Write Protection bit (Block 0 not write-protected)
#pragma config WRT1 = OFF // Write Protection bit (Block 1 not write-protected)
// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot block not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 not protected from table reads executed in other blocks)
// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot block not protected from table reads executed in other blocks)
/////////////////////////////
// Delay in 1 ms (approximately) for 12 MHz Internal Clock
void delay_ms(long mili)
{
while(mili > 0)
{
_delay(2927);//aprox. 1ms com clock de 12mhz
mili--;
}
// no caso do 18F o valor fica bem acima então é melhor montar essa funcão para que trabalhe bem
}
void MASTER_ESC_SPI(unsigned char dados)
{
LATCbits.LC6 = 0; // ativa CS(chip select do MCP23S17)
SSPBUF = 0X01;//opcode que sinaliza que quer deixar um dado
while(!SSPSTATbits.BF);//espera completar envio de dados
delay_ms(1);//espera slave processar informação
SSPBUF = dados;//envia os dados que será colocado no registrador
while(!SSPSTATbits.BF);//espera completar envio de dados
LATCbits.LC6 = 1;//desabilita chip
}
unsigned char MASTER_LER_SPI()
{
LATCbits.LC6 = 0; // ativa SS(slave select)
SSPBUF = 0X00;//um valor qualquer para pegar os dados
//desse registrador(assim gera o clock necessario para isto)
while(!SSPSTATbits.BF);//espera completar envio de dados
LATCbits.LC6 = 1;//desabilita chip
return(SSPBUF);
}
unsigned char SLAVE_LER_SPI()
{
while(!SSPSTATbits.BF);//espera completar recepção
return(SSPBUF);
}
void SPI_MASTER()//modo mestre
{
SSPCON1 = 0X20;//habilita modo SPI // FOSC/4 //
SSPSTAT = 0XC0;//pega amostras no fim do bit e a trasmissão será na borda de descida
TRISB = 0X10;//configura portB como saida exceto o pino b4(SDI)
TRISC = 0X00;//configura portc como saida
LATCbits.LC6 = 1;
}
void SPI_SLAVE()//modo slave
{
SSPCON1 = 0X24;//habilita modo SPI // habilita pino SS(slave select) pois é mais usual assim
SSPSTAT = 0X40;//trasmissão será na borda de descida
TRISB = 0XFF;//configura portB como entrada
TRISC = 0X40;//configura portc como saida exceto C6(SS)
LATCbits.LC7 = 1;//sdo = 1
}
void main(void)
{
TRISA = 0XFF;
ANSEL = 0x00;//desabilita porta analogicas(para não atrapalhar recepção no pino)
ANSELH = 0x00;//em alguns casos não funciona nem a interrupção de recepção.
if(PORTAbits.RA0 == 1)
{//ligado ao vcc é master
SPI_MASTER();
}
else
{//se ligado ao gnd é slave
SPI_SLAVE();
}
for(;;) {
if(PORTAbits.RA0 == 1)
{//ligado ao vcc é master
MASTER_ESC_SPI('F'); // ENVIA UM DADO
delay_ms(500);//tempo para nova solicitação
}
else
{//se ligado ao gnd é slave
if(PORTCbits.RC6 == 0)//pino de ativação foi habilitado?
{
if(SLAVE_LER_SPI() == 'F')//verifica se recebeu um dado do mestre
{
LATCbits.LC0 = 1;
delay_ms(100);
LATCbits.LC0 = 0;
}
}
}
}
}
A simulação:
Faça uma visita na página do face, basta procurar por microcontroladores-C,e dê um "curtir" assim vc fica por dentro das novidades do blog!
Nenhum comentário :
Postar um comentário
olá,digite aqui seu comentário!