uControl
Julio 28, 2014, 03:13:23 *
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.
¿Perdiste tu email de activación?

Ingresar con nombre de usuario, contraseña y duración de la sesión
 
   Inicio   Ayuda Buscar Ingresar Registrarse  

La gente de Niple nos ofrece un descuento especial para usuarios de uControl.
Entérate de como puedes aprovechar esta oferta haciendo click aqui.

Súmate, y ayuda a uControl con tu participación en esta interesante oportunidad que nos oferece Niple.

Páginas: [1] 2   Ir Abajo
  Imprimir  
Autor Tema: Tutorial MPLAB C18 Desde 0.  (Leído 125208 veces)
0 Usuarios y 1 Visitante están viendo este tema.
Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« : Mayo 03, 2009, 03:13:15 »

MPLAB C18.

Versión en pdf


Entorno de programación MPLAB IDE.
  • Ensamblador, enlazador, gestión de proyectos, depurador y simulador. La interfaz gráfica del usuario MPLAB IDE sirve como un único entorno para escribir, compilar y depurar código para aplicaciones embebidas. Permite manejar la mayoría de los detalles del compilador, ensamblador y enlazador, quedando la tarea de escribir y depurar la aplicación como foco principal del programador (usuario)
  • Gratuito, se puede descargar de www.microchip.com

Compilador MPLAB C18
  • MPLAB C18 es un compilador cruzado que se corre en un PC y produce código que puede ser ejecutado por la familia de microcontroladores de Microchip PIC18XXXX. Al igual que un ensamblador, el compilador traduce las declaraciones humanas en unos y ceros para ser ejecutados por el microcontrolador.
  • Sigue la norma ANSI C, salvo en particularidades de los microcontroladores
  • Librerías para comunicaciones SPI, I2C, UART, USART, generación PWM, cadena de caracteres y funciones matemáticas de coma flotante
  • Maneja números reales de 32 bits (float y double)
  • Versión demo de 60 días, descargable de www.microchip.com



Indice


* 2550gif.gif (4.81 KB - descargado 92688 veces.)
* microchip_logo2.gif (2.24 KB - descargado 92963 veces.)
« Última modificación: Agosto 24, 2012, 06:58:28 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #1 : Mayo 03, 2009, 03:28:27 »

Instalación

Se debe bajar directamente desde Microchip, hay disponible una versión gratuita para estudiantes que es un demo de 60 días. También para poder descargarlo es necesario registrarse.
Una vez descargado ejecutar el instalador MPLAB-C18-Evaluation-v3_30 versión actualmente disponible.
Para a instalación seguimos los siguientes pasos:











En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #2 : Mayo 03, 2009, 03:29:28 »

Creación de un nuevo proyecto.

Project -> New
Nos aparecerá una pantalla donde le indicamos el nombre de nuestro proyecto y la carpeta donde será guardado.

Pasamos a configurar el dispositivo con el cual trabajaremos: Configure->Select Device

Seleccionamos el compilador: Project->Select Lenguaje Toolsuite y nos aseguramos que todas las direcciones son correctas.

Configuramos los subdirectorios de trabajo: Project->Build options -> Project
Seleccionamos ubicación de ficheros de declaraciones, bibliotecas y script de enlazado.
Show directories for:
  • Include Search Path
  • Library Search Path
  • Linker-Script Search Path



Nota: Según la versión también se debe agregar al proyecto el archivo (PIC18F utilizado).lkr ubicado en MCC18/lkr, sino produce error de compilación.


Luego vamos a New File y lo guardamos en nuestra carpeta eligiendo extensión .c agregándolo a nuestro proyecto.  Wink


Con todo esto configurado ya podemos empezar a desarrollar nuestro código.  rolleyes2
« Última modificación: Agosto 18, 2009, 11:48:55 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #3 : Mayo 03, 2009, 03:30:36 »

Introducción al C18:

La idea es ir adquiriendo conceptos a medida que los utilicemos en el desarrollo de los ejemplos, de esta manera lo que se presenta teóricamente lo asociamos inmediatamente con la práctica. Aunque claro está que el lenguaje es muy amplio y no se pueden hacer ejemplos de cada concepto.

En el desarrollo de este tutorial se utilizará el microcontrolador PIC18F2550, y como en todo proyecto siempre se debe tener a mano el datasheet de los dispositivos utilizados, para la correcta interpretación y aplicación de las configuraciones realizadas.

Creando el código:

Lo que se presenta aquí es la estructura general de un archivo fuente de C, en donde como primera medida se incluyen  las librerías, colección de rutinas, que se van a utilizar en el proyecto. Tenemos las librerías estándar de Ansi C que incluye rutinas para manejo de cadenas de texto y operaciones con datos comunes como funciones matemáticas, librerías especificas del microcontrolador a utilizar (p18Fxxxx.h) la cual tiene estructuras de  los registros del microcontrolador para control de sus bits, librerías para control de periféricos del microcontrolador (UART, I2C, SPI, ect) y las librerías propias creadas por el usuario dedicadas al control de un dispositivo externo o una tarea en común.
La librería que siempre incluiremos en el archivo principal será la del PIC  a usar:
Código: (c)
#include <p18F2550.h>

Luego viene la configuración de los fuses del microcontrolador. Ósea configuración de oscilador, watch-dog, Brown-out reset, power-on reset, protección del código, etc. Esto depende del microcontrolador que se utilice:
La sintaxis seria: #pragma config Nombre del fuse=estado.
Para esto es muy útil la ayuda que trae C18, recomiendo mirarla:
C:\MCC18\doc\ hlpPIC18ConfigSet

Definición de variables globales, son las que se utilizaran en el programa principal y funciones del proyecto.
Código: (c)
int variableA, variableB
Ahora viene el código de nuestro programa:
Código: (c)
main{

}

El proceso de compilación

El texto fuente es compilado en bloques de código de programa y datos que luego son enlazados (linked) con otros bloques de código y datos, y colocados en las regiones de memoria del microcontrolador PIC18XXXX seleccionado. Este proceso se llama generación (build) y se suele llevar a cabo muchas veces en el desarrollo de programas en el proceso de probado y depurado. También tenemos la posibilidad de utilizar make que solo compila los archivos fuentes que han sido modificados desde la última vez agilizando el proceso.

Flujo de la generación del hex

En la siguiente imagen se tiene un ejemplo de los pasos que lleva un determinado proyecto, donde tenemos 2 archivos fuentes en c (*.c), 1 archivo en assembler (*.asm) y un archivo precompilado (*.o).

Los archivos fuentes *.c son compilados por MPLAB C y el archivo *.asm es ensamblado por MPASM generando los archivos intermedios llamados archivos objetos. Estos archivos junto al *.lkr del microcontrolador son tomados por el enlazador para generar el *.hex que será utilizado para la grabación en la memoria de programa del microcontrolador. Cabe la posibilidad de agrupar archivos objetos para crear bibliotecas (*.lib)
El archivo *lkr contiene información de la estructura y capacidades del microcontrolador con el cual se está trabajando, sirve como plantilla para el enlazador para organizar el código de programa y datos generados en el proceso de compilación.

Ahora ya tenemos una idea general de como es la estructura de un programa desarrollado en C y cual es el proceso que sigue en la generación del *.hex necesario para embeber a nuestro microcontrolador. Seguiremos con el estudio de las directivas utilizadas en C para el desarrollo de programas simples y más adelante encararemos el tema de las librerias, su modificación, creación, ect.


Primer ejemplo, control de leds con un pulsador.
Para este sencillo ejemplo vamos a necesitar definir operadores y estructuras de control:

