Saludos,
después de varios días debatiéndome en que
nuevo post publicar. Entre otras cosas tengo novedades que comentar, partidas
que publicar y alguna que otra sorpresa.
Hoy voy a volver a trabajar con Pics.
Exactamente con el PIC12F1840,
es un chip pequeño de 8 pines que tiene una particularidad, tiene I2C y es una buena
oportunidad de emplear este chip para hacer sensores y actuadores
“inteligentes” y poderlos colgar en el mismo bus.
En la imagen podemos ver la típica
configuración de un bus i2c, el maestro es el que controla la comunicación, pregunta
específicamente a cada esclavo y estos responden si es menester. Si has trabajado
con Arduino los sensores i2c no te serán extraños, empleando la librería Wire(), tienes ejemplos
para conectar sensores. Yo recomiendo emplear la librería I2C.h es más eficiente y más sencilla de usar, o a
mí me lo parece.
Utilizando el PIC12f1840 con el programa CCS compiler hay otros muchos
editores como el MPLAB, pero el CCS tiene una forma de iniciar los
proyectos que te facilita mucho la vida a la hora de iniciar un proyecto con el
PicWizard.
El primer ejemplo que voy a probar es el
programa blink, controlar el encendido y apagado de un Led. Es algo totalmente innecesario
para controlar un led no necesitamos utilizar i2c pero es un proyecto sencillo
que nos permite probar el sistema.
El main.h
tiene la siguiente configuración:
#include <12F1840.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES WDT_SW //No Watch Dog Timer,
enabled in Software
#FUSES NOMCLR //Master Clear pin used for
I/O
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming,
B3(PIC16) or B5(PIC18) used for I/O
#use delay(int=16000000)
#use i2c(Slave,Fast,sda=PIN_A2,scl=PIN_A1,address=0x50,force_hw,
stream=I2CS)
#define DELAY 100
#use FIXED_IO( A_outputs=PIN_A4 )
int rcv_buf[0x10];
int cmd=0xFF;
la salida PIN_A4 es donde conectaremos el led
La dirección i2c de este proyecto será 0x50.
0X50 = 01010000b
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
|
A6
|
A5
|
A4
|
A3
|
A2
|
A1
|
A0
|
R/W
|
ACK
|
0
|
1
|
0
|
1
|
0
|
0
|
0
|
0
|
0
|
2
|
8
|
El bit de menor peso se emplea para indicar si
la comunicación es de lectura o escritura. El ACK es el bit de reconocimiento que envía el receptor 0 indica ACK, 1 indica NO ACK y 2 indica colisión.
Si habéis trabajado con sensores i2c, todos
tienen registros donde podemos leer/escribir o solo leer o solo escribir. Cuando
empecé a realizar este proyecto tenía en mente situar una variable en una dirección
de memoria donde podría escribir y modificar el estado del led. Pues bien es más
simple que esto.
#int_SSP
void SSP_isr(void)
{
int state, incoming;
state = i2c_isr_state(I2CS);
if(state < 0x80) //Maestro enviando.
{
incoming = i2c_read(I2CS);
if (state == 1) { cmd = incoming; }
else if (state > 1) {
rcv_buf[state-2]=incoming;}
}
else if (state>=0x80) { i2c_write(I2CS,input(PIN_A4)); } // Master
leyendo.
}
Ahí tenéis la interrupción según el valor de state, sabremos si hemos recibido una instrucción
de lectura o de escritura. Si es menor de 128 (0x80) el máster quiere escribir
en memoria, y lo guardaremos en el buffer de memoria que hemos definido, diferenciamos
el primer byte como cmd, pues
podemos emplearlo para diferenciar programas. Si no se quiere diferenciar, se podría
hacer de la siguiente forma:
if(state
< 0x80) { rcv_buf[state-1]=i2c_read(I2CS);
}
El programa principal seria.
void
main()
{
enable_interrupts(INT_SSP); //Habilita la interrupcion de entrada i2c
enable_interrupts(GLOBAL);
setup_oscillator(OSC_16MHZ|OSC_TIMER1|OSC_PLL_OFF,0);
//Example blinking LED program
while(true)
{
if(rcv_buf[0]==0x01)
{
output_high(PIN_A4);
}else
{
output_low(PIN_A4);
}
}
}
Si el segundo byte que enviamos es un 1 el led se encenderá, si
enviamos otra cosa se apagará. Con los pics siempre me ha funcionado una prueba
antes de realizar el circuito y grabar el pic, simularlo en proteus para ello
creamos un maestro con el mismo tipo de pic y le añadimos dos pulsadores.
Los pulsadores se emplean para enviar la
secuencia de encendido y de apagado, no me he matado mucho a hacer programa del
master. Las resistencias R2 y R3 son para poner a nivel alto el bus SDA y SCL.
#include <main.h>
#include "iic.c"
int1 ctrl=false;
void
main()
{
setup_oscillator(OSC_16MHZ|OSC_TIMER1|OSC_PLL_OFF,0);
while(TRUE)
{
if(input(PIN_A0))
{
if(!ctrl){
iic_write(0x50,0x00,0x1); }
ctrl=true;
}
if(input(PIN_A3))
{
if(ctrl){ iic_write(0x50,0x00,0x00);}
ctrl=false;
}
}
}
Empleo una librería casera para enviar el i2c, porque con la que viene
en le compilar CCS no envía el ACK y la comunicación no se completa. Al
finalizar este articulo os dejare los enlaces de los programas.
Para hacer la prueba en realidad he empleado
como Master a una arduino el
programa envía la orden de encendido
cada 500 ms y la orden de apagado cada 500ms.
Programa de master
arduino.
Programa
blink
pic.
Programa master Pic.
El Pic12F1840 funciona tanto a 3,3V como a 5.0V,
esto nos permite que se adapte a cualquier sistema i2c.
Como ya os dije el blink es un proyecto de
prueba, ahora toca desarrollar nuevos sensores actuadores que nos permitan
liberar carga al master y potencien nuestros proyectos. Por ejemplo, un Driver
para motores I2C.
A la izquierda la placa con L272M para controlar
dos motores, y a la derecha la misma placa con el PIC12F1840 para controlarlo
por i2c.
Aquí os muestro la placa de motores y la led conectadas por i2c al arduino que hace de master. El led con la dirección 0x50 alimentado a 5V y el driver con dirección 0x48 alimentado a 3,3V.
Esto tiene muchas posibilidades.
Anakleto
No hay comentarios:
Publicar un comentario