Mostrando entradas con la etiqueta PIC18F4550. Mostrar todas las entradas
Mostrando entradas con la etiqueta PIC18F4550. Mostrar todas las entradas

domingo, 2 de enero de 2011

Conversor Analógico-Digital

  Hola a todos de nuevo!! bueno despues de estas mini-vacaciones de navidad (todavía quedan reyes), ya es hora de reemprender la explicación de los diferentes modulos de los que disponemos en los microcontroladores 18f2550 y 18f4550.
  Hasta ahora, los modulos que hemos dado, son genericos, es decir, tanto los temporizadores, como las interrupciones las podemos encontrar en la mayoria de los microcontroladores de la gama 16f y 18f, pero este ya es un poco diferente, ya que, aunque es raro, hay microcontroladores que no disponen de un conversor analógico-digital.
  El conversor AD va a ser uno de los módulos que más vamos a utilizar en nuestros proyectos mas cotidianos y mas vistosos, como por ejemplo, la medida de la temperatura. Pero no solo es útil en proyectos de ir por casa, sino que es muy útil en la electrónica de potencia para medir tanto intensidades (mediante una resistencia shunt), como tensiones. Es verdad que el conversor AD que nos ofrece un microcontrolador no es de lo mejor que hay, quizás tiene como carencias su velocidad, y aunque su resolución es buena , 10 bits, los hay por ahí de 16 e incluso 32 y 24, aunque para nuestras medidas 10 bits es mas de lo necesario.
  Descrito a grandes rasgos la herramienta de la que disponemos, vamos a aprender a utilizarla. Para configurar este módulo disponemos de los siguientes registros:
  • ADRESH: Parte alta del resultado de la conversión.
  • ADRESL: Parte baja del resultado de la conversión.
  • ADCON0: Registro de control 0.
  • ADCON1: Registro de control 1.
  • ADCON2: Registro de control 2.
  Debido a que el resultado es de 10 bits, no tenemos espacio suficiente con un registro de 8 bits, por lo que utilizamos 2, ADRESH y ADRESL. Dicho esto empezamos a describir un poco como configurar el módulo. 
  En primer lugar tenemos el ADCON0, debido a que aunque dispongamos de 16 canales de conversión, tan solo disponemos d eun conversor AD multiplexado, debemos decirle en que canal de los 16 disponibles queremos hacer la conversión, y eso lo haremos mediante los bits 5-2 de este registro. Los otros dos bits que nos quedan sirven para habilitar el conversor, ADON, y para que empiece la conversión, GO/DONE.
Conversor AD multiplexado.
  A continuación tenemos el registro ADCON1, en este podemos seleccionar las tensiones de referencia que vamos a utilizar para realizar la conversión, Vref- corresponderá con el valor 0, y Vref+ corresponderá con el valor 1024. Cabe destacar que ninguna de las dos podrá ser una tensión negativa. La otra parte del registro nos sirve para configurar los puertos que van a ser digitales, y cuales van a ser analógicos. Cuando seleccionamos un puerto como analógico, debemos configurarlo como entrada mediante el TRIS correspondiente.
  El último registro que nos queda es el ADCON2, con el que configuraremos los tiempos de conversión y adquisición. Para saber como utilizar este registro, debemos saber como funciona un conversor. Aquí va una explicación express. Cuando iniciamos la conversión, se cierra un "interruptor" que permite que se cargue un condensador con la tensión que hay en el pin, una vez pasado el tiempo de adquisición, el interruptor se abre y es entonces cuando el conversor lee el valor de ese condensador y lo convierte en digital.
Modelo interno del pin ADC
  El problema está cuando el tiempo que ese "interruptor" está cerrado es insuficiente para que se cargue con toda la tensión que hay en el pin. El tiempo correcto que debemos mantener el interruptor cerrado depende de la capacidad del condensador, de la impedancia de salida de la fuente de tensión que queremos medir, y d ela impedancia de entrada del pin. Si ese tiempo es demasiado pequeño, obtendriamos una lectura equivocada. Es este criterio con el debemos configurar el tiempo de adquisición del registro. otro parámetro que configuramos aquí es el reloj que utilizamos para el conversor, que debe ser un submultiplo de la frecuencia de oscilación, y siempre debe ser menor de 1.5MHz.
  En la siguiente entrada pondremos un ejemplo de utilización de este módulo. Espero, como siempre, que os haya sido útil la información que os he aportado.

Un saludo

sábado, 18 de diciembre de 2010