Operadores:
Aquí definiremos todos los operadores utilizados por C18.-
Operadores de Comparación:
Estos operadores se encargan de comparar dos condiciones de una expresión:

Operadores aritméticos:
Se utilizan para realizar cálculos matemáticos:

Operadores lógicos:
Son los encargados de producir resultados lógicos del tipo TRUE o FALSE

Operadores bitwise:
Son para modificar los bits de una variable:

Jukinch, usuario del foro y amigo ha realizado la siguiente contribución para mayor entendimiento de los operados bitwise:

El operador AND "&" compara dos bits; si los dos son 1 el resultado es 1, en otro caso el resultado será 0.
Ejemplo:

        c1 = 0x45      --> 01000101
        c2 = 0x71      --> 01110001
        ---------------------------
        c1 & c2 = 0x41 --> 01000001
-----------------------------------------------------------------------------------------------------------------------------
El operador OR  "|" compara dos bits; si cualquiera de los dos bits es 1, entonces el resultado es 1; en otro caso será 0. Ejemplo:

        i1 = 0x47      --> 01000111
        i2 = 0x53      --> 01010011
        ---------------------------
        i1 | i2 = 0x57 --> 01010111

-----------------------------------------------------------------------------------------------------------------------------
El operador exclusivo (XOR) "^", da por resultado uno cuando los dos operandos tienen distinto valor.

Cuando los dos operandos son distintos da 1.-
ej: 1 y 0    =1
    0 y 1    =1

Cuando los dos operandos son iguales da 0.-
    0 y 0    =0
    1 y 1    =0

 Ejemplo:
        i1 = 0x47      --> 01000111
        i2 = 0x53      --> 01010011
        ---------------------------
        i1 ^ i2 = 0x14 --> 00010100
-----------------------------------------------------------------------------------------------------------------------------
El operador de complemento a 1 "~" cambia cada dígito del operando por su opuesto:

Si el bit es 1 se cambia por 0 y viceversa

        c = 0x45  --> 01000101
        ----------------------
        ~c = 0xBA --> 10111010

-----------------------------------------------------------------------------------------------------------------------------
Los operadores de desplazamiento a nivel de bit "<<" y ">>" Desplazan a la izquierda o a la derecha un número especificado de bits.
En un desplazamiento a la izquierda los bits que sobran por el lado izquierdo se descartan y se rellenan los nuevos espacios con ceros. De manera análoga pasa con los desplazamientos a la derecha. Veamos un ejemplo:

    c = 0x1C    00011100

c << 1    c = 0x38    00111000
c >> 2    c = 0x07    00000111

Como en binario se trabaja en base dos cada posición de desplazamiento implica dividir o multiplicar por 2

>> divide por 2.

<< multiplica por 2

   c = 0x1C    00011100

c << 1    c = 0x38    00111000 multiplica por 2
c >> 2    c = 0x07    00000111 divide 2 veces por 2 (divide por 4)

-----------------------------------------------------------------------------------------------------------------------------
Ejemplos de precedencia de los operandos:

puerto &= ~(1<<6) primero se desplaza un 1 hacia la izquierda 6 posiciones y luego el operando ~ lo convierte en cero. Es resultado se combina mediante el operando & con el contenido del byte del puerto. Aplicándose así una máscara que pone en cero el bit 6 dejando pasar los demás bits. De esta manera se logra un equivalente en assembler de bitclr en la posición del bit 6.

#define bit_set(bit,puerto) (puerto |= 1<<bit)
#define bit_clr(bit,puerto) (puerto &= ~(1<<bit))

// ejemplo en código
bit_set(0,PORTB); // pone a 1 el bit 0 del puerto B.
bit_clr(0,PORTB); // pone a 0 el bit 0 del puerto B.
-----------------------------------------------------------------------------------------------------------------------------
Código binario en complemento a dos:

En este sistema, los números positivos se representan reservando el bit más significativo (que debe ser cero) para el signo. Para los números negativos, se utiliza un sistema distinto, denominado complemento a dos, en el que se cambian los bits que serían 0 por 1 y viceversa, y al resultado se le suma uno.
Este sistema sigue reservando el bit más significativo para el signo, que sigue siendo 1 en los negativos. Por ejemplo, la representación de 33 y -33 sería:

    +33    0010 0001
         se invierte todo
    -33    1101 1110
         se le suma 1
         + 0000 0001
          resultado
           1101 1111   numero -33 en complemento a dos

El hardware necesario para implementar operaciones aritméticas con números representados de este modo es mucho más sencillo que el del complemento a uno, por lo que es el sistema más ampliamente utilizado.
-----------------------------------------------------------------------------------------------------------------------------
Muchísimas gracias! Y esto queda abierto a que si tienen ejemplos que ayudan a entender otros operadores, o estructuras de control, etc., estamos abierto a sus recomendaciones  Wink

Estructuras:

Estructura if:
Esta estructura se utiliza para ejecutar instrucciones en forma condicional, de acuerdo con la evaluación de la expresión. Seria si una condición es dada entonces acción.
Código: (c)
if(condicion){
//Accion
}

Estructura if-else
En este caso se agrega la instrucción else. Ahora se evalúa una condición original, si es verdadera, se ejecuta y sino no lo es, se ejecuta el bloque debajo de else.
Código: (c)
if(condicion){
//Acción
else{
//Accion
}
}

Estructura while
Ejecuta un conjunto de instrucciones mientras una condición sea verdadera. La principal característica de esta estructura es que, antes de comenzar el bucle, verifica la condición, por lo que es posible que el bucle no llegue a ejecutarse.
Código: (c)
while(condicion){
// Sentencias
}

Estructura do-while
Es parecida a un while solo que la condición se evalúa al final, por lo que el bucle se ejecutara por lo menos una vez.
Código: (c)
do {
// Sentencias
} while (condicion);

Estructura For:
Esta estructura se usa para ejecutar un bloque de código cierto número de veces. Posee un valor de inicio, un valor final y un valor de incremento.
 
Código: (c)
for(valor inicial; valor final; valor de incremento ){
//Sentencias
}

Mas adelante explicaremos la estructura  switch.


Accediendo a los bits de un registro:

Para acceder individualmente a los bits de un registro se escribe la siguiente sentencia:
Registrobits.bit
Ejemplo:
Código: (c)
PORTBbits.RB0



Objetivo:Encender 4 leds del puerto B mientras se mantenga accionado el pulsador.

Hardware

Código:
Código: (c)
#include <p18f2550.h>

#pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
#pragma config PWRT = ON,BOR = OFF,BORV = 0
#pragma config WDT = OFF,WDTPS = 32768
#pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
#pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
#pragma config CP0 = ON,CP1 = ON,CP2 = ON
#pragma config CPB = ON,CPD = ON
#pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
#pragma config WRTB = ON,WRTC = ON,WRTD = ON
#pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
#pragma config EBTRB = ON


void main(void){
ADCON1=0x0F;//Todos entrada/salida digitales.-
TRISA=0xFF; //Todos como entrada.-
TRISB=0X00; //Todos como salida.-

PORTB=0x00; //Leds apagados.-
while(1){
        if(PORTAbits.RA0==1){ // testeamos RB0.
                LATB=0x00; // Si esta en 1 Apagamos leds
        }
        else{
                LATB=0x0F; // Si esta en 0 Encendemos leds.
        }
}
}
« Última modificación: Agosto 24, 2012, 06:49:33 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #4 : Mayo 03, 2009, 03:31:02 »

