1.8. Ejemplo de uso PIC18F4550, delays y USARTUn completo ejemplo de uso sobre el puerto serie que incorpora este microcontrolador. El
proyecto completo en un ZIP, probado y compilado en Windows 7 y Ubuntu 10.04.
/*
programa: prueba oscilador interno y módulo usart
pic: 18f4550
crystal: NO
CPU: 8Mhz (valor establecido dentro de main cambiando los bits IRCF2, IRCF1 e IRCF0 del registro OSCCON)
en RA6 sale la frecuencia de Fosc/4 -------> 8Mhz/4 = 2Mhz
CONEXIONES: los cambios se pueden hacer en el archivo configuracion_hard.c
1 led en port b0 con una resistencia en serie de 470ohms
1 led en port b1 con una resistencia en serie de 470ohms
Los leds cambian de estado cada 1 segundo. Uno enciende y el otro se apaga cada vez.
*/
#define _XTAL_FREQ 8000000 // Linea necesario para los cálculos de la función
// de delay. CUIDADO. no es para la configuración
// de la frecuencia de trabajo del cpu del pic.
// eso se determina en otro lado. :)
/*Includes globales*/
#include <pic18.h>
#include <xc.h>
#include <delays.h> /* Para utilizar demoras en nuestro código debemos incluir la librería delays.h.*/
#include <plib/usart.h> //Libreria para el manejo del modulo USART
/*Includes locales*/
#include "configuracion_de_fuses.c"
#include "configuracion_hard.c"
/*declaración de variables globales*/
char CaracterRx;
char MensajeTx[] = "COMUNICACION SATISFACTORIA";
/*declaración de funciones*/
void MyMsDelay(int ms);
//void interrupt Interrupcion();
///////////////////////////////////////////////////////////////////////////////
// Programa Principal //
///////////////////////////////////////////////////////////////////////////////
void main(void)
{
// cambiamos la frecuencia del oscilador interno del valor por defecto de 32khz
// a 8mhz mediante los bits del registro OSCCON
OSCCONbits.IRCF2 = 1;
OSCCONbits.IRCF1 = 1;
OSCCONbits.IRCF0 = 1;
ADCON0 = 0X00,ADCON1 = 0X0F,CMCON = 0X07; //puerto A con todos los pines digitales
TRISA = 0X00; // puertos A B y C como salida. Recordar Tip: el 0 es una o de ouput y el 1 una I de input!!!
TRISB = 0X00;
TRISC = 0X00;
LATA = 0X00; // ponemos los puertos en cero
LATB = 0X00;
LATC = 0X00;
PINLED0 = 0; // Seteamos el pin como salida para el LED
PINLED1 = 0; // Seteamos el pin como salida para el LED
// configuramos el puerto serie
OpenUSART(USART_TX_INT_OFF &
USART_RX_INT_ON & //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
USART_ASYNCH_MODE & //Modo asincrono (fullduplex)
USART_EIGHT_BIT & //8 bits de datos
USART_CONT_RX & //Recepción continua
USART_BRGH_HIGH, 51); //9600 Baudios
// (frecuencia a la que trabaja el cpu/dbaudrate)/16)-1
// (8.000.000/9600)/16)-1=51
INTCONbits.PEIE = 1; //Activamos interrupcion de perifericos
INTCONbits.GIE = 1; //Activamos las interrupciones globales
while(BusyUSART()); //Se espera a que el buffer de Tx este libre
putsUSART(MensajeTx); //Se envía un string de bienvenida
while(1){ //Bucle infinito
LED0 = ~LED0; // Intercambiamos el estado del pin del led (Toggle LED)
Delay10KTCYx(200); //ver como se hacen los cálculos del delay más abajo
LED1 = ~LED1; // Intercambiamos el estado del pin del led (Toggle LED)
}
}
void interrupt Interrupcion() //Funcion que atiende las interrupciones
{
CaracterRx = ReadUSART(); //Se lee el dato que esta en el buffer de Rx del USART
while(BusyUSART());
putsUSART("\n\rUsted digito la tecla: ");
while(BusyUSART());
WriteUSART(CaracterRx);
PIR1bits.RCIF = 0; //Desactivamos la bandera de recepción en el buffer de entrada del USART
}
void MyMsDelay(int ms)
{
while(ms--)
{
__delay_ms(1);
}
}
CÁLCULOS DE LOS RETARDOSPara utilizar demoras en nuestro código debemos incluir la librería
delays.h. En ella tenemos 4 funciones:
Delay10TCYx(i) -> 10.Tcy.i genera una demora de 10 ciclos de instrucciones * i
Delay100TCYx(i) -> 100.Tcy.i genera una demora de 100 ciclos de instrucciones * i
Delay1KTCYx(i) -> 1000.Tcy.i genera una demora de 1000 ciclos de instrucciones * i
Delay10KTCYx(i) -> 10000.Tcy.i genera una demora de 10000 ciclos de instrucciones * i
i puede tomar un valor de 1 a 255. Si se toma valor 0 i es 256
NOTA: Para hacer los cálculos de los retardos debemos tener en cuenta la frecuencia a la que trabaja la CPU del pic. Y ojo que la velocidad del CPU no siempre será la velocidad del cristal. Podríamos tener un cristal de 4Mhz y hacer trabajar la CPU del pic a 48Mhz mediante el uso del PLL. O trabajar con cristal interno a una frecuencia de 8Mhz y establecer una velocidad de 1 Mhz mediante los postcalers. Comprendido esto podemos pasar a hacer los cálculos.
1
1 ciclo de reloj es = ---------------------------------
Frecuencia que le llega al CPU (No la Frecuencia del cristal!!!)
1 TCY está formado por 4 ciclos de reloj. 4 ciclos de reloj tarda el pic en procesar una instrucción. Entonces si queremos saber cuanto demora 1 TCY debemos multiplicar 4 veces lo que demora 1 ciclo del reloj del CPU.
1
1 TCY se calcula como 4 * --------
Fosc
donde fosc = frecuencia que llega a la CPU del pic (NO LA FRECUENCIA DEL CRISTAL!!!)
Cálculo de delay para generar 1 segundo con frecuencia de trabajo de CPU a 8mhzLas funciones de retardos usan como parametro los TCY. Entonces tenemos que calcular cuantos TCY hay que utilizar para obtener 1 segundo. Dijimos que:
1
1 TCY se calcula como 4 * --------
Fosc
Fosc= 8Mhz = 8*10^6 hz = 8.000.000hz
1 1
por lo tanto 1 TCY = 4 * ---------- = ---------- = 0,0000005sec
8*10^6 Hz 2*10^6Hz
1 TCY = 0,0000005seg = 5*10^-7 seg
Es decir que 1 TCY tarda 0,0000005seg.
Si dividimos 1 sobre TCY nos da la frecuencia en Hertz
1
----- = frecuencia en hertz
TCY
1
-------------- = frecuencia en hertz
0,0000005seg.
2.000.000 Hertz = 2Mhz. Es decir que Fosc oscila 2.000.000 de veces durante 1 segundo
Entoces para calcular un segundo la formula es:
1
1seg * ----------- = 2.000.000 TCYs
0,0000005 seg
Ahora que sabemos que necesitamos 2.000.000 TCYs para demorar un segundo debemos elegir una de las funciones que nos brinda la librería delays.h debiendo tener presente que sólo reciben como parámetro valores de i de 1 a 255. Si se toma 0 equivale a 256. Para este caso debemos usar la función Delay10KTCYx(i) ya que:
2.000.000 TCYs
----------------- = nos da un valor de 200i
10.000 TCY
Y con dicho valor 200 logramos el retardo de 1 segundo!
Delay10KTCYx(200); //demora de 1 seg
Gracias a Jukinch por el excelente aporte a este capítulo!