Bits de configuración

   Hola a todos, en esta entrada os voy a contar un poco que son los bits de configuración. Como habéis visto hasta ahora, en todos los códigos que os he propuesto, hay una parte que llamo "bits de connfiguración". Esta parte del código es la primera que se ejecuta y le dice al microcontrolador como debe configurarse tanto para ejecutar el código como para programarse, por ejemplo podemos decirle al microcontrolador que lo que queremos hacer es ejecutar el programa, o por el contrario queremos depurarlo, o si queremos proteger el codigo para que no se puede volver a programar, o proteger los datos que guardemos en la EEPROM del chip, o incluso cambiar la frecuencia del oscilador configurando el PLL interno del microcontrolador, en fin, existen muchos bits que nosotros podemos programar a nuestro antojo pero. .  ¿como saber cuales son estos bits y que valores pueden tener?, bien, aunque hay ciertos bits que son comunes a todos los microcontroladores de la serie 18f, como por ejemplo el bit OSC en el que le decimos que tipo de oscilador vamos a utilizar, hay otros que no pueden funcionar en todos, básicamente porque configuran módulos que pude ser uno no tenga, por ejemplo los bits de configuración del USB. 
   Para saber que bits podemos configurar en nuestro microcontrolador, existe un archivo de ayuda para cada uno en el que nos lo indica, tanto el nombre del bit, como los valores que pueden tener. Estos archivos de ayuda los podemos encontrar en la carpeta de instalación de C18 en la siguiente ruta:  C:\MCC18\doc\hlpPIC18ConfigSet.chm. 

   Una vez abierto ese archivo, seleccionamos el PIC que nosotros vamos a utilizar y ahi nos saldrán todos los bits de configuración que utilizamos, una vez elegidos los que utilizaremos, los introduciremos en nuestro código justo después de la declaración del dispositivo.
Espero que como siempre esta entrada os haya sido de ayuda.
Un saludo

domingo, 28 de noviembre de 2010

Interrupciones en C18

Hola a todos!! bueno hoy os escribo para contaros un poco mas sobre los microcontroladores en general, y sobre la gama PIC18 de Microchip en particular.
En nuestro ejemplo del cruce de semáforos, o en el que hacíamos parpadear un led, si nos fijamos en el código, mientras esperamos a que el temporizador cuente hasta el final, el microcontrolador se encuentra "bloqueado", es decir, tenemos el código parado de forma que no podemos hacer nada mas que eso, esperar. Estaría genial que mientras nosotros hacemos otra cosas, hubiera algo que nos avisara cuando el temporizador llega al final, en ese momento nosotros dejamos de hacer lo que estabamos haciendo, atendemos al temporizador y luego seguimos con lo nuestro a la espera de que ese algo nos vuelve a avisar. Esto justamente es lo que hacen las interrupciones.
Una Interrupción (también conocida como interrupción hardware o petición de interrupción) es una señal recibida por la cpu del microcontrolador, indicando que debe "interrumpir" el curso de ejecución actual y pasar a ejecutar código específico para tratar esta situación. Estas señales que recibe la cpu del microcontrolador pueden venir de muchos sitios como pueden ser:
  • Desbordes del temporizador/contador.
  • Dato recibido en el buffer RS-232.
  • Dato recibido mediante comunicación serie síncrona.
  • Captura realizada por el modulo CCP.
  • Fin de conversión analogico - digital.
  • Cambio de estado en un PIN.
  • ...
Cuando un microcontrolador está ejecutando una programa, existe un elemento llamado pila (stack) que va memorizando la linea que está ejecutando, en el momento de produce una interrupción, que hemos activado previamente, el microcontrolador detiene la ejecución del programa principal y se va a una dirección de memoria, en nuestro caso 0x08, en la que se encuentra el código que pertenece a esa interrupción, una vez ejecutado ese código, el microcontrolador va a la pila, lee la instrucción por donde se había quedado, y sigue su ejecución hasta recibir otra interrupción.
Para configurar las interrupciones, el microcontrolador dispone de los siguiente registros:
  • RCON: Configuración del sleep-mode y reset.
  • INTCON,INTCON2,INTCON3: Control de interrupciones:
  • PIR1,PIR2: Flag de periféricos.
  • PIE1,PIE2: Habilitación de interrupciones de periféricos.
  • IPR1,IPR2: Configuración de prioridades.
No voy a analizar uno a uno todos los registros ya que son todos muy parecidos, asi que os explicaré los mas representativos.

- GIE/GIEH: Habilita o deshabilita las interrupciones a nivel global.
- PEIE/GIEL: Habilita o deshabilita las interrupciones de periféricos.
- XXXIF: Todos los bits que terminen con IF, son los bits que se pondrán a 1 cando salte la interrupción (IF= Interrupt Flag).
- XXXIE: Todos los bits que terminen con IE, son los que debemos poner a uno para activar cierta interrupción. (IE = Interrupt Enable).