Variables
Una variable es la asignación de un nombre a un espacio determinado en la memoria, en donde el espacio dependerá del tipo de variable. C18 define los siguientes tipos:

Según donde estén declaradas, las variables pueden ser globales (declaradas fuera de todo procedimiento o función) o locales (declaradas dentro de un procedimiento o función). Las primeras serán accesibles desde todo el código fuente y las segundas sólo en la función donde estén definidas.

Modificadores de las variables:
Mplab C18 utiliza los modificadores establecidos por ANSI:

Auto: las variables declaradas fuera de las funciones son globales y las declaradas en la función son locales. Si no se inicializan toman un valor indefinido.
Static: variables locales a una función, y sirven para retener el valor de la variable en llamadas sucesivas a dicha función. El espacio de memoria es reservado únicamente para dicha función.
Extern: La variable declarada pertenece a otro módulo, por lo que no es necesario reservar memoria para ella.
Const: El contenido de la variable es fijo.
Volatile: el contenido de la variable puede cambiar. En interrupciones se debe utilizar este tipo de datos. En la siguiente página pueden encontrar una explicación muy acertada de sus uso. (Información otorgado por Jukinch)
Register: La variable declarada debe guardarse en un registro del microcontrolador.
Overlay: Se aplica a variables locales, hace un almacenamiento estático y las inicializa en cada llamada.
Ram: La variable se sitúa en la memoria de datos.
Rom: la variable se sitúa en la memoria del programa. Por lo general se usa para cadena de caracteres contantes.

Especificación de banco de memoria de datos:
Far: La variable puede ir en cualquier banco.
Near: la variable tiene que estar en el banco de acceso.
Para las variables guardadas en la memoria de programa el acceso no es tan inmediato, sino que se realiza mediante las operaciones Table Reads o Table Writes, los cuales mueven los datos entre el espacio de memoria RAM y de Programa. Cuando se trabaja una variable NEAR solo se necesita 16-bits para su direccionamiento, en cambio para una variable FAR (Que puede estar en cualquier banco) se necesitan 24-bits para su direcionamiento. Esto último se podrá observas más claro cuando se trate punteros.

Demoras:

Para utilizar demoras en nuestro código debemos incluir la librería delays.h. En ella tenemos 4 funciones:
Delay10TCYx(i)      -> 10.Tcy.i
Delay100TCYx(i)   -> 100.Tcy.i
Delay1KTCYx(i)      -> 1000.Tcy.i
Delay10KTCYx(i)   -> 10000.Tcy.i

Donde i puede tomar valores entre 0 y 255.



Ejemplo: Leds titilando.

Objetivo: Hacer titilar 10 veces los leds del puerto B al accionar el pulsador.

Hardware: Idem anterior.

Código:
Código: (c)
#include <p18f2550.h>
#include <delays.h>

#pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
#pragma config PWRT = ON,BOR = OFF,BORV = 0
#pragma config WDT = OFF,WDTPS = 32768
#pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
#pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
#pragma config CP0 = ON,CP1 = ON,CP2 = ON
#pragma config CPB = ON,CPD = ON
#pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
#pragma config WRTB = ON,WRTC = ON,WRTD = ON
#pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
#pragma config EBTRB = ON

unsigned char i; //Para contar 0 titilaciones.-

void main(void){
ADCON1=0x0F;//Todos entrada/salida digitales.-
TRISA=0xFF; //Todos como entrada.-
TRISB=0X00; //Todos como salida.-

LATB=0x00; //Leds apagados.-
while(1){
        if(PORTAbits.RA0==1){
                LATB=0x00;
        }
        else{
                for(i=1;i<=10;++i){//Titila 10 veces
                        LATB=0x0F;
                        Delay10KTCYx(30);//Demora 300ms
                        LATB=0x00;
                        Delay10KTCYx(30);//Demora 300ms
                }
        }
}
}



« Última modificación: Agosto 24, 2012, 06:51:51 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #5 : Mayo 03, 2009, 03:31:20 »

Ejemplo:Leds secuenciales:

Objetivo: Al accionar el pulsador se realiza una secuencia de leds como se muestra en la figura:

Hardware: Idem anterior.

Código:
Código: (c)
/* ** Archivo con definicion de registros y bits del microcontrolador elegido */
#include <p18f2550.h>
/* ** Configuracion de los Fuses del microcontrolador  ** */
#pragma config FOSC = XT_XT, FCMEN = OFF, IESO = OFF, CPUDIV = OSC1_PLL2
#pragma config PWRT = ON, BOR = OFF, BORV = 0, WDT = OFF, WDTPS = 32768
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = OFF
#pragma config STVREN = OFF, LVP = OFF, XINST = OFF, DEBUG = OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTRB = OFF

unsigned char k; /* Variable utilizada para realizar efecto */

void main(void){
ADCON1=0x0F; /* Todos entradas/salidas digitales */
TRISA=0xFF; /* Todos como entradas */
TRISB=0xF0; /* Nible bajo como salida */
LATB=0x00; /* Todos los leds apagados */
while(1){ /* Bucle infinito */
if(PORTAbits.RA0==1){ /* Se testea estado del pulsador */
LATB=0x00; /* Si esta en 1 logico apagamos leds */
}else{
LATB=0x01; /* Encedemos primer Led */
for(k=1;k<=4;k++){ /* Rota 4 veces */
Delay10KTCYx(30); /* Demora 300ms */
LATB=(PORTB<<1); /* Rotamos Led encendido */
}
}
}
}
« Última modificación: Septiembre 12, 2010, 05:18:03 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #6 : Mayo 03, 2009, 03:31:45 »

Operaciones con variables de distintos tipos.
Cuando se evalúa una expresión donde las variables implicadas son de distinto tipos ocurre una conversión, ya sea implícita o explicita, para llevar ambos operando a un tipo común de datos con el que se pueda operar.
En la asignación de una expresión de un tipo dado a una variable de un tipo menor, la conversión se hace en forma automática. Por ejemplo:

Código:
unsigned char k,
float p =30.56;
k=p; // k= 30, p = 30.56. -

Aquí tenemos miembros de diferentes tamaños, por lo que habría un truncamiento del valor entero a la cantidad de bit que lo permita k. Si la parte entera excede el rango establecido por la variable k, el resultado no tendría lógica aparente.
Reglas de promoción automática de expresiones
Estas reglas dicen que el compilador haría estrictamente las conversiones necesarias para llevar todos los operandos al tipo del mayor. El resultado de evaluar una operación aritmética seria del tipo del mayor de sus operandos, en el sentido del tamaño en bits de cada objeto de datos. Por ejemplo:

Código:
unsigned char k;
float p;
k =5;
p=k /2; // p = 2

Por más que indiquemos que el resultado es float el truncamiento se produce en la evaluación del miembro derecho de la asignación.
Para resolver este problema existen dos formas, una es escribir cualquiera de las contantes en
Punto flotante o utilizar el operador cast.

Código:
p= k /2.0; // p = 2.5
p =(( float )k /2); // p = 2.5

No es útil implementar el cast de la siguiente forma:

Código:
p= ( float )(k /2); // p = 2

Dado que primero se realiza la operación, y al resultado se aplica el cast, lo que no soluciona el problema.-


Arreglos de Variables

Nos permite trabajar con un conjunto de variables  y acceder a cada una mediante un índice único que lo identifica. Todos los valores que contienen deben ser del mismo tipo.
Código: (c)
unsigned char Vector[5];
unsigned char Matriz[3][3];
.
.
.
//Cargamos vector y matriz:
Vector[0]=156;
Matriz[1][1]=85;
//Leemos vector y matriz:
PORTB=Vector[4];
PORTB=Matriz[0][0];

