Académique Documents
Professionnel Documents
Culture Documents
html
Comunicaciones Serie SPI
Supongamos que nuestro registro tiene 16 bits y al ser circular, el bit que
entra empujando a los dems es justo el que acaba de salir por el otro
lado. Ahora pensar que este registro se parte en dos, cada uno de 8 bits,
pero formando conceptualmente un nico registro de 16 bits:
SSPSTAT.SMP
(Sample bit)
MODE_00
MODE_01
MODE_10
MODE_11
(CKP=0,
(CKP=0,
(CKP=1,
(CKP=1,
CKE=1)
CKE=0)
CKE=1)
CKE=0)
smp_phase
--> SMPEND
--> SMPMID
void spi_enable(void)
// Enable SSP port and set TRIS register
{
TRISCbits.TRISC3=0; TRISCbits.TRISC5=0; TRISCbits.TRISC4=1; // SCL out, SDO,
out, SDI in
SSPCON1bits.SSPEN=1; // Enable SPI port
}
// Sets SPI mode (CPOL,CPHA,SMP)
void spi_mode(uint8 CPOL,uint8 CPHA,uint8 sample)
{
SSPCON1bits.CKP=CPOL; SSPSTATbits.CKE=1-CPHA;
SSPSTATbits.SMP=sample;
}
// Sets clock frequency for SPI in master mode
// clock =3 (TMR2/2) =2 (Fosc/64) =1 (Fosc/16)
void spi_master(uint8 clock)
{
SSPCON1 = (SSPCON1 & 0xF0) | clock;
}
=0 (Fosc/4)
Remarcar que estas funciones no aportan nada que las funciones de C18 o
MikroC no puedan hacer. Las listamos para mostrar que configurar un
perifrico no es complicado y para beneficio de aquellos que usen un
compilador sin soporte para SPI.
Una vez inicializado el puerto con unas u otras funciones, estamos listos
para mandar/recibir datos. Tanto en C18 (ReadSPI, WriteSPI) como en
MikroC (SPI_read, SPI_write) tenemos un par de funciones que
leen/escriben un byte en la lnea SPI.
La siguiente funcin sera nuestro equivalente:
uint8 spi_transfer(uint8 x)
{
haramos:
select_device;
SPI_talk ...
deselect_device;
El problema de este enfoque viene si en otro montaje nos viene mejor usar
un pin diferente como lnea CS. Si estamos usando nuestro propio cdigo no
hay problemas, cambiamos el #define y recompilamos. El problema es si
estamos escribiendo una librera. En ese caso el usuario final tendra que
estar buceando en nuestro cdigo y cambiando los ficheros fuente de la
librera. Eso en el caso de que disponga de los ficheros fuente. Si solo
publicamos la librera ya compilada forzamos al usuario a usar siempre el
pin RC1 cuando use un dispositivo SPI.
Obviamente esto no es muy conveniente, pero parece ser que en C18 no
hay otra alternativa. De hecho, en el manual de libreras del C18 (pag. 80)
indica que si se desea p.e, usar un LCD con una seleccin de pines diferente
de la asignada por defecto se deben modificar las definiciones del
correspondiente fichero xlcd.h.
Este es un caso donde el compilador de MikroC presenta una ventaja frente
al C18. En MikroC tenemos una solucin ms flexible: se trata de declarar
dos variables (p.e. devicename_CS ydevicename_CS_dir) para informar
al resto de las rutinas de que pin estamos usando como ChipSelect (CS) y
su correspondiente bit de direccin TRIS.
En MikroCPro podemos declarar dichas variables de tipo sbit y asociarlas a
los correspondientes pines:
sbit devicename_CS at LATC.B1;
De esta forma el usuario puede elegir el pin a usar para cada montaje o
definir diferentes pines para varios dispositivos, sin tener que modificar la
librera original.
Terminaremos este tutorial usando las rutinas dadas en un programa muy
sencillo que establezca una simple comunicacin SPI entre un PIC (master)
y un perifrico (slave).
Hardware:
Notad que estamos usando RC1 como lnea CS y que no usamos el pin SDI
(RC4) del PIC, puesto que no vamos a recibir ningn dato. La salida de los
canales A y B las conectamos al osciloscopio para ver los resultados.
Software:
El programa es muy sencillo y consiste en poco ms de las funciones que ya
hemos visto.
Lo primero que hay que hacer es determinar el modo SPI con el que trabaja
el perifrico. En su datasheet nos dicen que soporta los modos SPI (0,0) y
(1,1). Del momento de muestreo de los datos de entrada no debemos
preocuparnos porque no existen.
En la docu tambin se nos informa de que el dispositivo acepta hasta 20
MHz de reloj en la comunicacin SPI. En este montaje estoy usando un reloj
de 8 MHz, por lo que puedo usar la frecuencia mxima (Fosc/4 = 2 MHz) y
an as estar muy por debajo de las capacidades del dispositivo.
Una rutina que inicializase la comunicacin SPI con los parmetros
indicados usando las rutinas presentadas antes sera:
void DAC_spi_init(byte clock)
{
DAC_CS_dir=0; deselect_DAC; // Configure CS line as output and set it low.
spi_master(clock);
// Configure SPI as master and set clock
spi_mode(0,0,0);
// SPI mode (0,0). Third arg doesnt matter
spi_enable();
// Enable SPI
}
}
}