En principio siempre trabajaremos con los niveles de prioridad desactivados, por lo que todas las interrupciones serán de alta prioridad, pero aún asi tenemos que decidir una prioridad entre ellas. La prioridad sirve para que, en el caso de que salten dos interrupciones al mismo tiempo, seamos nosotros quienes decidamos cual es más importante. Esta selección la haremos por hardware. A continuacion os pongo un ejemplo de codigo para que veais como implementar las interrupciones:

##--------------------------------------------------------------
#include <p18F4550.h>
// Bits de configuración
// Declaración de la rutina de tratamiento interrupción de alta prioridad
void R_Int_Alta(void);
// Vectorización de las interrpciones de alta prioridad
#pragma code Vector_Int_Alta=0x08 // Dieccion de memoria donde iremos
//cuando salte la interrupción.
void Int_Alta (void)
{
_asm GOTO R_Int_Alta _endasm // Cuando se produce una interrupción de alta 
} // Prioridad se ejecuta la función R_Int_Alta
#pragma code
#pragma interrupt R_Int_Alta
void R_Int_Alta (void)
{
//LA PRIORIDAD LA ASIGNAMOS CON EL ORDEN EN QUE PONGAMOS LOS COMANDOS IF.
//EL QUE ESTE MAS HACIA ARRIBA SERÁ EL PRIMERO QUE SE EJECUTE, POR TANTO SERA LA
  //INTERRUPCIÓN MÁS IMPORTANTE
if(XXXIF){
XXXIF=0;
//Codigo que queremos que se ejecute para esta interrupción.
}
if(XXXIF){
XXXIF=0;
//Codigo que queremos que se ejecute para esta interrupción.
}
if(XXXIF){
XXXIF=0;
//Codigo que queremos que se ejecute para esta interrupción.
}
}
void main (void)
{
while (1){
//CODIGO NORMAL
} // Bucle sin fin
}
##--------------------------------------------------------------

En la próxima entrada  haremos los mismos ejemplos que hemos programado anteriormente, pero esta vez utilizando interrupciones.
Un saludo

viernes, 19 de noviembre de 2010

Cruce de semáforos (I)

Hola a todos!! bueno después de estar unos cuantos días liado con las clases y demás por fin puedo volver a escribir algo. En esta ocasión voy a proponeros un pequeño proyecto que de irá ampliando a medida que vayamos aprendiendo cosas. El proyecto que os propongo es el control de un cruce de semáforos mediante el pic18f2550 (valdría cualquier pic de la gama 18f), que, en este caso, funcione con un reloj de 8MHz. Este proyecto que puede parecer sencillo podemos complicarlo todo lo que queramos, desde añadirle sensores que alteren el ciclo normal, por ejemplo cuando hay un atasco, o conectarlo al PC de manera que podamos monitorizar e incluso controlar el cruce.
En esta primera entrega vamos a hacer que los semáforos funcionen de manera cíclica como puede funcionar cualquier cruce de semáforos en la realidad. 
Cruce de semáforos

Como veis en la imagen, es un cruce bastante sencillo que consta de 2 semáforos para los vehículos, y dos semáforos para los peatones. Existe una calle principal, donde se supone que hay mas afluente de vehículos,  y una calle secundaria, cada una de ellas con 1 semáforos para vehículos y otro semáforo para peatones. 
En la siguiente tabla podéis ver la asignación que hemos hecho de los puertos a cada una de las salidas, y las que activaremos en cada ciclo.

Tabla asignación puertos y ciclos

Como Veis, utilizamos el puerto B entero, y dos salidas del puerto C. Como suponemos que la calle principal tiene más afluente de vehículos que la secundaria, la luz verde de esta (Verde Coches Primaria VCP) dura mas tiempo que su análoga en la secundaria. hay dos tiempos que se repiten que corresponden al momento en que se encienden las luces ámbar.
A continuación tenéis el código que he utilizado.

#-------------------------------------------------------------
#include <p18F2550.h>

// Bits de configuración
#pragma config WDT=OFF
#pragma config FOSC=HS
#pragma config DEBUG=OFF
#pragma config LVP=OFF
#pragma config MCLRE = OFF            