En la declaración se pueden pre cargar los valores de la siguiente forma:
Código: (c)
unsigned char Vector[3]={1,0x10,0b000101}
unsigned char Matriz[3][3]={1,2,3,4,5,6,7,8,9,10};


Ejemplo: Control de display 7 segmentos

Objetivo: utilizaremos dos pulsadores para incrementar, decrementar o resetear un conteo de 0 a 9 que mostraremos en un display de 7 segmentos  de cátodo común. El reseteo será el caso en el que se presiona los dos pulsadores a la vez.

Hardware:

Código:
Código: (c)
/* ** Archivo con definicion de registros y bits del microcontrolador elegido */
# include <p18f2550 .h>
/* ** Include para realizacion de demoras ** */
# include <delays .h>
/* ** Configuracion de los Fuses del microcontrolador ** */
# pragma config FOSC =XT_XT , FCMEN =OFF , IESO =OFF , CPUDIV = OSC1_PLL2
# pragma config PWRT =ON , BOR =OFF , BORV =0, WDT =OFF , WDTPS =32768
# pragma config MCLRE =ON , LPT1OSC =OFF , PBADEN =OFF , CCP2MX = OFF
# pragma config STVREN =OFF , LVP =OFF , XINST =OFF , DEBUG = OFF
# pragma config CP0 =OFF , CP1 =OFF , CP2 =OFF , CPB =OFF , CPD = OFF
# pragma config WRT0 =OFF , WRT1 =OFF , WRT2 = OFF
# pragma config WRTB =OFF , WRTC =OFF , WRTD = OFF
# pragma config EBTR0 =OFF , EBTR1 =OFF , EBTR2 =OFF , EBTRB = OFF
unsigned char i; // Para controlar vizualizacion del Display .-
const rom unsigned char Display7Seg [10]={0 x3F , 0x06 , 0x5B , 0x4F , 0x66 ,
                                                                 0x6D , 0x7D , 0x07 , 0xFF , 0 x6F };
void main ( void ){
    ADCON1 =0 x0F ;// Todos entrada / salida digitales .-
    TRISA =0 xFF ; // Todos como entrada .-
    TRISB =0 X00 ; // Todos como salida .-
    LATB =0 x3F ; // Comienza en cero .-
    i =0;
    while (1){
        // Si se presionan los 2 a la vez se resetea .-
        if( PORTAbits . RA0 ==0 & PORTAbits . RA1 ==0){
            i =0;
            // Cargamos en puerto valor de la tabla indicado por i.-
            LATB = Display7Seg [0];
            Delay10KTCYx (30);
        } else if( PORTAbits . RA0 ==0){ // Se incrementa cuenta .-
            ++i;           
            // Volvemos a 0. Directamente se puede hacer if (++i ==10)
            if(i ==10){ i =0;}
            // Cargamos en puerto valor de la tabla indicado por i.-
            LATB = Display7Seg [i];
            Delay10KTCYx (30);
        } else if( PORTAbits . RA1 ==0){ // Se decrementa cuenta .-
            --i;
            if(i ==255){ i =9;} // Volvemos a 9.
            // Cargamos en puerto valor de la tabla indicado por i.-
            LATB = Display7Seg [i];
            Delay10KTCYx (30);
        }
    }
}
« Última modificación: Septiembre 12, 2010, 05:22:12 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #7 : Mayo 03, 2009, 03:32:02 »

La manera más elegante de construir nuestro programa es dividir la tarea a ejecutar en varias tareas más simples, de modo de facilitar el desarrollo y el entendimiento de la estructura del mismo. Otra ventaja que conlleva este proceder es la reutilización de estos módulos creados con anterioridad, además de facilitar el trabajo en equipo.

Declaración y definición de funciones.

La declaración da a conocer la función al compilador, a partir de su declaración ya se pueden realizar invocaciones a las mismas. La declaración de una función se conoce también como prototipo de la función. En el prototipo de una función se tienen que especificar los parámetros de la función, así como el tipo de dato que devuelve.

La definición estará en algún otro punto del programa, aquí se especifican las instrucciones que forman parte de la misma y que se utilizan para llevar a cabo la tarea específica de la función.

Sintaxis:
Código: (c)
Tipo de retorno  Nombre(Lista de parámetros)

Tipo de retorno : Representa el tipo del valor que devuelve la función. Si no devuelve ninguno de debe colocar void.
Nombre: indica el nombre que se le da a la función, se recomienda que este relacionado con la tarea que llevará a cabo.
Lista de parámetros : se enlista el tipo de dato y el nombre de cada parámetro. En caso de utilizar parámetros se deja el paréntesis vacio o se incluye la palabra void.
Ejemplos:
Código: (c)
unsigned int Suma(unsigned char A, unsigned char B){
unsigned int C;
C=A+B;
return(C);
}
Código: (c)
void Envio_Data(unsigned char A){
//Sentencia.-
}
Código: (c)
void Muestras(void){
//Sentencias.-
}

Dos formas de incluir una función en nuestro código:
Realizando la declaración en el encabezado y después la definición en cualquier sector del programa.
Ejemplo:
Código: (c)
// Declaracion de la funcion
void Funcion(void);
.
.
.
void main(void){
.
.
.
// Llamo a la función.
Funcion();
}

//Defincion de la funcion. (Puede estar en cualquier lugar del programa)
void Funcion(void){
// Sentencias
}

Otra forma es no realizar la declaración de la función y realizar directamente la definición, pero esta tiene que estar si o si antes de su invocación.
Ejemplo:
Código: (c)
.
.
.
//Defincion de la funcion
void Funcion(void){
// Sentencias
}
void main(void){
.
.
.
// Llamo a la función.
Funcion();
}

Preprocesador y Directivas del preprocesador

El preprocesador es el primer programa que se llama en la etapa de compilación de un programa. El preprocesador tiene su propio lenguaje y sus directivas inician con un #.
Las ventajas que tiene usar el preprocesador son:

 *los programas son más fáciles de desarrollar,
 *son más fáciles de leer,
 *son más fáciles de modificar
 *se pueden generalizar para varias  arquitecturas o compiladores.


Directivas

#include
Esta directiva ya la hemos utilizado, se emplea para incluir archivos y suele darse al principio de los programas, porque en general se desea que su efecto alcance a todo el archivo fuente. Por esta razon los archivos preparados para ser incluidos se denominan headers o archivos de cabecera. En ellos se declaran las funciones que se implementan y definiciones para su implementacion.

#define
La directiva define tiene dos tipos de uso, como si fuera un objecto o como si fuera una funcion. Las que se asemejan a funciones toman parametros mientras que las que se asemejan a objetos no.
Su formato es el siguiente:

# define <identificador > <lista de tokens a reemplazar >
# define <identificador >(< lista de parametros>)<lista de tokens a reemplazar >


Ejemplos:

Código:
# define e 2.718258
# define LED LATBbits . LATB5
# define Suma_10 (x) {x +=10;}
# define Suma_Divide_10 (x) {(x +=10);( x /=10);}

Nota: Se debe tener cuidado en la implementacion de esta directiva. Las que se asemejan a funciones, pueden tomar parametros pero no se comportan como una funcion, ya que el preprocesador reemplaza un texto por otro, lo cual conlleva al mayor uso de la memoria de programa.

#ifdef, #ifndef, #else, #elif y #endif
Estas directivas son utilizadas para realizar compilaciones condicionadas, por ejemplo para hacer una libreria generalizada para varias arquitecturas, para ser utilizada por varios compiladores o simplemente para seleccionar el nivel de uso de cierto proyecto.

Ejemplos:

Código:
#if defined ( __18CXX )
    # include <p18cxxx .h>
# elif defined ( __dsPIC30F__ )
    # include <p30fxxxx .h>
# elif defined ( __dsPIC33F__ )
    # include <p33Fxxxx .h>
# elif defined ( __PIC24H__ )
    # include <p24Hxxxx .h>
# elif defined ( __PIC24F__ )
    # include <p24Fxxxx .h>
# endif

Código:
// Para no utilizar pin RW sacar comentario a la siguiente linea .-
//# define __LCD_DONT_WAIT
# define LCD_PIN_E LATCbits . LATC4
# define LCD_PIN_RS LATCbits . LATC2
# ifndef __LCD_DONT_WAIT
    # define LCD_PIN_RW LATCbits . LATC3
# endif

Código:
// CCS
#if defined ( __PCH__ )
    char Buffer [512];
# endif
// C18
# ifdef __18CXX
    # pragma udata =0 x100
    unsigned char Buffer [512];
    # pragma udata
# endif
// C30 y C32
#if defined ( __C30__ ) || defined ( __PIC32MX__ )
    unsigned char __attribute__ (( aligned (4))) Buffer [512];
# endif


Ejemplo:Control de varios display, multiplexión de la señal.

Objetivo: Controlar 3 display de 7 segmentos visualizando el conteo automático de 0 a 999.
Hardware:

Código:
Código: (c)
#include <p18f2550.h>
#include <delays.h>

#pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
#pragma config PWRT = ON,BOR = OFF,BORV = 0
#pragma config WDT = OFF,WDTPS = 32768
#pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
#pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
#pragma config CP0 = ON,CP1 = ON,CP2 = ON
#pragma config CPB = ON,CPD = ON
#pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
#pragma config WRTB = ON,WRTC = ON,WRTD = ON
#pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
#pragma config EBTRB = ON

#define UnidadBit LATAbits.RA0
#define DecenaBit LATAbits.RA1
#define CentenaBit LATAbits.RA2

unsigned char i, Unidad, Decena, Centena;
const rom unsigned char Display7Seg[10]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0xFF, 0x6F};
void Visualizacion (void);

void main(void){
ADCON1=0x0F;//Todos entrada/salida digitales.-
TRISA=0xF0; //Todos como entrada.-
TRISB=0X00; //Todos como salida.-

LATA=0x00;
Unidad=0;
Decena=0;
Centena=0;

while(1){
Visualizacion();
++Unidad;
if(Unidad==10){
Unidad=0;
++Decena;
if(Decena==10){
Decena=0;
++Centena;
}
}
}
}
void Visualizacion (void){
for(i=1;i<=20;++i){
LATB=Display7Seg[Unidad];
UnidadBit=1; //Enciendo Display Unidad.-
Delay1KTCYx(5); //Demora de 5 ms (XT=4MHz)
UnidadBit=0;
LATB=Display7Seg[Decena];
DecenaBit=1;
Delay1KTCYx(5);
DecenaBit=0;
LATB=Display7Seg[Centena];
CentenaBit=1;
Delay1KTCYx(5);
CentenaBit=0; //Apago Display Centena.-
}
}

« Última modificación: Septiembre 12, 2010, 05:27:13 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #8 : Mayo 03, 2009, 08:56:32 »

Control de un LCD.

Para realizar el control de un LCD necesitamos usar la librería xlcd.h ubicada en C:\MCC18\h\. Esta librería es para un LCD con controlador Hitachi HD44780 o compatible, de 8 o 4 bits. El usuario debe proveer 3 delay para el correcto funcionamiento, DelayPORXLCD() de 15ms, DelayXLCD() de 5ms y DelayFor18TCY() de 18 Tcy.

En este caso no vamos a modificar la librería, pues lo vamos a controlar con el puerto B, pero en el caso de que se modifique sugiero siempre respaldarla con una copia de seguridad.

Ejemplo: Control de un LCD.

Objetivo: Vamos a escribir un simple mensaje en un LCD. Se crearon 2 funciones adicionales para un mejor el control, la primeria seria el envío de comandos, con una previa espera de disponibilidad del LCD y la segunda es para controlar la posición del cursor en el LCD.

Hardware:

Código: (c)
#include <p18f2550.h>
#include <delays.h>
#include <xlcd.h>

#pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
#pragma config PWRT = ON,BOR = OFF,BORV = 0
#pragma config WDT = OFF,WDTPS = 32768
#pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
#pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
#pragma config CP0 = ON,CP1 = ON,CP2 = ON
#pragma config CPB = ON,CPD = ON
#pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
#pragma config WRTB = ON,WRTC = ON,WRTD = ON
#pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
#pragma config EBTRB = ON


void DelayFor18TCY(void){
Delay10TCYx(2);
}
void DelayPORXLCD(void){
Delay1KTCYx(15);
}
void DelayXLCD(void){
Delay1KTCYx(2);
}

// Envia comando al LCD
void comandXLCD(unsigned char a){
BusyXLCD();
WriteCmdXLCD(a);
}
// Ubica cursor en (x = Posicion en linea, y = nº de linea)
void gotoxyXLCD(unsigned char x, unsigned char y){
unsigned char direccion;

if(y != 1)
direccion = 0x40;
else
direccion=0;

direccion += x-1;
comandXLCD(0x80 | direccion);
}

void main(void){
OpenXLCD(FOUR_BIT & LINES_5X7); // Iniciamos LCD.-
        comandXLCD(0x06); // Nos aseguramos incremento de direccion, display fijo
comandXLCD(0x0C); // Encendemos LCD.-
putrsXLCD("Probando LCD");
gotoxyXLCD(1,2); //Pasamos al oriden del Linea 2.-
putrsXLCD("Por Suky");
while(1){ // Bucle infinito.
}
}


« Última modificación: Septiembre 06, 2009, 05:11:30 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #9 : Mayo 09, 2009, 11:08:08 »

Conversión analógica digital.

Para realizar una conversión analógica digital usaremos la librería adc.h, esta tiene las funciones necesarias para las configuraciones y lectura de dicho módulo. En el caso de las configuraciones, este posee varias y depende del microcontrolador que se use. Para saber en que grupo cae nuestro microcontrolador abrimos pconfig.h, y por ejemplo para el PIC18F2550 es ADC_V5.

NOTA: Para más información respecto al módulo y sus configuraciones ver tema, Módulo de conversión ADC  Wink

Funciones (para ADC_V5) :
OpenADC (PARAM_SCLASS unsigned char , PARAM_SCLASS unsigned char , PARAM_SCLASS unsigned char );

Con ella se configure el reloj, el formato, tensión de referencia, puerto y canal de la conversión. Para saber que colocar en cada parámetro abrir AD Converter ubicado en C:\MCC18\doc\periph-lib.
Ejemplos:
Código: (c)
OpenADC(ADC_FOSC_32 & ADC_8_TAD & ADC_RIGHT_JUST, ADC_REF_VDD_VSS & ADC_INT_OFF, ADC_5ANA);

#define  USE_OR_MASKS
OpenADC(ADC_FOSC_RC | ADC_20_TAD| ADC_LEFT_JUST, ADC_REF_VREFPLUS_VREFMINUS |  ADC_INT_OFF, ADC_15ANA);

CloseADC(); Desactiva el conversor y la interrupción.

SetChanADC(Unsigned char); Selecciona el canal que se va a utilizar.

ConvertADC(); Comienza la conversión.

SelChanConvADC(Unsigned char); Selecciona canal y comienza conversión.