void main (void)
{
TRISB=0; //PUERTO C COMO SALIDA
TRISCbits.TRISC0=0; //BIT 0 PUERTO B COMO SALIDA
TRISCbits.TRISC1=0; //BIT 1 PUERTO B COMO SALIDA
T0CON=0x87; //MODO 16 BITS,FUENTE OSCILADOR,PREES.256
PORTB=0x32; //INICIALIZAMOS EL PUERTO B PARA PRIMER CICLO
PORTC=0x01; //INICIALIZAMOS EL PUERTO C PARA PRIMER CICLO
TMR0H=26473>>8;
TMR0L=26473;    //CARGAMOS EL VALOR PARA EL PRIMER CICLO(5s)
while (1){
while(INTCONbits.TMR0IF==0); //ESPERAMOS A QUE CUENTE
if(INTCONbits.TMR0IF){
PORTB=0x52;
PORTC=0x01; //SEGUNDO CICLO
TMR0H=57723>>8;
TMR0L=57723; //CARGAMOS TEMPORIZACIÓN SEGUNDO CICLO(1s)
INTCONbits.TMR0IF=0; //BORRAMOS FLAG DE TMR0
}
while(INTCONbits.TMR0IF==0); //ESPERAMOS A QUE CUENTE
if(INTCONbits.TMR0IF){
PORTB=0x85;
PORTC=0x02; //TERCER CICLO
TMR0H=42098>>8;
TMR0L=42098; //CARGAMOS TEMPORIZACIÓN TERCER CICLO(3s)
INTCONbits.TMR0IF=0; //BORRAMOS FLAG DE TMR0
}
while(INTCONbits.TMR0IF==0); //ESPERAMOS A QUE CUENTE
if(INTCONbits.TMR0IF){
PORTB=0x89;
PORTC=0x02; //CUARTO CICLO
TMR0H=57723>>8;
TMR0L=57723; //CARGAMOS TEMPORIZACIÓN CUARTO CICLO(1s)
INTCONbits.TMR0IF=0; //BORRAMOS FLAG DE TMR0
}
while(INTCONbits.TMR0IF==0); //ESPERAMOS A QUE CUENTE
if(INTCONbits.TMR0IF){
PORTB=0x32;
PORTC=0x01; //PRIMER CICLO
TMR0H=26473>>8;
TMR0L=26473; //CARGAMOS TEMPORIZACIÓN SEGUNDO CICLO(5s)
INTCONbits.TMR0IF=0; //BORRAMOS FLAG DE TMR0
}
}
}
#-------------------------------------------------------------

El cálculo de los valores de recarga no lo voy a explicar ya que está explicado en esta entrada anterior. Como explicaremos más adelante, este programa es muy poco eficiente ya que mientras estamos esperando a que el temporizador llegue al final, el microcontrolador está detenido, y no podemos, por ejemplo, poner un pulsador de avería que en cualquier momento ponga todos los semáforos en ámbar, problema que solucionaremos cuando expliquemos las interrupciones. 
Un saludo


Descargas:

sábado, 6 de noviembre de 2010

Temporizadores (TMR0)