BusyADC(); Comprueba si la conversión a finalizado.

Int ReadADC(); devuelve la lectura del canal analógico seleccionado.


Ejemplo: Uso del módulo de conversión analógico/digital.

Objetivo: Tomar lectura de 2 valores analógicos y mostrarlo en un LCD. Al accionar un pulsador, leeremos los 2 canales analógicos y los mostraremos en el LCD durante 1 segundo.

Hardware:

Código: (c)
#include <p18f2550.h>
#include <delays.h>
#include <xlcd.h>
#include <stdlib.h> //Libreria para conversiones.
#include <adc.h>

#pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
#pragma config PWRT = ON,BOR = OFF,BORV = 0
#pragma config WDT = OFF,WDTPS = 32768
#pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
#pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
#pragma config CP0 = ON,CP1 = ON,CP2 = ON
#pragma config CPB = ON,CPD = ON
#pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
#pragma config WRTB = ON,WRTC = ON,WRTD = ON
#pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
#pragma config EBTRB = ON


void DelayFor18TCY(void){
Delay10TCYx(2);
}
void DelayPORXLCD(void){
Delay1KTCYx(15);
}
void DelayXLCD(void){
Delay1KTCYx(2);
}

// Envia comando al LCD
void comandXLCD(unsigned char a){
BusyXLCD();
WriteCmdXLCD(a);
}
// Ubica cursor en (x = Posicion en linea, y = nº de linea)
void gotoxyXLCD(unsigned char x, unsigned char y){
unsigned char direccion;

if(y != 1)
direccion = 0x40;
else
direccion=0;

direccion += x-1;
comandXLCD(0x80 | direccion);
}



void main(void){
unsigned int Canal0, Canal1;
char String[4];
OpenXLCD(FOUR_BIT & LINES_5X7); // Iniciamos LCD.-
        comandXLCD(0x06); // Nos aseguramos incremento de direccion, display fijo
OpenADC(ADC_FOSC_RC & ADC_2_TAD & ADC_RIGHT_JUST, ADC_REF_VDD_VSS & ADC_INT_OFF, ADC_2ANA);
comandXLCD(0x0C); // Encendemos LCD.-

while(1){
comandXLCD(0x01); // Borra pantalla y vuelve al origen.-
putrsXLCD("Presionar boton");
while(PORTAbits.RA2==1){} // Espero a que se accione el pulsador.-
SetChanADC(0); // Selecciono canal a convertir.-
//Delay10TCYx(1); // 10us para que se cargue el  capacitor sample&hold  (Solo cuando se selecciona ADC_0_TAD).-
ConvertADC(); // Comienza conversión.-
While(BusyADC()==1){} // Hasta que se finalice conversión.-
Canal0= ReadADC(); // Realizo lectura.-

SetChanADC(1); // Selecciono canal a convertir.-
//Delay10TCYx(1); // 10us para que se cargue el  capacitor sample&hold  (Solo cuando se selecciona ADC_0_TAD).-
ConvertADC(); // Comienza conversión.-
While(BusyADC()==1){} // Hasta que se finalice conversión.-
Canal1= ReadADC(); // Realizo lectura.-

comandXLCD(0x01); // Borra pantalla y vuelve al origen.-
putrsXLCD("Canal 0 = ");
itoa(Canal0, String); // Convertimos entero a string.-
putsXLCD(String);
gotoxyXLCD(1,2);
putrsXLCD("Canal 1 = ");
itoa(Canal1, String); // Convertimos entero a string.-
putsXLCD(String);
Delay10KTCYx(100);
}
}

« Última modificación: Noviembre 01, 2009, 01:05:32 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #10 : Mayo 09, 2009, 11:08:32 »

Interrupciones:

Los dispositivos PIC18 tienen múltiples fuentes de interrupción y una característica de prioridad de interrupción, que permite a cada fuente de interrupción asignarle un nivel de prioridad bajo o alto. Cuando ocurre un evento de alta prioridad interrumpirá cualquier interrupción de baja prioridad que pueda estar en progreso. El vector de alta prioridad esta en 0x08 y el vector de baja prioridad en 0x18.

Cada fuente de interrupción tiene tres bits para controlar su operación. Las funciones de estos bits son:
  • Bit bandera, que indica si un evento de interrupción ha ocurrido
  • Bit Enable, que admiten la ejecución de la interrupción, permitiendo la bifurcación del programa a la dirección del vector de interrupción
  • Bit de prioridad, para seleccionar prioridad baja o alta

La característica de prioridad de interrupciones de activa seteando el bit IPEN. Si este no esta seteado,  no existen prioridades y las interrupciones se comportan como en los dispositivos de gama media (PIC16) y todas las interrupciones se bifurcan al vector 0x08.

Rutinas de atención a interrupciones:

La directiva #pragma interruplow nombre define rutina de servicio de interrupción (ISR) de baja prioridad y #pragma interrup nombre se alta prioridad.
Las ISR son funciones como cualquier otra, pero con las restricciones de que:
  • No devuelven ni aceptan parámetros
  • No se puede invocar desde otros puntos del programa
  • Las variables globales que utilice se den declarar como volatile

El C18 no sitúa automáticamente las ISR en las posiciones de los vectores de interrupción, por lo que el usuario debe ubicarlas. Ejemplos:

Código: (c)
#pragma interruplow ISRBajaPrioridad
Void ISRBajaPrioridad(void){
// Tratamiento de interrupción.-
}

// Creamos una nueva sección de código a partir de la dirección 0x18.-
#pragma code PrioridadBaja = 0x18
Void VectorBajaPrioridad(void){
// Instruccion insertada en la dirección 0x18.-
_asm goto ISRBajaPrioridad _endasm
}
#pragma code // Cerramos sección.-


Código: (c)
#pragma interruplow ISRAltaPrioridad
Void ISRAltaPrioridad(void){
// Tratamiento de interrupción.-
}

// Creamos una nueva sección de código a partir de la dirección 0x08.-
#pragma code PrioridadAlta = 0x08
Void VectorAltaPrioridad(void){
// Instruccion insertada en la dirección 0x08.-
_asm goto ISRAltaPrioridad _endasm
}
#pragma code // Cerramos sección.-

« Última modificación: Mayo 10, 2009, 10:12:43 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #11 : Mayo 10, 2009, 10:15:27 »

Módulo USART.

Para la comunicación serial es necesario agregar la librería usart.h. Con esta librería se configura el modo de transmisión y recepción serie de nuestro microcontrolador.

Funciones:

OpenUSART( unsigned char config, unsigned int spbrg);
Esta función corresponde a la configuración del módulo USART, asincrónica o sincrónica, 8 bits o 9 bits, velocidad de comunicación, etc.
Para saber que colocar en cada parámetro abrir USART ubicado en C:\MCC18\doc\periph-lib.

CloseUSART(); Deshabilita módulo USART.

putcUSART(char data); Envía un byte.

putsUSART(char *buffer); Envia un string desde la memoria de datos.

putrsUSART(const rom char *data); Envia un string desde la memoria de programa.

BusyUSART(); Determina si se ha transmitido el dato.

DataRdyUSART(); Indica si ha llegado un dato para ser leído.

getcUSART(); Lee un byte.

getsUSART(char *buffer, Unsigned char len); Lee un string.

Estructura switch.
Esta estructura permite ejecutar un bloque de código de acuerdo con el valor de una variable o expresión:
Código: (c)
switch(Variable){
Case 0x01:
//Sentencias.-
Break;
Case 0x02:
//Sentencias.-
Break;
Default:
//Sentencias.-
Break;
}

Default: ejecuta esa sentencia si no es ninguna de las anteriores.


Ejemplo: Comunicación Serial RS232.

Objetivo: La PC enviara comando de lectura de los canales analógicos. Si se recibe un 0x61 ('a'), enviar canal 0, si se recibe un 0x62 ('b') enviar canal 1 y si se recibe un 0x63 ('c') enviar los 2 canales analógicos.

Hardware:

La adaptación de tensiones se puede hacer con el MAX232 o con transistores, como se desee.-

Código: (c)
#include <p18f2550.h>
#include <delays.h>
#include <stdlib.h> //Libreria para conversiones.
#include <adc.h>
#include <usart.h>

#pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
#pragma config PWRT = ON,BOR = OFF,BORV = 0
#pragma config WDT = OFF,WDTPS = 32768
#pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
#pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
#pragma config CP0 = ON,CP1 = ON,CP2 = ON
#pragma config CPB = ON,CPD = ON
#pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
#pragma config WRTB = ON,WRTC = ON,WRTD = ON
#pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
#pragma config EBTRB = ON

void ISRRecepcion(void);
volatile char Data, Kbhit;

// Creamos una nueva seccion de codigo a partir de la direccion 0x08.-
#pragma code Interrupcion = 0X0008
void VectorInterrupcion(void){
_asm goto ISRRecepcion _endasm
}
#pragma code // Cerramos seccion.-

// Rutina de Interrupcion.-
#pragma interrupt ISRRecepcion
void ISRRecepcion(void){
if(PIR1bits.RCIF==1){
Data=getcUSART(); // Leemos Dato recibido
Kbhit=1; // Indicamos que se ha recibido un dato.-
PIR1bits.RCIF=0; // Borramos bandera.-
}
}


void main(void){
unsigned int Canal0, Canal1;
char String[4];

OpenUSART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE & USART_EIGHT_BIT &
USART_CONT_RX & USART_BRGH_HIGH,25); // 9600,8,n,1
OpenADC(ADC_FOSC_RC & ADC_2_TAD & ADC_RIGHT_JUST, ADC_REF_VDD_VSS & ADC_INT_OFF, ADC_2ANA);
Kbhit=0;
RCONbits.IPEN=0; // Deshabilitamos Prioridades
INTCONbits.PEIE=1; // Habilitamos interrupcion de perifericos.-
INTCONbits.GIE=1; // Habilitamos interrupcion Global.

putrsUSART("Prueba Comunicacion Serial \r");
while(1){
while(Kbhit==0){}; // esperamos a recibir dato.-
Kbhit=0;
switch(Data){
case 0x61: // letra a
SetChanADC(0); // Selecciono canal a convertir.-
//Delay10TCYx(1); // 10us para que se cargue el  capacitor sample&hold  (Solo cuando se selecciona ADC_0_TAD).-
ConvertADC(); // Comienza conversión.-
While(BusyADC()==1){} // Hasta que se finalice conversión.-
Canal0= ReadADC(); // Realizo lectura.-
putrsUSART("Canal 0 = ");
itoa(Canal0, String); // Convertimos entero a string.-
putsUSART(String);
putrsUSART("\r");
break;
case 0x62: // letra b
SetChanADC(1); // Selecciono canal a convertir.-
//Delay10TCYx(1); // 10us para que se cargue el  capacitor sample&hold  (Solo cuando se selecciona ADC_0_TAD).-
ConvertADC(); // Comienza conversión.-
While(BusyADC()==1){} // Hasta que se finalice conversión.-
Canal1= ReadADC(); // Realizo lectura.-
putrsUSART("Canal 1 = ");
itoa(Canal1, String); // Convertimos entero a string.-
putsUSART(String);
putrsUSART("\r");
break;
case 0x63: // letra c
SetChanADC(0); // Selecciono canal a convertir.-
//Delay10TCYx(1); // 10us para que se cargue el  capacitor sample&hold  (Solo cuando se selecciona ADC_0_TAD).-
ConvertADC(); // Comienza conversión.-
While(BusyADC()==1){} // Hasta que se finalice conversión.-
Canal0= ReadADC(); // Realizo lectura.-

SetChanADC(1); // Selecciono canal a convertir.-
//Delay10TCYx(1); // 10us para que se cargue el  capacitor sample&hold  (Solo cuando se selecciona ADC_0_TAD).-
ConvertADC(); // Comienza conversión.-
While(BusyADC()==1){} // Hasta que se finalice conversión.-
Canal1= ReadADC(); // Realizo lectura.-

putrsUSART("Canal 0 = ");
itoa(Canal0, String); // Convertimos entero a string.-
putsUSART(String);
putrsUSART("\r");
putrsUSART("Canal 1 = ");
itoa(Canal1, String); // Convertimos entero a string.-
putsUSART(String);
putrsUSART("\r");
break;
}
}
}
« Última modificación: Octubre 11, 2009, 05:08:17 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #12 : Mayo 10, 2009, 10:20:27 »

Otra manera de enviar los datos, usando printf:

Para utilizar esta función debemos agregar la librería stdio.h.
printf (const rom char *fmt, ...);
Nos permite especificar el formato en que queremos mostrar datos por pantalla
Parámetros: Cadena de formato (cómo se visualizan los datos) y Lista de valores (datos que se visualizan)
Formatos:

%d Entero con signo.
%u Entero sin signo.
%x Hexadecimal minúscula.
%X Hexadecimal mayúscula.

Ejemplo:
Código: (c)
printf(“Hola”);
Data=10;
printf(“El valor es : %u”,Data);

Ejemplo de formatos:

EspecificaciónValor=0x12Valor=0xFE
%03u018254
%u18254
%2u18*
%d18-2
%x12fe
%X12FE
         
Entonces se puede reemplazar:
Código: (c)
Canal0=ReadADC();
putrsUSART("Canal 0 = ");
itoa(Canal0, String);
putsUSART(String);
putrsUSART("\r");

Por:
Código: (c)
#include <stdio.h>
.
.
.
Canal0=ReadADC();
printf("Canal 0 = %u \r", Canal0);
   
En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #13 : Mayo 10, 2009, 10:21:07 »

Modificar las librerías.
Se explicará como realizar cambios en las librerías de C18, para que estas se hagan efectivas a la hora de compilar. En este caso cambiaremos el Puerto para el control del LCD.
Primero que nada se debe realizar una copia de seguridad, en este caso de xlcd.h. Luego en nuestro programa debemos incluir a xlcd.h  (MCC18\h) en Header Files, y los archivos fuentes de esta librería (MCC18\src\pmc_common\XLCD), excepto putrxlcd, quedando de la siguiente manera:
De esta manera se recompilan los archivos, creando sus respectivos archivos objetos (*.o) necesarios para el linkeo (MPLink) y así efectivizar los cambios realizados en las rutinas.

Vamos a modificar xlcd.h para que utilizar el Puerto C para controlar el LCD y los 4 bits más significativos del mismo (UPPER) para enviar los datos al LCD de la siguiente manera:
Código: (c)
#define UPPER
/* DATA_PORT defines the port to which the LCD data lines are connected */
#define DATA_PORT      PORTC
#define TRIS_DATA_PORT TRISC
/* CTRL_PORT defines the port where the control lines are connected.
 * These are just samples, change to match your application.
 */
#define RW_PIN   LATCbits.LATC1   /* PORT for RW */
#define TRIS_RW  TRISCbits.TRISC1    /* TRIS for RW */
#define RS_PIN   LATCbits.LATC0   /* PORT for RS */
#define TRIS_RS  TRISCbits.TRISC0    /* TRIS for RS */
#define E_PIN    LATCbits.LATC2   /* PORT for D  */
#define TRIS_E   TRISCbits.TRISC2    /* TRIS for E  */

Cualquier cambio, por mínimo que sea se debe hacer de esta manera para que se efectivicen los cambios.

Código: (c)
#include <p18f2550.h>
#include <delays.h>
#include <xlcd.h>


#pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
#pragma config PWRT = ON,BOR = OFF,BORV = 0
#pragma config WDT = OFF,WDTPS = 32768
#pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
#pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
#pragma config CP0 = ON,CP1 = ON,CP2 = ON
#pragma config CPB = ON,CPD = ON
#pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
#pragma config WRTB = ON,WRTC = ON,WRTD = ON
#pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
#pragma config EBTRB = ON


void DelayFor18TCY(void){
Delay10TCYx(2);
}
void DelayPORXLCD(void){
Delay1KTCYx(15);
}
void DelayXLCD(void){
Delay1KTCYx(2);
}

// Envia comando al LCD
void comandXLCD(unsigned char a){
BusyXLCD();
WriteCmdXLCD(a);
}
// Ubica cursor en (x = Posicion en linea, y = nº de linea)
void gotoxyXLCD(unsigned char x, unsigned char y){
unsigned char direccion;

if(y != 1)
direccion = 0x40;
else
direccion=0;

direccion += x-1;
comandXLCD(0x80 | direccion);
}

void main(void){
OpenXLCD(FOUR_BIT & LINES_5X7); // Iniciamos LCD.-
        comandXLCD(0x06); // Nos aseguramos incremento de direccion, display fijo
comandXLCD(0x0C); // Encendemos LCD.-
putrsXLCD("LCD en Puerto C");
gotoxyXLCD(1,2); //Pasamos al oriden del Linea 2.-
putrsXLCD("Por Suky");
while(1){ // Bucle infinito.
}
}


« Última modificación: Septiembre 06, 2009, 05:12:47 por Suky » En línea

Suky
**----- ^^ ------**
Moderador
dsPIC
******
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5434


Con Qt...


WWW
« Respuesta #14 : Junio 26, 2009, 01:18:15 »

Interrupción por cambio de estado RB4-RB7. Control de Teclado Matricial.

Objetivo:  Al accionar una tecla del Teclado Matricial, esta se mostrará en la pantalla LCD. Aprovecharemos la interrupción por cambio de estado RB4-RB7 para detectar que se ha presionado una tecla. Dentro de la interrupción se realiza el rastreo fino para determinar cual ha sido.

Hardware:

Nota: En Proteus se deben agregar las resistencias pull-up a RB4-RB7 para simular correctamente. Además se usa el puerto C para el control del LCD, y para que la compilación sea correcta se deben seguir los pasos del mensaje anterior.

Código: (c)
#include <p18f2550.h>
#include <delays.h>
#include <xlcd.h>

#pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
#pragma config PWRT = ON,BOR = OFF,BORV = 0
#pragma config WDT = OFF,WDTPS = 32768
#pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
#pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
#pragma config CP0 = ON,CP1 = ON,CP2 = ON
#pragma config CPB = ON,CPD = ON
#pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
#pragma config WRTB = ON,WRTC = ON,WRTD = ON
#pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
#pragma config EBTRB = ON

unsigned char Tecla;
unsigned char Teclas[17]={'7','8','9','/',
'4','5','6','x',
'1','2','3','-',
'.','0','=','+',''};

void ISRRB4_RB7(void);
void DelayFor18TCY(void);
void DelayPORXLCD(void);
void DelayXLCD(void);
void comandXLCD(unsigned char a);
void gotoxyXLCD(unsigned char x, unsigned char y);
char TestTeclado(void);

// Creamos una nueva seccion de codigo a partir de la direccion 0x08.-
#pragma code Interrupcion = 0X0008
void VectorInterrupcion(void){
_asm goto ISRRB4_RB7 _endasm
}
#pragma code // Cerramos seccion.-

//*************************************************************************
void main(void){
OpenXLCD(FOUR_BIT & LINES_5X7); // Iniciamos LCD.-
        comandXLCD(0x06); // Nos aseguramos incremento de direccion, display fijo

TRISB=0xF0; //eeeessss.-
PORTB=0x00;
INTCON2 = 0X80; // Habilitamos resistencias pull up.
INTCON = 0X88; //Configuración de interrupción por cambio de estado RB4-RB7

comandXLCD(0x0C); // Encendemos LCD.-
putrsXLCD("TeclaPulsada \" \"");
gotoxyXLCD(2,2); //Pasamos al oriden del Linea 2.-
putrsXLCD("<<Autor Suky>>");
while(1){ // Bucle infinito.
}
}

//*************************************************************************
void DelayFor18TCY(void){
Delay10TCYx(2);
}
void DelayPORXLCD(void){
Delay1KTCYx(15);
}
void DelayXLCD(void){
Delay1KTCYx(2);
}

// Envia comando al LCD
void comandXLCD(unsigned char a){
BusyXLCD();
WriteCmdXLCD(a);
}
// Ubica cursor en (x = Posicion en linea, y = nº de linea)
void gotoxyXLCD(unsigned char x, unsigned char y){
unsigned char direccion;

if(y != 1)
direccion = 0x40;
else
direccion=0;

direccion += x-1;
comandXLCD(0x80 | direccion);
}


/* Rastrea Tecla presionada, para ello, se va colocando a 0 lógico las filas de a una por vez,
* y se testea si alguna columna tambien lo esta. Se utiliza la variable i para indicar que tecla
* esta siendo testeada, y de esta manera al detectar la pulsacion usar esta variable para
* seleccionar el caracter en el Buffer Teclas.*/
char TestTeclado(void){
unsigned char i,j;
PORTB=0x0E; //xxxx1110.
i=0;
for(j=0;j<4;j++){
if(PORTBbits.RB4==0){break;}
i++;
if(PORTBbits.RB5==0){break;}
i++;
if(PORTBbits.RB6==0){break;}
i++;
if(PORTBbits.RB7==0){break;}
i++;
PORTB<<=1; //Trasladamos el 0 a siguiente Pin.
}
return(Teclas[i]);
}

//****************************************************************
// Rutina de Interrupcion.-
#pragma interrupt ISRRB4_RB7
void ISRRB4_RB7(void){
if(INTCONbits.RBIF==1){
Tecla=TestTeclado(); //Realizamos test del Teclado, y nos devuelve tecla pulsada
gotoxyXLCD(15,1);
putcXLCD(Tecla); // Visualizamos tecla pulsada.
while(PORTBbits.RB4==0 |PORTBbits.RB5==0 |PORTBbits.RB6==0 |PORTBbits.RB7==0){} //Esperamos a que se suelte.-
PORTB=0x00;
INTCONbits.RBIF = 0; //Borramos bandera
}
}
« Última modificación: Septiembre 06, 2009, 05:13:17 por Suky » En línea


La gente de Niple nos ofrece un descuento especial para usuarios de uControl.
Entérate de como puedes aprovechar esta oferta haciendo click aqui.

Súmate, y ayuda a uControl con tu participación en esta interesante oportunidad que nos oferece Niple.

Páginas: [1] 2   Ir Arriba
  Imprimir  
 
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.19 | SMF © 2011, Simple Machines
SMFAds for Free Forums
XHTML 1.0 válido! CSS válido!
Página creada en 0.151 segundos con 29 consultas. (Pretty URLs adds 0.015s, 3q)