Hola a todos, después de estar liado por las clases durante un par de dias he vuelto para explicaros otro de los módulos que nos podemos encontrar en un microcontrolador, y quizás uno  de los que mas vamos a utilizar. Este es el modulo de los Temporizadores, y lo digo en plural ya que los microcontroladores suelen llevar mas de uno, en concreto los microcontroladores que utilizamos (18f4550/18f2550) disponen de 3 temporizadores de 16 bits, y uno de 8 bits. Antes de explicar los registros que debéis configurar y demás, vamos a explicar como funciona el temporizador. 
Un temporizador, o mas bien dicho contador, es un modulo que como su nombre indica, cuenta eventos, en el caso del temporizador, cuenta ciclos de instrucción que en los microcontroladores ocurren cada 4 dividido por la frecuencia de oscilación segundos. Es decir, este modulo incrementara su valor con una frecuencia de 4/Fosc. Como nada es infinito, el contador tiene un limite, y es ahí donde entran los 8 o 16 bits. Los temporizadores de 8 bits, pueden contar hasta 255, mientras que los de 16 bits pueden contar hasta 65536 (2^8 y 2^16).  Una vez el contador ha llegado a uno de estos valores, hará dos cosas, la primera es que se reiniciará, y la segunda, y la que nos interesa, generará un cambio en un bit de un registro, que será el que mediante programación podremos detectar y actuar en consecuencia. Otra de las caracteristicas que tienen los temporizadores es que no es necesario que empiecen desde 0, sino que nosotros podemos decirle en que valor queremos que empiece a contar. Esto nos sirve para que seamos nosotros los que decidamos cuantas veces tiene que contar de una forma que veremos mas adelante.
En resumen, tenemos un modulo que ira incrementando su valor desde el valor que nosotros digamos cuando pase un determinado tiempo conocido, y cuando este llegue a su límite nos generara un cambio en un bit que leeremos y actuaremos.
Para poder configurar todos estos valores existen los registros de configuración, que en el caso de los temporizadores son los registros TxCON, donde la x nos dice el número de temporizador. Para no hacer esta entrada demasiado larga, vamos a centrarnos en el temporizador numero 0, ya que los demas son bastante parecidos. Lo primero que vamos a ver es el diagrama de bloques del temporizador.
Diagrama de Bloques Temporizador 0
Repasando el diagrama de izquierda a derecha, en primer lugar tenemos el tipo de eventos que va a contar nuestro temporizador, que puede ser o pulsos de un pin, o la frecuencia de oscilación dividida entre 4.  Esto lo podemos configurar mediante el bit T0CS. a continuación tenemos algo de lo que no hemos hablado hasta ahora pero es igualmente importante, y es el preescalar, en el que simplemente le decimos si queremos que incremente su valor por cada evento, o por cada 2 eventos, 4. . .  es decir, multiplicaremos el tiempo que tarda en llegar a su limite por el valor que pongamos en el preescalar. Así pues como veis, este valor del preescalar se selecciona con los bits T0PS2;T0PS0. Siempre podemos elegir si trabajar o no con preescalar, esto lo configuraremos con el bit PSA. Una vez configurado el temporizador, este almacena la configuración y se sincroniza con el reloj interno, y empieza a contar y a almacenar su valor en los registros TMR0H y TMR0L si utilizamos 16 bits, y solo el TMR0L si trabajamos con 8 bits. Hay que recordar que estos registros son de lectura y de escritura. A continuación os muestro el registro que debemos configurar.
Registro T0CON
En este registro podemos encontrar los bits d elos que hemos hablado antes T0CS, PSA, T0PS2;T0PS0, pero tenemos otros que todavía no conocemos como son el TMR0ON, que como habréis deducido sirve para activar o desactivar el temporizador, T08BIT, con el que elegiremos trabajar con 8 o 16 bits, y el T0CS con el que, si hemos elegido contar los eventos del pin en vez del temporizador, podremos decidir contar en los flancos de subida, o de bajada.
Por último, hemos dicho que cuando el temporizador llega a su límite pone a 1 un bit pero no hemos especificado cual. Para eso hace falta ir al registro INTCON que el el registro de interrupciones, y ahi el bit que cambia su valor es el TMR0IF.
En la próxima entrada pondré un ejemplo de uso del temporizador. 
Un saludo

martes, 12 de octubre de 2010

PIC18F4550 / 18F2550

  Hola a todos!! bueno para empezar a hacer proyectos con los microcontroladores, primero debemos saber que son los microcontroladores. Para ello nada mejor que nuestra amiga la wikipedia , aunque yo os lo voy a resumir un poco. Un microcontrolador es como un microprocesador en el que se han potenciado algunas funciones, y se han reducido otras que son de mayor interes en la industria. Por ejemplo, en la industria no son necesarias memorias tan rápidas como las memorias caché, o tampoco necesitamos que su reloj funcione a 2GHz. Y por el contrario pas alo mismo, en los ordenadores personales no necesitamos un modulo exclusivo para el control de motores, y no necesitamos captar señales anlógicas del exterior. 
  Otra diferencia reseñable, aunque para muchos no lo sea, es la arquitectura interna. Actualmente existen 2 arquitecturas, Von Neumann y Harvard. La arquitectura Von Neumann utiliza una sola memoria para programas y para datos, esta arquitectura es la que utilizan los microprocesadores. 

Arquitectura Von Neumann

  En cambio los microcontroladores utilizan memorias diferentes para datos y para programa, asi funciona la arquitectura harvard.
Arquitectura Harvard
  Una vez que sabemos lo que son los microcontroladores, vamos a centrarnos en los microcontroladores que vamos a utilizar mas frecuentemente en este blog, estos son el 18f2550 y el 18f4550. El porque d ela elección de estos microcontroladores es porque son los que aprendi a programar en la universidad, cosa que veo muy util porque realmente, sabiendo programar estos dos grandes microcontroladores, sabes programar cualquiera. A continuacion teneis una tabla de caracteristicas de los dos microcontroladores:

PIC 18F4550


PIC 18F2550
  Las unidades de cada microcontrolador las iremos viendo poco a poco a lo largo de la vida del blog. Espero que esteis nerviosos por hacer vuestro primer proyecto, en la proxima entrada haremos nuestro primer "Hola Mundo".

Un saludo


Descargas: