TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: lmtreser en 25 de Abril de 2013, 01:33:07

Título: Mini curso "Programación en XC8"
Publicado por: lmtreser en 25 de Abril de 2013, 01:33:07
Hola amigos, a continuación voy a publicar el mini curso que estoy armando de a poco en el foro uControl. Bienvenidas sugerencias, correcciones y aportes aquí mismo, por Twitter (http://www.twitter.com/lmtreser) o como sea!

Mini curso "Programación de micros en C desde 0"

Introducción

Hola, hoy empiezo este mini curso de programación de microcontroladores PIC en lenguaje C desde 0. La idea es aprender paso a paso, realizar algunos proyectos simples y sumar conocimientos.

Voy a trabajar sobre el sistema operativo Ubuntu, con software libre o gratuito. Para todos aquellos que utilizan Windows no van a tener inconvenientes porque los paquetes de software son multiplataforma. Voy a utilizar como entorno de desarrollo MPLAB X en conjunto con el compilador XC8. No me voy a detener en la instalación y configuración del IDE y del compilador ya que existen muchos tutoriales sobre esto (por ejemplo (http://www.automatismos-mdq.com.ar/blog/2011/04/instalar-mplab-x-en-ubuntu.html)). El microcontrolador por ahora es un PIC16F648A salvo indicación contraria!

El curso lo voy realizando sobre la marcha, en parte leyendo libros, en parte dudas consultadas a los expertos en el foro y en parte en experiencias propias. Por este motivo lo verán formarse "online" y a medida que el tiempo me lo permita ire sumando contenido. Les recomiendo que lean el tutorial sobre XC8 que escribió Suky (http://www.micros-designs.com.ar/tutorial-xc8-introduccion/) que es un buen punto de partida y el "Tutorial MPLAB C18 Desde Cero" (http://www.ucontrol.com.ar/forosmf/tutoriales-guias-y-cursos-en-ucontrol/tutorial-mplab-c18-desde-0/). También es de mucha utilidad tener a mano los ejemplos de Microchip para consulta: Microchip Code Examples (12F & 16F) (http://www.mediafire.com/?ajiish29dzjd09u).

Indice:

1.1. Estructura de un programa en C (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338215#msg338215)
1.2. ¡Hola Mundo! en C (o como hacer destellar un LED) (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338216#msg338216)
1.3. Leer un pulsador (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338217#msg338217)
1.4. Utilizando PWM (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338218#msg338218)
1.5. Uso de funciones (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338219#msg338219)
1.6. Variables y tipos de datos (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338220#msg338220)
1.7. Usando una interrupción por timer0 (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338221#msg338221)
1.8. Interrupciones de alta y baja prioridad (http://www.todopic.com.ar/foros/index.php?topic=40649.msg340202#msg340202)

Ejemplos y rutinas útiles:

2.1. Ejemplo de uso PIC18F4550, delays y USART (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339587#msg339587)
2.2. Escribir y leer una memoria EEPROM (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338370#msg338370)
2.3. Rutina para generar pausas extensas (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338510#msg338510)
2.4. PIC16F819 controlando un modulo LCD 2x16 - 4 bits (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339676#msg339676)
2.5. Conversores ADC/PWM (uso de la función ITOA) (http://www.todopic.com.ar/foros/index.php?topic=40649.msg340679#msg340679)
2.6. Uso de I2C por software (http://www.todopic.com.ar/foros/index.php?topic=40649.msg340651#msg340651)

Bugs, errores, herramientas:

3.1. Corrección del bug "maldita linea roja" (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339853#msg339853)
3.2. Dolor de cabeza con el uso de la librería del LCD xlcd.h (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339865#msg339865)
3.3. Integrar Proteus VSM para hacer debug en los proyectos de MPLABX con el plugin Proteus VSM viewer (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339909#msg339909)
3.4. View Includes Hierarchy (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339910#msg339910)
3.5. View macro expansion (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339911#msg339911)
3.6. Generador de código para los "Bits de configuración" (http://www.todopic.com.ar/foros/index.php?topic=40649.msg340566#msg340566)
Título: Re: Mini curso "Programación en XC8"
Publicado por: lmtreser en 25 de Abril de 2013, 01:35:42
1.1. Estructura de un programa en C

C es el lenguaje de programación que utilizaremos. Un programa C está compuesto por una o varias funciones, dentro de las cuales tendremos una o más instrucciones. Existe una función llamada "main" donde tendremos nuestro código principal.

Comentarios: Los comentarios son de mucha utilidad para entender lo que escribimos. Para realizar un comentario anteponemos en la línea de código "//" y el compilador la ignorará. También podemos comentar bloques de código utilizando "/*" para abrir y "*/" para cerrar.

Includes: utilizando "#include" incluimos en nuestro programa archivos de funciones o librerías que nos permitirán utilizar características especiales.

Ejemplo:

Código: C
  1. /*
  2.  * File:   main.c
  3.  * Author: lucas
  4.  * Created on 1 de abril de 2013, 22:20
  5.  *
  6.  * ESTO ES UN BLOQUE DE COMENTARIOS
  7.  */
  8.  
  9. #include <xc.h> // Incluimos la librería XC8
  10.  
  11. // ESTO ES UN COMENTARIO DE UNA LINEA
  12.  
  13. // Función principal
  14. void main ()
  15. {
  16.     OSCCONbits.IRCF = 0b110; // Instrucción
  17.  
  18. }
IMPORTANTE:

* Todas las instrucciones deben terminar si o si en ";".
* Los bloques de instrucciones empiezan con "{" y terminan con "}".
* C es case sensitive, es decir que distingue minúsculas de mayúsculas.
Título: Re: Mini curso "Programación en XC8"
Publicado por: lmtreser en 25 de Abril de 2013, 01:36:59
1.2. ¡Hola mundo! en C (o como hacer destellar un LED)

Hacer destellar un LED es muy sencillo. Tanto como crear un bucle infinito, escribir en un pin, generar una demora y volver a escribir. El ejemplito:

Código: C
  1. /*
  2.  * File:   main.c
  3.  * Author: lucas
  4.  * Created on 1 de abril de 2013, 22:20
  5.  * Microcontrolador: PIC16F648A
  6.  *
  7.  * ¡Hola Mundo! en C (o como hacer destellar un LED)
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <xc.h> // Librería XC8
  13.  
  14. #define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro
  15.  
  16. // PIC16F648A Configuration Bit Settings
  17. #pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
  18. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  19. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  20. #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
  21. #pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
  22. #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
  23. #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
  24. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  25.  
  26. // FUNCION PRINCIPAL
  27. void main ()
  28. {
  29.      TRISB = 0b00000000; // Configuro puerto B como salidas
  30.      while (1) // Bucle infinito
  31.      {
  32.          PORTBbits.RB0 = 0; // Apago pin RB0
  33.          __delay_ms(500);
  34.          PORTBbits.RB0 = 1; // Enciendo pin RB0
  35.          __delay_ms(500);
  36.      }
  37. }

* Podríamos hacer el cambio de estado del pin RB0 (toggle) utilizando la siguiente instrucción: PORTBbits.RB0 ^= 1;
Título: Re: Mini curso "Programación en XC8"
Publicado por: lmtreser en 25 de Abril de 2013, 01:38:02
1.3. Leer un pulsador

Utilizando una estructura condicional "if" podemos leer un pulsador conectado en RB0 para encender o apagar un LED en el pin RB4.

Código: C
  1. /*
  2.  * File:   main.c
  3.  * Author: lucas
  4.  * Created on 1 de abril de 2013, 22:20
  5.  * Microcontrolador: PIC16F648A
  6.  *
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <xc.h> // Librería XC8
  12.  
  13. #define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro
  14.  
  15. // PIC16F648A Configuration Bit Settings
  16. #pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
  17. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  18. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  19. #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
  20. #pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
  21. #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
  22. #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
  23. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  24.  
  25. // FUNCION PRINCIPAL
  26.  
  27. void main() {
  28.  
  29.     TRISB = 0b00000001; // Configuro puerto B
  30.     PORTB = 0b00000000;
  31.  
  32.     if (PORTBbits.RB0 == 1) {
  33.         PORTBbits.RB4 = 1;
  34.     } else {
  35.         PORTBbits.RB4 = 0;
  36.     }
  37. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: lmtreser en 25 de Abril de 2013, 01:39:26
1.4. Utilizando PWM

Vamos a utilizar una señal PWM de 8 bits para controlar el brillo de un LED. Para configurar el módulo CCP1 en modo PWM solo basta con escribir 0x0C en el registro CCP1CON.

Frecuencia PWM: el periodo de la onda PWM lo determina el tiempo que dura el conteo del Timer2 desde 0 hasta el valor cargado en el registro PR2. Y como la frecuencia es la inversa del período podemos deducir:

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=40649.0;attach=20531)



Donde:

* PR2 es el valor del registro PR2 (entre 0 y 255)
* FOSC es la frecuencia del cristal utilizado
* Prescaler es el prescaler del Timer2 (1, 4 ó 16). Se configura en el registro T2CON.

Ciclo de trabajo (duty cicle): es la cantidad de tiempo que en un periodo la salida PWM permanece en estado alto. El valor es determinado por el contenido del registro CCPR1L. Podemos deducir el tiempo utilizando la formula:

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=40649.0;attach=20533)



Donde:

* CCPR1L es el valor del registro CCPR1L (entre 0 y 255)
* FOSC es la frecuencia del cristal
* Prescaler   es el prescaler del Timer2 (1, 4 ó 16)

Ejemplo dimerizado de un LED conectado a RB3

Código: C
  1. /*
  2.  * File:   main.c
  3.  * Author: lucas
  4.  * Created on 1 de abril de 2013, 22:20
  5.  * Microcontrolador: PIC16F648A
  6.  *
  7.  * Utilizando PWM para dimerizar un LED
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <xc.h> // Librería XC8
  13.  
  14. #define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro
  15.  
  16. // PIC16F648A Configuration Bit Settings
  17. #pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
  18. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  19. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  20. #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
  21. #pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
  22. #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
  23. #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
  24. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  25.  
  26. // FUNCION PRINCIPAL
  27. void main(void) {
  28.     TRISB = 0;                  // Puerto B como salidas
  29.     PORTB = 0;                  // Limpio el puerto B
  30.  
  31. // CONFIGURANDO PWM  
  32.     CCP1CON = 0b00001100;       // Activamos el modo PWM
  33.     PR2 = 250;                  // Frecuencia 250Hz
  34.     T2CONbits.T2CKPS = 0b10;    // Prescaler del timer 2 en 1:16
  35.     T2CONbits.TMR2ON = 1;       // Arranca el PWM      
  36.  
  37. // BUCLE INFINITO
  38.     unsigned char i;           // Declaramos una variable
  39.     while (1){
  40.     for(i=0; i=50; i++)
  41.     {
  42.       CCPR1L = CCPR1L++;        // Seteando el ciclo de trabajo
  43.       __delay_ms (100);    
  44.     }
  45.     i=0;                       // Reiniciamos la variable para comenzar el ciclo de nuevo
  46.     }
  47.     }
Título: Re: Mini curso "Programación en XC8"
Publicado por: lmtreser en 25 de Abril de 2013, 01:44:27
1.5. Uso de funciones

Las funciones sirven para modularizar un programa. La idea es dividir nuestro código en distintos bloques, y asignarle una tarea especifica a cada uno. Esto nos ayudará a comprender el funcionamiento de nuestro programa y a hacerlo más ordenado.

Si bien todavía no hablamos para nada de variables, tenemos que tener en cuenta que juega un papel muy importante la forma en que las declaramos. Un poco más adelante lo veremos.

La sintaxis de una función es la siguiente:

tipo_de_datos nombre_de_la_funcion (tipo_y_nombre_de_argumentos) {
    instrucciones
    instrucciones
}
 
donde:

tipo_de_datos: es el tipo de dato que devolverá esa función.
nombre_de_la_funcion: es el identificador que le damos a nuestra función.
tipo_y_nombre_de_argumentos: son los parámetros que recibe la función.

No todas las funciones reciben argumentos. En caso que posean se tratan simplemente de variables locales que reciben un valor. Este valor se lo enviamos al hacer la llamada a la función.

Un sencillo ejemplo:

Código: C
  1. // FUNCION "EJEMPLO". NO RECIBE ARGUMENTOS
  2. void ejemplo (void){
  3.     PORTBbits.RB1 = 1;    // High pin RB1
  4.     __delay_ms (1700);    // Demora
  5.     PORTBbits.RB1 = 0;    // Low pin RB1
  6. }
  7.  
  8. // FUNCION PRINCIPAL
  9. void main(void) {
  10.     TRISB = 0b00000001;
  11.     PORTB = 0;                       // Limpio el puerto B
  12.  
  13.     while (1){                         // Bucle infinito  
  14.     if (PORTBbits.RB0 == 1){    // Chequeo estado de RB0
  15.         ejemplo();                    // Llamado a función "ejemplo"
  16.     }
  17.     }
  18. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: lmtreser en 25 de Abril de 2013, 01:45:14
1.6. Variables y tipos de datos

TIPOS DE DATOS. Siempre que arranquemos a estudiar un nuevo compilador lo primero que debemos analizar, a mi entender, son los tipos de datos disponibles. Ello nos permitirá tener control sobre el dimensionamiento de las variables determinando que tamaños y rangos de datos podremos almacenar en ellas.

Los puntos a tener en cuenta sobre los tipos de datos son los siguientes:

* Nombre del tipo y su correspondiente nombre estandarizado
* Existencia de tipos para almacenar números enteros y reales
* Tamaño en bits
* Tipo aritmético (si es con o sin signo)
* Comportamiento del tipo aritmético por defecto (si no especificamos si el tipo es con o sin signo ¿cual es el comportamiento?)
* Rango de valores que podremos almacenar

En XC8 tenemos los siguientes tipos para almacenar datos numéricos "enteros" (sin decimales), a saber:

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=40649.0;attach=20653)

En la tabla pueden ver que puse el nombre estandarizado de cada tipo. Ya que es más fácil de visualizar un int16 que un signed int o int32 que signed long (ya veremos como utilizar los nombres estandarizados en nuestro código).

Hay que tener en cuenta que los tipos de datos: bit y short long no son tipos estandar de C. Y el que tipo long long es C99 Standard. El tipo bit tiene ciertas limitaciones que ya veremos.

Tipos con signo o sin signo. Si el signo no se especifica junto al tipo de dato, el tipo de dato por defecto será signado con excepción del tipo char que por defecto es unsigned o sin signo. El tipo bit siempre se lo toma no signado.

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=40649.0;attach=20651)

Los rangos disponibles nos permitirán elegir eficientemente que tipo debemos utilizar al diseñar nuestro código. Por ejemplo para almacenar los días dentro de un mes (de 1 a 31) con un tipo char (int8) nos alcanzará. Pero si queremos almacenar los días consecutivos dentro de un año (de 1 a 365) ya no nos alcanzará debiendo utilizar un signed int (int16).

Para almacenar el kilometraje de un auto ya no nos alcanzará con un signed int (int16) y deberemos elegir un tipo mayor como ser signed short long (int24). Y si queremos almacenar los habitantes de un país nos quedamos cortos con un short long (int24) debiendo utilizar para ello un unsigned long long (int32) pudiendo almacenar hasta 4.294.967.295 habitantes.

En XC8 también contamos con tipos para almacenar datos numéricos "reales" o flotantes, a saber: 24-bit y 32-bit floating-point types. Por ahora sólo debemos saber que existen además float y double. Más adelante ampliaremos.

Gracias a Jukinch (http://www.todopic.com.ar/foros/index.php?action=profile;u=8836) por el excelente aporte a este capítulo!
Título: Re: Mini curso "Programación en XC8"
Publicado por: lmtreser en 25 de Abril de 2013, 01:46:05
1.7. Usando una interrupción por Timer 0

El PIC16F648A cuenta con un temporizador programable que efectúa una interrupción al desbordar su cuenta. Esto es muy útil para gran cantidad de artilugios.

Para trabajar con el Timer 0 debemos hacer uso de algunos registros y bits de configuraciones. A saber:

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=40649.0;attach=20535)

Registro TMR0: almacena el valor del contador en tiempo real. Se puede alterar su contenido.
Registro INTCON: configuración de interrupciones. Los siguientes bits están asociados al Timer0:

- T0IF: bandera que se pone a "1" al producirse un desbordamiento del timer.
- T0IE: habilita la interrupción por desbordamiento del timer.
- GIE: habilita las interrupciones globalmente.

Registro OPTION: contiene varios bits de control asociados a nuestro timer:

- PS0, PS1 y PS2: bits de configuración del prescaler (divisor de pulsos).
 
(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=40649.0;attach=20537)

- PSA: bit de asignación de prescaler, si está en "0" se asigna al TMR0.
- T0SE: bit de selección del tipo de flanco para el TMR0. No lo vamos a usar por ahora.
- T0CS: selecciona la entrada de reloj del TMR0, colocar a "0" para incrementar por ciclo de reloj interno.

El próximo paso será saber el tiempo que necesitamos para producir la interrupción por desborde del timer. Para hacer este calculo utilizamos la siguiente fórmula que relaciona las distintas variables:

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=40649.0;attach=20539)



Veamoslo en un ejemplo. Cada 65 ms desbordará el timer alterando el estado del pin RB0 donde colocamos un LED para hacerlo destellar.

Código: C
  1. /*
  2.  * File:   main.c
  3.  * Author: lucas
  4.  * Created on 1 de abril de 2013, 22:20
  5.  * Microcontrolador: PIC16F648A
  6.  *
  7.  * Uso de interrupción por Timer 0
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <xc.h> // Librería XC8
  13.  
  14. #define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro
  15. #define LED PORTBbits.RB0
  16.  
  17. // PIC16F648A Configuration Bit Settings
  18. #pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
  19. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  20. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  21. #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
  22. #pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
  23. #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
  24. #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
  25. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  26.  
  27. unsigned char cuenta = 0;   // Declaro una variable "cuenta"
  28.  
  29. // FUNCION DE INTERRUPCION
  30. void interrupt ISR(void) {
  31.     cuenta++;                   // Incremento variable
  32.     INTCONbits.TMR0IF = 0;      // Limpiamos bandera de desborde
  33. }
  34.  
  35. // FUNCION PRINCIPAL
  36. void main () {
  37.     TRISB = 0;                   // Puerto B como salidas
  38.     PORTB = 0;
  39.  
  40.     // Configuración del timer & interrupcion
  41.     TMR0 = 0;
  42.     INTCONbits.TMR0IE = 1;
  43.     INTCONbits.GIE = 1;
  44.     OPTION_REGbits.PS0 = 1;
  45.     OPTION_REGbits.PS1 = 1;
  46.     OPTION_REGbits.PS2 = 1;
  47.     OPTION_REGbits.PSA = 0;
  48.     OPTION_REGbits.T0CS = 0;
  49.  
  50.     // Bucle infinito
  51.     while (1){
  52.         if (cuenta == 10){
  53.             LED ^= 1;
  54.             cuenta = 0;
  55.         }
  56.     }
  57. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: electroipod en 25 de Abril de 2013, 22:04:06
Me ha gustado tu tutorial amigo, ojala continues con el tuto, somos muchos los que queremos aprender a programar con el mplabx y el xc8, gracias y sigue asi.
Título: Re: Mini curso "Programación en XC8"
Publicado por: jeremylf en 26 de Abril de 2013, 00:53:23
Muy bueno, gracias!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 27 de Abril de 2013, 13:23:52
Muy Bueno el curso ...una pregunta ?? al siguiente codigo lo quiero modificar de la siguiente manera

para un pic 12f683

y con variables led1



    /*
    * File:   main.c
    * Author: lucas
    * Created on 1 de abril de 2013, 22:20
    * Microcontrolador: PIC12f683
    *
    * ¡Hola Mundo! en C (o como hacer destellar un LED)
    */
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <xc.h> // Librería XC8
     
    #define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro

    #define led1 GPIO,GP1 ;
     
    // PIC12f683 Configuration Bit Settings
    #pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
    #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
    #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
    #pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
    #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
    #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
     
    // FUNCION PRINCIPAL
    void main ()
    {
        TRISIO = 0b00000000; // Configuro puerto B como salidas
        while (1) // Bucle infinito
        {
            led1 = 0; // Apago pin RB0
            __delay_ms(500);
           
             led1 = 1; // Enciendo pin RB0
            __delay_ms(500);
        }
    }


esta rutina me da error en led1 .....No entiendo porque ....gracias y disculpen soy nuevo

Título: Re: Mini curso "Programación en XC8"
Publicado por: lmtreser en 27 de Abril de 2013, 13:57:30
Hola! Buenisimo que se vayan sumando y subiendo ejemplos para avanzar... En el código de Rseliman hay un ; en el define de LED1 que causa el problema. Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 27 de Abril de 2013, 18:38:42
Hola! Buenisimo que se vayan sumando y subiendo ejemplos para avanzar... En el código de Rseliman hay un ; en el define de LED1 que causa el problema. Saludos!


MUCHISIMAS GRACIAS ....es muy cierto que cuando uno esta muy cansado no ve cosas que son obias ....lo mire y lo recontra mire ....y no me daba cuenta ....hasta llegue a pensar que andaba mal el c8 jajajajajaj

Seguire compartiendo mis experiencias asi este curso crece !!!!

Gracias IMtreser ....vamos por mas !!!!

Saludos a todos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 27 de Abril de 2013, 20:37:35
Amigos sigo escribiendo codigo sencillo por ahora , pero creo servira para el cursillo ....

la subrutina no sirve para nada solamente escribe la eeprom , la lee , y blinkea un led


Saludos a todos y Gracias .....ojala esto se agrande

Código: [Seleccionar]
/*
 * File:   main.c
 * Author: Ramiro Seliman
 *
 * Created on 26 de abril de 2013, 18:07
 */
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <htc.h>


//*************************** funciones grab y lee eeprom ***************************************

void write_eeprom(char address, char data)
{
EEADR = address;
EEDATA = data;
EECON1bits.WREN = 1; // habilito escritura
INTCONbits.GIE = 0; // desabilito las interrupciones
EECON2 = 0x55; // destrabo escritura
EECON2 = 0xAA;  //destrabo escritura
EECON1bits.WR = 1; // habilito escritura
INTCONbits.GIE = 1; // habilito la interrupcion
EECON1bits.WREN = 0; // desabilito escritura
  while (EECON1bits.WR); // espero hasta que WR se haga 0 por hard
}

char read_eeprom(char address)
{
    EEADR = address;
    EECON1bits.RD = 1 ;
    return EEDAT;
 
}
//****************************************************************************************************

#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown Out Detect (BOR disabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)



char tiempo, address, data ;  // defino variable tiempo para leer eeprom

#define _XTAL_FREQ 4000000      // Indicamos a que frecuencia de reloj esta funcionando el micro

#define ledverde GPIO,GP1
#define ledrojo GPIO,GP4
#define buzzer GPIO,GP0
#define microswitch GPIO,GP2
#define teclado GPIO,GP3
/***********************************************************************************************************/
/*                                   PROGRAMA PRINCIPAL                                                     */
/***********************************************************************************************************/

int main (void)
{


    CMCON0 = 7; // Disable comparators
          TRISIO = 0b00001100;  //  GP3 y GP4 entradas las demas salidas
          ANSEL = 0;  // No ADC

            write_eeprom(0,6); //leo la primer posicion memoria eeprom
            _delay(500);

          tiempo = read_eeprom(0); //la cargo en tiempo

          write_eeprom(2,tiempo); //cargo la 3r posicion de la eeprom con el valor de tiempo

         _delay(500); // espero
         
         write_eeprom(5,tiempo); //cargo la 6ta posicion de la eeprom con la variable tiempo
         _delay(500);

    while(1)     // bucle infiinito
    {
     ledverde = 0;                       // apago led verde en GP1
        _delay(1000);                  // espero 1 seg
     ledverde = 1;                    // prendo led verde en GP1
        _delay(1000);                  // espero 1 seg
       
    }

}
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 28 de Abril de 2013, 10:50:29
Buen dia Muchachos , el codigo Funciona y sigo aprendiendo , la pregunta es , donde coloco las subrutinas de eeprom si quisiera sacarlas del codigo main para no complicarlo , a lo mismo que las demas subrutinas que construya , por ejemplo subrutinas de audio ...pueden ir como librerias ??o tengo que ponerlas en header files o sources files

Gracias Amigos
Un Gran saludo a todos
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 28 de Abril de 2013, 14:52:12
  Rseliman, si no me equivoco incluir HTC.H no es necesario. Ése header se usaba cuando el compilador era HiTech, pero al pasar a ser XC8, creo que es suficiente con incluir XC.H

  Por otro lado, sí puedes colocar tus funciones en otros archivos .C y también puedes crear los .H de los mismos para hacer tus propias librerías.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 29 de Abril de 2013, 17:07:17
Pregunta ...estoy tratando de hacer una funcion pausa en segundos ...

void pausa (unsigned int num)
{
unsigned int tem;

   tem = num*((4/_XTAL_FREQ)*1000000);
   _delay(tem);
}

Porque esto no funciona en c18 ??

Como lo resuelvo ??

Muchas gracias a todos ??
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 29 de Abril de 2013, 17:43:06
  ¿Qué es lo que pasa? ¿Por qué dices que no funciona? ¿Genera algún error de compilación o no establece bien el tiempo?
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 29 de Abril de 2013, 19:28:57
  ¿Qué es lo que pasa? ¿Por qué dices que no funciona? ¿Genera algún error de compilación o no establece bien el tiempo?

Porque el _delay no me toma variables ...ese es el error que me da , existe otra forma de generar una funcion para segundos ??

Gracias
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 29 de Abril de 2013, 19:54:13
  Ah, ok.

  Si quieres hacer retardo de segundos puedes implementar algo así...

Código: C
  1. void pausa(unsigned int tiempo)
  2. {
  3.   unsigned int __tiempo;
  4.   for (__tiempo = tiempo; __tiempo > 0; __tiempo--)
  5.   {
  6.     __delay_ms(1000);
  7.   }
  8. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 30 de Abril de 2013, 15:53:54
Hola , sigo con mis preguntas , la verdad , me esta costando bastante adaptarme a este lenguaje , vengo de Mikroc que era muchisimo mas facil ...

Bueno las preguntas son dos

si tengo definido esto

void sonido(int x)  

   {
    while (x > 0)
    {
    buzzer = 1;
    _delay(500);
    buzzer = 0;
    _delay(500);
    x--;
    }

pero esta en el main , y si sigo metiendo voids en el main se me va complicando , como hago para ponerlo como una libreria o sonido.h o sonido.c , no se explicarme para mi seria una macro que la llamo desde el main ...no se si me explico ...muchas gracias


La otra pregunta era ...porque no puedo utilizar _delay_ms ?? veo en muchos ejemplos que la usan y yo no puedo uso #include delay y delays.h y de todas maneras no me deja usar esa funcion ....tampoco pùedo usar delay1ktcyx(50) ....porque me cuesta tanto entender este lenguaje ??

Gracias
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 30 de Abril de 2013, 20:40:49
Hola , sigo con mis preguntas , la verdad , me esta costando bastante adaptarme a este lenguaje , vengo de Mikroc que era muchisimo mas facil ...

Bueno las preguntas son dos

si tengo definido esto

void sonido(int x)  

   {
    while (x > 0)
    {
    buzzer = 1;
    _delay(500);
    buzzer = 0;
    _delay(500);
    x--;
    }

pero esta en el main , y si sigo metiendo voids en el main se me va complicando , como hago para ponerlo como una libreria o sonido.h o sonido.c , no se explicarme para mi seria una macro que la llamo desde el main ...no se si me explico ...muchas gracias


La otra pregunta era ...porque no puedo utilizar _delay_ms ?? veo en muchos ejemplos que la usan y yo no puedo uso #include delay y delays.h y de todas maneras no me deja usar esa funcion ....tampoco pùedo usar delay1ktcyx(50) ....porque me cuesta tanto entender este lenguaje ??

Gracias


  Para hacer una librería puedes crear un archivo.c y un archivo.h cuyo nombre será el de la librería. Dentro de la librería puedes dejar tu función. En el main incluyes tu librería con #include y luego en tu programas puedes llamar a la función. Asegúrate que tengas una copia de tu librería en la carpeta de trabajo de tu proyecto.


pausa.c (librería)

Código: C
  1. void espera(unsigned int tiempo) //espera de x segundos
  2. {
  3.   unsigned int __tiempo;
  4.   for (__tiempo = tiempo; __tiempo > 0; __tiempo--)
  5.   {
  6.     __delay_ms(1000)
  7.   }
  8. }

main.c (Programa principal)

Código: C
  1. #include <xc.h>
  2. #define _XTAL_FREQ 20000000 // defino la frecuencia de oscilacion
  3. // es necesario que este definido _XTAL_FREQ para poder utilizar __delay, __delay_us y __delay_ms
  4. // dichas "funciones" son con 2 guiones bajos delante de la palabra delay
  5.  
  6. #include "pausa.c"
  7.  
  8. void main(void)
  9. {
  10.   while (1)
  11.   {
  12.      // hacer algo...
  13.      espera (12);
  14.   }
  15. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 30 de Abril de 2013, 22:39:11
Muchas gracias por tu tiempo Angelgris ...espero poder dentro de poco colaborar yo tambien ....

Título: Re: Mini curso "Programación en XC8"
Publicado por: rotting79 en 12 de Mayo de 2013, 19:56:00
here is a small project over a PIC12F683  and XC8

Título: Re: Mini curso "Programación en XC8"
Publicado por: yamilongiano en 14 de Mayo de 2013, 17:04:27
hola tengo un problema al compilar (build) con la libreria
hola ya he solucionado mi problema

ahora tengo un problema con el PWM

como puedo programar el PWM para que el T2 del PWM no llegue a 0....osea para que el le nunca quede100% encendido

disculpen que no conosco mucho el lenguaje y estoy aprendiendo el circuito esta en un bucle infinito, pero quiero modificarlo quizas un if que lo reinicie en algun momento.
Título: Re: Mini curso "Programación en XC8"
Publicado por: lmtreser en 19 de Mayo de 2013, 22:23:52
1.8. Ejemplo de uso PIC18F4550, delays y USART

Un completo ejemplo de uso sobre el puerto serie que incorpora este microcontrolador. El proyecto completo en un ZIP (http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=40649.0;attach=20655), probado y compilado en Windows 7 y Ubuntu 10.04.

Código: [Seleccionar]
/*
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 RETARDOS

Para 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 8mhz

Las 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 (http://www.todopic.com.ar/foros/index.php?action=profile;u=8836) por el excelente aporte a este capítulo!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 21 de Mayo de 2013, 14:29:37
ejemplo de un Pic16f819 controlando un modulo lcd standar 2x16 en 4 bits



Aca les paso un proyecto ..de lcd 2x16 standar , con pic16f819 , Mplabx , XC8 ...en el port B anda perfecto , ahora estoy queriendo desocupar el mismo y llevar todo a PortA , pero no logro hacerlo andar ...si alguien tiene una sugerencia sera bienvenida

Gracias


Main.c
Código: [Seleccionar]
#include <xc.h>
#define _XTAL_FREQ 8000000
#include <stdio.h>
#include <stdlib.h>
#include "lcd_pic16.c"
#include "delay.h"

// PIC16F819 Configuration Bit Settings





//variables globales
unsigned char buffer [14];
// unsigned int contador=0;
//funciones prototipo
void init(void);


void main(void)
{

   OSCCONbits.IRCF2 = 1; //
   OSCCONbits.IRCF1 = 1; // defino oscilador interno en 4 mhz
   OSCCONbits.IRCF0 = 0; //


init();


            
SetDDRamAddr(0x00);
putrsXLCD("Ramiro Seliman");
                putsXLCD(buffer);
                SetDDRamAddr(0x40);
putrsXLCD("Victoria E.R");
        }

void init(void)
{
    ADCON0bits.ADON = 0;

    TRISB=0;    //todo el PORTB como salidas digitales
    PORTB=0;
    OpenXLCD(FOUR_BIT & LINES_5X7 );


}

lcd_pic16.c

Código: [Seleccionar]
/*
 *
 *   Notes:
 *      - These libraries routines are written to support the
 *        Hitachi HD44780 LCD controller.
 *      - The user must define the following items:
 *          - The LCD interface type (4- or 8-bits)
 *          - If 4-bit mode
 *              - whether using the upper or lower nibble
 *          - The data port
 *              - The tris register for data port
 *              - The control signal ports and pins
 *              - The control signal port tris and pins
 *          - The user must provide three delay routines:
 *              - DelayFor18TCY() provides a 18 Tcy delay
 *              - DelayPORXLCD() provides at least 15ms delay
 *              - DelayXLCD() provides at least 5ms delay
 */

/* Interface type 8-bit or 4-bit
 * For 8-bit operation uncomment the #define BIT8
 */
// #define BIT8

/* When in 4-bit interface define if the data is in the upper
 * or lower nibble.  For lower nibble, comment the #define UPPER
 */


#define UPPER

/* When in 6-10-bit interface comment the #define BUSY_LCD and conected PIN
 * R/W to GND in LCD
 */
 //#define BUSY_LCD

/* DATA_PORT defines the port to which the LCD data lines are connected */
 #define DATA_PORT       PORTB
 #define TRIS_DATA_PORT TRISB

/* CTRL_PORT defines the port where the control lines are connected.
 * These are just samples, change to match your application.
 */
 #define RW_PIN   PORTBbits.RB0   /* PORT for RW */
 #define TRIS_RW  TRISBbits.TRISB0     /* TRIS for RW */

 #define RS_PIN   PORTBbits.RB1   /* PORT for RS */
 #define TRIS_RS  TRISBbits.TRISB1     /* TRIS for RS */

 #define E_PIN    PORTBbits.RB2   /* PORT for D  */
 #define TRIS_E   TRISBbits.TRISB2     /* TRIS for E  */

/* Display ON/OFF Control defines */
#define DON         0b00001111  /* Display on      */
#define DOFF        0b00001011  /* Display off     */
#define CURSOR_ON   0b00001111  /* Cursor on       */
#define CURSOR_OFF  0b00001101  /* Cursor off      */
#define BLINK_ON    0b00001111  /* Cursor Blink    */
#define BLINK_OFF   0b00001110  /* Cursor No Blink */

/* Cursor or Display Shift defines */
#define SHIFT_CUR_LEFT    0b00000100  /* Cursor shifts to the left   */
#define SHIFT_CUR_RIGHT   0b00000101  /* Cursor shifts to the right  */
#define SHIFT_DISP_LEFT   0b00000110  /* Display shifts to the left  */
#define SHIFT_DISP_RIGHT  0b00000111  /* Display shifts to the right */

/* Function Set defines */
#define FOUR_BIT   0b00101100  /* 4-bit Interface               */
#define EIGHT_BIT  0b00111100  /* 8-bit Interface               */
#define LINE_5X7   0b00110000  /* 5x7 characters, single line   */
#define LINE_5X10  0b00110100  /* 5x10 characters               */
#define LINES_5X7  0b00111000  /* 5x7 characters, multiple line */

#ifdef _OMNI_CODE_
#define PARAM_SCLASS
#else
#define PARAM_SCLASS auto
#endif

/* CLS_Line2
 * Clear Screen Line 2
 */
void CLS_Line2(void);

/* CLS_Line1
 * Clear Screen Line 1
 */
void CLS_Line1(void);
/* OpenXLCD
 * Configures I/O pins for external LCD
 */
void OpenXLCD(PARAM_SCLASS unsigned char);

/* SetCGRamAddr
 * Sets the character generator address
 */
void SetCGRamAddr(PARAM_SCLASS unsigned char);

/* SetDDRamAddr
 * Sets the display data address
 */
void SetDDRamAddr(PARAM_SCLASS unsigned char);

/* BusyXLCD
 * Returns the busy status of the LCD
 */
unsigned char BusyXLCD(void);

/* ReadAddrXLCD
 * Reads the current address
 */
unsigned char ReadAddrXLCD(void);

/* ReadDataXLCD
 * Reads a byte of data
 */
char ReadDataXLCD(void);

/* WriteCmdXLCD
 * Writes a command to the LCD
 */
void WriteCmdXLCD(PARAM_SCLASS unsigned char);

/* WriteDataXLCD
 * Writes a data byte to the LCD
 */
void WriteDataXLCD(PARAM_SCLASS char);

/* putcXLCD
 * A putc is a write
 */
#define putcXLCD WriteDataXLCD

/* putsXLCD
 * Writes a string of characters to the LCD
 */
void putsXLCD(PARAM_SCLASS char *);

/* putrsXLCD
 * Writes a string of characters in  to the LCD
 */
void putrsXLCD(const char *);

// Rutinas de tiempo auxiliares para la libreria XLCD
void DelayFor18TCY(void)
{
__delay_us(18);
}

void DelayPORXLCD(void)
{
__delay_ms(20); //Delay de 15 ms
}

void DelayXLCD(void)
{
__delay_ms(20); //Delay de 20 ms
}

void CLS_Line2(void)
{
    SetDDRamAddr(0x40);
    putrsXLCD("                ");
}

void CLS_Line1(void)
{
    SetDDRamAddr(0x00);
    putrsXLCD("                ");
}
/********************************************************************
*       Function Name:  OpenXLCD                                    *
*       Return Value:   void                                        *
*       Parameters:     lcdtype: sets the type of LCD (lines)       *
*       Description:    This routine configures the LCD. Based on   *
*                       the Hitachi HD44780 LCD controller. The     *
*                       routine will configure the I/O pins of the  *
*                       microcontroller, setup the LCD for 4- or    *
*                       8-bit mode and clear the display. The user  *
*                       must provide three delay routines:          *
*                       DelayFor18TCY() provides a 18 Tcy delay     *
*                       DelayPORXLCD() provides at least 15ms delay *
*                       DelayXLCD() provides at least 5ms delay     *
********************************************************************/
void OpenXLCD(unsigned char lcdtype)
{
        // The data bits must be either a 8-bit port or the upper or
        // lower 4-bits of a port. These pins are made into inputs
#ifdef BIT8                             // 8-bit mode, use whole port
        DATA_PORT = 0;
        TRIS_DATA_PORT = 0x00;
#else                                   // 4-bit mode
#ifdef UPPER                            // Upper 4-bits of the port
        DATA_PORT &= 0x0f;
        TRIS_DATA_PORT &= 0x0F;
#else                                   // Lower 4-bits of the port
        DATA_PORT &= 0xf0;
        TRIS_DATA_PORT &= 0xF0;
#endif
#endif
        TRIS_RW = 0;                    // All control signals made outputs
        TRIS_RS = 0;
        TRIS_E = 0;
        RW_PIN = 0;                     // R/W pin made low
        RS_PIN = 0;                     // Register select pin made low
        E_PIN = 0;                      // Clock pin made low

        // Delay for 15ms to allow for LCD Power on reset
        DelayPORXLCD();
 //-------------------reset procedure through software----------------------      
WriteCmdXLCD(0x30);
__delay_ms(5);

WriteCmdXLCD(0x30);
__delay_ms(1);


WriteCmdXLCD(0x32);
while( BusyXLCD() );
//------------------------------------------------------------------------------------------


        // Set data interface width, # lines, font
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(lcdtype);          // Function set cmd

        // Turn the display on then off
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(DOFF&CURSOR_OFF&BLINK_OFF);        // Display OFF/Blink OFF
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(DON&CURSOR_ON&BLINK_ON);           // Display ON/Blink ON

        // Clear display
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(0x01);             // Clear display

        // Set entry mode inc, no shift
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(SHIFT_CUR_RIGHT);   // Entry Mode
 
while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(0x06);   // Incremente
 
        while(BusyXLCD());              // Wait if LCD busy
        SetDDRamAddr(0x80);             // Set Display data ram address to 0
        
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(CURSOR_OFF);       // Cursor OFF
        return;
}


/********************************************************************
*       Function Name:  WriteDataXLCD                               *
*       Return Value:   void                                        *
*       Parameters:     data: data byte to be written to LCD        *
*       Description:    This routine writes a data byte to the      *
*                       Hitachi HD44780 LCD controller. The user    *
*                       must check to see if the LCD controller is  *
*                       busy before calling this routine. The data  *
*                       is written to the character generator RAM or*
*                       the display data RAM depending on what the  *
*                       previous SetxxRamAddr routine was called.   *
********************************************************************/
void WriteDataXLCD(char data)
{
#ifdef BIT8                             // 8-bit interface
        TRIS_DATA_PORT = 0;             // Make port output
        DATA_PORT = data;               // Write data to port
        RS_PIN = 1;                     // Set control bits
        RW_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock data into LCD
        DelayFor18TCY();
        E_PIN = 0;
        RS_PIN = 0;                     // Reset control bits
        TRIS_DATA_PORT = 0xff;          // Make port input
#else                                   // 4-bit interface
#ifdef UPPER                            // Upper nibble interface
        TRIS_DATA_PORT &= 0x0f;
        DATA_PORT &= 0x0f;
        DATA_PORT |= data&0xf0;
#else                                   // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;
        DATA_PORT &= 0xf0;
        DATA_PORT |= ((data>>4)&0x0f);
#endif
        RS_PIN = 1;                     // Set control bits
        RW_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock nibble into LCD
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Upper nibble interface
        DATA_PORT &= 0x0f;
        DATA_PORT |= ((data<<4)&0xf0);
#else                                   // Lower nibble interface
        DATA_PORT &= 0xf0;
        DATA_PORT |= (data&0x0f);
#endif
        DelayFor18TCY();
        E_PIN = 1;                      // Clock nibble into LCD
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Upper nibble interface
        TRIS_DATA_PORT |= 0xf0;
#else                                   // Lower nibble interface
        TRIS_DATA_PORT |= 0x0f;
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  WriteCmdXLCD                                *
*       Return Value:   void                                        *
*       Parameters:     cmd: command to send to LCD                 *
*       Description:    This routine writes a command to the Hitachi*
*                       HD44780 LCD controller. The user must check *
*                       to see if the LCD controller is busy before *
*                       calling this routine.                       *
********************************************************************/
void WriteCmdXLCD(unsigned char cmd)
{
#ifdef BIT8                             // 8-bit interface
        TRIS_DATA_PORT = 0;             // Data port output
        DATA_PORT = cmd;                // Write command to data port
        RW_PIN = 0;                     // Set the control signals
        RS_PIN = 0;                     // for sending a command
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the command in
        DelayFor18TCY();
        E_PIN = 0;
        DelayFor18TCY();
        TRIS_DATA_PORT = 0xff;          // Data port input
#else                                   // 4-bit interface
#ifdef UPPER                            // Upper nibble interface
        TRIS_DATA_PORT &= 0x0f;
        DATA_PORT &= 0x0f;
        DATA_PORT |= cmd&0xf0;
#else                                   // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;
        DATA_PORT &= 0xf0;
        DATA_PORT |= (cmd>>4)&0x0f;
#endif
        RW_PIN = 0;                     // Set control signals for command
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock command in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Upper nibble interface
        DATA_PORT &= 0x0f;
        DATA_PORT |= (cmd<<4)&0xf0;
#else                                   // Lower nibble interface
        DATA_PORT &= 0xf0;
        DATA_PORT |= cmd&0x0f;
#endif
        DelayFor18TCY();
        E_PIN = 1;                      // Clock command in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Make data nibble input
        TRIS_DATA_PORT |= 0xf0;
#else
        TRIS_DATA_PORT |= 0x0f;
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  SetDDRamAddr                                *
*       Return Value:   void                                        *
*       Parameters:     CGaddr: display data address                *
*       Description:    This routine sets the display data address  *
*                       of the Hitachi HD44780 LCD controller. The  *
*                       user must check to see if the LCD controller*
*                       is busy before calling this routine.        *
********************************************************************/
void SetDDRamAddr(unsigned char DDaddr)
{
#ifdef BIT8                                     // 8-bit interface
        TRIS_DATA_PORT = 0;                     // Make port output
        DATA_PORT = DDaddr | 0b10000000;        // Write cmd and address to port
        RW_PIN = 0;                             // Set the control bits
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock the cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
        DelayFor18TCY();
        TRIS_DATA_PORT = 0xff;                  // Make port input
#else                                           // 4-bit interface
#ifdef UPPER                                    // Upper nibble  interface
        TRIS_DATA_PORT &= 0x0f;                 // Make port output
        DATA_PORT &= 0x0f;                      // and write upper nibble
        DATA_PORT |= ((DDaddr | 0b10000000) & 0xf0);
#else                                           // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;                 // Make port output
        DATA_PORT &= 0xf0;                      // and write upper nibble
        DATA_PORT |= (((DDaddr | 0b10000000)>>4) & 0x0f);
#endif
        RW_PIN = 0;                             // Set control bits
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock the cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        DATA_PORT &= 0x0f;                      // Write lower nibble
        DATA_PORT |= ((DDaddr<<4)&0xf0);
#else                                           // Lower nibble interface
        DATA_PORT &= 0xf0;                      // Write lower nibble
        DATA_PORT |= (DDaddr&0x0f);
#endif
        DelayFor18TCY();
        E_PIN = 1;                              // Clock the cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        TRIS_DATA_PORT |= 0xf0;                 // Make port input
#else                                           // Lower nibble interface
        TRIS_DATA_PORT |= 0x0f;                 // Make port input
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  SetCGRamAddr                                *
*       Return Value:   void                                        *
*       Parameters:     CGaddr: character generator ram address     *
*       Description:    This routine sets the character generator   *
*                       address of the Hitachi HD44780 LCD          *
*                       controller. The user must check to see if   *
*                       the LCD controller is busy before calling   *
*                       this routine.                               *
********************************************************************/
void SetCGRamAddr(unsigned char CGaddr)
{
#ifdef BIT8                                     // 8-bit interface
        TRIS_DATA_PORT = 0;                     // Make data port ouput
        DATA_PORT = CGaddr | 0b01000000;        // Write cmd and address to port
        RW_PIN = 0;                             // Set control signals
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
        DelayFor18TCY();
        TRIS_DATA_PORT = 0xff;                  // Make data port inputs
#else                                           // 4-bit interface
#ifdef UPPER                                    // Upper nibble interface
        TRIS_DATA_PORT &= 0x0f;                 // Make nibble input
        DATA_PORT &= 0x0f;                      // and write upper nibble
        DATA_PORT |= ((CGaddr | 0b01000000) & 0xf0);
#else                                           // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;                 // Make nibble input
        DATA_PORT &= 0xf0;                      // and write upper nibble
        DATA_PORT |= (((CGaddr |0b01000000)>>4) & 0x0f);
#endif
        RW_PIN = 0;                             // Set control signals
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        DATA_PORT &= 0x0f;                      // Write lower nibble
        DATA_PORT |= ((CGaddr<<4)&0xf0);
#else                                           // Lower nibble interface
        DATA_PORT &= 0xf0;                      // Write lower nibble
        DATA_PORT |= (CGaddr&0x0f);
#endif
        DelayFor18TCY();
        E_PIN = 1;                              // Clock cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        TRIS_DATA_PORT |= 0xf0;                 // Make inputs
#else                                           // Lower nibble interface
        TRIS_DATA_PORT |= 0x0f;                 // Make inputs
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  ReadDataXLCD                                *
*       Return Value:   char: data byte from LCD controller         *
*       Parameters:     void                                        *
*       Description:    This routine reads a data byte from the     *
*                       Hitachi HD44780 LCD controller. The user    *
*                       must check to see if the LCD controller is  *
*                       busy before calling this routine. The data  *
*                       is read from the character generator RAM or *
*                       the display data RAM depending on what the  *
*                       previous SetxxRamAddr routine was called.   *
********************************************************************/
char ReadDataXLCD(void)
{
        char data;

#ifdef BIT8                             // 8-bit interface
        RS_PIN = 1;                     // Set the control bits
        RW_PIN = 1;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the data out of the LCD
        DelayFor18TCY();
        data = DATA_PORT;               // Read the data
        E_PIN = 0;
        RS_PIN = 0;                     // Reset the control bits
        RW_PIN = 0;
#else                                   // 4-bit interface
        RW_PIN = 1;
        RS_PIN = 1;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the data out of the LCD
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data = DATA_PORT&0xf0;          // Read the upper nibble of data
#else                                   // Lower nibble interface
        data = (DATA_PORT<<4)&0xf0;     // read the upper nibble of data
#endif
        E_PIN = 0;                      // Reset the clock line
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the next nibble out of the LCD
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data |= (DATA_PORT>>4)&0x0f;    // Read the lower nibble of data
#else                                   // Lower nibble interface
        data |= DATA_PORT&0x0f;         // Read the lower nibble of data
#endif
        E_PIN = 0;                                      
        RS_PIN = 0;                     // Reset the control bits
        RW_PIN = 0;
#endif
        return(data);                   // Return the data byte
}

/*********************************************************************
*       Function Name:  ReadAddrXLCD                                 *
*       Return Value:   char: address from LCD controller            *
*       Parameters:     void                                         *
*       Description:    This routine reads an address byte from the  *
*                       Hitachi HD44780 LCD controller. The user     *
*                       must check to see if the LCD controller is   *
*                       busy before calling this routine. The address*
*                       is read from the character generator RAM or  *
*                       the display data RAM depending on what the   *
*                       previous SetxxRamAddr routine was called.    *
*********************************************************************/
unsigned char ReadAddrXLCD(void)
{
        char data;                      // Holds the data retrieved from the LCD

#ifdef BIT8                             // 8-bit interface
        RW_PIN = 1;                     // Set control bits for the read
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock data out of the LCD controller
        DelayFor18TCY();
        data = DATA_PORT;               // Save the data in the register
        E_PIN = 0;
        RW_PIN = 0;                     // Reset the control bits
#else                                   // 4-bit interface
        RW_PIN = 1;                     // Set control bits for the read
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock data out of the LCD controller
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data = DATA_PORT&0xf0;          // Read the nibble into the upper nibble of data
#else                                   // Lower nibble interface
        data = (DATA_PORT<<4)&0xf0;     // Read the nibble into the upper nibble of data
#endif
        E_PIN = 0;                      // Reset the clock
        DelayFor18TCY();
        E_PIN = 1;                      // Clock out the lower nibble
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data |= (DATA_PORT>>4)&0x0f;    // Read the nibble into the lower nibble of data
#else                                   // Lower nibble interface
        data |= DATA_PORT&0x0f;         // Read the nibble into the lower nibble of data
#endif
        E_PIN = 0;
        RW_PIN = 0;                     // Reset the control lines
#endif
        return (data&0x7f);             // Return the address, Mask off the busy bit
}

/********************************************************************
*       Function Name:  putsXLCD
*       Return Value:   void
*       Parameters:     buffer: pointer to string
*       Description:    This routine writes a string of bytes to the
*                       Hitachi HD44780 LCD controller. The user
*                       must check to see if the LCD controller is
*                       busy before calling this routine. The data
*                       is written to the character generator RAM or
*                       the display data RAM depending on what the
*                       previous SetxxRamAddr routine was called.
********************************************************************/
void putsXLCD(char *buffer)
{
        while(*buffer)                  // Write data to LCD up to null
        {
                while(BusyXLCD());      // Wait while LCD is busy
                WriteDataXLCD(*buffer); // Write character to LCD
                buffer++;               // Increment buffer
        }
        return;
}

/********************************************************************
*       Function Name:  putrsXLCD
*       Return Value:   void
*       Parameters:     buffer: pointer to string
*       Description:    This routine writes a string of bytes to the
*                       Hitachi HD44780 LCD controller. The user
*                       must check to see if the LCD controller is
*                       busy before calling this routine. The data
*                       is written to the character generator RAM or
*                       the display data RAM depending on what the
*                       previous SetxxRamAddr routine was called.
********************************************************************/
void putrsXLCD(const  char *buffer)
{
        while(*buffer)                  // Write data to LCD up to null
        {
                while(BusyXLCD());      // Wait while LCD is busy
                WriteDataXLCD(*buffer); // Write character to LCD
                buffer++;               // Increment buffer
        }
        return;
}

/********************************************************************
*       Function Name:  BusyXLCD                                    *
*       Return Value:   char: busy status of LCD controller         *
*       Parameters:     void                                        *
*       Description:    This routine reads the busy status of the   *
*                       Hitachi HD44780 LCD controller.             *
********************************************************************/
unsigned char BusyXLCD(void)
{
#ifdef BUSY_LCD
        RW_PIN = 1;                     // Set the control bits for read
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock in the command
        DelayFor18TCY();
#ifdef BIT8                             // 8-bit interface
        if(DATA_PORT&0x80)                      // Read bit 7 (busy bit)
        {                               // If high
                E_PIN = 0;              // Reset clock line
                RW_PIN = 0;             // Reset control line
                return 1;               // Return TRUE
        }
        else                            // Bit 7 low
        {
                E_PIN = 0;              // Reset clock line
                RW_PIN = 0;             // Reset control line
                return 0;               // Return FALSE
        }
#else                                   // 4-bit interface
#ifdef UPPER                            // Upper nibble interface
        if(DATA_PORT&0x80)
#else                                   // Lower nibble interface
        if(DATA_PORT&0x08)
#endif
        {
                E_PIN = 0;              // Reset clock line
                DelayFor18TCY();
                E_PIN = 1;              // Clock out other nibble
                DelayFor18TCY();
                E_PIN = 0;
                RW_PIN = 0;             // Reset control line
                return 1;               // Return TRUE
        }
        else                            // Busy bit is low
        {
                E_PIN = 0;              // Reset clock line
                DelayFor18TCY();
                E_PIN = 1;              // Clock out other nibble
                DelayFor18TCY();
                E_PIN = 0;
                RW_PIN = 0;             // Reset control line
                return 0;               // Return FALSE
        }
#endif
#else
        __delay_ms(5);
        return 0;
#endif

}



PIC16F819 Configuration Bit Settings

Código: [Seleccionar]
// PIC16F819 Configuration Bit Settings

#include <xc.h>

// CONFIG
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTRC oscillator; CLKO function on RA6/OSC2/CLKO pin and port I/O function on RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF      // Low-Voltage Programming Enable bit (RB3/PGM pin has PGM function, Low-Voltage Programming enabled)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2      // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// CONFIG2
//#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable





Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 21 de Mayo de 2013, 15:16:11
Bueno logre hacerlo andar en el PORT A les paso las modificaciones en main y libreria ....para que funcione en mi proteus le comento las lineas del main que lo ponen en 4 mHZ ...no se porque ...pero eso solo pasa en el proteus

Saludos ....adjunto tambien el archivo proteus modificado al PORTA...de esta manera me quedan disponibles los pines de I2C que nesecitaba


Gracias





Main.c
Código: [Seleccionar]
#include <xc.h>
#define _XTAL_FREQ 4000000
#include <stdio.h>
#include <stdlib.h>
#include "lcd_pic16.c"
#include "delay.h"

// PIC16F819 Configuration Bit Settings





//variables globales
unsigned char buffer [14];
// unsigned int contador=0;
//funciones prototipo
void init(void);






void main(void)
{
   //OSCCONbits.IRCF2 = 1; //
   //OSCCONbits.IRCF1 = 1; // defino oscilador interno en 4 mhz
   //OSCCONbits.IRCF0 = 0; //
 
    
    init(); // inicio lcd

while(1)

{
                SetDDRamAddr(0x00);
putrsXLCD("Ramiro Seliman");
                putsXLCD(buffer);
                SetDDRamAddr(0x40);
putrsXLCD("Victoria E.R");
              

}
}
void init(void)
{
    ADCON0bits.ADON = 0;
    ADCON1bits.PCFG3 = 0;
    ADCON1bits.PCFG2 = 1;
    ADCON1bits.PCFG1 = 1;
    ADCON1bits.PCFG0 = 1;
    ADCON1bits.ADCS2 = 0;

    
    TRISB=0;    //todo el PORTb como salidas digitales
    PORTB=0;
   // TRISA=0;
   // PORTA=0;
    OpenXLCD(FOUR_BIT & LINES_5X7 );
}

lcd_pic16.c

Código: [Seleccionar]
//*
 *
 *   Notes:
 *      - These libraries routines are written to support the
 *        Hitachi HD44780 LCD controller.
 *      - The user must define the following items:
 *          - The LCD interface type (4- or 8-bits)
 *          - If 4-bit mode
 *              - whether using the upper or lower nibble
 *          - The data port
 *              - The tris register for data port
 *              - The control signal ports and pins
 *              - The control signal port tris and pins
 *          - The user must provide three delay routines:
 *              - DelayFor18TCY() provides a 18 Tcy delay
 *              - DelayPORXLCD() provides at least 15ms delay
 *              - DelayXLCD() provides at least 5ms delay
 */

/* Interface type 8-bit or 4-bit
 * For 8-bit operation uncomment the #define BIT8
 */
// #define BIT8

/* When in 4-bit interface define if the data is in the upper
 * or lower nibble.  For lower nibble, comment the #define UPPER
 */

//#define UPPER

/* When in 6-10-bit interface comment the #define BUSY_LCD and conected PIN
 * R/W to GND in LCD
 */
 #define BUSY_LCD

/* DATA_PORT defines the port to which the LCD data lines are connected */
 #define DATA_PORT       PORTA
 #define TRIS_DATA_PORT TRISA

/* CTRL_PORT defines the port where the control lines are connected.
 * These are just samples, change to match your application.
 */
 #define RW_PIN   PORTAbits.RA6   /* PORT for RW */
 #define TRIS_RW  TRISAbits.TRISA6   /* TRIS for RW */

 #define RS_PIN   PORTAbits.RA7   /* PORT for RS */
 #define TRIS_RS  TRISAbits.TRISA7     /* TRIS for RS */

 #define E_PIN    PORTAbits.RA4 /* PORT for D  */
 #define TRIS_E   TRISAbits.TRISA4     /* TRIS for E  */

/* Display ON/OFF Control defines */
#define DON         0b00001111  /* Display on      */
#define DOFF        0b00001011  /* Display off     */
#define CURSOR_ON   0b00001111  /* Cursor on       */
#define CURSOR_OFF  0b00001101  /* Cursor off      */
#define BLINK_ON    0b00001111  /* Cursor Blink    */
#define BLINK_OFF   0b00001110  /* Cursor No Blink */

/* Cursor or Display Shift defines */
#define SHIFT_CUR_LEFT    0b00000100  /* Cursor shifts to the left   */
#define SHIFT_CUR_RIGHT   0b00000101  /* Cursor shifts to the right  */
#define SHIFT_DISP_LEFT   0b00000110  /* Display shifts to the left  */
#define SHIFT_DISP_RIGHT  0b00000111  /* Display shifts to the right */

/* Function Set defines */
#define FOUR_BIT   0b00101100  /* 4-bit Interface               */
#define EIGHT_BIT  0b00111100  /* 8-bit Interface               */
#define LINE_5X7   0b00110000  /* 5x7 characters, single line   */
#define LINE_5X10  0b00110100  /* 5x10 characters               */
#define LINES_5X7  0b00111000  /* 5x7 characters, multiple line */

#ifdef _OMNI_CODE_
#define PARAM_SCLASS
#else
#define PARAM_SCLASS auto
#endif

/* CLS_Line2
 * Clear Screen Line 2
 */
void CLS_Line2(void);

/* CLS_Line1
 * Clear Screen Line 1
 */
void CLS_Line1(void);
/* OpenXLCD
 * Configures I/O pins for external LCD
 */
void OpenXLCD(PARAM_SCLASS unsigned char);

/* SetCGRamAddr
 * Sets the character generator address
 */
void SetCGRamAddr(PARAM_SCLASS unsigned char);

/* SetDDRamAddr
 * Sets the display data address
 */
void SetDDRamAddr(PARAM_SCLASS unsigned char);

/* BusyXLCD
 * Returns the busy status of the LCD
 */
unsigned char BusyXLCD(void);

/* ReadAddrXLCD
 * Reads the current address
 */
unsigned char ReadAddrXLCD(void);

/* ReadDataXLCD
 * Reads a byte of data
 */
char ReadDataXLCD(void);

/* WriteCmdXLCD
 * Writes a command to the LCD
 */
void WriteCmdXLCD(PARAM_SCLASS unsigned char);

/* WriteDataXLCD
 * Writes a data byte to the LCD
 */
void WriteDataXLCD(PARAM_SCLASS char);

/* putcXLCD
 * A putc is a write
 */
#define putcXLCD WriteDataXLCD

/* putsXLCD
 * Writes a string of characters to the LCD
 */
void putsXLCD(PARAM_SCLASS char *);

/* putrsXLCD
 * Writes a string of characters in  to the LCD
 */
void putrsXLCD(const char *);

// Rutinas de tiempo auxiliares para la libreria XLCD
void DelayFor18TCY(void)
{
__delay_us(18);
}

void DelayPORXLCD(void)
{
__delay_ms(20); //Delay de 15 ms
}

void DelayXLCD(void)
{
__delay_ms(20); //Delay de 20 ms
}

void CLS_Line2(void)
{
    SetDDRamAddr(0x40);
    putrsXLCD("                ");
}

void CLS_Line1(void)
{
    SetDDRamAddr(0x00);
    putrsXLCD("                ");
}
/********************************************************************
*       Function Name:  OpenXLCD                                    *
*       Return Value:   void                                        *
*       Parameters:     lcdtype: sets the type of LCD (lines)       *
*       Description:    This routine configures the LCD. Based on   *
*                       the Hitachi HD44780 LCD controller. The     *
*                       routine will configure the I/O pins of the  *
*                       microcontroller, setup the LCD for 4- or    *
*                       8-bit mode and clear the display. The user  *
*                       must provide three delay routines:          *
*                       DelayFor18TCY() provides a 18 Tcy delay     *
*                       DelayPORXLCD() provides at least 15ms delay *
*                       DelayXLCD() provides at least 5ms delay     *
********************************************************************/
void OpenXLCD(unsigned char lcdtype)
{
        // The data bits must be either a 8-bit port or the upper or
        // lower 4-bits of a port. These pins are made into inputs
#ifdef BIT8                             // 8-bit mode, use whole port
        DATA_PORT = 0;
        TRIS_DATA_PORT = 0x00;
#else                                   // 4-bit mode
#ifdef UPPER                            // Upper 4-bits of the port
        DATA_PORT &= 0x0f;
        TRIS_DATA_PORT &= 0x0F;
#else                                   // Lower 4-bits of the port
        DATA_PORT &= 0xf0;
        TRIS_DATA_PORT &= 0xF0;
#endif
#endif
        TRIS_RW = 0;                    // All control signals made outputs
        TRIS_RS = 0;
        TRIS_E = 0;
        RW_PIN = 0;                     // R/W pin made low
        RS_PIN = 0;                     // Register select pin made low
        E_PIN = 0;                      // Clock pin made low

        // Delay for 15ms to allow for LCD Power on reset
        DelayPORXLCD();
 //-------------------reset procedure through software----------------------      
WriteCmdXLCD(0x30);
__delay_ms(5);

WriteCmdXLCD(0x30);
__delay_ms(1);


WriteCmdXLCD(0x32);
while( BusyXLCD() );
//------------------------------------------------------------------------------------------


        // Set data interface width, # lines, font
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(lcdtype);          // Function set cmd

        // Turn the display on then off
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(DOFF&CURSOR_OFF&BLINK_OFF);        // Display OFF/Blink OFF
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(DON&CURSOR_ON&BLINK_ON);           // Display ON/Blink ON

        // Clear display
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(0x01);             // Clear display

        // Set entry mode inc, no shift
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(SHIFT_CUR_RIGHT);   // Entry Mode
 
while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(0x06);   // Incremente
 
        while(BusyXLCD());              // Wait if LCD busy
        SetDDRamAddr(0x80);             // Set Display data ram address to 0
        
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(CURSOR_OFF);       // Cursor OFF
        return;
}


/********************************************************************
*       Function Name:  WriteDataXLCD                               *
*       Return Value:   void                                        *
*       Parameters:     data: data byte to be written to LCD        *
*       Description:    This routine writes a data byte to the      *
*                       Hitachi HD44780 LCD controller. The user    *
*                       must check to see if the LCD controller is  *
*                       busy before calling this routine. The data  *
*                       is written to the character generator RAM or*
*                       the display data RAM depending on what the  *
*                       previous SetxxRamAddr routine was called.   *
********************************************************************/
void WriteDataXLCD(char data)
{
#ifdef BIT8                             // 8-bit interface
        TRIS_DATA_PORT = 0;             // Make port output
        DATA_PORT = data;               // Write data to port
        RS_PIN = 1;                     // Set control bits
        RW_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock data into LCD
        DelayFor18TCY();
        E_PIN = 0;
        RS_PIN = 0;                     // Reset control bits
        TRIS_DATA_PORT = 0xff;          // Make port input
#else                                   // 4-bit interface
#ifdef UPPER                            // Upper nibble interface
        TRIS_DATA_PORT &= 0x0f;
        DATA_PORT &= 0x0f;
        DATA_PORT |= data&0xf0;
#else                                   // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;
        DATA_PORT &= 0xf0;
        DATA_PORT |= ((data>>4)&0x0f);
#endif
        RS_PIN = 1;                     // Set control bits
        RW_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock nibble into LCD
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Upper nibble interface
        DATA_PORT &= 0x0f;
        DATA_PORT |= ((data<<4)&0xf0);
#else                                   // Lower nibble interface
        DATA_PORT &= 0xf0;
        DATA_PORT |= (data&0x0f);
#endif
        DelayFor18TCY();
        E_PIN = 1;                      // Clock nibble into LCD
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Upper nibble interface
        TRIS_DATA_PORT |= 0xf0;
#else                                   // Lower nibble interface
        TRIS_DATA_PORT |= 0x0f;
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  WriteCmdXLCD                                *
*       Return Value:   void                                        *
*       Parameters:     cmd: command to send to LCD                 *
*       Description:    This routine writes a command to the Hitachi*
*                       HD44780 LCD controller. The user must check *
*                       to see if the LCD controller is busy before *
*                       calling this routine.                       *
********************************************************************/
void WriteCmdXLCD(unsigned char cmd)
{
#ifdef BIT8                             // 8-bit interface
        TRIS_DATA_PORT = 0;             // Data port output
        DATA_PORT = cmd;                // Write command to data port
        RW_PIN = 0;                     // Set the control signals
        RS_PIN = 0;                     // for sending a command
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the command in
        DelayFor18TCY();
        E_PIN = 0;
        DelayFor18TCY();
        TRIS_DATA_PORT = 0xff;          // Data port input
#else                                   // 4-bit interface
#ifdef UPPER                            // Upper nibble interface
        TRIS_DATA_PORT &= 0x0f;
        DATA_PORT &= 0x0f;
        DATA_PORT |= cmd&0xf0;
#else                                   // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;
        DATA_PORT &= 0xf0;
        DATA_PORT |= (cmd>>4)&0x0f;
#endif
        RW_PIN = 0;                     // Set control signals for command
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock command in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Upper nibble interface
        DATA_PORT &= 0x0f;
        DATA_PORT |= (cmd<<4)&0xf0;
#else                                   // Lower nibble interface
        DATA_PORT &= 0xf0;
        DATA_PORT |= cmd&0x0f;
#endif
        DelayFor18TCY();
        E_PIN = 1;                      // Clock command in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Make data nibble input
        TRIS_DATA_PORT |= 0xf0;
#else
        TRIS_DATA_PORT |= 0x0f;
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  SetDDRamAddr                                *
*       Return Value:   void                                        *
*       Parameters:     CGaddr: display data address                *
*       Description:    This routine sets the display data address  *
*                       of the Hitachi HD44780 LCD controller. The  *
*                       user must check to see if the LCD controller*
*                       is busy before calling this routine.        *
********************************************************************/
void SetDDRamAddr(unsigned char DDaddr)
{
#ifdef BIT8                                     // 8-bit interface
        TRIS_DATA_PORT = 0;                     // Make port output
        DATA_PORT = DDaddr | 0b10000000;        // Write cmd and address to port
        RW_PIN = 0;                             // Set the control bits
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock the cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
        DelayFor18TCY();
        TRIS_DATA_PORT = 0xff;                  // Make port input
#else                                           // 4-bit interface
#ifdef UPPER                                    // Upper nibble  interface
        TRIS_DATA_PORT &= 0x0f;                 // Make port output
        DATA_PORT &= 0x0f;                      // and write upper nibble
        DATA_PORT |= ((DDaddr | 0b10000000) & 0xf0);
#else                                           // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;                 // Make port output
        DATA_PORT &= 0xf0;                      // and write upper nibble
        DATA_PORT |= (((DDaddr | 0b10000000)>>4) & 0x0f);
#endif
        RW_PIN = 0;                             // Set control bits
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock the cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        DATA_PORT &= 0x0f;                      // Write lower nibble
        DATA_PORT |= ((DDaddr<<4)&0xf0);
#else                                           // Lower nibble interface
        DATA_PORT &= 0xf0;                      // Write lower nibble
        DATA_PORT |= (DDaddr&0x0f);
#endif
        DelayFor18TCY();
        E_PIN = 1;                              // Clock the cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        TRIS_DATA_PORT |= 0xf0;                 // Make port input
#else                                           // Lower nibble interface
        TRIS_DATA_PORT |= 0x0f;                 // Make port input
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  SetCGRamAddr                                *
*       Return Value:   void                                        *
*       Parameters:     CGaddr: character generator ram address     *
*       Description:    This routine sets the character generator   *
*                       address of the Hitachi HD44780 LCD          *
*                       controller. The user must check to see if   *
*                       the LCD controller is busy before calling   *
*                       this routine.                               *
********************************************************************/
void SetCGRamAddr(unsigned char CGaddr)
{
#ifdef BIT8                                     // 8-bit interface
        TRIS_DATA_PORT = 0;                     // Make data port ouput
        DATA_PORT = CGaddr | 0b01000000;        // Write cmd and address to port
        RW_PIN = 0;                             // Set control signals
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
        DelayFor18TCY();
        TRIS_DATA_PORT = 0xff;                  // Make data port inputs
#else                                           // 4-bit interface
#ifdef UPPER                                    // Upper nibble interface
        TRIS_DATA_PORT &= 0x0f;                 // Make nibble input
        DATA_PORT &= 0x0f;                      // and write upper nibble
        DATA_PORT |= ((CGaddr | 0b01000000) & 0xf0);
#else                                           // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;                 // Make nibble input
        DATA_PORT &= 0xf0;                      // and write upper nibble
        DATA_PORT |= (((CGaddr |0b01000000)>>4) & 0x0f);
#endif
        RW_PIN = 0;                             // Set control signals
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        DATA_PORT &= 0x0f;                      // Write lower nibble
        DATA_PORT |= ((CGaddr<<4)&0xf0);
#else                                           // Lower nibble interface
        DATA_PORT &= 0xf0;                      // Write lower nibble
        DATA_PORT |= (CGaddr&0x0f);
#endif
        DelayFor18TCY();
        E_PIN = 1;                              // Clock cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        TRIS_DATA_PORT |= 0xf0;                 // Make inputs
#else                                           // Lower nibble interface
        TRIS_DATA_PORT |= 0x0f;                 // Make inputs
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  ReadDataXLCD                                *
*       Return Value:   char: data byte from LCD controller         *
*       Parameters:     void                                        *
*       Description:    This routine reads a data byte from the     *
*                       Hitachi HD44780 LCD controller. The user    *
*                       must check to see if the LCD controller is  *
*                       busy before calling this routine. The data  *
*                       is read from the character generator RAM or *
*                       the display data RAM depending on what the  *
*                       previous SetxxRamAddr routine was called.   *
********************************************************************/
char ReadDataXLCD(void)
{
        char data;

#ifdef BIT8                             // 8-bit interface
        RS_PIN = 1;                     // Set the control bits
        RW_PIN = 1;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the data out of the LCD
        DelayFor18TCY();
        data = DATA_PORT;               // Read the data
        E_PIN = 0;
        RS_PIN = 0;                     // Reset the control bits
        RW_PIN = 0;
#else                                   // 4-bit interface
        RW_PIN = 1;
        RS_PIN = 1;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the data out of the LCD
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data = DATA_PORT&0xf0;          // Read the upper nibble of data
#else                                   // Lower nibble interface
        data = (DATA_PORT<<4)&0xf0;     // read the upper nibble of data
#endif
        E_PIN = 0;                      // Reset the clock line
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the next nibble out of the LCD
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data |= (DATA_PORT>>4)&0x0f;    // Read the lower nibble of data
#else                                   // Lower nibble interface
        data |= DATA_PORT&0x0f;         // Read the lower nibble of data
#endif
        E_PIN = 0;                                      
        RS_PIN = 0;                     // Reset the control bits
        RW_PIN = 0;
#endif
        return(data);                   // Return the data byte
}

/*********************************************************************
*       Function Name:  ReadAddrXLCD                                 *
*       Return Value:   char: address from LCD controller            *
*       Parameters:     void                                         *
*       Description:    This routine reads an address byte from the  *
*                       Hitachi HD44780 LCD controller. The user     *
*                       must check to see if the LCD controller is   *
*                       busy before calling this routine. The address*
*                       is read from the character generator RAM or  *
*                       the display data RAM depending on what the   *
*                       previous SetxxRamAddr routine was called.    *
*********************************************************************/
unsigned char ReadAddrXLCD(void)
{
        char data;                      // Holds the data retrieved from the LCD

#ifdef BIT8                             // 8-bit interface
        RW_PIN = 1;                     // Set control bits for the read
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock data out of the LCD controller
        DelayFor18TCY();
        data = DATA_PORT;               // Save the data in the register
        E_PIN = 0;
        RW_PIN = 0;                     // Reset the control bits
#else                                   // 4-bit interface
        RW_PIN = 1;                     // Set control bits for the read
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock data out of the LCD controller
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data = DATA_PORT&0xf0;          // Read the nibble into the upper nibble of data
#else                                   // Lower nibble interface
        data = (DATA_PORT<<4)&0xf0;     // Read the nibble into the upper nibble of data
#endif
        E_PIN = 0;                      // Reset the clock
        DelayFor18TCY();
        E_PIN = 1;                      // Clock out the lower nibble
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data |= (DATA_PORT>>4)&0x0f;    // Read the nibble into the lower nibble of data
#else                                   // Lower nibble interface
        data |= DATA_PORT&0x0f;         // Read the nibble into the lower nibble of data
#endif
        E_PIN = 0;
        RW_PIN = 0;                     // Reset the control lines
#endif
        return (data&0x7f);             // Return the address, Mask off the busy bit
}

/********************************************************************
*       Function Name:  putsXLCD
*       Return Value:   void
*       Parameters:     buffer: pointer to string
*       Description:    This routine writes a string of bytes to the
*                       Hitachi HD44780 LCD controller. The user
*                       must check to see if the LCD controller is
*                       busy before calling this routine. The data
*                       is written to the character generator RAM or
*                       the display data RAM depending on what the
*                       previous SetxxRamAddr routine was called.
********************************************************************/
void putsXLCD(char *buffer)
{
        while(*buffer)                  // Write data to LCD up to null
        {
                while(BusyXLCD());      // Wait while LCD is busy
                WriteDataXLCD(*buffer); // Write character to LCD
                buffer++;               // Increment buffer
        }
        return;
}

/********************************************************************
*       Function Name:  putrsXLCD
*       Return Value:   void
*       Parameters:     buffer: pointer to string
*       Description:    This routine writes a string of bytes to the
*                       Hitachi HD44780 LCD controller. The user
*                       must check to see if the LCD controller is
*                       busy before calling this routine. The data
*                       is written to the character generator RAM or
*                       the display data RAM depending on what the
*                       previous SetxxRamAddr routine was called.
********************************************************************/
void putrsXLCD(const  char *buffer)
{
        while(*buffer)                  // Write data to LCD up to null
        {
                while(BusyXLCD());      // Wait while LCD is busy
                WriteDataXLCD(*buffer); // Write character to LCD
                buffer++;               // Increment buffer
        }
        return;
}

/********************************************************************
*       Function Name:  BusyXLCD                                    *
*       Return Value:   char: busy status of LCD controller         *
*       Parameters:     void                                        *
*       Description:    This routine reads the busy status of the   *
*                       Hitachi HD44780 LCD controller.             *
********************************************************************/
unsigned char BusyXLCD(void)
{
#ifdef BUSY_LCD
        RW_PIN = 1;                     // Set the control bits for read
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock in the command
        DelayFor18TCY();
#ifdef BIT8                             // 8-bit interface
        if(DATA_PORT&0x80)                      // Read bit 7 (busy bit)
        {                               // If high
                E_PIN = 0;              // Reset clock line
                RW_PIN = 0;             // Reset control line
                return 1;               // Return TRUE
        }
        else                            // Bit 7 low
        {
                E_PIN = 0;              // Reset clock line
                RW_PIN = 0;             // Reset control line
                return 0;               // Return FALSE
        }
#else                                   // 4-bit interface
#ifdef UPPER                            // Upper nibble interface
        if(DATA_PORT&0x80)
#else                                   // Lower nibble interface
        if(DATA_PORT&0x08)
#endif
        {
                E_PIN = 0;              // Reset clock line
                DelayFor18TCY();
                E_PIN = 1;              // Clock out other nibble
                DelayFor18TCY();
                E_PIN = 0;
                RW_PIN = 0;             // Reset control line
                return 1;               // Return TRUE
        }
        else                            // Busy bit is low
        {
                E_PIN = 0;              // Reset clock line
                DelayFor18TCY();
                E_PIN = 1;              // Clock out other nibble
                DelayFor18TCY();
                E_PIN = 0;
                RW_PIN = 0;             // Reset control line
                return 0;               // Return FALSE
        }
#endif
#else
        __delay_ms(5);
        return 0;
#endif

}




PIC16F819 Configuration Bit Settings

Código: [Seleccionar]
// PIC16F819 Configuration Bit Settings

#include <xc.h>

// CONFIG
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTRC oscillator; CLKO function on RA6/OSC2/CLKO pin and port I/O function on RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF      // Low-Voltage Programming Enable bit (RB3/PGM pin has PGM function, Low-Voltage Programming enabled)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2      // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// CONFIG2
//#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable






[/quote]
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 21 de Mayo de 2013, 18:52:47
Rseliman:
         Gracias por compartir.  ((:-)).-
         Poco a poco iremos subiendo más y más ejemplos.
            Saludos.
                  Jukinch
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 23 de Mayo de 2013, 14:52:11
Rseliman:
         Gracias por compartir.  ((:-)).-
         Poco a poco iremos subiendo más y más ejemplos.
            Saludos.
                  Jukinch


Atento a tu pedido ...subo el proyecto completo ....comenten si les anda por favor ...gracias


Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 23 de Mayo de 2013, 15:06:59
Rseliman:
       Gracias nuevamente. Lo pude compilar a la primera y funciona perfecto en proteus.
             Saludos.
                Jukinch
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 24 de Mayo de 2013, 15:09:02
Maldita linea roja


Hola a todos ...aca ando de nuevo , despues de que la linea roja me marcara incansablemente los __delays ....busque porque era ...a pesar de que la compilacion se hacia bien ...y logre sacar el error  con esta linea ...    #define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))  ...es un bugs del compiler ...

Lo saque de un texto en ingles de microchip


Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 24 de Mayo de 2013, 18:49:08
Googleando encontré un comentario que hizo un usuario en el grupo del rtc_argentina con un gran dolor de cabeza a evitar con el uso de la librería del LCD xlcd.h, el cual lo sintetizo a continuación:
 
Por más que integremos el archivo a la carpeta del proyecto con la directiva #include  "xlcd.h" o desde la carpeta del árbol del proyecto, en la carpeta headers files,
 al hacer el #include <xc.h> estamos también incluyendo varios archivos más.
este archivo <xc.h> tiene dentro el  #include <htc.h>  y este archivo a su vez tiene un #include <pic18.h>.
Dentro del archivo <pic18.h>. están estas otras directivas de preprocesado:

                        #if defined _PLIB
                        #include <plib.h>
                        #endif

                       Con lo cual también se incluye al archivo plib.h el cual tiene dentro la directiva #include <xlcd.h>

Todo este trabalengua hace que el compilador utilice el archivo original <xlcd.h> sin tomar en cuenta el que tenemos "xlcd.h" en la carpeta del proyecto, no importando la forma en la que se haya declarado posteriormente el #include  "xlcd.h", esto porque el #include <xc.h> esta primero que el include local #include  "xlcd.h" de la carpeta del proyecto. Y por más que cambiemos de puerto B a puerto D no se reflejarán los cambios.-
 
 
Las soluciones son:
 
Solución  1: Editar directamente el archivo original xlcd.h, en la carpeta C:\Microchip\xc8\v1.12\include\plib (solución peligrosa porque cambiaríamos la librería en uso por otros proyectos. Hacer un backup)
 
Solución 2: En todos los archivos anteriormente mencionados cambiar
#include <pic18.h>
por #include "pic18.h " (solución peligrosa porque cambiaríamos la librería en uso por otros proyectos. hacer un backup)
 
Solución 3: hacer una copia local de la librería xlcd.h con otro nombre para evitar confusión #include  "xlcd_portd.h" y renombrar todos los #defines para que sean diferentes a los de la librería original.-
por ejemplo DATA_PORT cambiarlo por DATA_Puerto
Así por más que se la incluya a la original, los defines que surtirán efecto serán los renombrados.- (solución poco elegante. pero solución al fin)

Solución 4:
               agregar en nuestra librería local las directivas de preprocesado que quiten las definiciones que trae la librería xlcd standard así nuestra librería las puede redefinir:
Código: C
  1. #if defined  DATA_PORT
  2.     #undef   DATA_PORT
  3. #endif
  4.  
  5. #if defined  TRIS_DATA_PORT
  6.     #undef   TRIS_DATA_PORT
  7. #endif
  8.  
  9. #if defined  BIT8
  10.     #undef   BIT8
  11. #endif
  12.  
  13. #if defined  UPPER
  14.     #undef   UPPER
  15. #endif
  16.  
  17. #if defined  LINE_0
  18.     #undef   LINE_0
  19. #endif
  20.  
  21.  
  22. #if defined  NEXT_LINE
  23.     #undef   NEXT_LINE
  24. #endif
  25.  
  26. #if defined  RW_PIN
  27.     #undef   RW_PIN
  28. #endif
  29.  
  30. #if defined  TRIS_RW
  31.     #undef   TRIS_RW
  32. #endif
  33.  
  34. #if defined  RS_PIN
  35.     #undef   RS_PIN
  36. #endif
  37.  
  38. #if defined  TRIS_RS
  39.     #undef   TRIS_RS
  40. #endif
  41.  
  42. #if defined  E_PIN
  43.     #undef   E_PIN
  44. #endif
  45.  
  46. #if defined  TRIS_E
  47.     #undef   TRIS_E
  48. #endif
  49.  
  50. #if defined  DON
  51.     #undef   DON
  52. #endif
  53.  
  54. #if defined  DOFF
  55.     #undef   DOFF
  56. #endif
  57.  
  58. #if defined  CURSOR_ON
  59.     #undef   CURSOR_ON
  60. #endif
  61.  
  62. #if defined  CURSOR_OFF
  63.     #undef   CURSOR_OFF
  64. #endif
  65.  
  66. #if defined  BLINK_ON
  67.     #undef   BLINK_ON
  68. #endif
  69.  
  70. #if defined  BLINK_OFF
  71.     #undef   BLINK_OFF
  72. #endif
  73.  
  74. #if defined  SHIFT_CUR_LEFT
  75.     #undef   SHIFT_CUR_LEFT
  76. #endif
  77.  
  78. #if defined  SHIFT_CUR_RIGHT
  79.     #undef   SHIFT_CUR_RIGHT
  80. #endif
  81.  
  82. #if defined  SHIFT_DISP_LEFT
  83.     #undef   SHIFT_DISP_LEFT
  84. #endif
  85.  
  86. #if defined  SHIFT_DISP_RIGHT
  87.     #undef   SHIFT_DISP_RIGHT
  88. #endif
  89.  
  90. #if defined  FOUR_BIT
  91.     #undef   FOUR_BIT
  92. #endif
  93.  
  94. #if defined  EIGHT_BIT
  95.     #undef   EIGHT_BIT
  96. #endif
  97.  
  98. #if defined  LINE_5X7
  99.     #undef   LINE_5X7
  100. #endif
  101.  
  102. #if defined  LINE_5X10
  103.     #undef   LINE_5X10
  104. #endif
  105.  
  106. #if defined  LINES_5X7
  107.     #undef   LINES_5X7
  108. #endif
  109.  
  110. #if defined  PARAM_SCLASS
  111.     #undef   PARAM_SCLASS
  112. #endif


solución 5:
agregar al prinicipio de nuestro archivo main.c las siguientes dos directivas include:

#include <pic18f4550.h>
#include "xlcd.h" // lo agregamos primero para que el include standard <xlcd.h> no pise nuestro "xlcd.h" modificado.

Esta es la solución menos laboriosa.


modificado: agregué solución 5.
          
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 26 de Mayo de 2013, 00:38:56
COMO INTEGRAR PROTEUS A MPLAB X

Encontré un artículo muy interesante sobre como integrar proteus a Mplab. en el sitio http://milindapro.blogspot.com.ar/2012/12/proteus-vsm-viewer-to-debug-mplabx.html y lo traduje al Español para compartirlo en la presente guía.
 Saludos.
          Jukinch

COMO INTEGRAR Proteus VSM para hacer debug en los proyectos de MPLABX con el plugin Proteus VSM viewer.
MPLAB X está basado en la plataforma open-source NetBeans. Por lo tanto soporta plugins de herramientas de terceros.


Paso 1 - Primero debemos instalar el plugin VSM viewer en el IDE MPLABX. Para ello abrimos la ventana de Plugins seleccionando Tools->Plugins desde la barra de menu.

(http://img20.imageshack.us/img20/7223/toolsj.png)


Luego hacemos click en Available plugins, y allí veremos a Proteus VSM viewer dentro de la lista bajo la categoría 'MPLAB DBCore'. (Si proteus vsm viewer no está en la lista hay que presionar en el botón Reload Catalog button para refrescar la lista).



Luego hay que hacer click en Install y seguir los pasos para instalar el plugin en el IDE.
También podemos actualizar o remover los plugins existentes desde esta ventana.

(http://img593.imageshack.us/img593/9008/installi.png)


Paso 2 - Una vez instalado el plugin podremos crear nuestros proyectos desde MPLABX y cuando nos pregunte que herramienta queremos utilizar para hacer debug debemos seleccionar Proteus VSM viewer como herramienta de debugging.

(http://img27.imageshack.us/img27/8807/newprojectvsm.jpg)


También podemos setear como herramienta de debug a Proteus VSM desde un poyecto existente. Para ello hay que editar las propiedades del proyecto haciendo click derecho sobre el proyecto. Luego hacer click en la categoría 'Config: [default]'. Luego seleccionar Proteus VSM desde el list box que se encuentra al costado derecho como se muestra en la siguiente figura.

(http://imageshack.us/images/blue/external.png)

Paso 3 - Luego debemos compilar el proyecto en modo debug. Una vez hecho esto debemos crear un diseño en ISIS para nuestro proyecto.

Paso 4 - Una vez creado el archivo dsn para nuestro proyecto debemos cargar el programa que utilizará el microcontrolador seleccionando el archivo .cof que se encontrará en la carpeta  \dist\default\debug . Luego grabamos el archivo dsn dentro de la carpeta del proyecto de MPLAB X.

Paso 5 - Y por último deberemos agregar el archivo dsn al proyecto del MPLabX. Vamos a la ventana de las propiedades del proyecto y hacemos click en la categoría Proteus VSM Viewer bajo la categoría Config: [default] y seleccionamos el archivo dsn que hemos creado desde Design File Name: y presionamos en el botón apply.

(http://img694.imageshack.us/img694/1377/vsmd.jpg)


A partir de este momento podremos utilizar break points en el código y hacer Debug del proyecto con Proteus. Luego MPLabX automáticamente ejecutará el archivo dsn de ISIS simultáneamente con nuestro código.

Una vez abierto el diseño ISIS desde Proteus debemos activar en el menú debug la opción de "Remote Debug Monitor" (Debug->Use Remote Debug Monitor)

Luego podremos abrir ambas ventanas simultaneamente y hacer debug del proyecto como se ve en la figura.

(http://img850.imageshack.us/img850/7589/debugmplabxproteusvsmve.jpg)

Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 26 de Mayo de 2013, 01:05:10
View Includes Hierarchy:
Mplab X tiene una herramienta muy útil que se activa haciendo botón derecho sobre el editor de código y seleccionando en el menú emergente en la opción Navigate y luego seleccionando View Includes Hierarchy.

(http://img259.imageshack.us/img259/4028/viewincludeshierarchy.png)

Al elegir dicha herramienta se nos abrirá una nueva ventana con un árbol en donde podemos deplegar todos los archivos que se incluyen desde main.c

(http://img402.imageshack.us/img402/3617/viewincludeshierarchytr.png)
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 26 de Mayo de 2013, 01:22:38
View macro expansion

El Mplab X tiene una herramienta que nos permite visualizar el código del archivo que estemos editando con las macros expandidas.
 
para utilizarla hacemos click derecho sobre el editor de código y seleccionando en el menú emergente en la opción Navigate y luego seleccionando View Macro expansion.

(http://img694.imageshack.us/img694/2857/viewmacroexpansion.png)

Una vez seleccionada nos mostrará una nueva ventana con el código expandido. Y si hacemos doble click en título de la ventana de macro expansion podremos verla a pantalla completa como se ve en la siguiente figura:

(http://img829.imageshack.us/img829/584/viewmacroexpansion2.png)
Allí se puede ver como el siguiente código:

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

fue reemplazado por:

// configuramos el puerto serie
 OpenUSART(0b01111111 &
            0b11111111 &       //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
            0b11111110 &     //Modo asincrono (fullduplex)
            0b11111101 &       //8 bits de datos
            0b11111111 &         //Recepción continua
            0b11111111, 51);  //9600 Baudios

Luego para volver a la vista anterior volvemos a hacer doble click sobre el título de la ventana.

Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 26 de Mayo de 2013, 09:22:38
Fantástico!!!!

Ahora si que esta muy fácil probar el firmware que estemos desarrollando!!!

Alguien tiene algo de como hacer debug con el ID2 clone? Esa sería la frutilla del postre para mi...

Leo, una consulta, viste lo que estoy haciendo de ARM, viste las CMSIS y viste que esta muy bien documentado cada estructura con sus miembros para configurar cada periférico. En XC8 veo que es parecido, hay algún documento que enumere todos los nombres de registros (aquí no son estructuras, verdad?) agrupados por periférico como esta en el User Manual del uC LPC?

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 26 de Mayo de 2013, 10:15:30
Hola Leo. Vos te referís a los archivos de cabecera como el pic18f4550.h?
ahí se definen todos los registros del pic con los mismos nombres que encontramos en el datasheet.

ejemplo:

// Register: PORTB
extern volatile unsigned char           PORTB               @ 0xF81; // Asocia a PORTB con la dirección de memoria del legistro

y también hace uso de uniones, estructuras y macros para que podamos acceder a los bits del registro en forma individual (PORTBbits.RB0)

// bitfield definitions
typedef union {
    struct {
        unsigned RB0                    :1;
        unsigned RB1                    :1;
        unsigned RB2                    :1;
        unsigned RB3                    :1;
        unsigned RB4                    :1;
        unsigned RB5                    :1;
        unsigned RB6                    :1;
        unsigned RB7                    :1;
    };
    struct {
        unsigned INT0                   :1;
        unsigned INT1                   :1;
        unsigned INT2                   :1;
        unsigned                        :2;
        unsigned PGM                    :1;
        unsigned PGC                    :1;
        unsigned PGD                    :1;
    };
    struct {
        unsigned                        :3;
        unsigned CCP2_PA2               :1;
    };
} PORTBbits_t;
extern volatile PORTBbits_t PORTBbits @ 0xF81;

// bitfield macros
#define _PORTB_RB0_POSN                                     0x0
#define _PORTB_RB0_POSITION                                 0x0
#define _PORTB_RB0_SIZE                                     0x1
#define _PORTB_RB0_LENGTH                                   0x1
#define _PORTB_RB0_MASK                                     0x1
#define _PORTB_RB1_POSN                                     0x1
#define _PORTB_RB1_POSITION                                 0x1
#define _PORTB_RB1_SIZE                                     0x1
#define _PORTB_RB1_LENGTH                                   0x1
#define _PORTB_RB1_MASK                                     0x2
#define _PORTB_RB2_POSN                                     0x2
#define _PORTB_RB2_POSITION                                 0x2
#define _PORTB_RB2_SIZE                                     0x1
#define _PORTB_RB2_LENGTH                                   0x1
#define _PORTB_RB2_MASK                                     0x4
#define _PORTB_RB3_POSN                                     0x3
#define _PORTB_RB3_POSITION                                 0x3
#define _PORTB_RB3_SIZE                                     0x1
#define _PORTB_RB3_LENGTH                                   0x1
#define _PORTB_RB3_MASK                                     0x8
#define _PORTB_RB4_POSN                                     0x4
#define _PORTB_RB4_POSITION                                 0x4
#define _PORTB_RB4_SIZE                                     0x1
#define _PORTB_RB4_LENGTH                                   0x1
#define _PORTB_RB4_MASK                                     0x10
#define _PORTB_RB5_POSN                                     0x5
#define _PORTB_RB5_POSITION                                 0x5
#define _PORTB_RB5_SIZE                                     0x1
#define _PORTB_RB5_LENGTH                                   0x1
#define _PORTB_RB5_MASK                                     0x20
#define _PORTB_RB6_POSN                                     0x6
#define _PORTB_RB6_POSITION                                 0x6
#define _PORTB_RB6_SIZE                                     0x1
#define _PORTB_RB6_LENGTH                                   0x1
#define _PORTB_RB6_MASK                                     0x40
#define _PORTB_RB7_POSN                                     0x7
#define _PORTB_RB7_POSITION                                 0x7
#define _PORTB_RB7_SIZE                                     0x1
#define _PORTB_RB7_LENGTH                                   0x1
#define _PORTB_RB7_MASK                                     0x80
#define _PORTB_INT0_POSN                                    0x0
#define _PORTB_INT0_POSITION                                0x0
#define _PORTB_INT0_SIZE                                    0x1
#define _PORTB_INT0_LENGTH                                  0x1
#define _PORTB_INT0_MASK                                    0x1
#define _PORTB_INT1_POSN                                    0x1
#define _PORTB_INT1_POSITION                                0x1
#define _PORTB_INT1_SIZE                                    0x1
#define _PORTB_INT1_LENGTH                                  0x1
#define _PORTB_INT1_MASK                                    0x2
#define _PORTB_INT2_POSN                                    0x2
#define _PORTB_INT2_POSITION                                0x2
#define _PORTB_INT2_SIZE                                    0x1
#define _PORTB_INT2_LENGTH                                  0x1
#define _PORTB_INT2_MASK                                    0x4
#define _PORTB_PGM_POSN                                     0x5
#define _PORTB_PGM_POSITION                                 0x5
#define _PORTB_PGM_SIZE                                     0x1
#define _PORTB_PGM_LENGTH                                   0x1
#define _PORTB_PGM_MASK                                     0x20
#define _PORTB_PGC_POSN                                     0x6
#define _PORTB_PGC_POSITION                                 0x6
#define _PORTB_PGC_SIZE                                     0x1
#define _PORTB_PGC_LENGTH                                   0x1
#define _PORTB_PGC_MASK                                     0x40
#define _PORTB_PGD_POSN                                     0x7
#define _PORTB_PGD_POSITION                                 0x7
#define _PORTB_PGD_SIZE                                     0x1
#define _PORTB_PGD_LENGTH                                   0x1
#define _PORTB_PGD_MASK                                     0x80
#define _PORTB_CCP2_PA2_POSN                                0x3
#define _PORTB_CCP2_PA2_POSITION                            0x3
#define _PORTB_CCP2_PA2_SIZE                                0x1
#define _PORTB_CCP2_PA2_LENGTH                              0x1
#define _PORTB_CCP2_PA2_MASK                                0x8
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 26 de Mayo de 2013, 12:15:33

// bitfield definitions
typedef union {
    struct {
        unsigned RB0                    :1;
        unsigned RB1                    :1;
        unsigned RB2                    :1;
        unsigned RB3                    :1;
        unsigned RB4                    :1;
        unsigned RB5                    :1;
        unsigned RB6                    :1;
        unsigned RB7                    :1;
    };
    struct {
        unsigned INT0                   :1;
        unsigned INT1                   :1;
        unsigned INT2                   :1;
        unsigned                        :2;
        unsigned PGM                    :1;
        unsigned PGC                    :1;
        unsigned PGD                    :1;
    };
    struct {
        unsigned                        :3;
        unsigned CCP2_PA2               :1;
    };
} PORTBbits_t;
extern volatile PORTBbits_t PORTBbits @ 0xF81;


Ahí esta lo que buscaba. Primero se crea un tipo de datos (PORTBbits_t) como la union de 3 estructuras una "ensima" de la otra. La primer estructura para los pines RB, la segunda para las interrupciones y PG y la tercera para CCP2.
Luego se crea la variable que todos usan PORTBbits.

Lo importante para mí son estos registros:

Código: [Seleccionar]
// Register: T1CON
extern volatile unsigned char           T1CON               @ 0x010;
#ifndef _LIB_BUILD
asm("T1CON equ 010h");
#endif
// bitfield definitions
typedef union {
    struct {
        unsigned TMR1ON                 :1;
        unsigned TMR1CS                 :1;
        unsigned nT1SYNC                :1;
        unsigned T1OSCEN                :1;
        unsigned T1CKPS                 :2;
        unsigned TMR1GE                 :1;
        unsigned T1GINV                 :1;
    };
    struct {
        unsigned                        :2;
        unsigned T1INSYNC               :1;
        unsigned                        :1;
        unsigned T1CKPS0                :1;
        unsigned T1CKPS1                :1;
        unsigned                        :1;
        unsigned T1GIV                  :1;
    };
    struct {
        unsigned                        :2;
        unsigned T1SYNC                 :1;
    };
} T1CONbits_t;
extern volatile T1CONbits_t T1CONbits @ 0x010;
Con ese registro tenemos acceso, por ejemplo, al timer1.... está bueno, es similar al ARM.
Lo único que no me guta es el nivel de explicacion de los datasheet de microchip vs. el user manual de los ARM, pero será cuestion de acostumbrarce.... voy a ver si arranco a probar con mi próximo proyecto en un 16F883.

Saludos y gracias!
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 26 de Mayo de 2013, 13:03:09
Si garbe. comparto con vos lo de los manuales. Los de ARM son una delicia y los de Microchip son de terror  :5].
Para los timers, etc. tenés la guia pic18_plib.pdf allí tenés librerías para el uso de todos los periféricos.
         
Título: Re: Mini curso "Programación en XC8"
Publicado por: yamilongiano en 27 de Mayo de 2013, 18:29:00
1.2. ¡Hola mundo! en C (o como hacer destellar un LED)

Hacer destellar un LED es muy sencillo. Tanto como crear un bucle infinito, escribir en un pin, generar una demora y volver a escribir. El ejemplito:

Código: C
  1. /*
  2.  * File:   main.c
  3.  * Author: lucas
  4.  * Created on 1 de abril de 2013, 22:20
  5.  * Microcontrolador: PIC16F648A
  6.  *
  7.  * ¡Hola Mundo! en C (o como hacer destellar un LED)
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <xc.h> // Librería XC8
  13.  
  14. #define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro
  15.  
  16. // PIC16F648A Configuration Bit Settings
  17. #pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
  18. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  19. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  20. #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
  21. #pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
  22. #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
  23. #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
  24. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  25.  
  26. // FUNCION PRINCIPAL
  27. void main ()
  28. {
  29.      TRISB = 0b00000000; // Configuro puerto B como salidas
  30.      while (1) // Bucle infinito
  31.      {
  32.          PORTBbits.RB0 = 0; // Apago pin RB0
  33.          __delay_ms(500);
  34.          PORTBbits.RB0 = 1; // Enciendo pin RB0
  35.          __delay_ms(500);
  36.      }
  37. }

* Podríamos hacer el cambio de estado del pin RB0 (toggle) utilizando la siguiente instrucción: PORTBbits.RB0 ^= 1;

hola queria saber como prender mas de un led al mismo tiempo aqui prende un led del puerto b el RB0 ( PORTBbits.RB0 = 0; // Apago pin RB0)

ahora como puedo prender mas de un led en la misma intruccion yo vengo del assembler y me cuesta este lenguaje y no comprendo bien las instrucciones para dominar el pic.

creo que en asembler era algo asi.

        movlw b'00010001' ; rb0 encendido y rb4 encendido.
        movwf portb

envio de datos en forma paralela como para usarlo en un display.
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 27 de Mayo de 2013, 18:50:43
Hola yamilongiano. Para encender todo el puerto debés hacer referencia a todo el puerto con el identificador PORTB

así:
 
PORTB = b00010001; // Fijate que la sintaxis del valor del entero es diferente al assembler b'00010001'

Título: Re: Mini curso "Programación en XC8"
Publicado por: yamilongiano en 27 de Mayo de 2013, 19:09:14
Hola yamilongiano. Para encender todo el puerto debés hacer referencia a todo el puerto con el identificador PORTB

así:
 
PORTB = b00010001; // Fijate que la sintaxis del valor del entero es diferente al assembler b'00010001'



gracias si funciono.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 30 de Mayo de 2013, 15:00:26
He buscado por muchos sitios y no encuentro cómo definir interrupciones de alta prioridad y de baja prioridad con XC8

Estoy trasladando un programa en c del compilador C18 a XC8 para el micro PIC18F2550.

El original para C18 es este:
Código: [Seleccionar]
#pragma interrupt isr_main
void isr_low_main(void) {
   // Rutina de interrupción
}

#pragma code high_vector=0x08
void isr_high(void) {
   _asm GOTO isr_main  _endasm
}

#pragma code low_vector=0x18
void isr_low(void) {
   _asm GOTO isr_main  _endasm
}


¿Cómo puedo adaptarla?

Esta adaptación para XC8 no me convence porque no distingue el vector alto y el bajo:

Código: [Seleccionar]
void interrupt isr(void) {
   // Rutina de interrupción
}

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 30 de Mayo de 2013, 15:25:18
Hola Picuino.
En los Pic18 las interrupciones en xc8 son por defecto de alta prioridad.
Para crear una interrupción de baja prioridad debes usar además del calificador interrupt  el calificador low_priority.
Fuente: página 189 del manual de xc8.
Ds52053b-page189.

Saludos
        Jukinch
Código: C
  1. void interrupt low_priority tc_clr(void)
  2.  {     if  (TMR1IE && TMR1IF)
  3.         {    TMR1IF=0;  
  4.               tick_count = 0;  
  5.               return;  
  6.          }
  7.  
  8. // poner aquí el código de cualquier otra interrupción de bajá prioridad.
  9.  }
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 30 de Mayo de 2013, 15:39:58
Gracias jukinch
Al final he puesto esto:

Código: [Seleccionar]
void isr(void) {
   // Rutina de atención a interrupciones
   ...

}

void interrupt high_isr(void) {
   #asm
   GOTO _isr
   #endasm
}

void interrupt low_priority low_isr(void) {
   #asm
   GOTO _isr
   #endasm
}

El programa no funciona todavía, pero el error ahora no parece estar en las interrupciones.

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 31 de Mayo de 2013, 16:38:31
Hola a todos ....
estoy intentando compilar en xc8 esto



const rom unsigned char OSS_conversion_time[] = {5, 8, 14, 26};


o sea intento almacenar cadena en la rom



lo saque de un sub de xc18 ... me da el siguiente error

 ";" expected

 missing basic type; int assumed

Surround with ...

Porque no lo entiende el xc8 ?? alguien me da una mano por favor ?? Gracias
como hago lo mismo en xc8 ??Gracias


lo mismo me pasa aca



printf((const far rom char*) "%ld\r\n%ld\r\n%ld\r\n%ld\r\n%ld\r\n%ld\r\n%ld\r\n%ld\r\n%ld\r\n%ld\r\n%ld\r\n,",\
   ac1, ac2, ac3, ac4, ac5, ac6, b1, b2, mb, mc, md);



Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 31 de Mayo de 2013, 18:13:00
Prueba con definirla de esta manera

Código: C
  1. const unsigned char OSS_conversion_time[]={5,8,14,26};

es decir, sin la palabra "rom"
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 31 de Mayo de 2013, 20:40:57
Interrupciones de alta y baja prioridad.

 En este programa vamos a utilizar las interrupciones externas del pic18F4550 en los pines RB0, RB1 y RB2
   configurando lso flancos de subida para INT0, INT1, e INT2.

  En el 4550 la INT0 es siempre de alta prioridad. No se puede setear como de baja prioridad
   Las INT1 e INT2 las configuramos en baja prioridad.

   Cada vez que se produzca una interrupción en INT0 cambiará el estado del pin RA0
   Cada vez que se produzca una interrupción en INT1 cambiará el estado del pin RA1
   Cada vez que se produzca una interrupción en INT2 cambiará el estado del pin RA2

        Saludos.
              Jukinch

Código: C
  1. File:   main.c
  2.    Author: JUKINCH
  3.  
  4.    Created on 31 de mayo de 2013, 14:49
  5.  
  6.    PRUEBA DE INTERRUPCIONES en baja y alta prioridad
  7.    EN INT0 (RB0) INT1 (RB1) E INT2 (RB2)
  8.  
  9.  
  10.    pic: 18f4550
  11.    crystal: NO
  12.    CPU: 8Mhz (valor establecido dentro de main cambiando los bits IRCF2, IRCF1 e IRCF0 del registro OSCCON)
  13.         en RA6 sale la frecuencia de Fosc/4   ------->   8Mhz/4 = 2Mhz
  14.  
  15.    FUSES: los bits de configuración se establecen en el archivo "configuracion_de_fuses.c"
  16.  
  17.    CONEXIONES entrenadora FELIXLS:
  18.     1 módulo conectado en IDC(RB0) en modo botón
  19.     1 módulo conectado en IDC(RA0) en modo leds
  20.     los cambios se pueden hacer en el archivo configuracion_hard.c
  21.  
  22.  */
  23.  
  24.  
  25.  
  26. /*Includes globales*/
  27. #include <xc.h>
  28. #include <delays.h> /* Para utilizar demoras en nuestro código*/
  29.  
  30. /*Includes locales*/
  31. #include "configuracion_de_fuses.c"
  32. #include "configuracion_hard.c"
  33.  
  34.  
  35.  
  36.  
  37.  
  38. volatile int myVolatileVariable=0;//variable para utilizar con las interrupciones
  39.  
  40.  
  41. //******************************************************//
  42. // Rutina de Interrupcion de Alta Prioridad
  43. //******************************************************//
  44. //
  45.  
  46. void interrupt interrupcionDeAlta(void)//prototipo de la interrupción de alta prioridad
  47.         {
  48.             if(INTCONbits.INT0IF)          //pregunta por bandera de interrupción en rb0
  49.                     {
  50.                     LED0 = ~LED0;          // invierto estado del led
  51.                     myVolatileVariable++;
  52.                     INTCONbits.INT0IF = 0; //limpia bandera y salimos
  53.                     }
  54.         }
  55.  
  56.  
  57. //
  58. //******************************************************//
  59. // Rutina de Interrupcion de baja prioridad
  60. //******************************************************//
  61. //
  62. void interrupt low_priority   interrupcionDeBaja(void)//prototipo de la interrupción de baja prioridad
  63.         {
  64.             if(INTCON3bits.INT1IF)       //pregunta por bandera de interrupción
  65.                 {
  66.                 LED1 = ~LED1;            // invierto estado del led
  67.                 myVolatileVariable++;
  68.                 INTCON3bits.INT1IF = 0;  //limpia bandera y salimos
  69.                 }
  70.  
  71.  
  72.             if(INTCON3bits.INT2IF)       //pregunta por bandera de interrupción
  73.                 {
  74.                 LED2 = ~LED2;            // invierto estado del led
  75.                 myVolatileVariable++;
  76.                 INTCON3bits.INT2IF = 0;  //limpia bandera y salimos
  77.                 }
  78.         }
  79.  
  80.  
  81.  
  82.  
  83.  
  84. //******************************************************//
  85. // Programa Principal
  86. //******************************************************//
  87. void main(void)
  88. {
  89. ADCON0 = 0X00,ADCON1 = 0X0F,CMCON = 0X07; //puerto A con todos los pines digitales
  90.  
  91. PINLED0=0; // Configuración de pines como salida para los leds
  92. PINLED1=0;
  93. PINLED2=0;
  94. PINBOTON0=1; // Configuración de pines como entrada para los botones
  95. PINBOTON1=1;
  96. PINBOTON2=1;
  97.  
  98. LATA = 0X00; // todo el puerto A a cero.
  99.  
  100.  
  101. RCONbits.IPEN = 1; // Activa modo alta y baja prioridad
  102. INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
  103. INTCONbits.GIEH = 1;// permitimos interrupciones de alta prioridad (Global Interrupt Enable High)
  104. INTCON2bits.INTEDG0 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB0
  105. INTCON2bits.INTEDG1 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB1
  106. INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
  107.  
  108. INTCONbits.INT0IE=1; // activa la interrupción externa por flanco del pin RB0
  109.                      // La Int0 es siempre de alta prioridad. No se puede setear como de baja prioridad
  110.  
  111. INTCON3bits.INT1IE=1; // activa la interrupción externa por flanco del pin RB1
  112. INTCON3bits.INT1IP=0; // selecciona la interrupción de baja prioridad del pin RB1
  113.  
  114. INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
  115. INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2
  116.  
  117. //*******************************************************
  118. //*******************************************************
  119.  
  120.  
  121. while (1);
  122.  
  123.  
  124.  
  125. }
  126. //*******************************************************
  127. //*******************************************************
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 01 de Junio de 2013, 04:58:07
A mi me han dado muchos problemas las interrupciones hasta que las he activado antes de finalizar la rutina de interrupción:

Código: C
  1. void interrupt low_priority low_isr(void) {
  2.    // Timer0 interrupt counter
  3.    if (INTCONbits.TMR0IF == 1) {
  4.       INTCONbits.TMR0IF = 0;
  5.       timer0.dword++;
  6.    }
  7.  
  8.    INTCONbits.GIEL = 1;    // Sin esta instrucción, las interrupciones se deshabilitan después de cada interrupción
  9. }

Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 01 de Junio de 2013, 15:59:54
  Que raro lo que te ocurre Picuino!!! Todavía no lo he probado en XC8, pero en HiTech no tenía problemas al hacer uso de ambos tipos de interrupción.

  Creo que tengo instalada la versión 1.12.... voy a probarlo y te comento.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 01 de Junio de 2013, 17:54:57
  El siguiente código está compilado con la versión 1.12 de XC8 en MPLABX 1.60. Simulándolo en ISIS funciona bien.

  No lo probé en real, así que no sabría decirte si sólo funciona en la simulación o es que funciona por lo simple del programa.

Código: C
  1. #include <xc.h>
  2.  
  3. #pragma config IESO=OFF, FOSC=HS, FCMEN=OFF, CPUDIV=OSC1_PLL2, PLLDIV=1
  4. #pragma config VREGEN=OFF, BOR=OFF, BORV=0, PWRT=OFF, WDT=OFF, WDTPS=4
  5. #pragma config PBADEN=OFF, LPT1OSC=OFF, MCLRE=OFF, DEBUG=OFF, STVREN=OFF
  6. #pragma config LVP=OFF, CPD=OFF, CPB=OFF, USBDIV=1
  7.  
  8. #define _XTAL_FREQ 20000000
  9.  
  10. unsigned char contador;
  11.  
  12. void interrupt alta_prioridad()
  13. {
  14.     if (PIR1bits.TMR1IF == 1)
  15.     {
  16.         contador++;
  17.         if (contador >= 10)
  18.         {
  19.             LATBbits.LB1 = ~LATBbits.LB1;
  20.             contador = 0;
  21.         }
  22.         PIR1bits.TMR1IF = 0;
  23.     }
  24.  
  25. }
  26.  
  27. void interrupt low_priority baja_prioridad()
  28. {
  29.     if (INTCONbits.T0IF == 1)
  30.     {
  31.         LATBbits.LB0 = ~LATBbits.LB0;
  32.         INTCONbits.T0IF = 0;
  33.     }
  34. }
  35.  
  36. void main(void)
  37. {
  38.     const unsigned char palabra[]={5,4,8,6,};
  39.  
  40.     TRISB = 0;
  41.  
  42.     T0CON = 0b00000111;    //configuro timer0
  43.     T1CON = 0b10110000;    //configuro timer1
  44.  
  45.     INTCON2bits.T0IP = 0;  //timer0 baja prioridad
  46.     IPR1bits.TMR1IP = 1;   //timer1 alta prioridad
  47.  
  48.     RCONbits.IPEN = 1;     //habilito interrupcion de alta y baja prioridad
  49.     INTCON = 0b00100000;     //habilito interrupciones y borro flags
  50.     PIR1bits.TMR1IF = 0;   //borro flag timer1
  51.     PIE1bits.TMR1IE = 1;   //habilito interrupcion timer1
  52.  
  53.     T0CONbits.TMR0ON = 1;  //enciendo el timer0
  54.     T1CONbits.TMR1ON = 1;  //enciendo el timer1
  55.     INTCONbits.GIEL = 1;
  56.     INTCONbits.GIEH = 1;
  57.  
  58.     while(1);
  59. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 02 de Junio de 2013, 15:16:28
Puede ser un problema de mi programa, pero no me cuadra.
Estoy pasando un programa de C18 a XC8. En C18 funciona bien, y en XC8 no para de darme problemas.
Por ahora lo voy a seguir desarrollando en C18 y cuando tenga una versión estable preguntaré en el foro las dudas sobre cómo pasarlo a XC8.

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 02 de Junio de 2013, 16:02:14
Hola Picuino. Podrías subir el código o una versión reducida del mismo?
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 02 de Junio de 2013, 16:20:48
Hola jukinch,
Cuando lo tenga terminado en C18 lo subo.

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 02 de Junio de 2013, 19:48:04
La idea era que subas lo que habías echo en xc8 para que podamos ayudarte.  ;-)
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 04 de Junio de 2013, 14:37:48
Aquí dejo una parte del programa que me da problemas en XC8.
En C18 funciona perfectamente. El programa envía por la UART cada segundo el valor contado por el timer1 y sus desbordamientos.
En total es una cuenta de 48bits de longitud. Esa cuenta se pasa a ASCII y se envía.

En XC8, después de unos segundos, el programa se bloquea o se resetea. En otras versiones el micro se resetea. Sospecho que se debe a los punteros, pero no se que puede pasar.

El micro funciona con un xtal externo de 20Mhz. La frecuencia interna a partir del PLL es de 48Mhz.


Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: yamilongiano en 04 de Junio de 2013, 15:17:21
hola a todos como puedo hacer unos retardos  de uS
e encontrado puros retardos en milisegundos. y me gustaria tener los dos tipos de retardos tanto de milisegundos como microsegundos.

Código: [Seleccionar]
#include <xc.h>

#define _XTAL_FREQ 4000000
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

#pragma config FOSC = XT, WDTE = ON, PWRTE = OFF, CP = OFF

void main(void){
    PORTB = 0;
    TRISB = 0;

    while(1){

        PORTBbits.RB1 = 0b1;
        __delay_ms(1);
        PORTBbits.RB1 = 0b0;
        __delay_ms(1);
    }


muchas gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 04 de Junio de 2013, 15:19:27
hola a todos como puedo hacer unos retardos  de uS
e encontrado puros retardos en milisegundos. y me gustaria tener los dos tipos de retardos tanto de milisegundos como microsegundos.

Código: [Seleccionar]
#include <xc.h>

#define _XTAL_FREQ 4000000
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

#pragma config FOSC = XT, WDTE = ON, PWRTE = OFF, CP = OFF

void main(void){
    PORTB = 0;
    TRISB = 0;

    while(1){

        PORTBbits.RB1 = 0b1;
        __delay_ms(1);
        PORTBbits.RB1 = 0b0;
        __delay_ms(1);
    }


muchas gracias.

  Yo suelo utilizar __delay_us() y funciona bien
Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 04 de Junio de 2013, 16:04:40
Aquí dejo una parte del programa que me da problemas en XC8.
En C18 funciona perfectamente. El programa envía por la UART cada segundo el valor contado por el timer1 y sus desbordamientos.
En total es una cuenta de 48bits de longitud. Esa cuenta se pasa a ASCII y se envía.

En XC8, después de unos segundos, el programa se bloquea o se resetea. En otras versiones el micro se resetea. Sospecho que se debe a los punteros, pero no se que puede pasar.

El micro funciona con un xtal externo de 20Mhz. La frecuencia interna a partir del PLL es de 48Mhz.


Saludos.

Estuve revisando el código que subió y note que usa goto dentro de la rutina de interrupción. En XC8 no es necesario usar goto para ir a atender la interrupción el codigo para atender la interrupcion se pone directamente en la funcion void interrupt high_isr(void) o en la funcion void interrupt low_priority low_isr(void)

Yo utilizo las interrupciones en xc8 de la siguiente forma:

Código: [Seleccionar]
void interrupt ISR_HIGH(void)
{
    NOP();

}

void interrupt low_priority ISR_LOW(void)
{
       if(PIR1bits.RC1IF)
        IntRx1();
}


void IntRx1(void)
{
    unsigned char dato;
    if(RCSTA1bits.FERR && !PORTCbits.RC7)
        RESET(); //Si se recibio BREAK reiniciamos para entrar
//al bootloader
    else
        dato = RCREG; //Para procesar otro dato recibido
}


Lo que creo que esta pasando es que usted retorna a su programa desde la funcion void isr(void), entonces el xc8 en lugar de colocar RETFIE coloca RETURN, por eso no se habilitan de nuevo las interrupciones, y como no se  recupera los registros que guardo al ingresar a la interrupcion entoces puede ser que el programa no funcione bien.

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 04 de Junio de 2013, 16:29:41
Genial, Sander  ((:-))
Por eso tenía que habilitar las interrupciones de nuevo.
Muchas gracias y un saludo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: yamilongiano en 04 de Junio de 2013, 18:37:16
1.4. Utilizando PWM

Vamos a utilizar una señal PWM de 8 bits para controlar el brillo de un LED. Para configurar el módulo CCP1 en modo PWM solo basta con escribir 0x0C en el registro CCP1CON.

Frecuencia PWM: el periodo de la onda PWM lo determina el tiempo que dura el conteo del Timer2 desde 0 hasta el valor cargado en el registro PR2. Y como la frecuencia es la inversa del período podemos deducir:

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=40649.0;attach=20531)



Donde:

* PR2 es el valor del registro PR2 (entre 0 y 255)
* FOSC es la frecuencia del cristal utilizado
* Prescaler es el prescaler del Timer2 (1, 4 ó 16). Se configura en el registro T2CON.

Ciclo de trabajo (duty cicle): es la cantidad de tiempo que en un periodo la salida PWM permanece en estado alto. El valor es determinado por el contenido del registro CCPR1L. Podemos deducir el tiempo utilizando la formula:

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=40649.0;attach=20533)



Donde:

* CCPR1L es el valor del registro CCPR1L (entre 0 y 255)
* FOSC es la frecuencia del cristal
* Prescaler   es el prescaler del Timer2 (1, 4 ó 16)

Ejemplo dimerizado de un LED conectado a RB3

Código: C
  1. /*
  2.  * File:   main.c
  3.  * Author: lucas
  4.  * Created on 1 de abril de 2013, 22:20
  5.  * Microcontrolador: PIC16F648A
  6.  *
  7.  * Utilizando PWM para dimerizar un LED
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <xc.h> // Librería XC8
  13.  
  14. #define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro
  15.  
  16. // PIC16F648A Configuration Bit Settings
  17. #pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
  18. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  19. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  20. #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
  21. #pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
  22. #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
  23. #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
  24. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  25.  
  26. // FUNCION PRINCIPAL
  27. void main(void) {
  28.     TRISB = 0;                  // Puerto B como salidas
  29.     PORTB = 0;                  // Limpio el puerto B
  30.  
  31. // CONFIGURANDO PWM  
  32.     CCP1CON = 0b00001100;       // Activamos el modo PWM
  33.     PR2 = 250;                  // Frecuencia 250Hz
  34.     T2CONbits.T2CKPS = 0b10;    // Prescaler del timer 2 en 1:16
  35.     T2CONbits.TMR2ON = 1;       // Arranca el PWM      
  36.  
  37. // BUCLE INFINITO
  38.     unsigned char i;           // Declaramos una variable
  39.     while (1){
  40.     for(i=0; i=50; i++)
  41.     {
  42.       CCPR1L = CCPR1L++;        // Seteando el ciclo de trabajo
  43.       __delay_ms (100);    
  44.     }
  45.     i=0;                       // Reiniciamos la variable para comenzar el ciclo de nuevo
  46.     }
  47.     }

queria preguntar, por que no se como hacerlo, como puedo dejar el el tiempo de encendido del PWM en un estado fijo. que no varie contantemente ya que este PWM esta oscilante y no podemos dejar un T1 y T2 en tiempo fijo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 04 de Junio de 2013, 20:19:08
  yamilongiano, fíjate con atención en el mensaje de lmtreser que justamente indica muy bien que el ciclo de trabajo está dado por CCPR1L. Si el valor asignado a dicho registro se deja fijo, pues el duty cicle no variará.

  En el programa que él da de muestra, el duty varía porque está cargando al registro CCPR1L con un valor variable.
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 07 de Junio de 2013, 00:11:21
BITS DE CONFIGURACION - Generador de código

Mplab X nos brinda una herramienta que nos permite generar el código para el seteo de los bits de configuración del pic seleccionado en nuestro proyecto en forma automática.

Para acceder a la misma seleccionamos desde el menú principal, Windows, Pic Memory Views, Configuration bits.
Como se muestra en la siguiente figura:


(http://imageshack.us/a/img819/1075/configurationbits.png)



En la parte inferior de la pantalla se abrirá la ventana "Configuration Bits".
Ver flecha negra en la siguiente figura:

(http://imageshack.us/a/img854/401/configurationbits2.png)

Hacemos doble click en el título de la ventana para maximizarla.

Allí tendremos todas las opciones disponibles para nuestro pic.

Luego haciendo click en cualquier valor de la columna option (opción) se abrirá un combo para elegir los valores a setear.

(http://imageshack.us/a/img19/8435/configurationbits3.png)

Y por último apretamos el botón que dice Generate Source Code to Output para generar nuestro código en la consola de salida.

Como se ve en la siguiente figura el código ha sido generado en la parte inferior de la pantalla con todos los bits de configuración de nuestro pic. (si no hacemos cambios el código se genera igualmente con todos los valores por defecto del pic)

En este caso para un pic16f84a.

(http://imageshack.us/a/img89/892/configurationbits4g.png)


Una vez que hemos generado el código lo podemos copiar y pegar en nuestro programa como se ve en la siguiente figura:

(http://imageshack.us/a/img607/714/configurationbits5.png)


En la pantalla siguiente se ven a modo de ejemplo los bits de configuración de un pic18F4550

(http://imageshack.us/a/img593/8599/configurationbits6.png)

En esta otra pantalla se ve el código generado para el pic18F4550

(http://imageshack.us/a/img543/82/configurationbits7.png)


Cuando vi por primera vez todas las opciones del 4550 me recordaron el tablero de un helicóptero...

(http://img845.imageshack.us/img845/2794/panelm.jpg)

Espero les sea de utilidad.
  Saludos
            Jukinch

fuente: http://microchip.wikidot.com/mplab:how-to-view-and-set-configuration-bits
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 07 de Junio de 2013, 22:09:33
  Jukinch, muchas gracias por la info... cada vez que hice algo con un 18F4550, me volví chango entre el datasheet, y los docs del compilador.
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 08 de Junio de 2013, 08:00:59
Hola Angelgris. Que bueno poder ayudarte. Y aprovecho para agradecer todas las manos que nos has dado en el foro.
Un abrazo
        Jukinch
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 08 de Junio de 2013, 15:57:06
  Aquí comparto una librería muy básica para usar I2C por software. La simulé en ISIS y pude manejar una 24C04. Ya se me está ocurriendo una modificación de la rutina i2cs_write, para que devuelva un bit para saber si hubo o no ack por parte del dispositivo.
Otra posible modificación es la utilización de los registros LAT en el caso de los PIC que los posean, pero eso se podría hacer en el header... iré haciendo algunas pruebas.
  También podría agregarse alguna función para chequear el estado del bus antes de intentar comenzar una comunicación.

  En el .h hay que definir algunos parámetros para el manejo de la librería y también hay que definir _XTAL_FREQ de acuerdo al valor de frecuencia de oscilación del cristal. En realidad sería la frecuencia de funcionamiento del núcleo del PIC, ya que si se usa un 18F a 48MHz, ese sería el valor para _XTAL_FREQ.

  En la librería se incluyen dos mensajes de error que evitará que el programa compile si no se han definido los pines a utilizar por SDA y SCL o si no se han definidos los registros de dirección (TRIS) de los pines a utilizar.

swi2c.h
Código: C
  1. #ifndef SWI2C_H
  2. #define SWI2C_H
  3.  
  4. #ifndef _XC_H_
  5.   #include <xc.h>
  6. #endif
  7.  
  8. #define _XTAL_FREQ 20000000
  9.  
  10. #define SDAPIN PORTBbits.RB0
  11. #define SCLPIN PORTBbits.RB1
  12. #define SDADIR TRISBbits.TRISB0
  13. #define SCLDIR TRISBbits.TRISB1
  14.  
  15. void i2cs_start(void);
  16. void i2cs_stop(void);
  17. void i2cs_write(unsigned char);
  18. unsigned char i2cs_read(void);
  19. void i2cs_nack(void);
  20. void i2cs_ack(void);
  21.  
  22. #endif  /* SWI2C_H */

swi2c.c
Código: C
  1. #ifndef SWI2C_H
  2.   #include "swi2c.h"
  3. #endif
  4.  
  5. #if !defined(SDAPIN) || !defined(SCLPIN)
  6.   #error Falta definir los pines SDA y SCL
  7. #elif !defined(SDADIR) || !defined(SCLDIR)
  8.   #error Falta definir los registros de direccion
  9. #else
  10. void i2cs_start(void)
  11. {
  12.     SDADIR = 1;
  13.     SCLDIR = 1;
  14.     __delay_us(5);
  15.     SDAPIN = 0;
  16.     SDADIR = 0;
  17.     __delay_us(4);
  18.     SCLPIN = 0;
  19.     SCLDIR = 0;
  20. }
  21.  
  22. void i2cs_stop(void)
  23. {
  24.     SDAPIN = 0;
  25.     SDADIR = 0;
  26.     SCLPIN = 0;
  27.     SCLDIR = 0;
  28.     __delay_us(1);
  29.     SCLDIR = 1;
  30.     __delay_us(5);
  31.     SDADIR = 1;
  32. }
  33.  
  34. void i2cs_write(unsigned char _data)
  35. {
  36.     unsigned char _bits;
  37.  
  38.     __delay_us(5);
  39.     for (_bits = 8; _bits > 0; _bits--)
  40.     {
  41.         if ((_data & 0x80) == 0)
  42.         {
  43.             SDAPIN = 0;
  44.             SDADIR = 0;
  45.         }
  46.         else
  47.             SDADIR = 1;
  48.         _data = _data << 1;
  49.         __delay_us(1);
  50.         SCLDIR = 1;
  51.         __delay_us(4);
  52.         SCLPIN = 0;
  53.         SCLDIR = 0;
  54.         __delay_us(5);
  55.     }
  56.     SDADIR = 1;
  57.     __delay_us(1);
  58.     SCLDIR = 1;
  59.     __delay_us(4);
  60.     SCLPIN = 0;
  61.     SCLDIR = 0;
  62. }
  63.  
  64. unsigned char i2cs_read(void)
  65. {
  66.     unsigned char _data;
  67.     unsigned char _bits;
  68.  
  69.     for (_bits = 8; _bits > 0; _bits--)
  70.     {
  71.         __delay_us(5);
  72.         _data = _data << 1;
  73.         SCLDIR = 1;
  74.         __delay_us(2);
  75.         if (SDAPIN == 1) _data |= 1;
  76.         __delay_us(2);
  77.         SCLPIN = 0;
  78.         SCLDIR = 0;
  79.     }
  80.     return _data;
  81. }
  82.  
  83. void i2cs_nack(void)
  84. {
  85.     __delay_us(5);
  86.     SDADIR = 1;
  87.     __delay_us(1);
  88.     SCLDIR = 1;
  89.     __delay_us(4);
  90.     SCLPIN = 0;
  91.     SCLDIR = 0;
  92.     __delay_us(5);
  93.     SDAPIN = 0;
  94.     SDADIR = 0;
  95. }
  96.  
  97. void i2cs_ack(void)
  98. {
  99.     __delay_us(5);
  100.     SDAPIN = 0;
  101.     SDADIR = 0;
  102.     __delay_us(1);
  103.        SCLDIR = 1;
  104.     __delay_us(4);
  105.     SCLPIN = 0;
  106.     SCLDIR = 0;
  107.     __delay_us(5);
  108.     SDAPIN = 0;
  109.     SDADIR = 0;
  110. }
  111. #endif

Programa de ejemplo. Comunicación entre 16F648A y 24C04
Código: C
  1. #include <xc.h>
  2.  
  3. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
  4. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  5. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  6. #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
  7. #pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
  8. #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
  9. #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
  10. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  11.  
  12.  
  13. #include "swi2c.h"
  14.  
  15.  
  16. void main(void)
  17. {
  18.     unsigned char data;
  19.  
  20.     i2cs_start();            //comienzo comunicacion
  21.     i2cs_write(0b10100001);  //accedo a la memoria para lectura (posicion actual)
  22.     i2cs_read();             //leo la memoria
  23.     i2cs_nack();             //no respondo
  24.     i2cs_stop();             //termino comunicacion
  25.  
  26.     i2cs_start();            //comienzo comunicacion
  27.     i2cs_write(0b10100000);  //accedo a la memoria para escritura
  28.     i2cs_write(0x02);        //direccion que quiero escribir
  29.     i2cs_write(0x05);        //dato a escribir
  30.     i2cs_stop();             //termino comunicacion
  31.  
  32.     __delay_ms(5);           //espero para que se grabe el dato en la memoria
  33.  
  34.     i2cs_start();            //comienzo comunicacion
  35.     i2cs_write(0b10100000);  //accedo a la memoria para escritura
  36.     i2cs_write(0x02);        //direccion que quiero escribir
  37.     i2cs_start();            //comienzo comunicacion (para leer la posicion)
  38.     i2cs_write(0b10100001);  //accedo a la memoria para lectura (posicion actual)
  39.     i2cs_read();             //leo la memoria
  40.     i2cs_nack();             //no respondo
  41.     i2cs_stop();             //termino comunicacion
  42.  
  43.     while(1);
  44. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 09 de Junio de 2013, 03:08:52
CONVERSORES ADC - PWM

En el siguiente ejemplo se utilizan dos potenciómetros para controlar la intensidad de 2 leds por pwm.
Los valores de la conversión de cada canal (de 0 a 1023) se visualizan en un LCD.

Para mostrar en el LCD los valores leídos de los ADC se utiliza la función itoa. La misma convierte un valor entero en cadena de caracteres. En xc8 la función itoa recibe 3 parámetros en vez de 2 como era en c18.

Los nuevos parámetros de itoa    ahora son     (char * buf, int val, int base)


Código: C
  1. /*
  2. Mini curso "Programación en XC8"
  3.  
  4. programa: ejemplo módulo conversor adc
  5.  
  6. pic: 18f4550
  7. Ejemplo XC8 - LCD + Conversor AD + PWM. Uso de la nueva función itoa.
  8.  
  9. HARDWARE: Entrenadora Multiboard Pictrainer 2.0 Felixls
  10. Microcontrolador: pic18f4550
  11. cristal: 20mhz
  12.  
  13. CONEXIONES: Módulo LCD conectado en PUERTO D.
  14. El módulo LCD utilizado en este programa no es el standard de felixls.
  15. Quité el cd4094 y se utiliza el pin de RW
  16.  
  17. bus de datos en el nible alto conector IDC7 (rb 4 a 7)
  18.  
  19. DATA7    PUERTO D.7
  20. DATA6    PUERTO D.6
  21. DATA5    PUERTO D.5
  22. DATA4    PUERTO D.4
  23.  
  24.  
  25. bus de control en el nible bajo conector IDC4 (rb 0 a 3)
  26.  
  27. E_PIN    PUERTO D.3
  28. RS_PIN   PUERTO D.2
  29. RW_PIN   PUERTO D.1
  30.  
  31.  
  32.  
  33. Módulo Analógico conectado en conector IDC 2 (conector idc e0-e3) a P0
  34. POT1=E0
  35. POT2=E1
  36.  
  37.  
  38. Módulo IO digital conectado en conector IDC2
  39.  
  40. led pwm1 conector IDC2 (c0-c3)   EN RC2
  41. led pwm2 conector idc (C0-C3)   EN RC1
  42.  
  43.  
  44. Moviendo los potenciómetros del módulo analógico se controla la intensidad
  45. de 2 leds por pwm y se visualizan en el LCD los valores de 0 a 1023.
  46.  
  47. */
  48.  
  49. #define _XTAL_FREQ 20000000 // Linea necesaria para los cálculos de la función
  50.                            // de delay. CUIDADO. no es para la configuración
  51.                            // de la frecuencia de trabajo del cpu del pic.
  52.                            // eso se determina en otro lado. :)
  53.  
  54.  
  55.  
  56. /*Includes globales*/
  57. #include <xc.h>
  58. #include <pic18.h>
  59. #include <delays.h> /* Para utilizar demoras en nuestro código debemos incluir la librería delays.h.*/
  60. #include <plib/adc.h> // libreria para conversor ADC
  61. #include <plib/timers.h>
  62. #include <plib/pwm.h>
  63. #include <stdlib.h> // librería para poder usar itoa ?
  64.  
  65. /*Includes locales*/
  66. #include "configuracion_de_fuses.c"
  67. #include "xlcd_portd.h" // librería modificada para puerto D. Con dolor de cabeza solucionado. :)
  68.  
  69.  
  70. /*declaración de variables globales*/
  71.  
  72. /*declaración de funciones*/
  73. void myMsDelay(int ms);
  74.  
  75. void DelayFor18TCY(void);
  76. void DelayPORXLCD(void);
  77. void DelayXLCD(void);
  78.  
  79.  
  80. ///////////////////////////////////////////////////////////////////////////////
  81. //                     Programa Principal                                    //
  82. ///////////////////////////////////////////////////////////////////////////////
  83.  
  84.  
  85. void main(void)
  86. {
  87. unsigned int Canal5, Canal6;
  88. char cadena_de_texto[5];
  89.  
  90.  
  91.  
  92. TRISB=0b00000000;      // Puerto B como salidas
  93. LATB=0b00000000;      //todas las salidas abajo
  94.  
  95. TRISC=0b00000000;      // Puerto c como salidas
  96. LATC=0b00000000;      //todas las salidas abajo
  97.  
  98. Delay10KTCYx(255);    //Retardo para esperar que pase cualquier transitorio
  99.  
  100.  
  101.  
  102. OpenXLCD(FOUR_BIT&LINES_5X7);   //inicializamos LCD con varias lineas y caracteres 5x7
  103. WriteCmdXLCD(CURSOR_OFF & BLINK_OFF);
  104. Delay10KTCYx(255);    //Retardo
  105. WriteCmdXLCD(LINE_0); // Nos posicionamos en la posición 0
  106.  
  107. putrsXLCD("MULTIBOARD");
  108. WriteCmdXLCD(NEXT_LINE+3);
  109. myMsDelay(500);
  110. putrsXLCD("PICTRAINER"); //escribe en lcd cadena de texto guardada en rom
  111. myMsDelay(500);
  112. WriteCmdXLCD(0x01);             // Borra pantalla y vuelve al origen.-
  113. putrsXLCD("      XC8       ");
  114. myMsDelay(500);
  115.  
  116. WriteCmdXLCD(0x01);             // Borra pantalla y vuelve al origen.-
  117.  
  118.  
  119.  
  120.  
  121.  
  122. WriteCmdXLCD(0x01);     // Borra pantalla y vuelve al origen.-
  123. while(BusyXLCD()){}
  124. WriteCmdXLCD(0x80); // LINE_0
  125. while(BusyXLCD()){}
  126. putrsXLCD("CONV5 = "); //escribe en lcd cadena de texto guardada en rom
  127. while(BusyXLCD()){}
  128. WriteCmdXLCD(NEXT_LINE);        //NEXT_LINE Nos posicionamos en la posición 8
  129. while(BusyXLCD()){}
  130. putrsXLCD("CONV6 = "); //escribe en lcd cadena de texto guardada en rom
  131.  
  132. while(1)
  133.         {   // rutina de conversión ADC
  134.                 OpenADC(ADC_FOSC_RC & ADC_2_TAD & ADC_RIGHT_JUST, ADC_REF_VDD_VSS & ADC_INT_OFF, ADC_7ANA);
  135.                 SetChanADC(ADC_CH5);    // Selecciono canal a convertir.-
  136.                                 Delay10TCYx(1); // Retardo para que se cargue el  capacitor sample&hold  (Solo cuando se selecciona ADC_0_TAD).-
  137.                                 ConvertADC();           // Comienza conversión.-
  138.                                 while(BusyADC()){}      // Hasta que se finalice conversión.-
  139.                                 Canal5= ReadADC();      // Realizo lectura.-
  140.  
  141.                 SetChanADC(ADC_CH6);    // Selecciono canal a convertir.-
  142.                                 Delay10TCYx(1); // Retardo para que se cargue el  capacitor sample&hold  (Solo cuando se selecciona ADC_0_TAD).-
  143.                                 ConvertADC();           // Comienza conversión.-
  144.                                 while(BusyADC()){}      // Hasta que se finalice conversión.-
  145.                                 Canal6= ReadADC();      // Realizo lectura.-
  146.  
  147.             // escribimos valores leidos en el LCD
  148.                 while(BusyXLCD()){}
  149.                 WriteCmdXLCD(0x87); // Nos posicionamos en la posición 8 de la linea 1
  150.                 while(BusyXLCD()){}
  151.                 putrsXLCD("        "); //escribe en lcd cadena de texto guardada en rom
  152.                 while(BusyXLCD()){}
  153.                 WriteCmdXLCD(0x87); // Nos posicionamos en la posición 0
  154.                
  155.                 itoa( cadena_de_texto, Canal5, 10 ); // Convertimos entero a cadena de texto.-
  156.                                                      // Tener en cuenta que en XC8 la función itoa recibe tres
  157.                                                      // parámetros (char * buf, int val, int base)
  158.  
  159.                 while(BusyXLCD()){}
  160.                 putsXLCD(cadena_de_texto); // escribe en lcd variable canal 5 guardada en ram
  161.  
  162.                 itoa( cadena_de_texto, Canal6, 10 );            // Convertimos entero a cadena de texto.-
  163.                 while(BusyXLCD()){}
  164.                 WriteCmdXLCD(0xC7); // Nos posicionamos en la posición 8
  165.                 while(BusyXLCD()){}
  166.                 putrsXLCD("        ");//escribe en lcd cadena de texto guardada en rom
  167.                 while(BusyXLCD()){}
  168.                 WriteCmdXLCD(0xC7); // Nos posicionamos en la posición 0
  169.                 putsXLCD(cadena_de_texto); // escribe en lcd variable canal 6 guardada en ram
  170.                 while(BusyXLCD()){}
  171.                 WriteCmdXLCD(CURSOR_OFF & BLINK_OFF);
  172.  
  173.                 // rutina cambio de intencidad de leds por PWM
  174.                 OpenTimer2( TIMER_INT_OFF & T2_PS_1_4 & T2_POST_1_8 );
  175.  
  176.                 OpenPWM1(0xff);
  177.                 SetDCPWM1 (Canal6);
  178.  
  179.                 OpenPWM2(0xff);
  180.                 SetDCPWM2 (Canal5);
  181.  
  182.                 Delay10KTCYx(50);    //Retardo para evitar parpadeo en lcd.
  183.  
  184.         } //final del while
  185. } //final de main
  186.  
  187.  
  188. /*desarrollo de Funciones*/
  189. void myMsDelay(int ms)
  190. {
  191.     while(ms--)
  192.     {
  193.         __delay_ms(1);
  194.     }
  195. }
  196.  
  197.  
  198.  
  199. void DelayFor18TCY(void)
  200. {
  201. Delay1KTCYx(1); //provides a 20 Tcy delay
  202. }
  203.  
  204. void DelayPORXLCD(void)
  205.     {
  206.      Delay1KTCYx(180);
  207.     }
  208.  
  209.  
  210. void DelayXLCD(void)
  211. {
  212. Delay1KTCYx(60);
  213. }

(http://img837.imageshack.us/img837/6302/adcg.png)
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 10 de Junio de 2013, 15:40:02
Hola Amigos ....alguno de uds me puede explicar por favor si existe la forma de hacer una funcion que devuelva dos valores ...de este tipo
creo que estas estan escritas en css ...las quiero hacer porsupuesto en xc8


prototipo de la funcion

void bmp085Convert(long *temperature, long *pressure,unsigned char readings);


y para usar en el main asi :

void bmp085Convert(float *temperature, float *pressure)


Muchas gracias

Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 10 de Junio de 2013, 16:01:00
Hola Amigos ....alguno de uds me puede explicar por favor si existe la forma de hacer una funcion que devuelva dos valores ...de este tipo
creo que estas estan escritas en css ...las quiero hacer porsupuesto en xc8


prototipo de la funcion

void bmp085Convert(long *temperature, long *pressure,unsigned char readings);


y para usar en el main asi :

void bmp085Convert(float *temperature, float *pressure)


Muchas gracias



  La llamada a la función tiene que coincidir con el prototipo. Si necesitas llamarla y obtener valores float, debes crearla también con float dentro de los paréntesis.

  Creo que deberías leer un poco más respecto a la creación de funciones. Para refrescar y/o aclarar algunos conceptos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 10 de Junio de 2013, 16:07:00
Hola Amigos ....alguno de uds me puede explicar por favor si existe la forma de hacer una funcion que devuelva dos valores ...de este tipo
creo que estas estan escritas en css ...las quiero hacer porsupuesto en xc8


prototipo de la funcion

void bmp085Convert(long *temperature, long *pressure,unsigned char readings);


y para usar en el main asi :

void bmp085Convert(float *temperature, float *pressure)


Muchas gracias



  La llamada a la función tiene que coincidir con el prototipo. Si necesitas llamarla y obtener valores float, debes crearla también con float dentro de los paréntesis.

  Creo que deberías leer un poco más respecto a la creación de funciones. Para refrescar y/o aclarar algunos conceptos.



Perdon perdon me equivoque ....si es cierto al escribirla aca me equivoque  esta con float y long , pero no es eso lo que buscaba ...me referia a otra cosa

me referia a que esa funcion esta para css y yo quiero usarla en xc8

Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 10 de Junio de 2013, 19:17:34
  Rseliman, efectivamente se puede hacer ya que se le pasarían dos punteros como parámetros de la función y es a través de ellos mismo que el dato es devuelto.

  Aquí hay un ejemplo muy muy muy sencillo de la definición y utilización de una función que devuelve un valor a través del puntero.

Código: C
  1. #include <xc.h>
  2.  
  3. void funcion(long *_variable)
  4. {
  5.     *_variable = 55;  //valor apuntado por _variable
  6. }
  7.  
  8. void main(void)
  9. {
  10.     long *datoptr;
  11.     long dato;
  12.  
  13.     dato = 5;
  14.  
  15.     datoptr = &dato;  //el puntero "datoptr" apunta a la variable dato
  16.  
  17.     funcion (datoptr);
  18.  
  19.     while(1);
  20. }

  La función "funcion" recibe un puntero del tipo "long" en el cual devuelve el valor.

  Primeramente la variable "dato" toma el valor 5. Luego hago que el puntero "datoptr" apunte a "dato". Al ingresar a "funcion", "_variable" apunta a la dirección de "datoptr" y por lo tanto a "dato". Dentro de la función al hacer *_variable = 55 indicamos que el dato apuntado por "_variable" será 55. Por lo tanto el valor de "dato" también sera 55.

  Será cuestión de modificar la función según la necesidad.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 17 de Junio de 2013, 15:40:54
INTERRUPCIONES.

Me surge un problema. Al llamar a una función desde la rutina de interrupciones me da error de compilación:

Código: [Seleccionar]
void interrupt low_priority low_isr(void) {

   // CCP1 interrupt
   if (PIR1bits.CCP1IF == 1) {
      PIR1bits.CCP1IF = 0;
      PIE1bits.CCP1IE = 0;
      timer_read();                      // Esta instrucción da error
      st.timer_read = 1;
   }
}


La función se compila y funciona sin problemas si se la llama fuera de la interrupción.
En el programa actual sólo la llamo desde la rutina de interrupción.
El error que aparece es el siguiente:

Código: [Seleccionar]
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s3m4.; 12522. undefined symbol "?i1_sl48"
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s3m4.; 12614. undefined symbol "??i1_timer_read"
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s3m4.; 12717. undefined symbol "?i1___wmul"
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s3m4.; 12893. undefined symbol "i1___wmul@product"
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s3m4.; 12904. undefined symbol "i1___wmul@multiplier"
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s3m4.; 12913. undefined symbol "i1___wmul@multiplicand"
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s3m4.; 13008. undefined symbol "i1sl48@a"

¿Alguna idea?
Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 17 de Junio de 2013, 19:18:12
  ¿Podrías mostrar tu programa? Aunque sea la parte de los include y tanto la interrupción como la función que te genera problemas.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 18 de Junio de 2013, 14:55:31
El programa es bastante grande, pero he conseguido acotar el problema a unas pocas instrucciones.

Si ejecuto lo siguiente dentro de la rutina de interrupción no me da error:

Código: [Seleccionar]
void interrupt low_priority low_isr(void) {

   // CCP1 interrupt
   if (PIR1bits.CCP1IF == 1) {
      PIR1bits.CCP1IF = 0;

      for(char i=0; i<BUF_LEN; ) {
         time_buf[i++] = time_buf[i];
      }
   }
}


Por el contrario, si lo ejecuto en una función separada, me da error:

Código: [Seleccionar]

void interrupt low_priority low_isr(void) {

   // CCP1 interrupt
   if (PIR1bits.CCP1IF == 1) {
      PIR1bits.CCP1IF = 0;

      fill_buffer();
   }
}


void fill_buffer(void) {
   for(char i=0; i<BUF_LEN; ) {
      time_buf[i++] = time_buf[i];
   }
}

El error es:


Microchip MPLAB XC8 C Compiler V1.12
Copyright (C) 2012 Microchip Technology Inc.
License type: Node Configuration

Advisory[1233] Employing 18F2550 errata work-arounds:
Advisory[1234]  * Corrupted fast interrupt shadow registers
Warning [1273] ; . Omniscient Code Generation not available in Free mode
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s368.; 11618. undefined symbol "??_fill_buffer"
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s368.; 11620. undefined symbol "fill_buffer@i"
(908) exit status = 1

********** Build failed! **********


Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 18 de Junio de 2013, 14:57:58
El buffer que da error al copiar es una estructura de 6 bytes de tamaño:

Código: [Seleccionar]
typedef union {
   unsigned char  byte[6];
   unsigned int   word[3];
   struct {
      unsigned int __word;
      unsigned long dword;
   };
   struct {
      unsigned b0:1;      // LSB
      unsigned b1:1;
      unsigned b2:1;
      unsigned b3:1;
      unsigned b4:1;
      unsigned b5:1;
      unsigned b6:1;
      unsigned b7:1;
      unsigned b8:1;
      unsigned b9:1;
      unsigned b10:1;
      unsigned b11:1;
      unsigned b12:1;
      unsigned b13:1;
      unsigned b14:1;
      unsigned b15:1;
      unsigned b16:1;
      unsigned b17:1;
      unsigned b18:1;
      unsigned b19:1;
      unsigned b20:1;
      unsigned b21:1;
      unsigned b22:1;
      unsigned b23:1;
      unsigned b24:1;
      unsigned b25:1;
      unsigned b26:1;
      unsigned b27:1;
      unsigned b28:1;
      unsigned b29:1;
      unsigned b30:1;
      unsigned b31:1;
      unsigned b32:1;
      unsigned b33:1;
      unsigned b34:1;
      unsigned b35:1;
      unsigned b36:1;
      unsigned b37:1;
      unsigned b38:1;   // MSB
      unsigned b39:1;   // MANTISSA SIGN
      unsigned b40:1;
      unsigned b41:1;
      unsigned b42:1;
      unsigned b43:1;
      unsigned b44:1;
      unsigned b45:1;
      unsigned b46:1;
      unsigned b47:1;
      unsigned b48:1;
   };
} uint48;

uint48 time_buf[BUF_LEN];

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 18 de Junio de 2013, 15:33:46
Hola a todos ...por favor alguien sabe de que se trata este error en xc8 ..

:: warning: Omniscient Code Generation not available in Free mode
C:\Users\Ramiro\AppData\Local\Temp\s4e8.:712: error: undefined symbol "_STATUS"
(908) exit status = 1
make[2]: *** [dist/default/production/Rs232Prueba.X.production.hex] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
make[2]: Leaving directory `C:/Users/Ramiro/pic/pic16f819/Rs232Prueba.X'
make[1]: Leaving directory `C:/Users/Ramiro/pic/pic16f819/Rs232Prueba.X'

BUILD FAILED (exit value 2, total time: 2s)


Muchas gracias Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 18 de Junio de 2013, 22:15:11
El programa es bastante grande, pero he conseguido acotar el problema a unas pocas instrucciones.

Si ejecuto lo siguiente dentro de la rutina de interrupción no me da error:

Código: [Seleccionar]
void interrupt low_priority low_isr(void) {

   // CCP1 interrupt
   if (PIR1bits.CCP1IF == 1) {
      PIR1bits.CCP1IF = 0;

      for(char i=0; i<BUF_LEN; ) {
         time_buf[i++] = time_buf[i];
      }
   }
}


Por el contrario, si lo ejecuto en una función separada, me da error:

Código: [Seleccionar]

void interrupt low_priority low_isr(void) {

   // CCP1 interrupt
   if (PIR1bits.CCP1IF == 1) {
      PIR1bits.CCP1IF = 0;

      fill_buffer();
   }
}


void fill_buffer(void) {
   for(char i=0; i<BUF_LEN; ) {
      time_buf[i++] = time_buf[i];
   }
}

El error es:


Microchip MPLAB XC8 C Compiler V1.12
Copyright (C) 2012 Microchip Technology Inc.
License type: Node Configuration

Advisory[1233] Employing 18F2550 errata work-arounds:
Advisory[1234]  * Corrupted fast interrupt shadow registers
Warning [1273] ; . Omniscient Code Generation not available in Free mode
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s368.; 11618. undefined symbol "??_fill_buffer"
Error   [800] C:\DOCUME~1\Usuario\CONFIG~1\Temp\s368.; 11620. undefined symbol "fill_buffer@i"
(908) exit status = 1

********** Build failed! **********


Saludos.


  ¿Tienes la definición de la función fill_bufer() antes que la interrupción? ¿La variable I, es global? Porque no la veo definida dentro de la función fill_buffer.

  A su vez, los bit de tu buffer deberían ir de 0 a 47 para que sean justo 6 bytes y no de 0 a 48 ya que eso serían 49 bits.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 18 de Junio de 2013, 22:22:28
Hola a todos ...por favor alguien sabe de que se trata este error en xc8 ..

:: warning: Omniscient Code Generation not available in Free mode
C:\Users\Ramiro\AppData\Local\Temp\s4e8.:712: error: undefined symbol "_STATUS"
(908) exit status = 1
make[2]: *** [dist/default/production/Rs232Prueba.X.production.hex] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
make[2]: Leaving directory `C:/Users/Ramiro/pic/pic16f819/Rs232Prueba.X'
make[1]: Leaving directory `C:/Users/Ramiro/pic/pic16f819/Rs232Prueba.X'

BUILD FAILED (exit value 2, total time: 2s)


Muchas gracias Saludos

  Pon tu programa Rseliman.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 19 de Junio de 2013, 04:50:14
  ¿Tienes la definición de la función fill_bufer() antes que la interrupción? ¿La variable I, es global? Porque no la veo definida dentro de la función fill_buffer.

  A su vez, los bit de tu buffer deberían ir de 0 a 47 para que sean justo 6 bytes y no de 0 a 48 ya que eso serían 49 bits.

Declaro fill_buffer() antes de la interrupción (con un fichero *.h) y la defino después.
La variable i es local y la defino como char dentro del bucle for.

Voy a mirar lo de los bits.

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 19 de Junio de 2013, 04:51:46
Tienes razón, me he pasado 1 bit en la definición del tipo uint48  :shock:

Lo cambio ahora mismo.

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 19 de Junio de 2013, 14:32:31
Amigos ..les paso una subrutina que Hizo AngelGris para HiTech ...es una Uart por soft ...estoy intentando hacerla andar en xc8 y la verdad me esta volviendo loco ...el error que tengo aparentemente es un error del xc8 en putch ...por lo que alcanzo a entender ...el error me lo da con el main  en estas lineas

       putst_s ("Hola");   // envia el string "Hola" al puerto serie
       putst_s ("\n");     // envia el salto de linea al puerto serie
       putst_s (pantalla);  // envia el string apuntado por pantalla al puerto serie

Si las saco compila bien ....pero si estan me da este error

:: warning: Omniscient Code Generation not available in Free mode
C:\Users\Ramiro\AppData\Local\Temp\so4g.:714: error: undefined symbol "_STATUS"
(908) exit status = 1
make[2]: Leaving directory `C:/Users/Ramiro/pic/pic16f819/Rs232Prueba.X'
make[1]: Leaving directory `C:/Users/Ramiro/pic/pic16f819/Rs232Prueba.X'
make[2]: *** [dist/default/production/Rs232Prueba.X.production.hex] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

BUILD FAILED (exit value 2, total time: 8s)

el error es un error de link no de linea .....



Les paso el codigo

main.c


Código: [Seleccionar]
#define _XTAL_FREQ 8000000         // esto es de HiTech para los delays    

    #include <stdio.h>
    #include <stdlib.h>
    #include <htc.h>
    #include "uart.c"
  


 void init (void);


     void main ()


     {
      
    OSCCONbits.IRCF2 = 1; //
    OSCCONbits.IRCF1 = 1; // defino oscilador interno en 8 mhz
    OSCCONbits.IRCF0 = 1; //

    TRISAbits.TRISA0 = 0 ;
    TRISAbits.TRISA1 = 1 ;
      
      
    const char *pantalla = "Mundo";


       InitSoftUart;
       putst_s ("Hola");   // envia el string "Hola" al puerto serie
       putst_s ("\n");     // envia el salto de linea al puerto serie
       putst_s (pantalla);  // envia el string apuntado por pantalla al puerto serie

     }

     void init (void)
     {
         ADCON0bits.ADON = 0;  //
    ADCON1bits.PCFG3 = 0; //
    ADCON1bits.PCFG2 = 1; // pongo todas las entradas digitales porta
    ADCON1bits.PCFG1 = 1; //
    ADCON1bits.PCFG0 = 1; //
    ADCON1bits.ADCS2 = 0; //
    
    TRISB =1;
    PORTB =0;
     }
    


uart.c

Código: [Seleccionar]
  /**************************************************************************
    *    Libreria para emular puerto serie asincronico (UART) para HiTech     *
    ***************************************************************************

    ***************************************************************************
    * Con clock de 4MHz la velocidad maxima de transmision es de 38400 Baud   *
    * Con clock de 8MHz en adelante la velocidad minima de transmision es de  *
    * 2400 Baud                                                               *
    ***************************************************************************

    ***************************************************************************
    *                                                                         *
    * Antes de incluir este archivo en nuestro programa hay que definir       *
    * algunos parametros. Estos son                                           *
    *                                                                         *
    * PIC_CLK   (es necesario para los delay usados internamente)             *
    *                                                                         *
    * TxPin     (puerto de salida)                                            *
    * RxPin     (puerto de entrada)                                           *
    * BaudRate  (velocidad de transferencia)                                  *
    *                                                                         *
    ***************************************************************************

    ***************************************************************************
    *                                                                         *
    * Las rutinas de delay se encuentran en el archivo "delayhd.h"            *
    * El nombre original del archivo es:                                      *
    * "delay_alternative_enchanced_precision.h" y esta incluido dentro de     *
    * "PIC_Hi-Tech_C_delay_and_timeout_routines_for_PIC16xxxx_v7-1.zip"       *
    * Bajado de www.microchipc.com                                            *
    *                                                                         *
    * Hay que tener este archivo dentro de la carpeta de trabajo.             *
    *                                                                         *
    *  Si se quiere transmitir, el pin que se utilice como TX tiene que       *
    * configurarse como salida.                                               *
    *  Si se quiere recibir, el pin que se utilice como RX tiene que          *
    * configurarse como entrada.                                              *
    *                                                                         *
    ***************************************************************************

    ***************************************************************************
    *                                                                         *
    * En esta libreria se encuentran las siguientes funciones                 *
    *                                                                         *
    * InitSoftUart()                (inicializa el puerto serie)              *
    * char getch_s()                (lee un byte del puerto serie)            *
    * putch_s(char)                 (envia un byte al puerto serie)           *
    * putst_s(char*)                (envia un string al puerto serie)         *
    * char * getst_s(char*)         (lee una cadena que termine con '\r')     *
    *                                                                         *
    *  El parametro de la funcion anterior puede ser un puntero a un String   *
    * o el propio String                                                      *
    *                                                                         *
    ***************************************************************************

    * Ejemplo de configuracion y utilizacion

     #define PIC_CLK 10000000
     #define TxPin RA0
     #define RxPin RB1
     #define BaudRate 9600

     #include "SoftUart.c"

     void main (void)
     {
       const char * pantalla = "Mundo";

       .....
       .....
       .....
       TRISA0 = 0;
       TRISB1 = 1;
       InitSoftUart();
       Putst_s ("Hola");   // envia el string "Hola" al puerto serie
       Putst_s ("\n");     // envia el salto de linea al puerto serie
       Putst_s (pantalla)  // envia el string apuntado por pantalla al puerto serie

     }

    */
#include <htc.h>
#include "delayhd.h"



/*******************funcionrd prototipos*************************/

//void InitSoftUart(void);
 unsigned char getch_s();
 unsigned char getch_s();
 extern void putch_s (unsigned char data);
 void putst_s (const char *word);
 char * getst_s (char * st);



    #define TxPin PORTAbits.RA0
    #define RxPin PORTAbits.RA1
    #define BaudRate 9600

  
    
    


#if defined (PIC_CLK) && defined (BaudRate) && defined (TxPin) && defined (RxPin)

     #if (PIC_CLK < 16000000)
       #define BitDelay (1000000/BaudRate)
       #define HalfBitDelay (500000/BaudRate)
     #else
       #define BitDelay (500000/BaudRate)
       #define HalfBitDelay (250000/BaudRate)
     #endif

     #if (PIC_CLK == 4000000)
       #define DelayReceivebit DelayUs(BitDelay-7)\
    DelayUs(HalfBitDelay-7)
       #if (BaudRate <= 19200)
         #define DelayStartBit DelayUs(BitDelay-7)
         #define DelaySendBit NDelayUs(BitDelay-18)
       #elif (BaudRate == 28800)
         #define DelayStartBit DelayUs(BitDelay-6)
         #define DelaySendBit NDelayUs(BitDelay-18)
       #elif (BaudRate == 38400)
         #define DelayStartBit DelayUs(BitDelay-7)\
    dly2u
         #define DelaySendBit DelayUs(BitDelay-19)\
      dly1u
       #endif

     #elif (PIC_CLK == 8000000)
       #define DelayReceivebit DelayUs(BitDelay-7)\
    DelayUs(HalfBitDelay-2)
       #define DelayStartBit DelayUs(BitDelay-4)
       #if (BaudRate <= 38400)
         #define DelaySendBit NDelayUs(BitDelay-10)
       #else  //(BaudRate == 57600)
         #define DelaySendBit NDelayUs(BitDelay-9)
    #endif

     #elif (PIC_CLK == 10000000)
       #define DelayReceivebit DelayUs(BitDelay-7)\
      DelayUs(HalfBitDelay)
       #if (BaudRate <= 38400)
         #define DelayStartBit DelayUs(BitDelay-4)
         #define DelaySendBit NDelayUs(BitDelay-8)
       #else //(BaudRate == 57600)
         #define DelayStartBit DelayUs(BitDelay-3)
         #define DelaySendBit NDelayUs(BitDelay-7)
    #endif

     #elif (PIC_CLK == 16000000) || (PIC_CLK == 20000000)
       #if (PIC_CLK == 16000000)
         #define DelayReceivebit DelayUs(BitDelay)\
     DelayUs(BitDelay)\
     DelayUs(BitDelay-5)
       #else //(PIC_CLK == 20000000)
         #define DelayReceivebit DelayUs(BitDelay)\
     DelayUs(BitDelay)\
     DelayUs(BitDelay-4)
       #endif
    #if (BaudRate <= 38400)
         #define DelayStartBit DelayUs(BitDelay)\
    DelayUs(BitDelay-2)
         #define DelaySendBit NDelayUs(BitDelay)\
      NDelayUs(BitDelay-4)
       #else //(BaudRate == 57600)
         #define DelayStartBit DelayUs(BitDelay)\
    DelayUs(BitDelay-1)
         #define DelaySendBit NDelayUs(BitDelay)\
      NDelayUs(BitDelay-3)
       #endif
     #endif

    /*
    void InitSoftUart(void)
    {
     TxPin = 1;
    }
    */
    #else
    #error Faltan definir parametros
    #endif
    


 #define InitSoftUart TxPin = 1


unsigned char getch_s(void)
 {
   unsigned char contador = 7;
   unsigned char letra = 0;

   while (RxPin == 1);
   DelayReceivebit;
   do
   {
     if (RxPin == 1) letra += 128;
     letra = letra >> 1;
     contador--;
     DelaySendBit;
   }
   while (contador > 0);
   DelaySendBit;
   return letra;
 }

 void putch_s (unsigned char data)
 {
   unsigned char contador = 8;

   TxPin = 0;
   DelayStartBit;
   do
   {
     TxPin = data;
     DelaySendBit;
     data = data >> 1;
     contador--;
   }
   while (contador > 0);
   TxPin = 1;
   DelayStartBit;   //tiempo de espera del bit de stop
 }

 void putst_s (const char *word)
 {
   while (*word != 0)
   {
     putch_s(*word);
     word++;
   }
 }

 char * getst_s (char * st)
 {
   char * st1;
   char caracter;

   st1 = st;
   do
   {
     caracter = getch_s();
     if (caracter != '\r')
     {
       *st1 = caracter;
       st1++;
     }
     *st1 = '\0';
   }
   while (caracter != '\r');
   return st;
 }

delayhd.h

Código: [Seleccionar]
/*

lowlevel delay routines

Designed by Shane Tolmie of www.microchipC.com corporation.  Freely distributable.
Questions and comments to webmaster@microchipC.com.

Completely re-written by Matthew Swabey and Paul Hoy of Southampton University, July 2005.
Questions and comments to mas@ecs.soton.ac.uk

Freely distributable, as above. Please add any other clock frequencies you want.

This uses no memory resources, and is precise.

Hi-Tech C and

Example C:

#define PIC_CLK 8000000
#include "delay.h"

void main(void)
{
TRISC = 0x00;
while(1)
{
PORTC = 0x00;
DelayUs(x);
PORTC = 0xFF;
}
}

*/

//#include "delay.h"
#define PIC_CLK 8000000



#ifndef __DELAY_H
#define __DELAY_H

#if (PIC_CLK == 4000000)
#define dly125n please remove; for 32Mhz+ only
#define dly250n please remove; for 16Mhz+ only
#define dly500n please remove; for 8Mhz+ only
#define dly1u asm("nop")
#define dly2u dly1u;dly1u
#elif (PIC_CLK == 8000000)
#define dly125n please remove; for 32Mhz+ only
#define dly250n please remove; for 16Mhz+ only
#define dly500n asm("nop")
#define dly1u dly500n;dly500n
#define dly2u dly1u;dly1u
#elif (PIC_CLK == 10000000)
#define dly400n asm("nop")
#elif (PIC_CLK == 16000000)
#define dly125n please remove; for 32Mhz+ only
#define dly250n asm("nop")
#define dly500n dly250n;dly250n
#define dly1u dly500n;dly500n
#define dly2u dly1u;dly1u
#elif (PIC_CLK == 20000000)
#define dly200n asm("nop")
#define dly400n dly200n;dly200n
#define dly1u dly400n;dly400n;dly200n
#define dly2u dly1u;dly1u
#elif (PIC_CLK == 32000000)
#define dly125n asm("nop")
#define dly250n dly125n;dly125n
#define dly500n dly250n;dly250n
#define dly1u dly500n;dly500n
#define dly2u dly1u;dly1u
#else
#error please define PIC_CLK correctly

#endif

/* ======================================== */
/* Delay Routines for less than 255us       */
/* These give a precise delay.              */
/* DelayUs(10) is 10us exactly!             */
/* Only multiples of 2 available at slower  */
/* speeds (16Mhz or less) */

#if PIC_CLK == 4000000
#define DelayUs(x)\
asm("\tMOVLW "___mkstr(x>>2));\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 2");
#elif PIC_CLK == 8000000
#define DelayUs(x)\
asm("\tMOVLW "___mkstr(x>>1));\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 2");
#elif PIC_CLK == 10000000
#define DelayUs(x)\
asm("\tMOVLW "___mkstr(x>>1));\
asm("\tNOP");\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 3");
#elif PIC_CLK == 16000000
#define DelayUs(x)\
asm("\tMOVLW "___mkstr(x));\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 2");
#elif PIC_CLK == 20000000
#define DelayUs(x)\
asm("\tMOVLW "___mkstr(x));\
asm("\tNOP");\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 3");
#elif PIC_CLK == 32000000
#define DelayUs(x)\
asm("\tMOVLW "___mkstr(x));\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 6");
#else
#error please define PIC_CLK correctly
#endif

/* ======================================== */
/* NDelay Routines for less than 255us      */
/* These give a precise delay to the Next   */
/* Instructions ACTIVATION, so NDelayUs(10) */
/* is 10us - 1 instruction!                 */

#if PIC_CLK == 4000000
#define NDelayUs(x)\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tMOVLW "___mkstr((x>>2)-1) );\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 2");
#elif PIC_CLK == 8000000
#define NDelayUs(x)\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tMOVLW "___mkstr((x>>1)-1) );\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 2");
#elif PIC_CLK == 10000000
#define NDelayUs(x)\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tMOVLW "___mkstr((x>>1)-1) );\
asm("\tNOP");\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 3");
#elif PIC_CLK == 16000000
#define NDelayUs(x)\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tMOVLW "___mkstr(x-1));\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 2");
#elif PIC_CLK == 20000000
#define NDelayUs(x)\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tMOVLW "___mkstr(x-1));\
asm("\tNOP");\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 3");
#elif PIC_CLK == 32000000
#define NDelayUs(x)\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tMOVLW "___mkstr(x-1));\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tNOP");\
asm("\tADDLW 0xFF");\
asm("\tBTFSS _STATUS, 2");\
asm("\tGOTO $ - 6");
#else
#error please define PIC_CLK correctly
#endif

#endif

bits de configuracion

Código: [Seleccionar]
// PIC16F819 Configuration Bit Settings

#include <xc.h>

// CONFIG
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTRC oscillator; CLKO function on RA6/OSC2/CLKO pin and port I/O function on RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2      // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)





Muchas gracias a todos

Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 20 de Junio de 2013, 17:15:09
  Aquí dejo una librería en para manejo de UART por SoftWare
  Hay que tener en cuenta que no todas las velocidades de comunicación serán posibles en todas las frecuencias de trabajo del microcontrolador. Por ejemplo, con 4MHz no se puede comunicar a una velocidad mayor a 19200
  En el header de la librería están definidos los tiempos y hay una "especie de compensación" según la frecuencia a la que esté trabajando.

  Lo simulé en ISIS con un 16F876A y va bien.

swuart.h
Código: C
  1. #ifndef SWUART_H
  2. #define SWUART_H
  3.  
  4. #ifndef _XC_H_
  5. #include <xc.h>
  6. #endif
  7.  
  8.  
  9. /*******************************************************************************
  10. *  Parametros configurables por el usuario                                     *
  11. *******************************************************************************/
  12.  
  13. /*
  14.  * El valor de _XTAL_FREQ debe coincidir con el valor definido
  15.  * en el programa principal
  16.  */
  17.  
  18. /*
  19.  * En el caso que solo se desee transmitir se debe definir TXONLY
  20.  * En el caso que solo se desee recibir se debe definir RXONLY
  21.  * En el caso de querer transmitir y recibir se debe definir TXRX
  22.  */
  23.  
  24. #ifndef _XTAL_FREQ
  25. #define _XTAL_FREQ 4000000
  26. #endif
  27.  
  28. #define TXPIN PORTBbits.RB0
  29. #define RXPIN PORTBbits.RB1
  30. #define TXDIR TRISBbits.TRISB0
  31. #define RXDIR TRISBbits.TRISB1
  32.  
  33. #define SWUARTBAUD 19200
  34. #define TXRX
  35.  
  36.  
  37. /*******************************************************************************
  38. *  Parametros internos para los tiempos de cada bit                            *
  39. *******************************************************************************/
  40.  
  41. #define _BitOutDelay (1000000UL/SWUARTBAUD)
  42. #define StartDelay (1500000UL/SWUARTBAUD)
  43.  
  44. #if (_XTAL_FREQ <= 4000000)
  45. #define BitOutDelay (_BitOutDelay - 24)
  46. #define BitInDelay (_BitOutDelay - 24)
  47. #elif (_XTAL_FREQ <= 6000000) && (_XTAL_FREQ > 4000000)
  48. #define BitOutDelay (_BitOutDelay - 16)
  49. #define BitInDelay (_BitOutDelay - 16)
  50. #elif (_XTAL_FREQ <= 8000000) && (_XTAL_FREQ > 6000000)
  51. #define BitOutDelay (_BitOutDelay - 12)
  52. #define BitInDelay (_BitOutDelay -12)
  53. #elif (_XTAL_FREQ <= 10000000) && (_XTAL_FREQ > 8000000)
  54. #define BitOutDelay (_BitOutDelay - 10)
  55. #define BitInDelay (_BitOutDelay -9)
  56. #elif (_XTAL_FREQ <= 12000000) && (_XTAL_FREQ > 10000000)
  57. #define BitOutDelay (_BitOutDelay - 8)
  58. #define BitInDelay (_BitOutDelay - 7)
  59. #elif (_XTAL_FREQ <= 16000000) && (_XTAL_FREQ > 12000000)
  60. #define BitOutDelay (_BitOutDelay - 6)
  61. #define BitInDelay (_BitOutDelay - 5)
  62. #elif (_XTAL_FREQ <= 20000000) && (_XTAL_FREQ > 16000000)
  63. #define BitOutDelay (_BitOutDelay - 5)
  64. #define BitInDelay (_BitOutDelay - 4)
  65. #elif (_XTAL_FREQ <= 26000000) && (_XTAL_FREQ > 20000000)
  66. #define BitOutDelay (_BitOutDelay - 3)
  67. #define BitInDelay (_BitOutDelay - 3)
  68. #elif (_XTAL_FREQ <= 48000000) && (_XTAL_FREQ > 26000000)
  69. #define BitOutDelay (_BitOutDelay - 2)
  70. #define BitInDelay (_BitOutDelay - 2)
  71. #endif
  72.  
  73.  
  74. /*******************************************************************************
  75. *  Definicion de funciones                                                     *
  76. *******************************************************************************/
  77.  
  78. /*
  79.  * La funcion swgets recibe una cadena que termine con '\r' (decimal 13)
  80.  * la cadena es devuelta a travez del puntero que se le pasa como parametro
  81.  */
  82.  
  83. void swinit_uart(void);
  84. void swputch(unsigned char);
  85. void swputs(unsigned char *);
  86. unsigned char swgetch(void);
  87. void swgets(unsigned char *);
  88.  
  89. #endif  /* SWUART_H */

swuart.c
Código: C
  1. #ifndef SWUART_H
  2. #include "swuart.h"
  3. #endif
  4.  
  5. #if !defined(TXPIN) || !defined(RXPIN) || !defined(TXDIR) || !defined(RXDIR)
  6. #error No estan definidos los pines
  7. #else
  8. #ifndef SWUARTBAUD
  9. #error Falta definir la velocidad
  10. #endif
  11.  
  12. void swinit_uart(void)
  13. {
  14. #if defined TXONLY
  15.     TXDIR = 0;
  16. #elif defined RXONLY
  17.     RXDIR = 1;
  18. #elif defined TXRX
  19.     TXDIR = 0;
  20.     RXDIR = 1;
  21. #endif
  22. }
  23.  
  24. void swputch(unsigned char _data)
  25. {
  26.     unsigned char _bits = 8;
  27.  
  28.     TXPIN = 0;
  29.     __delay_us(BitOutDelay);
  30.     do
  31.     {
  32.         TXPIN = _data & 1;
  33.         __delay_us(BitOutDelay);
  34.         _data = _data >> 1;
  35.         _bits--;
  36.     }
  37.     while (_bits > 0);
  38.     TXPIN = 1;
  39.     __delay_us(_BitOutDelay);
  40. }
  41.  
  42. void swputs(unsigned char *_st)
  43. {
  44.     while (*_st != 0)
  45.     {
  46.         swputch(*_st);
  47.         _st++;
  48.     }
  49. }
  50.  
  51. unsigned char swgetch(void)
  52. {
  53.     unsigned char _datain = 0;
  54.     unsigned char _bits = 8;
  55.  
  56.     while (RXPIN == 1);
  57.     __delay_us(StartDelay);
  58.     do
  59.     {
  60.         _datain = _datain >> 1;
  61.         if (RXPIN == 1) _datain |= 0b10000000;
  62.         __delay_us(BitInDelay);
  63.         _bits--;
  64.     }
  65.     while (_bits > 0);
  66.     __delay_us(BitOutDelay/2);
  67.     return _datain;
  68. }
  69.  
  70.  void swgets(unsigned char *st)
  71. {
  72.     unsigned char *word;
  73.     unsigned char character;
  74.  
  75.     word = st;
  76.     do
  77.     {
  78.         character = swgetch();
  79.         if (character != '\r')
  80.         {
  81.             *word = character;
  82.             word++;
  83.         }
  84.     }
  85.     while (character != '\r');
  86.     *word = 0;
  87. }
  88. #endif

Programa Ejemplo
Código: C
  1. #include <xc.h>
  2.  
  3. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
  4. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  5. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  6. #pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
  7. #pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
  8. #pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
  9. #pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
  10. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  11.  
  12.  
  13.  
  14. //#define _XTAL_FREQ 26000000
  15. #include "swuart.h"
  16.  
  17. void main(void)
  18. {
  19.     unsigned char mensaje[10] = "TodoPic";
  20.     unsigned char *punterostring;
  21.     unsigned char caracter;
  22.  
  23.     punterostring = mensaje;
  24.     caracter = 'a';
  25.     swinit_uart();           //inicialiso el UART
  26.     swputch('H');
  27.     swputch('o');
  28.     swputch('l');
  29.     swputch(caracter);       //mando la palabra Hola letra por letra
  30.     swputch('\r');           //salto de linea
  31.     swputs(mensaje);         //mando la cadena almacenada en mensaje
  32.     swputch('\r');           //salto de linea
  33.     swgets(punterostring);   //recibo una cadena terminada con '\r'
  34.     swputch('\r');           //salto de linea
  35.     swputs(punterostring);   //mando la cadena apuntada por punterostring
  36.                              //(recibida anteriormente)
  37.  
  38.     while(1);
  39. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: gab163 en 21 de Junio de 2013, 01:22:52
Les queria compartir otra libreria para manejo de lcd en modo control cuatro bits. Les cuelgo un codigo main y la libreria flex_lcd. El programa esta para funcionar con un PIC16f887 pero facilmente puede funcionar con cualquier otro:

main:
Código: [Seleccionar]
#include <xc.h>
#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
#define _XTAL_FREQ 8000000
#include "flex_lcd.h"

// CONFIG1
#pragma config FOSC = INTRC_CLKOUT// Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = ON       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Reset Selection bits (BOR enabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)

// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)

void main(void)
{
unsigned char i, j;
unsigned char buffer1[20];

ANSEL=0;
ANSELH=0;
Lcd_Init();
Lcd_Cmd(LCD_CLEAR);
Lcd_Cmd(LCD_CURSOR_OFF);
__delay_ms(100);

for(i=10; i>0; i--)
{
//sprintf(buffer1,"%3d",i);      //Right aligned text
sprintf(buffer1,"Cuenta %03d",i);   //Right aligned text and adding zeros if necessary
//sprintf(buffer1,"%d   ",i);  //Left  aligned text
Lcd_Out2(1, 1, buffer1);
__delay_ms(100);
}
Lcd_Out(2, 1, "Gabriel");
__delay_ms(600);
Lcd_Cmd(LCD_BLINK_CURSOR_ON);
__delay_ms(1000);
Lcd_Cmd(LCD_BLINK_CURSOR_ON);
Lcd_Cmd(LCD_UNDERLINE_ON);
__delay_ms(1000);
Lcd_Cmd(LCD_CURSOR_OFF);
__delay_ms(1000);
Lcd_Cmd(LCD_CLEAR);
Lcd_Out(1, 4, "Gracias");
Lcd_Out(2, 4, "Thank u");
while(1);
}

lcd_flex.h
Código: [Seleccionar]
//******************************************
//  Libreria para control de LCD           *

//#define LCD_RD7     PORTBbits.RB7       // D7
#define LCD_RD7     LATDbits.LATD7       // D7
//#define TRISRD7     TRISBbits.TRISB7
#define TRISRD7     TRISDbits.TRISD7
//#define LCD_RD6     PORTBbits.RB6       // D6
#define LCD_RD6     LATDbits.LATD6       // D6
//#define TRISRD6     TRISBbits.TRISB6
#define TRISRD6     TRISDbits.TRISD6
//#define LCD_RD5     PORTBbits.RB5       // D5
#define LCD_RD5     LATDbits.LATD5       // D5
//#define TRISRD5     TRISBbits.TRISB5
#define TRISRD5     TRISDbits.TRISD5
//#define LCD_RD4     PORTBbits.RB4       // D4
#define LCD_RD4     LATDbits.LATD4       // D4
//#define TRISRD4     TRISBbits.TRISB4
#define TRISRD4     TRISDbits.TRISD4
//#define LCD_EN      PORTBbits.RB3       // EN
#define LCD_EN      LATEbits.LATE2       // EN
//#define TRISEN      TRISBbits.TRISB3
#define TRISEN      TRISEbits.TRISE2
//#define LCD_RS      PORTBbits.RB2       // RS
#define LCD_RS      LATEbits.LATE1       // RS
//#define TRISRS      TRISBbits.TRISB2
#define TRISRS      TRISEbits.TRISE1

//comandos disponibles
#define      LCD_FIRST_ROW           128
#define      LCD_SECOND_ROW          192
#define      LCD_THIRD_ROW           148
#define      LCD_FOURTH_ROW          212
#define      LCD_CLEAR               1
#define      LCD_RETURN_HOME         2
#define      LCD_CURSOR_OFF          12
#define      LCD_UNDERLINE_ON        14
#define      LCD_BLINK_CURSOR_ON     15
#define      LCD_MOVE_CURSOR_LEFT    16
#define      LCD_MOVE_CURSOR_RIGHT   20
#define      LCD_TURN_OFF            0
#define      LCD_TURN_ON             8
#define      LCD_SHIFT_LEFT          24
#define      LCD_SHIFT_RIGHT         28


void Lcd_Init(void);
void Lcd_Out(unsigned char y, unsigned char x, const char *buffer);
void Lcd_Out2(unsigned char y, unsigned char x, char *buffer);
void Lcd_Chr_CP(char data);
void Lcd_Cmd(unsigned char data);

void Lcd_Init(void){
unsigned char data;
TRISRD7 = 0;
TRISRD6 = 0;
TRISRD5 = 0;
TRISRD4 = 0;
TRISEN = 0;
TRISRS = 0;
LCD_RD7 = 0;
LCD_RD6 = 0;
LCD_RD5 = 0;
LCD_RD4 = 0;
LCD_EN = 0;
LCD_RS = 0;
__delay_us(5500);
__delay_us(5500);
__delay_us(5500);
__delay_us(5500);
__delay_us(5500);
__delay_us(5500);
for(data = 1; data < 4; data ++)
{
    LCD_RD7 = 0;    LCD_RD6 = 0;    LCD_RD5 = 1;    LCD_RD4 = 1;    LCD_EN = 0;
    LCD_RS = 0;    LCD_RD7 = 0;    LCD_RD6 = 0;    LCD_RD5 = 1;    LCD_RD4 = 1;
    LCD_EN = 1;    LCD_RS = 0;
    __delay_us(5);
    LCD_RD7 = 0;    LCD_RD6 = 0;    LCD_RD5 = 1;    LCD_RD4 = 1;    LCD_EN = 0;
    LCD_RS = 0;
    __delay_us(5500);
}
LCD_RD7 = 0; LCD_RD6 = 0; LCD_RD5 = 1; LCD_RD4 = 0; LCD_EN = 0; LCD_RS = 0;
LCD_RD7 = 0; LCD_RD6 = 0; LCD_RD5 = 1; LCD_RD4 = 0; LCD_EN = 1; LCD_RS = 0;
__delay_us(5);
LCD_RD7 = 0; LCD_RD6 = 0; LCD_RD5 = 1; LCD_RD4 = 0; LCD_EN = 0; LCD_RS = 0;
__delay_us(5500);
data = 40; Lcd_Cmd(data);
data = 16; Lcd_Cmd(data);
data = 1;  Lcd_Cmd(data);
data = 15; Lcd_Cmd(data);
}


void Lcd_Out(unsigned char y, unsigned char x, const char *buffer)
{
unsigned char data;
switch (y)
{   
    case 1: data = 128 + x; break;
    case 2: data = 192 + x; break;
    case 3: data = 148 + x; break;
    case 4: data = 212 + x; break;
    default: break;
}
Lcd_Cmd(data);
while(*buffer)              // Write data to LCD up to null
{               
    Lcd_Chr_CP(*buffer);
    buffer++;               // Increment buffer
}
return;
}


void Lcd_Out2(unsigned char y, unsigned char x, char *buffer)
{
unsigned char data;
switch (y)
{
    case 1: data = 128 + x; break;
    case 2: data = 192 + x; break;
    case 3: data = 148 + x; break;
    case 4: data = 212 + x; break;
    default: break;
}
Lcd_Cmd(data);
while(*buffer)              // Write data to LCD up to null
{               
    Lcd_Chr_CP(*buffer);
    buffer++;               // Increment buffer
}
return;
}


void Lcd_Chr_CP(char data){
LCD_EN = 0; LCD_RS = 1;
LCD_RD7 = (data & 0b10000000)>>7; LCD_RD6 = (data & 0b01000000)>>6;
LCD_RD5 = (data & 0b00100000)>>5; LCD_RD4 = (data & 0b00010000)>>4;
_delay(10);
LCD_EN = 1; __delay_us(5); LCD_EN = 0;
LCD_RD7 = (data & 0b00001000)>>3; LCD_RD6 = (data & 0b00000100)>>2;
LCD_RD5 = (data & 0b00000010)>>1; LCD_RD4 = (data & 0b00000001);
_delay(10);
LCD_EN = 1; __delay_us(5); LCD_EN = 0;
__delay_us(5); __delay_us(5500);
}


void Lcd_Cmd(unsigned char data){
LCD_EN = 0; LCD_RS = 0;
LCD_RD7 = (data & 0b10000000)>>7; LCD_RD6 = (data & 0b01000000)>>6;
LCD_RD5 = (data & 0b00100000)>>5; LCD_RD4 = (data & 0b00010000)>>4;
_delay(10);
LCD_EN = 1; __delay_us(5); LCD_EN = 0;
LCD_RD7 = (data & 0b00001000)>>3; LCD_RD6 = (data & 0b00000100)>>2;
LCD_RD5 = (data & 0b00000010)>>1; LCD_RD4 = (data & 0b00000001);
_delay(10);
LCD_EN = 1; __delay_us(5); LCD_EN = 0;
__delay_us(5500);//Delay_5us();
}
#endif
Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 21 de Junio de 2013, 11:04:44
Hola Rseliman,

He probado tu libreria de LCD tal y como la subistes y me da este error:
Código: [Seleccionar]
lcd_pic16.c:145: warning: function declared implicit int
lcd_pic16.c:150: warning: function declared implicit int
lcd_pic16.c:192: error: undefined identifier "PORTB"
lcd_pic16.c:193: error: undefined identifier "TRISB"
lcd_pic16.c:199: error: undefined identifier "TRISBbits"
lcd_pic16.c:199: error: struct/union required
lcd_pic16.c:200: error: struct/union required
lcd_pic16.c:201: error: struct/union required
lcd_pic16.c:202: error: undefined identifier "PORTBbits"
lcd_pic16.c:202: error: struct/union required
lcd_pic16.c:203: error: struct/union required
lcd_pic16.c:204: error: struct/union required
lcd_pic16.c:278: error: undefined identifier "TRISB"
lcd_pic16.c:279: error: undefined identifier "PORTB"
lcd_pic16.c:286: error: undefined identifier "PORTBbits"
lcd_pic16.c:286: error: struct/union required
lcd_pic16.c:287: error: struct/union required
lcd_pic16.c:289: error: struct/union required
lcd_pic16.c:291: error: struct/union required
lcd_pic16.c:300: error: struct/union required
lcd_pic16.c:302: error: struct/union required
lcd_pic16.c:336: error: undefined identifier "TRISB"
lcd_pic16.c:337: error: undefined identifier "PORTB"
lcd_pic16.c:337: advisory: too many errors (21)

Es como si no los #define no hicieran su trabajo ¿Puede que sea alguna configuracion del MPLABX?
Gracias.

Edito: Con la libreria del compañero gab163 me da el mismo error..
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 21 de Junio de 2013, 11:41:46
Hola Rseliman,

He probado tu libreria de LCD tal y como la subistes y me da este error:
Código: [Seleccionar]
lcd_pic16.c:145: warning: function declared implicit int
lcd_pic16.c:150: warning: function declared implicit int
lcd_pic16.c:192: error: undefined identifier "PORTB"
lcd_pic16.c:193: error: undefined identifier "TRISB"
lcd_pic16.c:199: error: undefined identifier "TRISBbits"
lcd_pic16.c:199: error: struct/union required
lcd_pic16.c:200: error: struct/union required
lcd_pic16.c:201: error: struct/union required
lcd_pic16.c:202: error: undefined identifier "PORTBbits"
lcd_pic16.c:202: error: struct/union required
lcd_pic16.c:203: error: struct/union required
lcd_pic16.c:204: error: struct/union required
lcd_pic16.c:278: error: undefined identifier "TRISB"
lcd_pic16.c:279: error: undefined identifier "PORTB"
lcd_pic16.c:286: error: undefined identifier "PORTBbits"
lcd_pic16.c:286: error: struct/union required
lcd_pic16.c:287: error: struct/union required
lcd_pic16.c:289: error: struct/union required
lcd_pic16.c:291: error: struct/union required
lcd_pic16.c:300: error: struct/union required
lcd_pic16.c:302: error: struct/union required
lcd_pic16.c:336: error: undefined identifier "TRISB"
lcd_pic16.c:337: error: undefined identifier "PORTB"
lcd_pic16.c:337: advisory: too many errors (21)

Es como si no los #define no hicieran su trabajo ¿Puede que sea alguna configuracion del MPLABX?
Gracias.

Edito: Con la libreria del compañero gab163 me da el mismo error..

Pon tu programa, Limbo
Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 21 de Junio de 2013, 12:24:29
Es identico al de Rseliman..
main.c
Código: [Seleccionar]
#include <xc.h>
#define _XTAL_FREQ 8000000
#include <stdio.h>
#include <stdlib.h>
#include "lcd_pic16.c"
#include "delay.h"

// PIC16F819 Configuration Bit Setting
// CONFIG
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTRC oscillator; CLKO function on RA6/OSC2/CLKO pin and port I/O function on RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF      // Low-Voltage Programming Enable bit (RB3/PGM pin has PGM function, Low-Voltage Programming enabled)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2      // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// CONFIG2
//#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable




//variables globales
unsigned char buffer [14];
// unsigned int contador=0;
//funciones prototipo
void init(void);


void main(void)
{

   OSCCONbits.IRCF2 = 1; //
   OSCCONbits.IRCF1 = 1; // defino oscilador interno en 4 mhz
   OSCCONbits.IRCF0 = 0; //


init();


           
SetDDRamAddr(0x00);
putrsXLCD("Ramiro Seliman");
                putsXLCD(buffer);
                SetDDRamAddr(0x40);
putrsXLCD("Victoria E.R");
        }

void init(void)
{
    ADCON0bits.ADON = 0;

    TRISB=0;    //todo el PORTB como salidas digitales
    PORTB=0;
    OpenXLCD(FOUR_BIT & LINES_5X7 );


}

lcd_pic16.c
Código: [Seleccionar]
* For 8-bit operation uncomment the #define BIT8
 */
// #define BIT8

/* When in 4-bit interface define if the data is in the upper
 * or lower nibble.  For lower nibble, comment the #define UPPER
 */


#define UPPER

/* When in 6-10-bit interface comment the #define BUSY_LCD and conected PIN
 * R/W to GND in LCD
 */
 //#define BUSY_LCD

/* DATA_PORT defines the port to which the LCD data lines are connected */
 #define DATA_PORT      PORTB
 #define TRIS_DATA_PORT TRISB

/* CTRL_PORT defines the port where the control lines are connected.
 * These are just samples, change to match your application.
 */
 #define RW_PIN   PORTBbits.RB0    /* PORT for RW */
 #define TRIS_RW  TRISBbits.TRISB0    /* TRIS for RW */

 #define RS_PIN   PORTBbits.RB1    /* PORT for RS */
 #define TRIS_RS  TRISBbits.TRISB1    /* TRIS for RS */

 #define E_PIN    PORTBbits.RB2  /* PORT for D  */
 #define TRIS_E   TRISBbits.TRISB2    /* TRIS for E  */

/* Display ON/OFF Control defines */
#define DON         0b00001111  /* Display on      */
#define DOFF        0b00001011  /* Display off     */
#define CURSOR_ON   0b00001111  /* Cursor on       */
#define CURSOR_OFF  0b00001101  /* Cursor off      */
#define BLINK_ON    0b00001111  /* Cursor Blink    */
#define BLINK_OFF   0b00001110  /* Cursor No Blink */

/* Cursor or Display Shift defines */
#define SHIFT_CUR_LEFT    0b00000100  /* Cursor shifts to the left   */
#define SHIFT_CUR_RIGHT   0b00000101  /* Cursor shifts to the right  */
#define SHIFT_DISP_LEFT   0b00000110  /* Display shifts to the left  */
#define SHIFT_DISP_RIGHT  0b00000111  /* Display shifts to the right */

/* Function Set defines */
#define FOUR_BIT   0b00101100  /* 4-bit Interface               */
#define EIGHT_BIT  0b00111100  /* 8-bit Interface               */
#define LINE_5X7   0b00110000  /* 5x7 characters, single line   */
#define LINE_5X10  0b00110100  /* 5x10 characters               */
#define LINES_5X7  0b00111000  /* 5x7 characters, multiple line */

#ifdef _OMNI_CODE_
#define PARAM_SCLASS
#else
#define PARAM_SCLASS auto
#endif

/* CLS_Line2
 * Clear Screen Line 2
 */
void CLS_Line2(void);

/* CLS_Line1
 * Clear Screen Line 1
 */
void CLS_Line1(void);
/* OpenXLCD
 * Configures I/O pins for external LCD
 */
void OpenXLCD(PARAM_SCLASS unsigned char);

/* SetCGRamAddr
 * Sets the character generator address
 */
void SetCGRamAddr(PARAM_SCLASS unsigned char);

/* SetDDRamAddr
 * Sets the display data address
 */
void SetDDRamAddr(PARAM_SCLASS unsigned char);

/* BusyXLCD
 * Returns the busy status of the LCD
 */
unsigned char BusyXLCD(void);

/* ReadAddrXLCD
 * Reads the current address
 */
unsigned char ReadAddrXLCD(void);

/* ReadDataXLCD
 * Reads a byte of data
 */
char ReadDataXLCD(void);

/* WriteCmdXLCD
 * Writes a command to the LCD
 */
void WriteCmdXLCD(PARAM_SCLASS unsigned char);

/* WriteDataXLCD
 * Writes a data byte to the LCD
 */
void WriteDataXLCD(PARAM_SCLASS char);

/* putcXLCD
 * A putc is a write
 */
#define putcXLCD WriteDataXLCD

/* putsXLCD
 * Writes a string of characters to the LCD
 */
void putsXLCD(PARAM_SCLASS char *);

/* putrsXLCD
 * Writes a string of characters in  to the LCD
 */
void putrsXLCD(const char *);

// Rutinas de tiempo auxiliares para la libreria XLCD
void DelayFor18TCY(void)
{
__delay_us(18);
}

void DelayPORXLCD(void)
{
__delay_ms(20); //Delay de 15 ms
}

void DelayXLCD(void)
{
__delay_ms(20); //Delay de 20 ms
}

void CLS_Line2(void)
{
    SetDDRamAddr(0x40);
    putrsXLCD("                ");
}

void CLS_Line1(void)
{
    SetDDRamAddr(0x00);
    putrsXLCD("                ");
}
/********************************************************************
*       Function Name:  OpenXLCD                                    *
*       Return Value:   void                                        *
*       Parameters:     lcdtype: sets the type of LCD (lines)       *
*       Description:    This routine configures the LCD. Based on   *
*                       the Hitachi HD44780 LCD controller. The     *
*                       routine will configure the I/O pins of the  *
*                       microcontroller, setup the LCD for 4- or    *
*                       8-bit mode and clear the display. The user  *
*                       must provide three delay routines:          *
*                       DelayFor18TCY() provides a 18 Tcy delay     *
*                       DelayPORXLCD() provides at least 15ms delay *
*                       DelayXLCD() provides at least 5ms delay     *
********************************************************************/
void OpenXLCD(unsigned char lcdtype)
{
        // The data bits must be either a 8-bit port or the upper or
        // lower 4-bits of a port. These pins are made into inputs
#ifdef BIT8                             // 8-bit mode, use whole port
        DATA_PORT = 0;
        TRIS_DATA_PORT = 0x00;
#else                                   // 4-bit mode
#ifdef UPPER                            // Upper 4-bits of the port
        DATA_PORT &= 0x0f;
        TRIS_DATA_PORT &= 0x0F;
#else                                   // Lower 4-bits of the port
        DATA_PORT &= 0xf0;
        TRIS_DATA_PORT &= 0xF0;
#endif
#endif
        TRIS_RW = 0;                    // All control signals made outputs
        TRIS_RS = 0;
        TRIS_E = 0;
        RW_PIN = 0;                     // R/W pin made low
        RS_PIN = 0;                     // Register select pin made low
        E_PIN = 0;                      // Clock pin made low

        // Delay for 15ms to allow for LCD Power on reset
        DelayPORXLCD();
 //-------------------reset procedure through software----------------------       
WriteCmdXLCD(0x30);
__delay_ms(5);

WriteCmdXLCD(0x30);
__delay_ms(1);


WriteCmdXLCD(0x32);
while( BusyXLCD() );
//------------------------------------------------------------------------------------------


        // Set data interface width, # lines, font
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(lcdtype);          // Function set cmd

        // Turn the display on then off
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(DOFF&CURSOR_OFF&BLINK_OFF);        // Display OFF/Blink OFF
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(DON&CURSOR_ON&BLINK_ON);           // Display ON/Blink ON

        // Clear display
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(0x01);             // Clear display

        // Set entry mode inc, no shift
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(SHIFT_CUR_RIGHT);   // Entry Mode
 
while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(0x06);    // Incremente
 
        while(BusyXLCD());              // Wait if LCD busy
        SetDDRamAddr(0x80);             // Set Display data ram address to 0
       
        while(BusyXLCD());              // Wait if LCD busy
        WriteCmdXLCD(CURSOR_OFF);       // Cursor OFF
        return;
}


/********************************************************************
*       Function Name:  WriteDataXLCD                               *
*       Return Value:   void                                        *
*       Parameters:     data: data byte to be written to LCD        *
*       Description:    This routine writes a data byte to the      *
*                       Hitachi HD44780 LCD controller. The user    *
*                       must check to see if the LCD controller is  *
*                       busy before calling this routine. The data  *
*                       is written to the character generator RAM or*
*                       the display data RAM depending on what the  *
*                       previous SetxxRamAddr routine was called.   *
********************************************************************/
void WriteDataXLCD(char data)
{
#ifdef BIT8                             // 8-bit interface
        TRIS_DATA_PORT = 0;             // Make port output
        DATA_PORT = data;               // Write data to port
        RS_PIN = 1;                     // Set control bits
        RW_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock data into LCD
        DelayFor18TCY();
        E_PIN = 0;
        RS_PIN = 0;                     // Reset control bits
        TRIS_DATA_PORT = 0xff;          // Make port input
#else                                   // 4-bit interface
#ifdef UPPER                            // Upper nibble interface
        TRIS_DATA_PORT &= 0x0f;
        DATA_PORT &= 0x0f;
        DATA_PORT |= data&0xf0;
#else                                   // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;
        DATA_PORT &= 0xf0;
        DATA_PORT |= ((data>>4)&0x0f);
#endif
        RS_PIN = 1;                     // Set control bits
        RW_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock nibble into LCD
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Upper nibble interface
        DATA_PORT &= 0x0f;
        DATA_PORT |= ((data<<4)&0xf0);
#else                                   // Lower nibble interface
        DATA_PORT &= 0xf0;
        DATA_PORT |= (data&0x0f);
#endif
        DelayFor18TCY();
        E_PIN = 1;                      // Clock nibble into LCD
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Upper nibble interface
        TRIS_DATA_PORT |= 0xf0;
#else                                   // Lower nibble interface
        TRIS_DATA_PORT |= 0x0f;
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  WriteCmdXLCD                                *
*       Return Value:   void                                        *
*       Parameters:     cmd: command to send to LCD                 *
*       Description:    This routine writes a command to the Hitachi*
*                       HD44780 LCD controller. The user must check *
*                       to see if the LCD controller is busy before *
*                       calling this routine.                       *
********************************************************************/
void WriteCmdXLCD(unsigned char cmd)
{
#ifdef BIT8                             // 8-bit interface
        TRIS_DATA_PORT = 0;             // Data port output
        DATA_PORT = cmd;                // Write command to data port
        RW_PIN = 0;                     // Set the control signals
        RS_PIN = 0;                     // for sending a command
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the command in
        DelayFor18TCY();
        E_PIN = 0;
        DelayFor18TCY();
        TRIS_DATA_PORT = 0xff;          // Data port input
#else                                   // 4-bit interface
#ifdef UPPER                            // Upper nibble interface
        TRIS_DATA_PORT &= 0x0f;
        DATA_PORT &= 0x0f;
        DATA_PORT |= cmd&0xf0;
#else                                   // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;
        DATA_PORT &= 0xf0;
        DATA_PORT |= (cmd>>4)&0x0f;
#endif
        RW_PIN = 0;                     // Set control signals for command
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock command in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Upper nibble interface
        DATA_PORT &= 0x0f;
        DATA_PORT |= (cmd<<4)&0xf0;
#else                                   // Lower nibble interface
        DATA_PORT &= 0xf0;
        DATA_PORT |= cmd&0x0f;
#endif
        DelayFor18TCY();
        E_PIN = 1;                      // Clock command in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                            // Make data nibble input
        TRIS_DATA_PORT |= 0xf0;
#else
        TRIS_DATA_PORT |= 0x0f;
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  SetDDRamAddr                                *
*       Return Value:   void                                        *
*       Parameters:     CGaddr: display data address                *
*       Description:    This routine sets the display data address  *
*                       of the Hitachi HD44780 LCD controller. The  *
*                       user must check to see if the LCD controller*
*                       is busy before calling this routine.        *
********************************************************************/
void SetDDRamAddr(unsigned char DDaddr)
{
#ifdef BIT8                                     // 8-bit interface
        TRIS_DATA_PORT = 0;                     // Make port output
        DATA_PORT = DDaddr | 0b10000000;        // Write cmd and address to port
        RW_PIN = 0;                             // Set the control bits
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock the cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
        DelayFor18TCY();
        TRIS_DATA_PORT = 0xff;                  // Make port input
#else                                           // 4-bit interface
#ifdef UPPER                                    // Upper nibble  interface
        TRIS_DATA_PORT &= 0x0f;                 // Make port output
        DATA_PORT &= 0x0f;                      // and write upper nibble
        DATA_PORT |= ((DDaddr | 0b10000000) & 0xf0);
#else                                           // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;                 // Make port output
        DATA_PORT &= 0xf0;                      // and write upper nibble
        DATA_PORT |= (((DDaddr | 0b10000000)>>4) & 0x0f);
#endif
        RW_PIN = 0;                             // Set control bits
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock the cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        DATA_PORT &= 0x0f;                      // Write lower nibble
        DATA_PORT |= ((DDaddr<<4)&0xf0);
#else                                           // Lower nibble interface
        DATA_PORT &= 0xf0;                      // Write lower nibble
        DATA_PORT |= (DDaddr&0x0f);
#endif
        DelayFor18TCY();
        E_PIN = 1;                              // Clock the cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        TRIS_DATA_PORT |= 0xf0;                 // Make port input
#else                                           // Lower nibble interface
        TRIS_DATA_PORT |= 0x0f;                 // Make port input
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  SetCGRamAddr                                *
*       Return Value:   void                                        *
*       Parameters:     CGaddr: character generator ram address     *
*       Description:    This routine sets the character generator   *
*                       address of the Hitachi HD44780 LCD          *
*                       controller. The user must check to see if   *
*                       the LCD controller is busy before calling   *
*                       this routine.                               *
********************************************************************/
void SetCGRamAddr(unsigned char CGaddr)
{
#ifdef BIT8                                     // 8-bit interface
        TRIS_DATA_PORT = 0;                     // Make data port ouput
        DATA_PORT = CGaddr | 0b01000000;        // Write cmd and address to port
        RW_PIN = 0;                             // Set control signals
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
        DelayFor18TCY();
        TRIS_DATA_PORT = 0xff;                  // Make data port inputs
#else                                           // 4-bit interface
#ifdef UPPER                                    // Upper nibble interface
        TRIS_DATA_PORT &= 0x0f;                 // Make nibble input
        DATA_PORT &= 0x0f;                      // and write upper nibble
        DATA_PORT |= ((CGaddr | 0b01000000) & 0xf0);
#else                                           // Lower nibble interface
        TRIS_DATA_PORT &= 0xf0;                 // Make nibble input
        DATA_PORT &= 0xf0;                      // and write upper nibble
        DATA_PORT |= (((CGaddr |0b01000000)>>4) & 0x0f);
#endif
        RW_PIN = 0;                             // Set control signals
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                              // Clock cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        DATA_PORT &= 0x0f;                      // Write lower nibble
        DATA_PORT |= ((CGaddr<<4)&0xf0);
#else                                           // Lower nibble interface
        DATA_PORT &= 0xf0;                      // Write lower nibble
        DATA_PORT |= (CGaddr&0x0f);
#endif
        DelayFor18TCY();
        E_PIN = 1;                              // Clock cmd and address in
        DelayFor18TCY();
        E_PIN = 0;
#ifdef UPPER                                    // Upper nibble interface
        TRIS_DATA_PORT |= 0xf0;                 // Make inputs
#else                                           // Lower nibble interface
        TRIS_DATA_PORT |= 0x0f;                 // Make inputs
#endif
#endif
        return;
}

/********************************************************************
*       Function Name:  ReadDataXLCD                                *
*       Return Value:   char: data byte from LCD controller         *
*       Parameters:     void                                        *
*       Description:    This routine reads a data byte from the     *
*                       Hitachi HD44780 LCD controller. The user    *
*                       must check to see if the LCD controller is  *
*                       busy before calling this routine. The data  *
*                       is read from the character generator RAM or *
*                       the display data RAM depending on what the  *
*                       previous SetxxRamAddr routine was called.   *
********************************************************************/
char ReadDataXLCD(void)
{
        char data;

#ifdef BIT8                             // 8-bit interface
        RS_PIN = 1;                     // Set the control bits
        RW_PIN = 1;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the data out of the LCD
        DelayFor18TCY();
        data = DATA_PORT;               // Read the data
        E_PIN = 0;
        RS_PIN = 0;                     // Reset the control bits
        RW_PIN = 0;
#else                                   // 4-bit interface
        RW_PIN = 1;
        RS_PIN = 1;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the data out of the LCD
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data = DATA_PORT&0xf0;          // Read the upper nibble of data
#else                                   // Lower nibble interface
        data = (DATA_PORT<<4)&0xf0;     // read the upper nibble of data
#endif
        E_PIN = 0;                      // Reset the clock line
        DelayFor18TCY();
        E_PIN = 1;                      // Clock the next nibble out of the LCD
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data |= (DATA_PORT>>4)&0x0f;    // Read the lower nibble of data
#else                                   // Lower nibble interface
        data |= DATA_PORT&0x0f;         // Read the lower nibble of data
#endif
        E_PIN = 0;                                     
        RS_PIN = 0;                     // Reset the control bits
        RW_PIN = 0;
#endif
        return(data);                   // Return the data byte
}

/*********************************************************************
*       Function Name:  ReadAddrXLCD                                 *
*       Return Value:   char: address from LCD controller            *
*       Parameters:     void                                         *
*       Description:    This routine reads an address byte from the  *
*                       Hitachi HD44780 LCD controller. The user     *
*                       must check to see if the LCD controller is   *
*                       busy before calling this routine. The address*
*                       is read from the character generator RAM or  *
*                       the display data RAM depending on what the   *
*                       previous SetxxRamAddr routine was called.    *
*********************************************************************/
unsigned char ReadAddrXLCD(void)
{
        char data;                      // Holds the data retrieved from the LCD

#ifdef BIT8                             // 8-bit interface
        RW_PIN = 1;                     // Set control bits for the read
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock data out of the LCD controller
        DelayFor18TCY();
        data = DATA_PORT;               // Save the data in the register
        E_PIN = 0;
        RW_PIN = 0;                     // Reset the control bits
#else                                   // 4-bit interface
        RW_PIN = 1;                     // Set control bits for the read
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock data out of the LCD controller
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data = DATA_PORT&0xf0;          // Read the nibble into the upper nibble of data
#else                                   // Lower nibble interface
        data = (DATA_PORT<<4)&0xf0;     // Read the nibble into the upper nibble of data
#endif
        E_PIN = 0;                      // Reset the clock
        DelayFor18TCY();
        E_PIN = 1;                      // Clock out the lower nibble
        DelayFor18TCY();
#ifdef UPPER                            // Upper nibble interface
        data |= (DATA_PORT>>4)&0x0f;    // Read the nibble into the lower nibble of data
#else                                   // Lower nibble interface
        data |= DATA_PORT&0x0f;         // Read the nibble into the lower nibble of data
#endif
        E_PIN = 0;
        RW_PIN = 0;                     // Reset the control lines
#endif
        return (data&0x7f);             // Return the address, Mask off the busy bit
}

/********************************************************************
*       Function Name:  putsXLCD
*       Return Value:   void
*       Parameters:     buffer: pointer to string
*       Description:    This routine writes a string of bytes to the
*                       Hitachi HD44780 LCD controller. The user
*                       must check to see if the LCD controller is
*                       busy before calling this routine. The data
*                       is written to the character generator RAM or
*                       the display data RAM depending on what the
*                       previous SetxxRamAddr routine was called.
********************************************************************/
void putsXLCD(char *buffer)
{
        while(*buffer)                  // Write data to LCD up to null
        {
                while(BusyXLCD());      // Wait while LCD is busy
                WriteDataXLCD(*buffer); // Write character to LCD
                buffer++;               // Increment buffer
        }
        return;
}

/********************************************************************
*       Function Name:  putrsXLCD
*       Return Value:   void
*       Parameters:     buffer: pointer to string
*       Description:    This routine writes a string of bytes to the
*                       Hitachi HD44780 LCD controller. The user
*                       must check to see if the LCD controller is
*                       busy before calling this routine. The data
*                       is written to the character generator RAM or
*                       the display data RAM depending on what the
*                       previous SetxxRamAddr routine was called.
********************************************************************/
void putrsXLCD(const  char *buffer)
{
        while(*buffer)                  // Write data to LCD up to null
        {
                while(BusyXLCD());      // Wait while LCD is busy
                WriteDataXLCD(*buffer); // Write character to LCD
                buffer++;               // Increment buffer
        }
        return;
}

/********************************************************************
*       Function Name:  BusyXLCD                                    *
*       Return Value:   char: busy status of LCD controller         *
*       Parameters:     void                                        *
*       Description:    This routine reads the busy status of the   *
*                       Hitachi HD44780 LCD controller.             *
********************************************************************/
unsigned char BusyXLCD(void)
{
#ifdef BUSY_LCD
        RW_PIN = 1;                     // Set the control bits for read
        RS_PIN = 0;
        DelayFor18TCY();
        E_PIN = 1;                      // Clock in the command
        DelayFor18TCY();
#ifdef BIT8                             // 8-bit interface
        if(DATA_PORT&0x80)                      // Read bit 7 (busy bit)
        {                               // If high
                E_PIN = 0;              // Reset clock line
                RW_PIN = 0;             // Reset control line
                return 1;               // Return TRUE
        }
        else                            // Bit 7 low
        {
                E_PIN = 0;              // Reset clock line
                RW_PIN = 0;             // Reset control line
                return 0;               // Return FALSE
        }
#else                                   // 4-bit interface
#ifdef UPPER                            // Upper nibble interface
        if(DATA_PORT&0x80)
#else                                   // Lower nibble interface
        if(DATA_PORT&0x08)
#endif
        {
                E_PIN = 0;              // Reset clock line
                DelayFor18TCY();
                E_PIN = 1;              // Clock out other nibble
                DelayFor18TCY();
                E_PIN = 0;
                RW_PIN = 0;             // Reset control line
                return 1;               // Return TRUE
        }
        else                            // Busy bit is low
        {
                E_PIN = 0;              // Reset clock line
                DelayFor18TCY();
                E_PIN = 1;              // Clock out other nibble
                DelayFor18TCY();
                E_PIN = 0;
                RW_PIN = 0;             // Reset control line
                return 0;               // Return FALSE
        }
#endif
#else
        __delay_ms(5);
        return 0;
#endif

}

Ese codigo me da todo este churro de errores:
Código: [Seleccionar]
lcd_pic_16.c:127: warning: function declared implicit int
lcd_pic_16.c:132: warning: function declared implicit int
lcd_pic_16.c:174: error: undefined identifier "PORTB"
lcd_pic_16.c:175: error: undefined identifier "TRISB"
lcd_pic_16.c:181: error: undefined identifier "TRISBbits"
lcd_pic_16.c:181: error: struct/union required
lcd_pic_16.c:182: error: struct/union required
lcd_pic_16.c:183: error: struct/union required
lcd_pic_16.c:184: error: undefined identifier "PORTBbits"
lcd_pic_16.c:184: error: struct/union required
lcd_pic_16.c:185: error: struct/union required
lcd_pic_16.c:186: error: struct/union required
lcd_pic_16.c:260: error: undefined identifier "TRISB"
lcd_pic_16.c:261: error: undefined identifier "PORTB"
lcd_pic_16.c:268: error: undefined identifier "PORTBbits"
lcd_pic_16.c:268: error: struct/union required
lcd_pic_16.c:269: error: struct/union required
lcd_pic_16.c:271: error: struct/union required
lcd_pic_16.c:273: error: struct/union required
lcd_pic_16.c:282: error: struct/union required
lcd_pic_16.c:284: error: struct/union required
lcd_pic_16.c:318: error: undefined identifier "TRISB"
lcd_pic_16.c:319: error: undefined identifier "PORTB"
lcd_pic_16.c:319: advisory: too many errors (21)
Título: Re: Mini curso "Programación en XC8"
Publicado por: gab163 en 21 de Junio de 2013, 13:49:06
Que versión tienes de xc8? Limbo
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 21 de Junio de 2013, 14:00:46
Limbo :

Fijate que yo pase el zippara que lo bajes y habras directamente con mplabx ...y tambien para la simulacion con proteus ...

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 21 de Junio de 2013, 14:09:45
Citar
Que versión tienes de xc8? Limbo)
xc8 v1.12

Citar
Fijate que yo pase el zippara que lo bajes y habras directamente con mplabx ...y tambien para la simulacion con proteus ...
Ya ya, tus archivos no me compilan tampoco.. por eso creo que es algo del compilador pero no logro descubrir que es..
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 21 de Junio de 2013, 18:23:30
Citar
Que versión tienes de xc8? Limbo)
xc8 v1.12

Citar
Fijate que yo pase el zippara que lo bajes y habras directamente con mplabx ...y tambien para la simulacion con proteus ...
Ya ya, tus archivos no me compilan tampoco.. por eso creo que es algo del compilador pero no logro descubrir que es..

  Prueba incluir delay.h antes de incluir la librería del LCD
Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 21 de Junio de 2013, 19:23:16
Citar
  Prueba incluir delay.h antes de incluir la librería del LCD
Ya probe todo eso, porque sé que hay liso aveces con el orden de las librerias, pero nada, lo he vuelto a probar lo que dices y nada.

Creo que avanzo, la libreria la he cambiado de lcd_pic16.c a lcd_pic16.h y solo me salta este error ahora sin tocar nada mas:

Código: [Seleccionar]
:: warning: Omniscient Code Generation not available in Free mode
:0: error: undefined symbols:
        _WriteCmdXLCD(dist/default/production\pru18.X.production.obj) _putrsXLCD(dist/default/production\pru18.X.production.obj) _OpenXLCD(dist/default/production\pru18.X.production.obj) _BusyXLCD(dist/default/production\pru18.X.production.obj)
(908) exit status = 1
Solo he cambiado la extension de la libreria y me da este error... ¿Alguna sugerencia?¿Porque al cambiar la extension em da solo un error?
Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 21 de Junio de 2013, 20:06:25
Solucionaaaaaadooooo :-/ :-/ :-/ :mrgreen: :mrgreen: :mrgreen: ((:-)) ((:-)) ((:-)) jajajaja Que corra el ron! jaja 2 dias dandole vueltas... Ha dado la casualidad de que esta tarde estaba probando cosas y he dejado en el proyecto añadido una libreria de otra prueba, que pasa, que modificaba la que no era, cuando me he puesto esta noche jaja El error de arriba me lo saba por eso.. Pero lo mas curioso es que si incluyo la libreria como lcd_pic16.c da error de compilacion, pero si la incluyo como lcd_pic16.h, walá, compila perfecto..
Claro, yo lo puse como .c porque asi venia en el zip que nos dejo el compañero Rseliman, aunque supuestamente hay gente que le funciono con .c ¿Alguien sabe porque? Si es archivo header lo toma de diferente modo, ¿se autoincluye alguna libreria o algo? No lo entiendo..

Una cosa, el LCD me parpadea como si fuera un bucle pero no hay bucle.. esta constantemente escribiendo, es coorecto?

Gracias!!
P.D: Espero que el teclado no me de tanto quebradero jaja  :mrgreen:
Título: Re: Mini curso "Programación en XC8"
Publicado por: gab163 en 21 de Junio de 2013, 20:42:52
Si no dejas un tiempo entre escritura estará actualizando tan rápido que parecería estar parpadeando intenta poner un delay y prueba
Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 21 de Junio de 2013, 21:00:21
Citar
Si no dejas un tiempo entre escritura estará actualizando tan rápido que parecería estar parpadeando intenta poner un delay y prueba
No, no, digo que el programa se repite indefinidamente sin haber bucle en ningun sitio..
Si pongo un bucle while al final del main. me muestra elemnsaje sin parpadeo porque solo lo escribe una vez, me explic?Es un bucle infinito del programa entero.. Hay alguna configuracion del pic o del mplab que haga esto sin necesidad de un bucle?
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 21 de Junio de 2013, 21:12:22
Las extensiones h se usan para los header, o sea para las definicion de las funciones por ejemplo


1.h

void prueba(void); //defino la funcion prueba


1.c

#include 1.h

  void prueba(int)   // funcion prueba , devuelve c
  {
int a  ;
int b  ;
int c ;


c= a + b ;

return  ;
  }


main.c

#include 1.c

while (1)

{
int d;

d = prueba() ;  // d es igual al valor calculado en prueba

}


espero haber ayudado y que este bien ...tambien estoy aprendiendo ....


Saludos



Ahhhh otra cosa ...si estas usando Mplabx ....en el arbol que aparece al costado del IDE ...no definas las funcines en souce ni en header ....solamente el main en source ....me explico ???

yo particularmente en souce defino un archivo como configuration_bits.c que es donde estan todos los pragma de definicion de fuses del pic ...que el mplabx los da en foema manual ...es muy facil hacerlo


Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 22 de Junio de 2013, 09:20:16
Citar
Si no dejas un tiempo entre escritura estará actualizando tan rápido que parecería estar parpadeando intenta poner un delay y prueba
No, no, digo que el programa se repite indefinidamente sin haber bucle en ningun sitio..
Si pongo un bucle while al final del main. me muestra elemnsaje sin parpadeo porque solo lo escribe una vez, me explic?Es un bucle infinito del programa entero.. Hay alguna configuracion del pic o del mplab que haga esto sin necesidad de un bucle?

Si tu programa es un bucle infinito en sí mimos

Código: C
  1. voidmain(void)
  2. {
  3.   while(1)
  4.   {
  5.     .....
  6.     .....
  7.     .....
  8.     escritura en lcd
  9.     ......
  10.     ......
  11.   }
  12. }

  Debes asegurarte que entre escritura y escritura haya un delay... o mejor aún, escribir en el LCD únicamente cuando sea necesario. Si estás mostrando algún dato, sólo escribir en el LCD si el dato cambio de valor.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 22 de Junio de 2013, 10:16:21
Citar
Si tu programa es un bucle infinito en sí mimos
Mi programa no es un bucle que yo defina,¿ o quieres decir que TODO programa en mplabx es un bucle? Yo siempre, tanto en C como en asembler hacia un bucle infinito para que el programa no se acabara, sino no se veia el resultado del programa, me explico?
Citar
Las extensiones h se usan para los header, o sea para las definicion de las funciones por ejemplo
Ya ya, pero esa no es la cuestion, la cuestion es porque me funciona con la extension .h y con la .c no..
Citar
Ahhhh otra cosa ...si estas usando Mplabx ....en el arbol que aparece al costado del IDE ...no definas las funcines en souce ni en header ....solamente el main en source ....me explico ???
mmmm que ocurre sino hago eso? Tengo añadidos el archivo main y el archivo de libreria en source... ¿Donde añado las librerias sino?
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 22 de Junio de 2013, 12:43:30

mmmm que ocurre sino hago eso? Tengo añadidos el archivo main y el archivo de libreria en source... ¿Donde añado las librerias sino?

[/quote]

Saca el archivo de la libreria en source ...ahi solamente pone el main.c  y si queres hacer mas legible el main ...separa los pragma en un archivo diferente ...configuratiob_bits.c ...que ese si lo agregas en el source junto con el main ....desp las librerias las agregas con los #include al rpincipio del main ...ahi te puese un ejemplo ....en el main.c al principio pones #include la libreria.c ...y al principio de la lñibreria pones el #include libreria.h que es donde estan los headers ...que son las definiciones de las funciones ....me explico ....si haces esto y a su ves los agregas en el source ...vas a tener conflictos ...y errores que no vas a saber de donde vienen .....te vuelvo a repetir yo logre compilar bien ..solamente teniendo en el arbol de la izquierda ..en el source ...el main y el config bits ....y nada mas


Saludos

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 22 de Junio de 2013, 12:52:43
Me estoy imaginando lo siguiente --...

Si pones en el arbol ...en el source el main ...hasta ahi todo bien ...desp le agregas los pragma en un cof bits .c ...seguimos bien ....pero en el moemnto de agregar un libreria .c .....el programa no sabe donde va esa libreria ...porque no es general ...o sea deberia en otra libreria por ejemplo una depende de la otra ...entonces i la pones en el source ...como sabe el IDE donde va ??? ...ojo es solo algo que yo me imagino y pienso ...si a alguien se le ocurre algo diferente que lo exponga ....lo mismo pasa con los headers ...si los pongo en el arbol ...el ide adonde los asocia ??? a que .c ???? me explico ???


Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 22 de Junio de 2013, 13:02:06
Muchachos ...alguien me puede explicar estos defines por favor ...no logro entenderlos ??? ...los primeros si ...pero los ultimos o los entiendo

   #define TxTris TRISA
   #define TxPort PORTA   //-- PORT A Bit 1 for Tx
   #define TxBit  1



   #define RxTris TRISA
   #define RxPort PORTA    //-- PORT A Bit 0 for Rx
   #define RxBit  0
 



 #define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit))
  

  static bit   TxData @ PORTBIT(TxPort,TxBit);   //-- TXD Pin
  static bit   RxData @ PORTBIT(RxPort,RxBit);   //-- RXD Pin
  static bank1 bit TxTRIS @ PORTBIT(TxTris,TxBit);
  static bank1 bit RxTRIS @ PORTBIT(RxTris,RxBit);
  bit   TxRxInit = 0;

Muchas gracias

Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 23 de Junio de 2013, 18:35:40
Tengo un pequeño problema que creo que se debe a que la rutina de interrupción no salvaguarda bien los datos.

¿Como se salva el contexto en las interrupciones con XC8? ¿Es todo automático o hay que hacerlo a mano para ciertos registros?


Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 23 de Junio de 2013, 18:51:54
Tengo un pequeño problema que creo que se debe a que la rutina de interrupción no salvaguarda bien los datos.

¿Como se salva el contexto en las interrupciones con XC8? ¿Es todo automático o hay que hacerlo a mano para ciertos registros?


Saludos.

  Según tengo entendido, es todo automático.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 23 de Junio de 2013, 19:18:10

Programa Ejemplo
Código: C
  1. #include <xc.h>
  2.  
  3. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
  4. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  5. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  6. #pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
  7. #pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
  8. #pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
  9. #pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
  10. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  11.  
  12.  
  13.  
  14. //#define _XTAL_FREQ 26000000
  15. #include "swuart.h"
  16.  
  17. void main(void)
  18. {
  19.     unsigned char mensaje[10] = "TodoPic";
  20.     unsigned char *punterostring;
  21.     unsigned char caracter;
  22.  
  23.     punterostring = mensaje;
  24.     caracter = 'a';
  25.     swinit_uart();           //inicialiso el UART
  26.     swputch('H');
  27.     swputch('o');
  28.     swputch('l');
  29.     swputch(caracter);       //mando la palabra Hola letra por letra
  30.     swputch('\r');           //salto de linea
  31.     swputs(mensaje);         //mando la cadena almacenada en mensaje
  32.     swputch('\r');           //salto de linea
  33.     swgets(punterostring);   //recibo una cadena terminada con '\r'
  34.     swputch('\r');           //salto de linea
  35.     swputs(punterostring);   //mando la cadena apuntada por punterostring
  36.                              //(recibida anteriormente)
  37.  
  38.     while(1);
  39. }
[/quote]


Perdon AngelGris ....como yo veo la subrutina ...segun entiendo ...con lo poco que se , que en el main , deberias referirte al swuart.c y NO al swuart.h ...


O sea que primero debes incluir el swuart.c para que el mismo incluya los headers ..en el swuart.h ...

Perdon si me equivoco ...


Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 24 de Junio de 2013, 10:57:24

Perdon AngelGris ....como yo veo la subrutina ...segun entiendo ...con lo poco que se , que en el main , deberias referirte al swuart.c y NO al swuart.h ...


O sea que primero debes incluir el swuart.c para que el mismo incluya los headers ..en el swuart.h ...

Perdon si me equivoco ...


Saludos

  El archivo .C lo agrego directamente en el árbol del proyecto en "source files"

  Por lo que puede verse en el log que muestra el compilador, al hacerlo de esta manera se compila cada archivo por separado (cada uno que se encuentre en "source files") y luego se linkean todos.

  Anteriormente yo sólo creaba un archivo .C y lo incluía directamente en el programa -como tú comentas- pero después de mucho ver códigos tanto para microcontroladores como para PC he notado que no incluyen directamente el .C en el programa principal sino que incluyen los header.

Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 24 de Junio de 2013, 17:12:43
Citar
Saca el archivo de la libreria en source ...ahi solamente pone el main.c  y si queres hacer mas legible el main ...separa los pragma en un archivo diferente ...configuratiob_bits.c ...que ese si lo agregas en el source junto con el main ....desp las librerias las agregas con los #include al rpincipio del main ...ahi te puese un ejemplo ....en el main.c al principio pones #include la libreria.c ...y al principio de la lñibreria pones el #include libreria.h que es donde estan los headers ...que son las definiciones de las funciones ....me explico ....si haces esto y a su ves los agregas en el source ...vas a tener conflictos ...y errores que no vas a saber de donde vienen .....te vuelvo a repetir yo logre compilar bien ..solamente teniendo en el arbol de la izquierda ..en el source ...el main y el config bits ....y nada mas
Solo tengo el main.c en el arbol de la izquierda, intento incluir la libreria en .c y me da errores, en cambio incluyo el MISMO codigo en un archivo .h y me va perfecto... no lo entiendo..
Porcierto ¿como puedo escribir una variable numerica en el LCD?
Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 25 de Junio de 2013, 20:28:13
Estoy trabajando en un pequeña "libreria", si se le puede llamar así, para leer un teclado 4x4, en principio la estaba haciendo para mi, pero he pensado en subirla y colaborar con el manual. Si la quereis añadir decidmelo, asi la comento más y explico su funiconamiento (Es muy basica)..
Título: Re: Mini curso "Programación en XC8"
Publicado por: QIQE en 26 de Junio de 2013, 12:20:16
se podría abrir un hilo de recursos para XC8, y así tenerlos un poco mas ordenados
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 26 de Junio de 2013, 12:25:49
hola Qiqe.
          El hilo tiene un índice en el primer post. cada tanto el usuario que lo creo "lmtreser" lo va actualizando.
          La idea es ir poniendo ejemplos y guias sobre los temas sobre los cuales se van generando dudas.- Luego mandarle un mensaje privado a él o al administrador del foro para que lo agreguen al ínidice.
        Saludos.
              Jukinch
Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 26 de Junio de 2013, 13:22:51
Citar
se podría abrir un hilo de recursos para XC8, y así tenerlos un poco mas ordenados
Pienso yo que para eso esta este tema no?

Lo que si podriamos abrir un tema con ejercicios para hacer en XC8 y poner la solucion en un spoiler de esos desplegables ¿Que os parece?O bueno, podemos usar este mismo tema.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 26 de Junio de 2013, 17:06:35
  Aquí dejo una librería en para manejo de UART por SoftWare
  Hay que tener en cuenta que no todas las velocidades de comunicación serán posibles en todas las frecuencias de trabajo del microcontrolador. Por ejemplo, con 4MHz no se puede comunicar a una velocidad mayor a 19200
  En el header de la librería están definidos los tiempos y hay una "especie de compensación" según la frecuencia a la que esté trabajando.

  Lo simulé en ISIS con un 16F876A y va bien.


He estado Probando esta libreria que Posteo AngelGris ...y anda perfectamente simulada en proteus , pero a la hora de llevarla al Protoboard ...no funciona ....habra tanta diferencia entre Proteus 8.0 y la realidad ?? porque puede ser que no funcione ? ..estoy llevando los pines a unas placas de rf apc230 las de ctm electronica ...probe antes las placas puenteando txrx y andan perfecto ...es como si el micro no le enviara nada ...no se como verificarlo ...si a alguien se le ocurre algo ??

Gracias

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 26 de Junio de 2013, 18:15:51
  Si tienes un max232 puedes probar comunicación entre el PIC y la PC... también puedes intentar una comunicación a menor velocidad. Postea tu programa y el header de la librería como lo estés utilizando, tal vez hay algún problema.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 26 de Junio de 2013, 18:26:35
  Si tienes un max232 puedes probar comunicación entre el PIC y la PC... también puedes intentar una comunicación a menor velocidad. Postea tu programa y el header de la librería como lo estés utilizando, tal vez hay algún problema.

Gracias AngelGris ...es raro porque anda bien en Proteus ...tengo un programador de la firma RDss que tiene un analizador de uart ..y tampoco me funciona ...es el pic pero no entiendo porque anda en proteus ...es un pic 16f819 el que vengo usando en todo lo que hago ...estaba pensando en ponerle un led que me marque cuando transmite ...bueno mañana seguire experimentando ..desp posteare los resultados ...las conexiones en el proto estan bien ...aparte no son muchas es sencillo ...es evidente que es algo de la programacion ...el tema es que no se como verificarlo porque siempre uso el proteus para eso

Saludos y gracias

Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 27 de Junio de 2013, 14:15:26
  Si tienes un max232 puedes probar comunicación entre el PIC y la PC... también puedes intentar una comunicación a menor velocidad. Postea tu programa y el header de la librería como lo estés utilizando, tal vez hay algún problema.


AngelGris , posteo el codigo a ver si se te ocurre algo que se me este pasando a mi ....lo estoy probando con un programador de la firma RdSS en funcion UART TOOL ...ya probe la herramienta puenteando txrx y mandando caracteres y anda perfecto ...o sea que con el codigo deberia funcionar ...pero no es asi ..este solamente funciona con PROTEUS 8.0  tanto main como swuart.c estan definidos en el projecto junto con los bits de configuracion

Muchas gracias por la ayuda



main.c

Código: [Seleccionar]
  #define _XTAL_FREQ 8000000

    #include <xc.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <htc.h>
   // #include "i2c.h"
   // #include "BMP085.h"
    #include "swuart.h"
     char mensaje[10] = "Ramiro";
     long temperature;



void init ();



    void main(void)
    {

         
        __delay_ms(1000);
        unsigned char *punterostring;

   
   punterostring = mensaje;
   swinit_uart(); //inicialiso el UART
   
   __delay_ms(10);

   swputch('T');
   swputch('E');
   swputch('M');
   swputch('P');       //mando la palabra Hola letra por letra
   swputch('\r');           //salto de linea
   swputs(mensaje);         //mando la cadena almacenada en mensaje
   swputch('\r');           //salto de linea
   swgets(punterostring);   //recibo una cadena terminada con '\r'
   swputch('\r');           //salto de linea
   swputs(punterostring);   //mando la cadena apuntada por punterostring
                            //(recibida anteriormente)

         //temperature =  bmp085ReadTemp();
         //itoa( mensaje, temperature, 10 );
while(1);


 
         
    }
    void init(void)
   {

    OSCCONbits.IRCF2 = 1; //
    OSCCONbits.IRCF1 = 1; // defino oscilador interno en 8 mhz
    OSCCONbits.IRCF0 = 1; //


       


    ADCON0bits.ADON = 0;  //
    ADCON1bits.PCFG3 = 0; //
    ADCON1bits.PCFG2 = 1; // pongo todas las entradas digitales porta
    ADCON1bits.PCFG1 = 1; //
    ADCON1bits.PCFG0 = 1; //
    ADCON1bits.ADCS2 = 0; //
    TRISA=0;
    PORTA=0;
   // TRISB =1;
  //  PORTB =0;
      //  BMP085_Calibration();

    }


swuart.h

Código: [Seleccionar]
#ifndef SWUART_H
    #define SWUART_H

    #ifndef _XC_H_
    #include <xc.h>
    #endif


    /*******************************************************************************
    *  Parametros configurables por el usuario                                     *
    *******************************************************************************/

    /*
    * El valor de _XTAL_FREQ debe coincidir con el valor definido
    * en el programa principal
    */

    /*
    * En el caso que solo se desee transmitir se debe definir TXONLY
    * En el caso que solo se desee recibir se debe definir RXONLY
    * En el caso de querer transmitir y recibir se debe definir TXRX
    */

    #ifndef _XTAL_FREQ
    #define _XTAL_FREQ 8000000
    #endif

    #define TXPIN PORTBbits.RB0
    #define RXPIN PORTBbits.RB2
    #define TXDIR TRISBbits.TRISB0
    #define RXDIR TRISBbits.TRISB2

    #define SWUARTBAUD 9600
    #define TXRX


    /*******************************************************************************
    *  Parametros internos para los tiempos de cada bit                            *
    *******************************************************************************/

    #define _BitOutDelay (1000000UL/SWUARTBAUD)
    #define StartDelay (1500000UL/SWUARTBAUD)

    #if (_XTAL_FREQ <= 4000000)
    #define BitOutDelay (_BitOutDelay - 24)
    #define BitInDelay (_BitOutDelay - 24)
    #elif (_XTAL_FREQ <= 6000000) && (_XTAL_FREQ > 4000000)
    #define BitOutDelay (_BitOutDelay - 16)
    #define BitInDelay (_BitOutDelay - 16)
    #elif (_XTAL_FREQ <= 8000000) && (_XTAL_FREQ > 6000000)
    #define BitOutDelay (_BitOutDelay - 12)
    #define BitInDelay (_BitOutDelay -12)
    #elif (_XTAL_FREQ <= 10000000) && (_XTAL_FREQ > 8000000)
    #define BitOutDelay (_BitOutDelay - 10)
    #define BitInDelay (_BitOutDelay -9)
    #elif (_XTAL_FREQ <= 12000000) && (_XTAL_FREQ > 10000000)
    #define BitOutDelay (_BitOutDelay - 8)
    #define BitInDelay (_BitOutDelay - 7)
    #elif (_XTAL_FREQ <= 16000000) && (_XTAL_FREQ > 12000000)
    #define BitOutDelay (_BitOutDelay - 6)
    #define BitInDelay (_BitOutDelay - 5)
    #elif (_XTAL_FREQ <= 20000000) && (_XTAL_FREQ > 16000000)
    #define BitOutDelay (_BitOutDelay - 5)
    #define BitInDelay (_BitOutDelay - 4)
    #elif (_XTAL_FREQ <= 26000000) && (_XTAL_FREQ > 20000000)
    #define BitOutDelay (_BitOutDelay - 3)
    #define BitInDelay (_BitOutDelay - 3)
    #elif (_XTAL_FREQ <= 48000000) && (_XTAL_FREQ > 26000000)
    #define BitOutDelay (_BitOutDelay - 2)
    #define BitInDelay (_BitOutDelay - 2)
    #endif


    /*******************************************************************************
    *  Definicion de funciones                                                     *
    *******************************************************************************/

    /*
    * La funcion swgets recibe una cadena que termine con '\r' (decimal 13)
    * la cadena es devuelta a travez del puntero que se le pasa como parametro
    */
    void swinit_uart(void);
    void swputch(unsigned char);
    void swputs(unsigned char *);
    unsigned char swgetch(void);
    void swgets(unsigned char *);

    #endif /* SWUART_H */

swuart.c

Código: [Seleccionar]
#ifndef SWUART_H
    #include "swuart.h"
    #endif

    #if !defined(TXPIN) || !defined(RXPIN) || !defined(TXDIR) || !defined(RXDIR)
    #error No estan definidos los pines
    #else
    #ifndef SWUARTBAUD
    #error Falta definir la velocidad
    #endif

   void swinit_uart(void)
{
#if defined TXONLY
   TXDIR = 0;
#elif defined RXONLY
   RXDIR = 1;
#elif defined TXRX
   TXDIR = 0;
   RXDIR = 1;
#endif
}

void swputch(unsigned char _dato)
{
   unsigned char _bits2 = 8;

   TXPIN = 0;
   __delay_us(BitOutDelay);
   do
   {
TXPIN = _dato & 1;
__delay_us(BitOutDelay);
_dato = _dato >> 1;
_bits2--;
   }
   while (_bits2 > 0);
   TXPIN = 1;
   __delay_us(_BitOutDelay);
}

void swputs(unsigned char *_st)
{
   while (*_st != 0)
   {
swputch(*_st);
_st++;
   }
}

unsigned char swgetch(void)
{
   unsigned char _datain = 0;
   unsigned char _bits2 = 8;

   while (RXPIN == 1);
   __delay_us(StartDelay);
   do
   {
_datain = _datain >> 1;
if (RXPIN == 1) _datain |= 0b10000000;
__delay_us(BitInDelay);
_bits2--;
   }
   while (_bits2 > 0);
   __delay_us(BitOutDelay/2);
   return _datain;
}

void swgets(unsigned char *st)
{
   unsigned char *word;
   unsigned char character;

   word = st;
   do
   {
character = swgetch();
if (character != '\r')
{
   *word = character;
   word++;
}
   }
   while (character != '\r');
   *word = 0;
}
#endif

configurations_bits.c

Código: [Seleccionar]
// PIC16F819 Configuration Bit Settings

#include <xc.h>

// CONFIG
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTRC oscillator; CLKO function on RA6/OSC2/CLKO pin and port I/O function on RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2      // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 27 de Junio de 2013, 15:48:28
Logre que funcione ...es la segunda vez que cometo el mismo error ...la programacion del oscilador !!!!!

    OSCCONbits.IRCF2 = 1; //
    OSCCONbits.IRCF1 = 1; // defino oscilador interno en 8 mhz
    OSCCONbits.IRCF0 = 1; //

estaban fuera del main ...y evidentemente a Proteus no le interesa ....


Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 27 de Junio de 2013, 16:34:32
Logre que funcione ...es la segunda vez que cometo el mismo error ...la programacion del oscilador !!!!!

    OSCCONbits.IRCF2 = 1; //
    OSCCONbits.IRCF1 = 1; // defino oscilador interno en 8 mhz
    OSCCONbits.IRCF0 = 1; //

estaban fuera del main ...y evidentemente a Proteus no le interesa ....


Saludos


  Pues no, porque proteus trabaja a la frecuencia que le definas manualmente.
Título: Re: Mini curso "Programación en XC8"
Publicado por: neto100 en 03 de Julio de 2013, 21:17:16
Hola yamilongiano. Para encender todo el puerto debés hacer referencia a todo el puerto con el identificador PORTB

así:
 
PORTB = b00010001; // Fijate que la sintaxis del valor del entero es diferente al assembler b'00010001'



gracias si funciono.

Ten cuidado una cosa es LATB y otra muy diferente es PORTB, la primera es colocar datos en el puerto B y la segunda es leer datos del puertoB, oviamente se debe estar configurado el puertoB como salida o sea TRISB = 0; o TRISBbits.TRISB0 = 0, para solo encender el bit 0 del puertoB.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 03 de Julio de 2013, 22:06:01
Hola yamilongiano. Para encender todo el puerto debés hacer referencia a todo el puerto con el identificador PORTB

así:
 
PORTB = b00010001; // Fijate que la sintaxis del valor del entero es diferente al assembler b'00010001'



gracias si funciono.

Ten cuidado una cosa es LATB y otra muy diferente es PORTB, la primera es colocar datos en el puerto B y la segunda es leer datos del puertoB, oviamente se debe estar configurado el puertoB como salida o sea TRISB = 0; o TRISBbits.TRISB0 = 0, para solo encender el bit 0 del puertoB.

  neto100, no todos los PICs tienen registro LAT. En aquellos que no tienen dicho registro la forma de escribir en el puerto es justamente haciendo

Código: C
  1. PORTB = xxxxx;
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 04 de Julio de 2013, 13:47:28
Hola.
      Cito post del usuario bigluis en donde comparte dos tutoriales de instalación de Mplab X y XC8,16,y32 en linux
         Saludos.
             Jukinch


Hola amigos en esta ocasion les traigo dos videos. El primero muestra como instalar MPLABX en Linux Mint 14 y el segundo muestra como instalar los compiladores XC8, XC16 Y XC32.

Espero que los Disfruten  :-/


Título: Re: Mini curso "Programación en XC8"
Publicado por: jeremylf en 07 de Julio de 2013, 05:45:22
PIC: 16F887 a 4Mhz
Solo simulacion: con ISIS 7.10
XC8 v1.12 y MPLABX v1.80

A pesar que el datasheet dice que no es necesario ajustar el registro ANSELH para usar el puerto B como salida...
Código: [Seleccionar]
3.4.1 ANSELH REGISTER
The ANSELH register (Register 3-4) is used to
configure the Input mode of an I/O pin to analog.
Setting the appropriate ANSELH bit high will cause all
digital reads on the pin to be read as ‘0’ and allow
analog functions on the pin to operate correctly.
The state of the ANSELH bits has no affect on digital
output functions. A pin with TRIS clear and ANSELH
set will still operate as a digital output, but the Input
mode will be analog. This can cause unexpected
behavior when executing read-modify-write
instructions on the affected port.


Ha sido necesario ponerlo a 0 para que el siguiente programa corra como debe en la simulacion:
Código: [Seleccionar]

#include <xc.h>

#define _XTAL_FREQ 4000000

// PIC16F887 Configuration Bit Settings
// CONFIG1
#pragma config FOSC = XT        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = ON       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown Out Reset Selection bits (BOR disabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)
// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)


void main(void)
{
    ANSELH = 0;  //si comentan esto RB5 nunca prende.

    PORTB = 0;  
    TRISB = 0;    

    while (1)
    {
        RB5 = 1;
        RB7 = 1;
        __delay_ms(2000);
        RB5 = 0;
        RB7 = 0;
        __delay_ms(1000);

    }
}

El problema cuando no esta borrado ANSELH es que hace que al ejecutarse RB7=1, este apage al RB5 y por eso nunca lo deja prender.
Talvez sea por que es simulacion o por que no entiendo bien el ingles del datasheet o porque en otra parte dice lo contrario pero esto me ha tenido asi varias horas.

Solo es una advertencia para que no sufran como yo xD, otro dia ya lo probare en fisico.

Porsiacaso lo dejo adjuntado todo para haber si, a los que puedan probarlo, les pasa los mismo en sus proteus.


Por cierto, muy buenos datos que están poniendo por aquí. Se agradece.

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Limbo en 09 de Julio de 2013, 18:22:19
Yo uso el 886 y si no configuras ANSELH date por jodido  :lol: Si no lo defines los programas dan fallos. No he leido  esa parte del datasheet, pero siempre me han dicho que es necesario configurarlo..
Título: Re: Mini curso "Programación en XC8"
Publicado por: jeremylf en 09 de Julio de 2013, 21:32:22
Claro, la pregunta sería porque?
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 09 de Julio de 2013, 22:12:22
  Hablando de simulación, con ISIS 7.8 sólo es necesario configurar el registro ANSELH si se va a utilizar el puerto como entrada. Siempre que lo utilicé como salida no me fue necesario configurarlo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: fabytodo en 10 de Julio de 2013, 11:44:38
Excelente curso lmtreser PIC12, 1ro. muchas gracias  ((:-)), ya hice titilar el led, pwm y ADC, sin utilizar xtal. alguien conoce  algún demo sencillo como estos para mostrar la comunicación usb con el 18F2550 o 18F4550 por vitual com o como sea utilizando MPlabX y XC8
Gracias de antemano Fabián
Título: Re: Mini curso "Programación en XC8"
Publicado por: jeremylf en 12 de Julio de 2013, 06:57:12
Quiero hacer esto:
unsigned char pines[3] = {RD0, RB1, RC2};

Pero no me deja. Dice que solo admite constantes. Bueno mi idea es controlar varios pines de una forma mas didactica. Entonces pense en punteros, pero como no soy muy bueno en este tema, no logro dar que me compile:

unsigned char *pines;

pines = &RD0;

Y me da ilegal operation on bit variable y ilegal conversion

Alguien sabe como hacerle?

Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: alvaro2043 en 17 de Julio de 2013, 12:15:46
Buenos días.. saludos a todos. La verdad soy nuevo en el mundo de los microcontroladores actualmente ando trabajando con el 18F4550 he realizado ejercicios sencillos, como encender y apagar led, leer ADC y generar PWM, utilizo MPLAB y el compilador C18 y quiero unirme a este subforo. Tengo un reto el cual llevo casi una semana leyendo y leyendo pero no doy, ya ando saturado.
Necesito generar 4 señales a las cuales se le debe variar el ciclo de trabajo todas a la vez, la caracteristica de estas señales es que deben de estar desfasadas. Se que por el modulo CCP no se puede por que el PIC18F4550 trae solo 2 CCP y los dos modulos dependen del timer2.
He pensado hacer esta señales por interrupciones utilizando los timer. Pero antes de pasar al pez gordo (generar las 4 señales pwm) Quiero arrancar generando una señal PWM por interrupciones ya sea utilizando el timer0 o timer1,timer2,timer3. La verdad no se si hay otra forma de realizar, yo creeria que si, pero no se cual.

Esta es la imagen de las señales.. Bueno no quiero que me escriban un codigo. Me gustaria que a medida que vaya haciendo lo mio, me puedan orientar y darme a conocer en donde estoy fallando.. Digamos que como unos tutores jejejeje  A penas tenga algo de codigo lo subiré.. Lo que si quiere es que me ayuden hacerme una idea de como enfrentar este problemas.

Gracias.. Exitos a todos

(http://imageshack.us/a/img703/7859/xxk9.th.png) (http://imageshack.us/photo/my-images/703/xxk9.png/)
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 17 de Julio de 2013, 12:39:40
Hola alvaro2043. Por aquí hay algo sobre el tema. No está en xc8 pero se podrá migrar el concepto.
http://personales.alumno.upv.es/mapedgi/pfc/simulacionespwm.html
http://www.ucontrol.com.ar/forosmf/proyectos-con-pic/pwm-por-software/
Andá dándole forma al código.
       Saludos.
           Jukinch


       
Título: Re: Mini curso "Programación en XC8"
Publicado por: alvaro2043 en 17 de Julio de 2013, 12:56:49
Gracias Jukinch.. Voy a estar quemando neurona haciendo este codigo.. y poco a poco lo ire subiendo... Gracias..
Estas respuestas son mas rápidas que la justicia aquí en colombia jejejejej

Exitos a todos..
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 17 de Julio de 2013, 13:02:42
Gracias Jukinch.. Voy a estar quemando neurona haciendo este codigo.. y poco a poco lo ire subiendo... Gracias..
Estas respuestas son mas rápidas que la justicia aquí en colombia jejejejej

Exitos a todos..

  No te preocupes, que también fue mucho más rápida que la justicia en Argentina  :D
Título: Re: Mini curso "Programación en XC8"
Publicado por: alvaro2043 en 18 de Julio de 2013, 03:01:10
Bueno.. estaba intentado generar una señal cuadrada de frecuencia de 10khz.. por medio del timer0, con el fin de familiarizarme con los timer.. La verdad pense que lo que estaba haciendo estaba bien, ya que me lei la hoja de datos  la parte de las interrupciones y el timer0 .. pero Pufff no se generaa nada.. solo un cambio de estado en el PINB1.. Dejo el codigo a ver que ayuda me pueden pegar.. Nota: Apenas esto arrancando con este cuento de programar.

Código: [Seleccionar]
///Generacion de onda cuadrada 10Khz con duty-cycle 50%

//Cofiguración de Bits

#pragma config PLLDIV = 1 //No importa por que vamos a trabajar con el oscilador interno
#pragma config CPUDIV = OSC1_PLL2  //No importa por que vamos a trabajar con el oscilador interno
#pragma config USBDIV = 1
#pragma config FOSC = INTOSC_EC  //Configurado para trabajar oscilador interno, si se deja por default trabajará a 1MHZ de clock
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = ON
#pragma config BOR = OFF
#pragma config BORV = 0
#pragma config VREGEN = OFF
#pragma config WDT = OFF
#pragma config WDTPS = 8192
#pragma config MCLRE = OFF
#pragma config LPT1OSC = OFF
#pragma config PBADEN = OFF
#pragma config CCP2MX = OFF
#pragma config STVREN = OFF
#pragma config LVP = OFF
#pragma config ICPRT = OFF
#pragma config XINST = OFF
#pragma config DEBUG = OFF
#pragma config CP0 = OFF,CP1 = OFF,CP2 = OFF,CP3 = OFF
#pragma config CPB = OFF,CPD = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRT2 = OFF
#pragma config WRT3 = OFF
#pragma config EBTRB = OFF
#pragma config EBTR3 = OFF
#pragma config EBTR2 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTR0 = OFF

#include <p18f4550.h>
//Declarando funciones de interrupciones



void Interrupt_isr_Tmr0(void);

void main(void){

    //Configuracion
    INTCON = 0b00100000;  //Habilito el TMR0 overflow Interrupt
    INTCON2 = 0b10000100; //Resistencia pull-up son off
    RCONbits.IPEN = 1; //Habilito interrupciones por prioridad
    TMR0H=0xFF;
    TMR0L=0XFA;         //Cargo el timer0 para trabajar a 16bits para que se me desborde cada 50us para obtener una frecuencia de  10KHz
    T0CON=0b10000011;                     //Los calculos son realizado de la siguiente manera:
    INTCONbits.GIEH=1;                   //Timer_Frecuencia = Fos/4 ==> 8Mhz/4 = 2Mhz.
    TRISB = 0X00;                         //utilizando un prescales de 16 2Mhz/16 = 125Khz
    PORTB = 0X00;                         //(125Khz)(50us) = 6, como estoy trabajando a 16bits
                                          //la cuenta va desde 0x0000-0xFFFF (0-65535)
     while(1);                            //65535-6 = 65530 Ó 0xFFFA, que es lo que cargo en el timer

}

#pragma code Interrupt_vector_TMR0 = 0x08
void Interrupt_vector_TMR0(void)
{
    _asm goto Interrupt_isr_Tmr0
            _endasm
}
//Rutina de interrupción

#pragma code
#pragma  interrupt Interrupt_isr_Tmr0

void Interrupt_isr_Tmr0(void)
{
    if(INTCONbits.TMR0IF ==1){  //Preguntamos por la bandera

        INTCONbits.TMR0IF=0;  //Borramos la bandera

        LATBbits.LATB1=!LATBbits.LATB1;


    }
}



 Buenos me ire a dormir.. ya son la 1:33am jejje esto es algo vicioso.. el querer hacer cosas con esas arañas de silicio ejejeje
Éxitos a todos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 18 de Julio de 2013, 12:50:38
Hola alvaro2043. El código que has subido está en c18 y si lo que quieres es pasarlo a xc8 podés darle una mirada a estos post:

http://www.todopic.com.ar/foros/index.php?topic=40649.msg340202#msg340202
http://www.todopic.com.ar/foros/index.php?topic=40649.msg338221#msg338221

Allí verás como se programan las interruciones en xc8.
       Saludos.
            Jukinch
Título: Re: Mini curso "Programación en XC8"
Publicado por: jeremylf en 20 de Julio de 2013, 01:58:10
Quiero hacer esto:
unsigned char pines[3] = {RD0, RB1, RC2};

Pero no me deja. Dice que solo admite constantes. Bueno mi idea es controlar varios pines de una forma mas didactica. Entonces pense en punteros, pero como no soy muy bueno en este tema, no logro dar que me compile:

unsigned char *pines;

pines = &RD0;

Y me da ilegal operation on bit variable y ilegal conversion

Alguien sabe como hacerle?

Gracias.
No saben tampoco como?  :mrgreen:
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 20 de Julio de 2013, 04:03:41
Hola jeremylf. No entiendo bien que es lo que quieres hacer.
Explica un poco más la duda que tienes.

Igualmente ten presente que los punteros a variables de tipo bit son ilegales.
Mira la página 145 del manual del compilador xc8 ds52053B-page 145.
"It not possible to declare a pointer to bit." No es posible declarar un puntero a bit.
Por eso el compilador te esta dando esos errores.

Dale una mirada a estos link
http://www.microchip.com/forums/m701812.aspx
Allí verás varios ejemplos sobre como acceder a bits individuales de un puerto.
http://www.gooligum.com.au/tutorials/baseline/PIC_Base_C_5.pdf

http://programandopics.blogspot.com.ar/2012/09/primer-proyecto-en-xc8-parte-2-codigo.html?m=1



Título: Re: Mini curso "Programación en XC8"
Publicado por: jeremylf en 20 de Julio de 2013, 13:26:48
Lo que intento hacer es poder controlar el estado de varios pines de diferentes puertos del PIC.

Lo mejor que se me ocurre es un array de los pines que quiero controlar: unsigned char pines_a_controlar[5] = {RA0, RB3, RC4, RD4, RD6};
De esta forma, setearia al pin RA0 poniendo: pines_a_controlar[0] = 1;

Pero esto no compila.

Estoy mirando los links que has propuesto, estan interesantes. Graias por tu tiempo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 20 de Julio de 2013, 18:33:25
Lo que intento hacer es poder controlar el estado de varios pines de diferentes puertos del PIC.

Lo mejor que se me ocurre es un array de los pines que quiero controlar: unsigned char pines_a_controlar[5] = {RA0, RB3, RC4, RD4, RD6};
De esta forma, setearia al pin RA0 poniendo: pines_a_controlar[0] = 1;

Pero esto no compila.

Estoy mirando los links que has propuesto, estan interesantes. Graias por tu tiempo.


Y porque no lo haces de esta forma :


         #define ledpin1 TRISBbits.TRISB1
         #define ledtxpin1 PORTBbits.RB1
         #define ledpin2 TRISBbits.TRISB2
         #define ledtxpin2 PORTBbits.TRISB2

y despues cuando lo queres usar

ledpin2 = 0;     // pin 2 como salida
ledpin1 = 0;     // pin 1 como salida
 
ledtxpin1 = 1;  // prendo el led

ledtxpin1 = 0;  // apago el led

ledpin1 = 1 ;   // pin 1 como entrada

if (ledtxpin1 == 1) then ledtxpin2 = 1;  // si 1 en pin 1 enciendo pin2


Saludos espero te sirva
Título: Re: Mini curso "Programación en XC8"
Publicado por: carferper en 21 de Julio de 2013, 07:52:00
Saludos, puedes crear funciones como en el ejemplo siguiente:

Código: [Seleccionar]
#include <xc.h>                      /* definiciones 12F683 */

#define _XTAL_FREQ 4000000
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

#pragma config FOSC = INTOSCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF
#pragma config CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF

void toggle_bit(int pin){
    GPIO ^= (1<<pin);               /* cambia estado de pin en GPIO */
}

void main (void){
    CMCON0     |= 0b00000111;       /* desactiva comparadores */
    ANSEL      &= 0b11110000;       /* puerto como E/S digitales */
    GPIO        = 0b000000;         /* inicia con LEDs apagados */
    TRISIO      = 0b111000;         /* GP1, GP2 y GP3 como salidas */
    OPTION_REG &= 0b01111111;       /* habilita "pull-ups" internos */

    int pin = 0;

    while (1){
        for (pin = 0; pin < 3; pin++){
            toggle_bit(pin);            
            __delay_ms(200);
        }
    }
}

asi solo debes pasar el bit que quieres modificar mediante la variable pin.
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 22 de Julio de 2013, 18:38:16
Jeremylf:
         sumando a lo que han propuesto carferper y rseliman también podés tratar el puerto con una máscara (funciona como un colador dejando pasar sólo el bit que le permitimos) con operadores a nivel de bits para acceder a los bits individuales del registro en cuestión con una variable a modo de índice.
         

Código: [Seleccionar]
int n=0;
while (1)
{
   
    for(n=0;n<8;n++)
    {
        LATD =(LATD |= 1<<n); // pone en 1 el bit n del puerto D
        myMsDelay(100);
        LATD &= (~(1<<n));    // pone en 0 el bit n del puerto D
    }
    for(n=6;n>=1;n--)
    {
        LATD=(LATD |= 1<<n); // pone en 1 el bit n del puerto D
        myMsDelay(100);
        LATD &= (~(1<<n));   // pone en 0 el bit n del puerto D
    }
}

Con estas líneas de código podemos hacerle honor al más preciado programa del auto fantástico!


Adjunto proyecto completo y simulación en proteus.
pic4550 con oscilador interno.
8 leds conectados en el puerto D.


para refrescar el tema de los operadores a nivel de bits agrego una pequeña guia con ejemplos.
Código: [Seleccionar]
Operadores a nivel de bit (bitwise operators)
-----------------------------------------------------------------------------------------------------------------------------





-----------------------------------------------------------------------------------------------------------------------------
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)








Dependiendo el compilador El operador shift   >> tiene diferente comportamiento
--------------------------------------------------------------------------------
depende del tipo de dato al que se le va a aplicar. Más precisamente si la variable fue creada con signo o sin signo.


EJEMPLO:
creamos dos variables

unsigned char A=100;
signed char B=-100;




Valor de A= 100 // valor decimal
Valor de A en binario: 01100100
Valor de A en binario luego de aplicarle shift >> 2:
Valor en binario:      00011001 // en este caso el bit más significativo se indica con un cero.
                                //  y los bits que se desplacen hacia la derecha del bit más significativo
                                // se completan con ceros 0.

Valor de B= -100 // valor decimal
Valor de B en binario: 10011100
Valor de B en binario luego de aplicarle shift >> 2:
Valor de B en binario: 11100111 // en este caso el bit más significativo se mantiene para indicar el signo negativo
                                // y los bits que se desplacen hacia la derecha del bit más significativo
                                // se completan con unos 1.


-----------------------------------------------------------------------------------------------------------------------------
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.
-----------------------------------------------------------------------------------------------------------------------------



PARA ROTAR UN BYTE


C language does not specify a rotate operator; however, it does allow shifts. The compiler will detect expressions that implement rotate operations using shift and logical operators and compile them efficiently.

EJEMPLO:
c = (c << 1) | (c >> 7);







    Saludos.
       Jukinch
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 23 de Julio de 2013, 00:57:19
comparto guia de estudio sobre proyectos con múltiples archivos y ámbito de variables. No está en xc8 pero es C y servirá para comprender los conceptos en xc8.
Está en confección. De a poco se irá puliendo.
Saludos.
         Jukinch
Título: Re: Mini curso "Programación en XC8"
Publicado por: jeremylf en 24 de Julio de 2013, 23:45:49
Gracias por sus respuestas. En estos días haré mas pruebas en base a todo lo expuesto haber si sale como quiero. Nuevamente, gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: ottanawa en 05 de Septiembre de 2013, 12:33:39
Hola a todos!! Soy nuevo en éste foro y también estoy comenzando en este lenguaje de programación. Vengo del ccs pic, y bueno en realidad quería saber como hacer para configurar los fuses para un circuito simple de encender y apagar un led con el pic 18f46j50, porque he visto por ejemplo el 18f45j50, pero cuando yo lo realizo, el delay que me realiza es el doble de lo calculado. Desde ya muchas gracias y espero su pronta respuesta
Título: Re: Mini curso "Programación en XC8"
Publicado por: ottanawa en 05 de Septiembre de 2013, 13:43:25
Hola a todos! Soy nuevo en este foro, y bueno me estoy iniciando en XC8. Estoy teniendo problemas para declarar los fuses para un pic: 18f46j50. Lo que quiero realizar es solamente un circuito sencillo, prender y apagar un led. Pero como tengo problemas con la declaración de los fuses, no lo puedo realizar. Desde ya estaría agradecido si me pueden a solucionar el problema. Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Suky en 05 de Septiembre de 2013, 19:57:09
Hola! Podes revisar la documentación especifica para ese micro: doc/pic18_chipinfo.html...



Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: electroipod en 07 de Septiembre de 2013, 23:34:53
Hola amigo queria saber si tu libreria i2c puede manejar el ds1307, y tambien quería saber si esta libreria lo sacaste de algun lugar o lo hiciste tu.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 10 de Septiembre de 2013, 19:03:50
Hola amigo queria saber si tu libreria i2c puede manejar el ds1307, y tambien quería saber si esta libreria lo sacaste de algun lugar o lo hiciste tu.

  ¿A cuál librería te refieres? Yo subí una de I2C por software, por ello la pregunta. En el caso de mi librería, trabaja a una velocidad aproximada de 70Khz y la velocidad máxima para el modo standard es de 100KHz así que supongo que funcionaría, a no ser que necesite una mayor velocidad.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 11 de Septiembre de 2013, 08:50:40
Hola amigo queria saber si tu libreria i2c puede manejar el ds1307, y tambien quería saber si esta libreria lo sacaste de algun lugar o lo hiciste tu.

  ¿A cuál librería te refieres? Yo subí una de I2C por software, por ello la pregunta. En el caso de mi librería, trabaja a una velocidad aproximada de 70Khz y la velocidad máxima para el modo standard es de 100KHz así que supongo que funcionaría, a no ser que necesite una mayor velocidad.


Yo use la libreria de Angelgris y anda perfecto ...la use en un BMP085 de bosh ...es un sensor de presion ...Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 26 de Septiembre de 2013, 15:38:20
Hola a todos ...

Desde hace unos dias me estoy volviendo loco con el Mplabx y xc8 ...no he querido preguntar porque siempre trato de googlear antes de hacerlo , pero la verdad es que me tiene cansado ..

Estoy usando un pic 18f2550 ..y un lcd de nokia 5110 ...el cual se comunica por SPI ...googleando encontre una libreria que pareciera funcionara bien , al menos viendola deberia ...pero el tema es que no puedo acceder a la SPI.h ...al compilar compila todo bien , pero por ejemplo si veo la SPI.h esta toda comentada ...es como si el compilador no agrega el pic18xx.h ...les paso la libreria y sigo comentando

Código: [Seleccionar]
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <delays.h>
#include <spi.h>
#include "5110lcd.h"


   #define SCE_5110  LATBbits.LATB3
   #define RESET_5110 LATBbits.LATB2
   #define DC_5110 LATBbits.LATB4



 const char font[] = {0x00, 0x00, 0x00, 0x00, 0x00, // 20 space
    0x00, 0x00, 0x5f, 0x00, 0x00, // 21 !
    0x00, 0x07, 0x00, 0x07, 0x00, // 22 "
    0x14, 0x7f, 0x14, 0x7f, 0x14, // 23 #
    0x24, 0x2a, 0x7f, 0x2a, 0x12, // 24 $
    0x23, 0x13, 0x08, 0x64, 0x62, // 25 %
    0x36, 0x49, 0x55, 0x22, 0x50, // 26 &
    0x00, 0x05, 0x03, 0x00, 0x00, // 27 '
    0x00, 0x1c, 0x22, 0x41, 0x00, // 28 (
    0x00, 0x41, 0x22, 0x1c, 0x00, // 29 )
    0x14, 0x08, 0x3e, 0x08, 0x14, // 2a *
    0x08, 0x08, 0x3e, 0x08, 0x08, // 2b +
    0x00, 0x50, 0x30, 0x00, 0x00, // 2c ,
    0x08, 0x08, 0x08, 0x08, 0x08, // 2d -
    0x00, 0x60, 0x60, 0x00, 0x00, // 2e .
    0x20, 0x10, 0x08, 0x04, 0x02, // 2f /
    0x3e, 0x51, 0x49, 0x45, 0x3e, // 30 0
    0x00, 0x42, 0x7f, 0x40, 0x00, // 31 1
    0x42, 0x61, 0x51, 0x49, 0x46, // 32 2
    0x21, 0x41, 0x45, 0x4b, 0x31, // 33 3
    0x18, 0x14, 0x12, 0x7f, 0x10, // 34 4
    0x27, 0x45, 0x45, 0x45, 0x39, // 35 5
    0x3c, 0x4a, 0x49, 0x49, 0x30, // 36 6
    0x01, 0x71, 0x09, 0x05, 0x03, // 37 7
    0x36, 0x49, 0x49, 0x49, 0x36, // 38 8
    0x06, 0x49, 0x49, 0x29, 0x1e, // 39 9
    0x00, 0x36, 0x36, 0x00, 0x00, // 3a :
    0x00, 0x56, 0x36, 0x00, 0x00, // 3b ;
    0x08, 0x14, 0x22, 0x41, 0x00, // 3c <
    0x14, 0x14, 0x14, 0x14, 0x14, // 3d =
    0x00, 0x41, 0x22, 0x14, 0x08, // 3e >
    0x02, 0x01, 0x51, 0x09, 0x06, // 3f ?
    0x32, 0x49, 0x79, 0x41, 0x3e, // 40 @
    0x7e, 0x11, 0x11, 0x11, 0x7e, // 41 A
    0x7f, 0x49, 0x49, 0x49, 0x36, // 42 B
    0x3e, 0x41, 0x41, 0x41, 0x22, // 43 C
    0x7f, 0x41, 0x41, 0x22, 0x1c, // 44 D
    0x7f, 0x49, 0x49, 0x49, 0x41, // 45 E
    0x7f, 0x09, 0x09, 0x09, 0x01, // 46 F
    0x3e, 0x41, 0x49, 0x49, 0x7a, // 47 G
    0x7f, 0x08, 0x08, 0x08, 0x7f, // 48 H
    0x00, 0x41, 0x7f, 0x41, 0x00, // 49 I
    0x20, 0x40, 0x41, 0x3f, 0x01, // 4a J
    0x7f, 0x08, 0x14, 0x22, 0x41, // 4b K
    0x7f, 0x40, 0x40, 0x40, 0x40, // 4c L
    0x7f, 0x02, 0x0c, 0x02, 0x7f, // 4d M
    0x7f, 0x04, 0x08, 0x10, 0x7f, // 4e N
    0x3e, 0x41, 0x41, 0x41, 0x3e, // 4f O
    0x7f, 0x09, 0x09, 0x09, 0x06, // 50 P
    0x3e, 0x41, 0x51, 0x21, 0x5e, // 51 Q
    0x7f, 0x09, 0x19, 0x29, 0x46, // 52 R
    0x46, 0x49, 0x49, 0x49, 0x31, // 53 S
    0x01, 0x01, 0x7f, 0x01, 0x01, // 54 T
    0x3f, 0x40, 0x40, 0x40, 0x3f, // 55 U
    0x1f, 0x20, 0x40, 0x20, 0x1f, // 56 V
    0x3f, 0x40, 0x38, 0x40, 0x3f, // 57 W
    0x63, 0x14, 0x08, 0x14, 0x63, // 58 X
    0x07, 0x08, 0x70, 0x08, 0x07, // 59 Y
    0x61, 0x51, 0x49, 0x45, 0x43, // 5a Z
    0x00, 0x7f, 0x41, 0x41, 0x00, // 5b [
    0x02, 0x04, 0x08, 0x10, 0x20, // 5c 55
    0x00, 0x41, 0x41, 0x7f, 0x00, // 5d ]
    0x04, 0x02, 0x01, 0x02, 0x04, // 5e ^
    0x40, 0x40, 0x40, 0x40, 0x40, // 5f _
    0x00, 0x01, 0x02, 0x04, 0x00, // 60 `
    0x20, 0x54, 0x54, 0x54, 0x78, // 61 a
    0x7f, 0x48, 0x44, 0x44, 0x38, // 62 b
    0x38, 0x44, 0x44, 0x44, 0x20, // 63 c
    0x38, 0x44, 0x44, 0x48, 0x7f, // 64 d
    0x38, 0x54, 0x54, 0x54, 0x18, // 65 e
    0x08, 0x7e, 0x09, 0x01, 0x02, // 66 f
    0x0c, 0x52, 0x52, 0x52, 0x3e, // 67 g
    0x7f, 0x08, 0x04, 0x04, 0x78, // 68 h
    0x00, 0x44, 0x7d, 0x40, 0x00, // 69 i
    0x20, 0x40, 0x44, 0x3d, 0x00, // 6a j
    0x7f, 0x10, 0x28, 0x44, 0x00, // 6b k
    0x00, 0x41, 0x7f, 0x40, 0x00, // 6c l
    0x7c, 0x04, 0x18, 0x04, 0x78, // 6d m
    0x7c, 0x08, 0x04, 0x04, 0x78, // 6e n
    0x38, 0x44, 0x44, 0x44, 0x38, // 6f o
    0x7c, 0x14, 0x14, 0x14, 0x08, // 70 p
    0x08, 0x14, 0x14, 0x18, 0x7c, // 71 q
    0x7c, 0x08, 0x04, 0x04, 0x08, // 72 r
    0x48, 0x54, 0x54, 0x54, 0x20, // 73 s
    0x04, 0x3f, 0x44, 0x40, 0x20, // 74 t
    0x3c, 0x40, 0x40, 0x20, 0x7c, // 75 u
    0x1c, 0x20, 0x40, 0x20, 0x1c, // 76 v
    0x3c, 0x40, 0x30, 0x40, 0x3c, // 77 w
    0x44, 0x28, 0x10, 0x28, 0x44, // 78 x
    0x0c, 0x50, 0x50, 0x50, 0x3c, // 79 y
    0x44, 0x64, 0x54, 0x4c, 0x44, // 7a z
    0x00, 0x08, 0x36, 0x41, 0x00, // 7b {
    0x00, 0x00, 0x7f, 0x00, 0x00, // 7c |
    0x00, 0x41, 0x36, 0x08, 0x00, // 7d }
    0x10, 0x08, 0x08, 0x10, 0x08, // 7e ~
    0x78, 0x46, 0x41, 0x46, 0x78};


  void LCD5110_init(void)
{
    Delay10KTCYx(20);
    SCE_5110 = 0; // Enable the 5110 device (Active Low)
    RESET_5110 = 0; // Reset the device. Again, active low
    Delay10KTCYx(20); // Delay 20ms to make sure its ok!
    RESET_5110 = 1;

    OpenSPI(SPI_FOSC_16, MODE_00, SMPEND );

    LCD5110_send(0x20 + 0x01, 0); // Extended instructions enabled
    LCD5110_send(0x80 + 0x40, 0); // Set contrast 0 - 127
    LCD5110_send(0x04 + 0x02, 0); // Temperature control
    LCD5110_send(0x10 + 0x03, 0); // Set bias system
    LCD5110_send(0x20 + 0x00, 0); // Return to basic instruction set, power on, set horizontal addressing
    LCD5110_send(0x08 + 0x04, 0); // Display control set to normal mode
}

void LCD5110_send(unsigned char data, unsigned char dc)
{
    DC_5110 = dc; // Set the appropriate status for command=0 or data=1
    putcSPI (data);
}

void LCD5110_cls(unsigned char b_w)
{
    unsigned int i;
    unsigned char bg;

    if (b_w == 0) // set the background color
    {
        bg = 0x00;
    }
    else if (b_w == 1)
    {
        bg = 0xFF;
    }

    LCD5110_send(0x40, 0); // set Y address
    LCD5110_send(0x80, 0); // set X address
    for (i = 0; i < 504; i++)
    {
        LCD5110_send(bg, 1); // Clear everything
    }
}

void LCD5110_sendchar(unsigned char character)
{
    unsigned char column = 0;
    character = character - 0x20; // 0x20 is the first element of the array

    for (column = 0; column < 5; column++) // Pass through each column
    {
        LCD5110_send(font[(int) character * 5 + column], 1);
    }

    LCD5110_send(0x00, 1); // Send a small space
}

void LCD5110_sendstring(const char *str)
{
    while (*str) // pass through each character
    {
        LCD5110_sendchar(*str); // and send it
        str++;
    }

     }


la libreria compila perfectamente bien ...

el headers es el siguiente

Código: [Seleccionar]
void LCD5110_init(void);
void LCD5110_send(unsigned char data, unsigned char dc);
void LCD5110_cls(unsigned char b_w);
void LCD5110_sendchar(unsigned char character);
void LCD5110_sendstring(const char *str);



pero cuando pongo el mouse en putcspi (data) y mantengo apretado control ...me deberia llevar a esa funcion ...
y sin embargo me pone no puedo habrir el elemento putcspi ...

si habro SPI.h ...es como que si no interpreta los prototipos de las funciones ....y si sigo para atras en pconfig.h ....tambien esta todo comentado como que si no interpretaria el pic18f2550 ....no se si me explico ....perdon si me expreso mal


Ojala alguno pueda darme una mano porque esto me ha vuelto loco ...estoy usando el xc8 v1.20

Gracias a todos
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 26 de Septiembre de 2013, 16:06:07
Hola rodrigo.
Probaste poner la línea del include del pic al comienzo?
#include <pic18f2550.h>
Hubo algunas veces que agregándola se me solucionaron los problemas.
No debería ser así porque xc.h se encarga de ello pero con probar no se pierde nada.

Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 26 de Septiembre de 2013, 16:07:14
Bueno ...logre solucionarlo ....al menos ahora si saque los comentarios del spi.h

espero a alguien le sirva ...ahora si veo porque no funciona la libreria !!!

agregue en las propiedades del proyecto la macro de esta forma __18f2550

Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 26 de Septiembre de 2013, 16:08:41
Hola rodrigo.
Probaste poner la línea del include del pic al comienzo?
#include <pic18f2550.h>
Hubo algunas veces que agregándola se me solucionaron los problemas.
No debería ser así porque xc.h se encarga de ello pero con probar no se pierde nada.



Gracias Jukinch ...si lo habia hecho pero sin resultados positivos ...
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 26 de Septiembre de 2013, 16:45:34
  Estuve revisando un poco los headers y es en pconfig.h donde se establece el tipo de ADC, SPI, I2C etc que posee cada pic de la familia 18.
  Para mi poco entendimiento parecería ser que el problema radica en que en dicho header se evalúa si está definido por ejemplo "__18F2550" o "__18F458" y sin embargo en uno de los hedaers correspondientes al pic (p18f2550.h) se define como "__18F2550_H" y en el otro (pic18f2550.h) se define como "_PIC18F2550_H_". En ninguno de los casos concuerda con la evaluación que se realiza en "pconfig.h".
Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 26 de Septiembre de 2013, 23:31:55
Hola Angelgris. El tema viene por el problema que referís.

Recuerdo haber renegado con ello. Cito post

Con estas dos directivas se me fueron todos los unable to resolve identifiers :-/

#define __18CXX // con esta solucioné los de la libreria de los delays
#define __18F4550 // y con esta los de las funciones de la usart y de los adc

Pareciera que el IDE no define correctamente el pic seleccionado en el proyecto.  :5]
agregúe al principio de mi archivo  main.c estos dos defines



Creo que el problema está en que si no se los define a mano el preprocesador no expande el código correspondiente a nuestro pic dentro del archivo pconfig.h:

Código: [Seleccionar]
#ifdef   __18F4550
/*############################################################*/
/*          Configuration for device =  'PIC18F4550'          */
/*############################################################*/

/* ADC */
#define ADC_V5

/* ECC */
/*No configuration chosen for this peripheral*/

/* CC */
#define CC_V2

/* EPWM */
#define PWM_V5

/* PWM */
#define PWM_V5

/* PCPWM */
/*No configuration chosen for this peripheral*/

/* USART */
#define EAUSART_V5

/* SPI */
#define SPI_V1

/* I2C */
#define I2C_V1

/* TIMERS */
#define TMR_V2

/* EEPROM */
#define EEP_V2

/* PORT_B */
#define PTB_V1

/* ANCOMP */
#define ANCOM_V3

/* MWIRE */
#define MWIRE_V1

/* CTMU */
/*No configuration chosen for this peripheral*/

/* PPS */
/*No configuration chosen for this peripheral*/

/* RTCC */
/*No configuration chosen for this peripheral*/

/* DPSLP */
/*No configuration chosen for this peripheral*/

/* PMP */
/*No configuration chosen for this peripheral*/

/* FLASH */
#define FLASH_V1_2

#endif

Y por ello dentro de los headers de los periféricos se saltean los prototipos de las funciones.

Es necesario que estén definidas las versiones de cada uno de ellos por ejemplo en mi 4550 #define ADC_V5 . De lo contrario se saltean los prototipos de las funciones.

Como por ejemplo la de OpenADC en el header adc.h

Código: [Seleccionar]
#elif defined (ADC_V3) || defined (ADC_V4) || defined (ADC_V5) || defined (ADC_V6) ||\
      defined (ADC_V7) || defined (ADC_V7_1)|| defined (ADC_V12) || defined (ADC_V13)\
 || defined (ADC_V13_1) || defined (ADC_V13_2) || defined (ADC_V13_3) || \
 defined (ADC_V14) || defined (ADC_V14_1) || defined (ADC_V14_2) || defined (ADC_V14_3)

void OpenADC ( unsigned char ,
               unsigned char ,
               unsigned char );

Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 29 de Septiembre de 2013, 20:05:03
En estos día he estado trabajando en varios proyectos del colegio y ya los empecé a plantear en XC8. La verdad estoy muy conforme! Con esta guía, mas algunas cosas que me paso juknich pude hacer andar todo vastante rápido.

Pongo acá un ejemplo de uso del Enhanced CCP del PIC 16F883, utilizando el PWM para control de un motor de DC en modo full bridge. Esa capacidad del micro está muy, pero muy buena. Una vez configurado el PWM, solo hay que modificar 2 registros para cambiar el sentido de giro y el ciclo de trabajo. El módulo solo se encarga de activar un pin de salida, hacer PWM sobre el otro y desactivar los otros 2 en forward y vice verza en backward....

Dejo el código:

Código: [Seleccionar]
#define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro
//Funciones para delay's. No son muy precisas por lo que vi en el osciloscopio
//REVISAR
#pragma intrinsic(_delay)
extern void _delay(unsigned long);
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>         // Librería XC8. Este include termina incluyendo al 16F883.h
//#include <delays.h>     // Para utilizar demoras en nuestro código debemos incluir la librería delays.h.

//Includes locales, configuracion de fusibles y del IO
#include "configuracion_de_fuses.c"
#include "configuracion_hard.c"

unsigned char cont = 0;                   //Contador para destello de LED

/*------------------------DECLARACION DE FUNCIONES---------------------------*/

void conf_oscilador (void); // Configuracion del oscilador
void conf_puertos (void);   // Configuracion de puertos I/O
void conf_timer0 (void);    // Configuracion registros TIMER0
void conf_timer1 (void);    // Configuracion registros TIMER1
void conf_pwm (void);

/********** Funcion para la ISR (Rutina de Servicio de Interrupcion) **********/
void interrupt interrupciones (void) {
    //Verifico que interrupcion se disparó
    if (TMR0IE && TMR0IF){      // se verifica si la interrupcion es por TMR0

        //Destello de LED cada 20 * 65,535 mS -> 1,3Seg
        if(++cont == 20){
            cont=0;
            LED_tst ^= 1;
        }
        TMR0IF = 0;             // Pongo en 0 el Flag de interrupcion del TMR0
    }
/* el resto de las interrupciones utilizadas se deben analizar a coninuacion*/
}




/*************************** Programa Principal ******************************/
 void main(void) {
    conf_oscilador ();
    conf_puertos ();
    conf_timer0 ();
    conf_pwm();

    //conf_timer1 ();

    INTCONbits.TMR0IE = 1;       //Habilito interrupcion por TMR0
    INTCONbits.PEIE = 1;         //Habilito las interrupciones de los perifericos
    INTCONbits.GIE = 1;          //Habilito Interrupcion Global

    PORTC=0b00000000;
    int i=0;
    /*-------------------------- Bucle infinito ------------------------------*/
    do{
        CCP1CONbits.P1M=0b01;       //Motor en Forward
        CCPR1L=0;                   // DC en 0
        for(i=0; i<255; i+=5){      // Voy incrementando el DC de a 5
            CCPR1L = CCPR1L++;
            __delay_ms (50);
        }
        CCPR1L=0;                   // DC en 0
        CCP1CONbits.P1M=0b11;       // Motor en Backward
        for(i=0; i<255; i+=5){      // Voy incrementando el DC de a 5
            CCPR1L = CCPR1L++;
            __delay_ms (50);
        }
   }while(1);
}


/*------------------------------FUNCIONES------------------------------------*/

/* Funcion para la configuracion del oscilador del pic16f88 */
void conf_oscilador (void) {

    OSCCONbits.IRCF2 = 1;
    OSCCONbits.IRCF1 = 1;
    OSCCONbits.IRCF0 = 0; // IRCF <2:0> = 110 setea Fosc 4MHz

    OSCCONbits.SCS = 0; /* SCS = 0 Modo del oscilador definido por
                         * FOSC <2:0> en #pragma config FOSC = INTOSCIO */
}
/* Funcion para la configuracion de los puertos entrada salida del pic 16f88 */
void conf_puertos (void) {

    ANSEL=0x00;         //Todos entrada/salida digitales - Puerto A.
    ANSELH=0x00;        //Todos entrada/salida digitales - Puerto B.
    TRISA=0b00101010; //RA0, 2 y 4 Salidas. RA1, 3 y 5 Entradas-
    TRISB=0x00; //Todos como SALIDAS.
    TRISC=0x0F; //RC0-3 Entrada. RC4-7 Salida
    PORTC=0;
    PORTB=0;
}

/* Funcion para la configuracion del modulo Timer0 como temporizador */
void conf_timer0 (void) {

    // Configuración del timer 0. Con Osc de 4MHz la frecuencia de entrada del TMR
    // es 1MHz, con el prescaler en 256 tenemos una cuenta cada 256uSeg. Al ser
    // de 8 bits tenemos interrupcion cada 65,535 mSeg.
    TMR0 = 0;
    OPTION_REGbits.PS0 = 1;
    OPTION_REGbits.PS1 = 1;
    OPTION_REGbits.PS2 = 1;     //Prescaler en 256
    OPTION_REGbits.PSA = 0;     //Prescaler al TMR0 y no al WDT
    OPTION_REGbits.T0CS = 0;    //Clock Source es el Ciclo de Instruccion
}

/* Funcion para la configuracion del modulo Timer1 como temporizador */
void conf_timer1 (void) {

    // Configuración del timer 1. Con Osc de 4MHz la frecuencia de entrada del TMR
    // es 1MHz, con el prescaler en 1 tenemos una cuenta cada 1uSeg. Al ser
    // de 16 bits tenemos interrupcion cada 65,535 mSeg.
    // El timer 1 se usa como base de tiempos de CCP2
    TMR1 = 0;
    T1CONbits.T1CKPS = 0x00;    //Prescaler en 2 -> XX00
    T1CONbits.TMR1ON = 0;       //Enable Timer1
}


/* Funcion para la configuracion del modulo Timer1 como temporizador */
void conf_timer2 (void) {

    // Configuración del timer 1. Con Osc de 4MHz la frecuencia de entrada del TMR
    // es 1MHz, con el prescaler en 1 tenemos una cuenta cada 1uSeg. Al ser
    // de 16 bits tenemos interrupcion cada 65,535 mSeg.
    // El timer 1 se usa como base de tiempos de CCP2
    TMR1 = 0;
    T1CONbits.T1CKPS = 0x00;    //Prescaler en 2 -> XX00
    T1CONbits.TMR1ON = 0;       //Enable Timer1
}

void conf_pwm(void){
    // CONFIGURANDO PWM  - Pagina 133 datasheet
    TRISCbits.TRISC2=1;     //Configuro como entrada los pines del PWM
    TRISB |= 0b00010110;
    PR2 = 0x65;             // Frecuencia
    CCP1CONbits.CCP1M = 0b1100;     // Activamos el modo PWM.
    CCP1CONbits.P1M = 0b01;         // Full Bridge Forward
    CCP1CONbits.DC1B = 0b00;        // LSB del DC=0
    CCPR1=0x00;                     // MSB del DC=0

    PIR1bits.TMR2IF=0;              // Borro posible bandera de Int del TMR2
    T2CONbits.T2CKPS = 0b01;        // Prescaler del timer 2 en 1:4
    T2CONbits.TMR2ON = 1;           // Arranca el PWM
    while(PIR1bits.TMR2IF==0);      // Espero a primera interrupcion del TMR2
    TRISCbits.TRISC2=0;             // Configuro como Salida los pines del PWM
    TRISB &= ~(0b00010110);         // para que comience a funcionar
}

El archivo configuracion_de_hardware.c no lo incluyo porque en este caso no hay nada, solo la definicion del LED_tst que esta en RB5.

Este es el configuracion_de_fuses.c

Código: [Seleccionar]
// PIC16F883 Configuration Bit Settings

// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown Out Reset Selection bits (BOR disabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)

// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)

Si a halguien le interesa subo un videito del efecto que se consigue sobre unos LED. Todavia no tengo el puente H armado para verlo en el motor.

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 01 de Octubre de 2013, 16:00:44
Amigos ...les paso escrito en xc8 una subrutina modificada por mi para escribir un lcd 5110 de nokia ..con un pic18f2550 ....lo unico que no puedo llegar a entender todavia ..es la posicion de x ...me he cansado de leer el pdf del lcd y a mi entender estoy haciendo las cosas bien , pero no logro que escriba en la posicion x que quiero ...con y no tengo problemas ..esa va bien ...pero en x la verdad no lo entiendo si alguien me puede dar una mano ...bienvenido !!!!

5110lcd.h


Código: [Seleccionar]
/*
 * File:   5110lcd.h
 * Author: Ramiro
 *
 * Created on 22 de septiembre de 2013, 20:03
 */
  void gotoxy(int x , int y );
void LCD5110_init(void);
void LCD5110_send(unsigned char data, unsigned char dc);
void LCD5110_cls(unsigned char b_w);
void LCD5110_sendchar(unsigned char character);
void LCD5110_sendstring(const char *str);




5110lcd.c


Código: [Seleccionar]
/*
 * File:   5110lcd.c
 * Author: Ramiro Seliman 2013
 *
 * Created on 22 de septiembre de 2013, 20:32
 */


#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <delays.h>
#include <spi.h>
#include "5110lcd.h"

// define the pins

   #define SCE_5110  LATBbits.LATB3
   #define RESET_5110 LATBbits.LATB2
   #define DC_5110 LATBbits.LATB4



 const char font[] = {0x00, 0x00, 0x00, 0x00, 0x00, // 20 space
    0x00, 0x00, 0x5f, 0x00, 0x00, // 21 !
    0x00, 0x07, 0x00, 0x07, 0x00, // 22 "
    0x14, 0x7f, 0x14, 0x7f, 0x14, // 23 #
    0x24, 0x2a, 0x7f, 0x2a, 0x12, // 24 $
    0x23, 0x13, 0x08, 0x64, 0x62, // 25 %
    0x36, 0x49, 0x55, 0x22, 0x50, // 26 &
    0x00, 0x05, 0x03, 0x00, 0x00, // 27 '
    0x00, 0x1c, 0x22, 0x41, 0x00, // 28 (
    0x00, 0x41, 0x22, 0x1c, 0x00, // 29 )
    0x14, 0x08, 0x3e, 0x08, 0x14, // 2a *
    0x08, 0x08, 0x3e, 0x08, 0x08, // 2b +
    0x00, 0x50, 0x30, 0x00, 0x00, // 2c ,
    0x08, 0x08, 0x08, 0x08, 0x08, // 2d -
    0x00, 0x60, 0x60, 0x00, 0x00, // 2e .
    0x20, 0x10, 0x08, 0x04, 0x02, // 2f /
    0x3e, 0x51, 0x49, 0x45, 0x3e, // 30 0
    0x00, 0x42, 0x7f, 0x40, 0x00, // 31 1
    0x42, 0x61, 0x51, 0x49, 0x46, // 32 2
    0x21, 0x41, 0x45, 0x4b, 0x31, // 33 3
    0x18, 0x14, 0x12, 0x7f, 0x10, // 34 4
    0x27, 0x45, 0x45, 0x45, 0x39, // 35 5
    0x3c, 0x4a, 0x49, 0x49, 0x30, // 36 6
    0x01, 0x71, 0x09, 0x05, 0x03, // 37 7
    0x36, 0x49, 0x49, 0x49, 0x36, // 38 8
    0x06, 0x49, 0x49, 0x29, 0x1e, // 39 9
    0x00, 0x36, 0x36, 0x00, 0x00, // 3a :
    0x00, 0x56, 0x36, 0x00, 0x00, // 3b ;
    0x08, 0x14, 0x22, 0x41, 0x00, // 3c <
    0x14, 0x14, 0x14, 0x14, 0x14, // 3d =
    0x00, 0x41, 0x22, 0x14, 0x08, // 3e >
    0x02, 0x01, 0x51, 0x09, 0x06, // 3f ?
    0x32, 0x49, 0x79, 0x41, 0x3e, // 40 @
    0x7e, 0x11, 0x11, 0x11, 0x7e, // 41 A
    0x7f, 0x49, 0x49, 0x49, 0x36, // 42 B
    0x3e, 0x41, 0x41, 0x41, 0x22, // 43 C
    0x7f, 0x41, 0x41, 0x22, 0x1c, // 44 D
    0x7f, 0x49, 0x49, 0x49, 0x41, // 45 E
    0x7f, 0x09, 0x09, 0x09, 0x01, // 46 F
    0x3e, 0x41, 0x49, 0x49, 0x7a, // 47 G
    0x7f, 0x08, 0x08, 0x08, 0x7f, // 48 H
    0x00, 0x41, 0x7f, 0x41, 0x00, // 49 I
    0x20, 0x40, 0x41, 0x3f, 0x01, // 4a J
    0x7f, 0x08, 0x14, 0x22, 0x41, // 4b K
    0x7f, 0x40, 0x40, 0x40, 0x40, // 4c L
    0x7f, 0x02, 0x0c, 0x02, 0x7f, // 4d M
    0x7f, 0x04, 0x08, 0x10, 0x7f, // 4e N
    0x3e, 0x41, 0x41, 0x41, 0x3e, // 4f O
    0x7f, 0x09, 0x09, 0x09, 0x06, // 50 P
    0x3e, 0x41, 0x51, 0x21, 0x5e, // 51 Q
    0x7f, 0x09, 0x19, 0x29, 0x46, // 52 R
    0x46, 0x49, 0x49, 0x49, 0x31, // 53 S
    0x01, 0x01, 0x7f, 0x01, 0x01, // 54 T
    0x3f, 0x40, 0x40, 0x40, 0x3f, // 55 U
    0x1f, 0x20, 0x40, 0x20, 0x1f, // 56 V
    0x3f, 0x40, 0x38, 0x40, 0x3f, // 57 W
    0x63, 0x14, 0x08, 0x14, 0x63, // 58 X
    0x07, 0x08, 0x70, 0x08, 0x07, // 59 Y
    0x61, 0x51, 0x49, 0x45, 0x43, // 5a Z
    0x00, 0x7f, 0x41, 0x41, 0x00, // 5b [
    0x02, 0x04, 0x08, 0x10, 0x20, // 5c 55
    0x00, 0x41, 0x41, 0x7f, 0x00, // 5d ]
    0x04, 0x02, 0x01, 0x02, 0x04, // 5e ^
    0x40, 0x40, 0x40, 0x40, 0x40, // 5f _
    0x00, 0x01, 0x02, 0x04, 0x00, // 60 `
    0x20, 0x54, 0x54, 0x54, 0x78, // 61 a
    0x7f, 0x48, 0x44, 0x44, 0x38, // 62 b
    0x38, 0x44, 0x44, 0x44, 0x20, // 63 c
    0x38, 0x44, 0x44, 0x48, 0x7f, // 64 d
    0x38, 0x54, 0x54, 0x54, 0x18, // 65 e
    0x08, 0x7e, 0x09, 0x01, 0x02, // 66 f
    0x0c, 0x52, 0x52, 0x52, 0x3e, // 67 g
    0x7f, 0x08, 0x04, 0x04, 0x78, // 68 h
    0x00, 0x44, 0x7d, 0x40, 0x00, // 69 i
    0x20, 0x40, 0x44, 0x3d, 0x00, // 6a j
    0x7f, 0x10, 0x28, 0x44, 0x00, // 6b k
    0x00, 0x41, 0x7f, 0x40, 0x00, // 6c l
    0x7c, 0x04, 0x18, 0x04, 0x78, // 6d m
    0x7c, 0x08, 0x04, 0x04, 0x78, // 6e n
    0x38, 0x44, 0x44, 0x44, 0x38, // 6f o
    0x7c, 0x14, 0x14, 0x14, 0x08, // 70 p
    0x08, 0x14, 0x14, 0x18, 0x7c, // 71 q
    0x7c, 0x08, 0x04, 0x04, 0x08, // 72 r
    0x48, 0x54, 0x54, 0x54, 0x20, // 73 s
    0x04, 0x3f, 0x44, 0x40, 0x20, // 74 t
    0x3c, 0x40, 0x40, 0x20, 0x7c, // 75 u
    0x1c, 0x20, 0x40, 0x20, 0x1c, // 76 v
    0x3c, 0x40, 0x30, 0x40, 0x3c, // 77 w
    0x44, 0x28, 0x10, 0x28, 0x44, // 78 x
    0x0c, 0x50, 0x50, 0x50, 0x3c, // 79 y
    0x44, 0x64, 0x54, 0x4c, 0x44, // 7a z
    0x00, 0x08, 0x36, 0x41, 0x00, // 7b {
    0x00, 0x00, 0x7f, 0x00, 0x00, // 7c |
    0x00, 0x41, 0x36, 0x08, 0x00, // 7d }
    0x10, 0x08, 0x08, 0x10, 0x08, // 7e ~
    0x78, 0x46, 0x41, 0x46, 0x78};


  void LCD5110_init(void)
{
   
     OpenSPI(SPI_FOSC_64, MODE_00, SMPEND );


    Delay10KTCYx(20);
    SCE_5110 = 0; // Enable the 5110 device (Active Low)
    RESET_5110 = 0; // Reset the device. Again, active low
    Delay10KTCYx(20); // Delay 20ms to make sure its ok!
    RESET_5110 = 1;


    LCD5110_send(0x21, 0); // Extended instructions enabled
    LCD5110_send(0xC0, 0); // Set VOLTAJE 5V
    LCD5110_send(0x07, 0); // Temperature control
    LCD5110_send(0x13, 0); // Set bias system
    LCD5110_send(0x20, 0); // Display control set to BASIC mode
    LCD5110_send(0x0C, 0); // Display modo NORMAL
 

  }

  void gotoxy(int x , int y )
  {
   LCD5110_send((0x80 | x) , 0); //X address
   LCD5110_send((0x40 | y) , 0); //Y address

  }

void LCD5110_send(unsigned char data, unsigned char dc)
{
    DC_5110 = dc; // Set the appropriate status for command=0 or data=1
    putcSPI (data);
}


void LCD5110_cls(unsigned char b_w)
{
    unsigned int i;
    unsigned char bg;

    if (b_w == 0) // set the background color
    {
        bg = 0x00;
    }
    else if (b_w == 1)
    {
        bg = 0xFF;
    }

    LCD5110_send(0x40, 0); // set Y address
    LCD5110_send(0x80, 0); // set X address
    for (i = 0; i < 504; i++)
    {
        LCD5110_send(bg, 1); // Clear everything
    }
}

void LCD5110_sendchar(unsigned char character)
{
   
    unsigned char column = 0;
    character = character - 0x20; // 0x20 is the first element of the array

    for (column = 0; column < 5; column++) // Pass through each column
    {
        LCD5110_send(font[(int) character * 5 + column], 1);
    }

    LCD5110_send(0x00, 1); // Send a small space
}

void LCD5110_sendstring(const char *str)
{

//   LCD5110_send((0x40 | y) , 0); //Y address
//   LCD5110_send((0x80 | x) , 0); //X address

    while (*str) // pass through each character
    {
        LCD5110_sendchar(*str); // and send it
        str++;
    }

     }



main .c


Código: [Seleccionar]
/*
 * File:   main.c
 * Author: Ramiro Seliman 2013
 *
 * Created on 5 de septiembre de 2013, 14:24
 */
#include <xc.h>
#include <delays.h>
#include <stdio.h>
#include <stdlib.h>
#include "system.h"
#include <PIC18F2550.h>
#include <spi.h>
#include "5110lcd.h"


#define _XTAL_FREQ 8000000

   void main(void) {
   
     ConfigureOscillator();

     _delay(500);

  //  BMP085_Calibration();
    LATB = 0x00 ;
    PORTB = 0x00 ;
    TRISB = 0x00;
    TRISA = 0x00 ;
    LATC = 0x00 ;
    PORTC = 0x00 ;
    TRISC = 0x00 ;
    LCD5110_init();
    LCD5110_cls(0);



        gotoxy(1,0); // coordenada x , coordenada y
        LCD5110_sendstring("Hola Mundo!"); //envio string
while (1)
    {
    };
    return;
}


Bitsconfiguracion.c

Código: [Seleccionar]

// PIC18F2550 Configuration Bit Settings

// CONFIG1L

#pragma config PLLDIV = 1       // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
#pragma config USBDIV = 1       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)

// CONFIG1H
#pragma config FOSC = INTOSC_HS // Oscillator Selection bits (Internal oscillator, HS oscillator used by USB (INTHS))
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = ON       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = OFF         // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
#pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)

// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = OFF      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF      // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = OFF      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM is not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)





system.h


Código: [Seleccionar]
/*
 * File:   system.h
 * Author: Ramiro
 *
 * Created on 23 de septiembre de 2013, 15:03
 */

#ifndef SYSTEM_H
#define SYSTEM_H

#ifdef __cplusplus
extern "C" {
#endif




#ifdef __cplusplus
}
#endif

#endif /* SYSTEM_H */

 #define _XTAL_FREQ 8000000

void ConfigureOscillator(void);



system.c


Código: [Seleccionar]
/*
 * File:   system.c
 * Author: Ramiro
 *
 * Created on 23 de septiembre de 2013, 15:08
 */

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "system.h"

void ConfigureOscillator(void)
{
 
    ADCON1 = 0x0f ; //todos los bits como digitales

     CMCONbits.CM0 = 1;
     CMCONbits.CM1 = 1; // deshabilito los comparadores
     CMCONbits.CM2 = 1;

     OSCCONbits.IRCF2 = 1; //
     OSCCONbits.IRCF1 = 1; // defino oscilador interno en 8 mhz
     OSCCONbits.IRCF0 = 1; //
}
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 02 de Octubre de 2013, 13:30:41
Amigos ...ya encontre el problema de las coordenadas del lcd ...como siempre pasaba por alto parte del pdf ...los datos estan bien al comienzo del pdf del 5110 ...

Aplique una pequeña formula para que sea menos confuso ...entonces se puede tomar coordenadas reales ...la formula es la siguiente

elimine el gotoxy y agregue a la funcion sendstring las coordenadas ...quedando de esta manera

Código: [Seleccionar]
void LCD5110_sendstring(int x, int y, const char *str)
    {

    if (y == 1 ) y == 0 ;
    {
    x = (6*x)+y ;
    }
   LCD5110_send((0x80 | x) , 0); //X address
   LCD5110_send((0x40 | y) , 0); //Y address


    while (*str) // pass through each character
    {
        LCD5110_sendchar(*str); // and send it
        str++;
    }

y en el main llamo a la funcion de esta manera


Código: [Seleccionar]
   LCD5110_sendstring(4, 0, "Ramiro");
   LCD5110_sendstring(3,0, "Seliman");


Saludos ...espero a alguien le sirva ....


Título: Re: Mini curso "Programación en XC8"
Publicado por: jukinch en 08 de Octubre de 2013, 09:38:02
Rodrigo: Como siempre gracias por compartir. :)

Leo:
    subí el video!  :)
En cuanto a lo de los includes estos:
#include "configuracion_de_fuses.c"
#include "configuracion_hard.c"

deberían incluirse y llamarse así.
 #include "configuracion_de_fuses.h"
 #include "configuracion_hard.h"

 Y renombrar los respectivos archivos que incluimos a su correspondiente *.h
 Si los dejás con *.c funcionan igual. Pero conceptualmente lo que debemos incluir son *.h para hacer de interfaz y los archivos *.c debemos compilarlos y luego linkearlos junto a los demás.
Estoy medio perdido en el foro por el laburo pero en cuanto pueda retomar volcaré lo que estudié y ampliaré el concepto ese en la guia que está unos post atrás.
Abrazo
         Jukinch


 
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 08 de Octubre de 2013, 22:31:59
Hola, leo!!!

si, sabia lo de los .h, pero no tengo presente como compilar los .c aparte y linkearlos en el proyecto actual... recuerdo que en la facu hacíamos eso, incluso teniamos parte del codigo en asm y parte en c y compartian variables y todo, pero ya olvide como se hacía todo eso.

Tamien me pasó querer crear un archivo funciones.c y tratar de vincularlo al proyecto, pero no podía compilar. cuando lo saque del arbol de archivos fuentes en el proyecto se soluciono todo... eso es raro...

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 11 de Octubre de 2013, 14:38:27
Hola Muchachos !!! les hago una pregunta ....se podra usar en un 18f2550 ..el I2C y el SPI ..los dos a la ves ?? se podran conmutar o tendre que usar una subr por soft de i2c ??

Gracias
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 11 de Octubre de 2013, 14:53:49
  Se podría intentar apagar uno de los módulos cuando se vaya a utilizar el otro... Cuando hagas una comunicación I2C, el dispositivo SPI es casi seguro que no interpretará nada si es que usas una línea de habilitación. En el caso de hacer una comunicación SPI, habría que ver si las variaciones sobre las líneas SDA y SCL no son mal interpretadas por los dispositivos I2C que tengas en el bus.

  Puedes hacer algo sencillo con ambos tipos de dispositivos y simularlo en ISIS.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 15 de Noviembre de 2013, 11:02:13
  Dejo aquí este link (está aparte porque no sabía a qué resultado iba a llegar y no quería llenar de mensajes sin sentido éste hilo)   http://www.todopic.com.ar/foros/index.php?topic=41671.0 para quienes estén interesados en hacer pruebas con USB en XC8 y con el stack de microchip. Es simplemente unas pruebas que fui haciendo y funcionaron simulando en ISIS.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 15 de Noviembre de 2013, 20:55:03
Hola, estoy intentando adaptar un codigo de RedPic a un Pic18F4550, pero no consigo entrar en la interrupcion y por mas que lo miro no consigo dar con el problema.
Alguien seria tan amable de ayudarme.
Código: C
  1. /*
  2.  * Ejemplo de movimiento de un servo
  3.  * LICENCIA GPL
  4.  *
  5.  * File:   main.c
  6.  * Author: Miquel Servera
  7.  * Microcontrolador: PIC18F4550
  8.  * Compiler:   XC8 v1.21
  9.  * Ide:    MPLABX v1.95
  10.  *
  11.  * Date:    10-11-2013
  12.  */
  13.  
  14. // Ejemplo con un servo FUTABA S3003
  15. // Alimentación y pulsos a 5V
  16. // Cuadro de Tiempos :
  17. // Periodo 20 ms (Frecuencia 50 Hz)
  18. // Ancho Pulso minimo 0.5 ms
  19. // Ancho pulso medio 1.5 ms
  20. // Ancho pulso maximo 2.5 ms
  21. // TMR0 a 1:256 -> 1 RTCC cada 3.99 ms
  22. // -> 1 Tick cada 3.99 / 256 = 0.015 ms
  23. // -> 20 ms = (5 x RTCC completas)
  24. // Ancho Pulso minimo 0.5 ms -> 31 ticks de TMR0
  25. // Ancho pulso medio 1.5 ms -> 93 ticks de TMR0
  26. // Ancho pulso maximo 2.5 ms -> 155 ticks de TMR0
  27.  
  28. #define _XTAL_FREQ 48000000
  29. #include <xc.h>
  30. #include <plib/timers.h>
  31.  
  32. #pragma config FOSC=HSPLL_HS, PLLDIV=3, CPUDIV=OSC1_PLL2
  33. #pragma config IESO=OFF, FCMEN=OFF
  34. #pragma config PWRT=OFF, BOR=OFF, BORV=3, VREGEN=ON, WDT=OFF
  35. #pragma config MCLRE=ON, XINST=OFF, LVP=OFF, PBADEN=OFF
  36.  
  37. /* Definir el bit del pulsador de pruebas*/
  38. #define PULSADOR       LATA0
  39.  
  40. /* Definir el bit del PWM para el servo*/
  41. #define PIN_SERVO1     LATB0
  42.  
  43. /* Constantes para determinar si pulsador esta apretado o no */
  44. #define ESTADO_ON             1
  45. #define ESTADO_OFF            0
  46.  
  47. /*******************************************************/
  48. /* Declaracion de Variables.*/
  49. /*******************************************************/
  50. unsigned char contadorRTCC = 0;
  51. unsigned char flagRTCC = 0;
  52. unsigned char flagSERVO1 = 0;
  53.  
  54. /**********************************************************************************/
  55. /* Declaración del prototipo de las funciones implementadas en el archivo fuente. */
  56. /**********************************************************************************/
  57. void interrupt low_priority interrupcionDeBaja(void);
  58. void main(void);
  59. //void WriteTimer0(unsigned int timer0);
  60. //unsigned int ReadTimer0(void);
  61.  
  62. /*******************************************************/
  63. /* RUTINA DE ATENCION A LAS INTERRUPCIONES             */
  64. /*******************************************************/
  65. void interrupt low_priority interrupcionDeBaja(void)
  66. {
  67. //-- INT_TMR0 = 4*1/FOSC*(256-VALORTIMER)*PRESCALER
  68. //-- INT_TMR0 = 4*1/48000000*(256-68)*256
  69. //-- INT_TMR0 = 0.000000083*188*256
  70. //-- INT_TMR0 = 0.00399 => 3.99ms
  71.     if(INTCONbits.TMR0IF){
  72.         ++contadorRTCC;
  73.             if(contadorRTCC == 5){
  74.                 flagRTCC = 1;
  75.                 contadorRTCC = 0x00;
  76.                 INTCONbits.TMR0IF = 0;
  77.             }
  78.     }
  79. }
  80.  
  81. void main(void)
  82. {
  83.     unsigned char ValorTIMER0;
  84.  
  85.     //-- Configurar el pulsador y servo
  86.     ADCON1 = 0X06;  //-- Configurar RA0-RB0 como digital
  87.     TRISA0 = 1;     //-- RA0 como entrada
  88.     TRISB0 = 0;     //-- RB0 como salida
  89.  
  90. //-- Configuración del timer & interrupcion
  91.     TMR0 = 68;
  92.     INTCONbits.TMR0IE = 1;  //-- Habilitamos interrupcion por desbordamiento del TMR0
  93.     RCONbits.IPEN = 1;      //-- Activa modo alta y baja prioridad
  94.     INTCONbits.GIEL = 1;    //-- Permitimos interrupciones de baja prioridad
  95.     INTCONbits.GIEH = 1;    //-- Permitimos interrupciones de alta prioridad
  96.     T0CONbits.T0PS0 = 1;    //-- Prescale value
  97.     T0CONbits.T0PS1 = 1;    //-- Prescale value
  98.     T0CONbits.T0PS2 = 1;    //-- Prescale value
  99.     T0CONbits.PSA = 0;      //-- Timer0 prescaler is assigned
  100.     T0CONbits.T08BIT = 1;   //-- Timer0 is configured as an 8-bit timer/counter
  101.     T0CONbits.TMR0ON = 1;   //-- Timer0 On/Off Control bit
  102.  
  103.     /* Bucle principal */
  104.     while(1){
  105.     //-- Disparo del Pulso
  106.         if(flagRTCC == 1){
  107.             flagRTCC = 0x00;
  108.             PIN_SERVO1 = 0x01;
  109.             flagSERVO1 = 1;
  110.         }
  111.  
  112.     //-- Control del ancho del Pulso
  113.         if(flagSERVO1 == 1){
  114.             ValorTIMER0 = ReadTimer0();
  115.             if(ValorTIMER0>93){
  116.                 flagSERVO1 = 0;
  117.                 PIN_SERVO1 = 0x00;
  118.             }
  119.         }
  120.     }
  121. }

Gracias!
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 15 de Noviembre de 2013, 21:53:29
  Por defecto (luego de un PowerOnReset) el timer0 queda configurado en interrupción de alta prioridad y en tu programa lo quieres utilizar en el vector de baja prioridad. Te falta cambiar el bit TMR0IP del registro INTCON2.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 16 de Noviembre de 2013, 07:08:20
Gracias por el dato AngelGris, se me paso por alto dicho bit pero sigue sin entrar en la interrupcion, me volvere a leer el datasheet y os cuento.
De todas formas voy a hacer un programa que sea una simple interrupcion, parpadeo de un led, nada mas para probar.

Saludos y Gracias de nuevo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 16 de Noviembre de 2013, 10:36:41
Gracias por el dato AngelGris, se me paso por alto dicho bit pero sigue sin entrar en la interrupcion, me volvere a leer el datasheet y os cuento.
De todas formas voy a hacer un programa que sea una simple interrupcion, parpadeo de un led, nada mas para probar.

Saludos y Gracias de nuevo.

  Te falto seleccionar la fuente de clock para el timer, por defecto queda configurada la entrada por el pin T0CKI. Tienes que hacer 0 el bit TOCS del registro T0CON para que tome como fuente el clock de instrucción, es decir a la frecuencia que trabaja el núcleo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 16 de Noviembre de 2013, 14:02:46
Gracias AngelGris, ahora si, justo antes de leerte me había percatado de que faltaba dicho bit de configuración. Una pregunta que siempre me ronda, ¿Influye el orden con que configuras los bit de una interrupción?
Por ejemplo yo lo tengo así:
Código: C
  1. //-- Configuración del timer & interrupcion
  2.     TMR0 = 68;
  3.     INTCONbits.TMR0IE = 1;  //-- Habilitamos interrupcion por desbordamiento del TMR0
  4.     RCONbits.IPEN = 1;      //-- Activa modo alta y baja prioridad
  5.     INTCONbits.GIEL = 1;    //-- Permitimos interrupciones de baja prioridad
  6.     INTCONbits.GIEH = 1;    //-- Permitimos interrupciones de alta prioridad
  7.     INTCON2bits.TMR0IP = 0; //-- TMR0 Overflow Interrupt Priority bit
  8.     T0CONbits.T0PS0 = 1;    //-- Prescale value
  9.     T0CONbits.T0PS1 = 1;    //-- Prescale value
  10.     T0CONbits.T0PS2 = 1;    //-- Prescale value
  11.     T0CONbits.PSA = 0;      //-- Timer0 prescaler is assigned
  12.     T0CONbits.T08BIT = 1;   //-- Timer0 is configured as an 8-bit timer/counter
  13.     T0CONbits.T0CS = 0;     //-- Timer0 Clock Source Select bit
  14.     T0CONbits.TMR0ON = 1;   //-- Timer0 On/Off Control bit
Da lo mismo cual vaya primero.

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 16 de Noviembre de 2013, 15:30:15
  Yo siempre tengo en cuenta que los últimos bits en habilitar sean GIEL y GIEH, y antes de ello borrar todos los flag para asegurarme que no se dispare ninguna en el momento de la habilitación general.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 21 de Noviembre de 2013, 14:05:45
Hola a todos ...los molesto por lo siguiente a ver si alguien me puede dar una mano , estoy trasnsmitiendo a travez de una placa apc220 de ctm electronica los datos en NMEA de un gps locosys 20033 , y los recibo en una pc en delphi donde hago el parseo y extraigo los datos que nesecito ...hasta ahi todo bien , por otro lado estoy con un 18f2550 ..y un bmp085 ..sacando datos de temperatura presion y altura ...a esto le sumo los datos de tension de la bateria ...ahora la pregunta es la siguiente

como puedo hacer para a travez del 18f2550 enviar todos los datos juntos separados por comas ...o sea los del gps mas los del bmp085 mas los de la bateria ...Me explico ?? al bmp085 mas la bateria ya los organice a los datos separados por comas y los saco por la apc220 ...el tema es como armar una misma trama ...bmp085 mas gps mas bateria ...todos separados por comas ...

Espero alguien se le ocurra algo , muchas gracias

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 21 de Noviembre de 2013, 20:24:52
quizás debieras abrir un hilo nuevo por ese tema particular...
no obstante ello, muy interesantes los modulos!!!! tienes el precio de ellos?
en cuanto a la aplicacion me suena a uav, puede ser?
en cuanto a la solución no estoy seguro de como implementarlo....

saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 21 de Noviembre de 2013, 20:54:18
quizás debieras abrir un hilo nuevo por ese tema particular...
no obstante ello, muy interesantes los modulos!!!! tienes el precio de ellos?
en cuanto a la aplicacion me suena a uav, puede ser?
en cuanto a la solución no estoy seguro de como implementarlo....

saludos!


Hola como estas ?? gracias por responder ....si tenes razon deberia abrir un hilo nuevo ...en cuanto a la aplicacion ...les va a parecer raro lo que hago ya que no muchos se dedican a esto pero bueno ...se los comento igual ...hago coheteria civil (diseño y construyo cohetes ) ...y el sistema que estoy desarrollando es un sistema de telemetria para un vector de mediano porte ....

Gracias

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 21 de Noviembre de 2013, 22:02:27
quizás debieras abrir un hilo nuevo por ese tema particular...
no obstante ello, muy interesantes los modulos!!!! tienes el precio de ellos?
en cuanto a la aplicacion me suena a uav, puede ser?
en cuanto a la solución no estoy seguro de como implementarlo....

saludos!


Hola como estas ?? gracias por responder ....si tenes razon deberia abrir un hilo nuevo ...en cuanto a la aplicacion ...les va a parecer raro lo que hago ya que no muchos se dedican a esto pero bueno ...se los comento igual ...hago coheteria civil (diseño y construyo cohetes ) ...y el sistema que estoy desarrollando es un sistema de telemetria para un vector de mediano porte ....

Gracias

Saludos

  Que interesante lo tuyo, felicitaciones!!!!!!
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 21 de Noviembre de 2013, 23:14:01
interesante, interesante!!!!! de pibe siempre veia en la lupin los temas de coheteria y he visto en unos foros las cosas tremendas que hacen!!!! se puede ver en algun sitio lo que estas haciendo?

saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 23 de Noviembre de 2013, 07:16:00
interesante, interesante!!!!! de pibe siempre veia en la lupin los temas de coheteria y he visto en unos foros las cosas tremendas que hacen!!!! se puede ver en algun sitio lo que estas haciendo?

saludos!

Bueno muchas gracias ....claro que se puede ver ...tengo un canal en youtube ...ramiroseliman  www.youtube.com/user/ramiroseliman‎

me alegro les guste .....LUPIN !!!!!! jajajajajaja mi revista de la infancia ...que grande no !!!! siempre la tengo presente ...

tambien soy participe de www.grupoartax.com.ar

al que le interese me chifla ....somos pocos los locos !!!

Un Abrazo
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 23 de Noviembre de 2013, 07:23:39
quizás debieras abrir un hilo nuevo por ese tema particular...
no obstante ello, muy interesantes los modulos!!!! tienes el precio de ellos?
en cuanto a la aplicacion me suena a uav, puede ser?
en cuanto a la solución no estoy seguro de como implementarlo....

saludos!


Elgarbe ....perdoname se me paso tu pregunta de los precios ....con respecto al locosys 20033 ...si mal no recuerdo lo pague 55 dolares ....y la placa apc220 de ctm la pague algo de 20 dolares c/u ...ultimamente me falla la memoria ...asi que si queres estar seguro de los precios ...te averiguo bien y te confirmo ....el BMP085 ...lo compre por ebay ...a 2,5 dolares ...tambien compre un acelerometro por algo de 11 dolares ...y unas placas de bluetooth en 2 o 3 dolares ....por ebay me demoraron entre 1 y 2 meses

un Abrazo
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 23 de Noviembre de 2013, 09:06:55
  Hola Ramiro, intenté entrar al canal de youtube y salió un mensaje diciendo que el canal no existe. Algo está pasando con dicho sitio porque a mí se me borraron algunos videos.

  ¿Podrías comentarme eso de NMEA? Ya que no tengo idea  :oops:
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 23 de Noviembre de 2013, 09:24:30
  Hola Ramiro, intenté entrar al canal de youtube y salió un mensaje diciendo que el canal no existe. Algo está pasando con dicho sitio porque a mí se me borraron algunos videos.

  ¿Podrías comentarme eso de NMEA? Ya que no tengo idea  :oops:

Hola Angelgris ....sabes que no se porque le puso caracteres raros al link ....el canal anda ...       http://www.youtube.com/user/ramiroseliman      ....a ver ahora     http://www.youtube.com/user/ramiroseliman   

NMEA ....es una forma de separar la informacion que se usa en GPS ...es un protocolo de informacion maritima National Marine Electronics Association ...si queres informarte mas ...wikipedia ....

Un Abrazo
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 23 de Noviembre de 2013, 09:51:20
  Ahora sí pude entrar, tendré que tomarme el tiempo de ver esos videos ya que parecen muy interesantes  ((:-))  ((:-))  ((:-))
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 23 de Noviembre de 2013, 12:28:04
Ramiro, pero que buenos trabajos!!!!! me estare poniendo en contacto por privado para ver si podemos armar algún vinculo, yo tmb soy profesor en una est aca en ramallo...

saludos!!!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 23 de Noviembre de 2013, 18:40:17
Ramiro, pero que buenos trabajos!!!!! me estare poniendo en contacto por privado para ver si podemos armar algún vinculo, yo tmb soy profesor en una est aca en ramallo...

saludos!!!

Como no Leonardo cuando quieras ...

Un Abrazo
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 23 de Noviembre de 2013, 22:47:19
volviendo al tema podrías poner parte del codigo que tienes como para ver un poco mas el tema? la placa de cmt se comunica con el micro por uart? en delphi lo mismo, los datos llegan por la uart?
algo que se me ocurre y que creo que es lo que se hace normalmente es crear una estructra de datos con los miembros que quieras, un miembro sería la trama del gps actual, otro miembro la altura, otro la presion, otra la temperatura.... luego lo que haces es enviar la estructura completa por la uart y en delphi, creas la misma estructura con los mismos mimbros al recivir los datos los tendras en una estructura, bien facil de mostrar... es medio complicado asi esxlicado, pero creo que se implementa fácil....
igual posteando el codigo que estas usando podemos ver que te falta...

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Suky en 24 de Noviembre de 2013, 00:09:51
Hola! Lo que necesitas ahora es comunicar el GPS y el bmp085 con el 18F2550, y utilizando el APC220 enviar los datos a una PC?

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 24 de Noviembre de 2013, 11:37:16
Hola! Lo que necesitas ahora es comunicar el GPS y el bmp085 con el 18F2550, y utilizando el APC220 enviar los datos a una PC?

Saludos!

Bueno el tema es asi a ver si lo puedo explicar mejor ....

el gps tiene salida ttl ...y salen de ahi ya los datos separados por comas en formato NMEA ....eso no importa (el formato ) ..el tema es que ya salen listos ..o sea que aca no hay codigo en pic ...en delphi no tengo problemas pra recibier esto ...en uno de los videos se ve que esto ya esta todo implementado ..y funciona ...la placa apc220 es ttl tambien o sea que recibe los datos directos del gps y los transmite solamente cruzo rx tx y listo ...aca el trabajo es puro delphi ...
ahora por otro lado ..codigo en el pic 18f2550 ...aca ingrso por i2c con el bmp085 ..del cual saco presion y temperatura ...y con la presion calculo la altura ...en xc8 ...luego de estar los calculos , envio por la uart del pic los datos de presion temperatura y altura , separados por coma , con un caracter # de inicio y un $ de fin para armar la trama ....hasta todo bien tambien en uno de los videos se ve ....

El tema es ahora meter las dos cosas juntas ...y que los datos vayan en una misma trama ...o dos separadas no importa ...pero que los dos salgan por la placa apc220 ....para desp recibirlos en delphi todo junto ...

Me eplico ???

Muchisimas gracias Amigos !!!!

Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 24 de Noviembre de 2013, 11:56:17
y si metes los datos del gps al 2550 y alli armas la trama completa?
si no tiene 2 uart, la que recive los datos del gps la puedes hacer por software....

otra podría ser poner unas llaves electrónicas (no se si el 4066 sirve para eso) y que el micro elija si pasan los datos del gps o los mismos del micro. hay unos integrados digitales que no recuerdo como se llaman, transeiver, codificadores, no recuerdo, pero posee 2 entradas por cada línea de salida y con un pin de control se elije que dato pasa a la salida...

Me interesa el código del bmp, estoy por utilizar uno igual, está disponible?

Salludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 24 de Noviembre de 2013, 12:09:35
y si metes los datos del gps al 2550 y alli armas la trama completa?
si no tiene 2 uart, la que recive los datos del gps la puedes hacer por software....

otra podría ser poner unas llaves electrónicas (no se si el 4066 sirve para eso) y que el micro elija si pasan los datos del gps o los mismos del micro. hay unos integrados digitales que no recuerdo como se llaman, transeiver, codificadores, no recuerdo, pero posee 2 entradas por cada línea de salida y con un pin de control se elije que dato pasa a la salida...

Me interesa el código del bmp, estoy por utilizar uno igual, está disponible?

Salludos!

Porsupuesto que si esta disponible ...se aprende mucho al compartir ...creo que ahi esta el secreto ahora te paso el codigo ....

Yo tambien pense en poner un integrado que separe ...pero me gusta mas la idea de entrar por una uart por soft ...ya vere que hago

te paso el codigo del Bmp

Código: [Seleccionar]
/*
 * File:   bmp085.c
 * Author: Ramiro
 *
 * Created on 21 de septiembre de 2013, 13:09
 */

#define _XTAL_FREQ 8000000

#include "xc.h"
#include <math.h>
#include "bmp085.h"



// * Defines ************************************************************
#define BMP085_R 0xEF
#define BMP085_W 0xEE
#define OSS 3 // Oversampling Setting

// * Globals Variables **************************************************

const unsigned char OSS_conversion_time[] = {5, 8, 14, 26};

signed char BMP_err;

long ac1;
long ac2;
long ac3;
long b1;
long b2;
long mb;
long mc;
long md;
unsigned long ac4;
unsigned long ac5;
unsigned long ac6;

/************************************************************************
*
*
************************************************************************/
void delay_ms(unsigned short ms)
{
for(; ms > 0; ms--)
{
Delay100TCYx(20);
}
}

/************************************************************************
*
*
************************************************************************/
void BMP085_Calibration(void)
{
ac1 = (signed short) bmp085ReadShort(0xAA);
ac2 = (signed short) bmp085ReadShort(0xAC);
ac3 = (signed short) bmp085ReadShort(0xAE);
ac4 = bmp085ReadShort(0xB0);
ac5 = bmp085ReadShort(0xB2);
ac6 = bmp085ReadShort(0xB4);
b1 = (signed short) bmp085ReadShort(0xB6);
b2 = (signed short) bmp085ReadShort(0xB8);
mb = (signed short) bmp085ReadShort(0xBA);
mc = (signed short) bmp085ReadShort(0xBC);
md = (signed short) bmp085ReadShort(0xBE);
}

/************************************************************************
*
*
************************************************************************/
void BMP085_Known_Calibration(void)
{
ac1 = 408;
ac2 = -72;
ac3 = -14383;
ac4 = 32741;
ac5 = 32757;
ac6 = 23153;
b1 = 6190;
b2 = 4;
mb = -32768;
mc = -8711;
md = 2868;
}


/************************************************************************
*
************************************************************************/
void BMP_process_error()
{
#ifdef ERROR_HANDLING
if(BMP_err != 0)
{
flag |= BMP_ERROR;
printf((const far rom char*) "BMP_err: %d\r\n", BMP_err);
BMP_err = 0;
}
#endif
}

/************************************************************************
*
*
************************************************************************/
unsigned short bmp085ReadShort(unsigned char address)
{
unsigned short msb, lsb;
unsigned short data;
StartI2C();

BMP_err |= WriteI2C(BMP085_W); // Write 0xEE
BMP_err |= WriteI2C(address); // Write register address

RestartI2C();

BMP_err |= WriteI2C(BMP085_R); // Write 0xEF

msb = ReadI2C(); // Get MSB result
BMP_err |= AckI2C();
lsb = ReadI2C(); // Get LSB result


NotAckI2C();
StopI2C();

delay_ms(10);

data = msb << 8;
data |= lsb;

BMP_process_error();

return data;
}

/************************************************************************
*
*
************************************************************************/
unsigned long bmp085ReadThreeBytes(unsigned char address)
{
unsigned short msb, lsb, xlsb;
unsigned long data;

StartI2C();

BMP_err |= WriteI2C(BMP085_W); // Write 0xEE
BMP_err |= WriteI2C(address); // Write register address

RestartI2C();

BMP_err |= WriteI2C(BMP085_R); // Write 0xEF

msb = ReadI2C(); // Get MSB result
AckI2C();
lsb = ReadI2C(); // Get LSB result

NotAckI2C();
StopI2C();

delay_ms(10);

data = msb;
data <<= 8;
data |= lsb;
data <<= 8;
data |= xlsb;

BMP_process_error();

return data;
}

/************************************************************************
*
*
************************************************************************/
long bmp085ReadTemp(void)
{
StartI2C();

WriteI2C(BMP085_W); // Write 0xEE
WriteI2C(0xF4); // Write register address
WriteI2C(0x2E); // Write register data for temp

StopI2C();

delay_ms(10); // Max time is 4.5ms

return (signed short) bmp085ReadShort(0xF6);
}

/************************************************************************
*
*
************************************************************************/
long bmp085ReadPressure(void)
{
StartI2C();

WriteI2C(BMP085_W); // Write 0xEE
WriteI2C(0xF4); // Write register address
WriteI2C(0x34 | (OSS << 6)); // Write register data for temp

StopI2C();

delay_ms(OSS_conversion_time[OSS]); // Max time is 4.5ms
if(OSS) {
return bmp085ReadThreeBytes(0xF6);
} else {
return ((long) bmp085ReadShort(0xF6)) << 8;
}
}

/************************************************************************
*
*
************************************************************************/

#define SHIFT(shift) (((long) 1) << (shift))

void bmp085Convert(long *temperature, long *pressure, unsigned char readings)
{
long ut;
long up;
long x1, x2, b5, b6, x3, b3, p;
unsigned long b4, b7;
unsigned char i;

ut = 0;
up = 0;

for(i = 0; i < readings; i++)
{
ut += bmp085ReadTemp();
up += bmp085ReadPressure();
}
ut = ut / readings;
up = up / readings;

up = up >> (8-OSS);

x1 = (ut - ac6) * ac5 / SHIFT(15);
x2 = (mc * SHIFT(11)) / (x1 + md);
b5 = x1 + x2;
*temperature = (b5 + 8) / SHIFT(4);

b6 = b5 - 4000;
x1 = (b2 * (b6 * b6 / SHIFT(12))) / SHIFT(11);
x2 = ac2 * b6 / SHIFT(11);
x3 = x1 + x2;

b3 = ((((ac1 * 4) + x3) << OSS) + 2) / SHIFT(2);
x1 = ac3 * b6 / SHIFT(13);
x2 = (b1 * (b6 * b6 / SHIFT(12))) / SHIFT(16);
x3 = ((x1 + x2) + 2) / SHIFT(2);
b4 = (ac4 * (unsigned long) (x3 + 32768)) / SHIFT(15);
b7 = ((unsigned long) up - b3) * (50000 >> OSS);
p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;

x1 = p / SHIFT(8);
x1 *= x1;
x1 = (x1 * 3038) / SHIFT(16);
x2 = (-7357 * p) / SHIFT(16);
x2 = x2 / SHIFT(16);

*pressure = p + (x1 + x2 + 3791) / SHIFT(4);

}


en el main usas primero

BMP085_Calibration()   

lo cual obtiene los valores fijos de calibracion , y desp de esto lees directamente los datos

 bmp085Convert(&temperature, &pressure, 5);


Cualquier cosa me preguntas !!! un abrazo






Título: Re: Mini curso "Programación en XC8"
Publicado por: Suky en 24 de Noviembre de 2013, 12:53:21
Comparto la idea con elgarbe, hay que leer los datos del GPS con el 18f2550, cada vez que llegue una trama agregarle lo de los demás parámetros, y de ahí enviarlo a la PC... Este ultimo podes hacerlo con una uart por SW. (porque según recuerdo el GPS envía datos cada x tiempo, y ahí te conviene usar interrupciones)

Colocar llaves electrónicas puede ser mas complicado, porque hay que determinar cuando esta enviando datos, sino tenes posibilidad de cortar la trama enviada.

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 24 de Noviembre de 2013, 13:16:16
por cierto, en:
C:\Archivos de programa\Microchip\xc8\v1.21\include\plib
tenes un archivo llamado sw_uart, ahí esta la implementacion para pic18 de una uart por software.

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 01 de Diciembre de 2013, 09:57:18
Ramiro, las funciones writei2c y las demas referentes al i2c donde estan las definiciones? son de alguna plib de microchip?

me llego la imu para empezar a jugar y probablemente comience con este sensor hasta que le agarre la mano al i2c, que nunca he usado...

saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 01 de Diciembre de 2013, 12:48:14
Ramiro, las funciones writei2c y las demas referentes al i2c donde estan las definiciones? son de alguna plib de microchip?

me llego la imu para empezar a jugar y probablemente comience con este sensor hasta que le agarre la mano al i2c, que nunca he usado...

saludos!

Como andas ?? busca en el doc plibs de xc8 en procesador 2550 ...yo la saque de ahi ...en la carpeta de xc8 en docs ...ahi tenes el pdf de las libs ...

Un Abrazo
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 01 de Diciembre de 2013, 12:58:57
Ramiro, las funciones writei2c y las demas referentes al i2c donde estan las definiciones? son de alguna plib de microchip?

me llego la imu para empezar a jugar y probablemente comience con este sensor hasta que le agarre la mano al i2c, que nunca he usado...

saludos!

Perdoname te entendi mal ....lo que pasa es que yo llame la lib desde otro lado ...esta en la carpeta plib de xc8 ...i2c.h ...y como usarla esta en el doc de las libs de xc8 ...bahhh c18 pero es lo mismo ...el doc esta en la carpeta docs en la carpeta del compiler xc8
Abrazo
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 01 de Diciembre de 2013, 12:59:37
Perfecto, me imaginaba que andaría por ahí.
Ya estudie el código que posteaste junto con el datasheet y ya entiendo como funcionan las funciones.

Ahora biene lo más lindo, tengo que portar esas funciones a ARM ya que estoy usando la LPCXpresso para conectar el sensor... ya iremos viendo que pasa.

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 01 de Diciembre de 2013, 15:51:46
Ramiro, tendras el bmp085.h a mano?

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 01 de Diciembre de 2013, 18:47:53
  Yo utilizaría UART por hard para la comunicación con el GPS. I2C por Hard para la comunicación con el BMP y UART por soft para la comunicación con la PC.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 02 de Diciembre de 2013, 09:15:50
Ramiro, tendras el bmp085.h a mano?

Saludos!

Te lo paso cuando llegue a casa disculpame !!!

Abrazo
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 02 de Diciembre de 2013, 13:35:59
Ramiro, tendras el bmp085.h a mano?

Saludos!

Te lo paso cuando llegue a casa disculpame !!!

Abrazo

Aca va el .h

Código: [Seleccionar]
/*
 * File:   bmp085.h
 * Author: Ramiro
 *
 * Created on 21 de septiembre de 2013, 13:12
 */

#ifndef BMP085_H
#define BMP085_H

#ifdef __cplusplus
extern "C" {
#endif




#ifdef __cplusplus
}
#endif

#endif /* BMP085_H */

void delay_ms(unsigned short ms);
void BMP085_Calibration(void);
long bmp085ReadTemp(void);
long bmp085ReadPressure(void);
unsigned short bmp085ReadShort(unsigned char address);
void bmp085Convert(long *temperature, long *pressure, unsigned char readings);
void BMP_process_error();
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rojasfx en 28 de Diciembre de 2013, 19:50:28
Buenas Compañeros de electronica..

Quiero hacer un proyecto sencillo de un contador que incremente al presionar un pulsador, y que muestre el valor en un display de 7 seg, sin embargo tengo problemas con el contador tengo una leve idea, si alguien pudiera darme una mano se lo agradeceria..    Lo que pretendo es que en la variable llamada contador se almacene el valor...  no inclui la parte de display de 7 seg porque quisiera ir por partes..

// PIC16F877A Configuration Bit Settings
#define XTAL_FREQ  12000000
#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF        // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON         // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

int contador;

int main(int argc, char** argv) {
    TRISD = 0x00;
    TRISC = 0x01;
    contador = 0;
    PORTC = 0x00;
    PORTD = 0x00;

    if(RC0 ==0){
            contador = contador++;}
      end if

Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 28 de Diciembre de 2013, 20:02:26
  El problema que hay en como haces la lectura del pin es que si el pin queda presionado mucho tiempo el contador seguirá contando y ademas sería bueno colocar algún delay como antirrebote... si no es eso lo que necesitas debería modificar la forma de la lectura... tal vez algo así pueda funcionar...

Código: C
  1. unsigned int contado = 0; // contador
  2. unsigned char estado = 0; // guardo el estado del pulsador (1 indica presionado y 0 sin presionar)
  3.  
  4. if ((estado == 1) && (PORTCbits.RC0 == 1)) // si estaba presionado y ahora esta suelto
  5.   estado = 0; // boton suelto
  6. if ((estado == 0) && (PORTCbits.RC0 == 0)) // si estaba suelto y ahora esta presionado...
  7. {
  8.   __delay_ms(15); // 15 mS de antirrebote
  9.   if (PORTCbits.RC0 == 0) // si sigue presionado
  10.   {
  11.     contador++; // incremento el contador
  12.     estado = 1; // boton presionado
  13.   }
  14. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rojasfx en 28 de Diciembre de 2013, 20:57:02
Gracias compañero por el aporte.. 
   Veo que estas mas familiarizado que yo en esto.

   Preguntas:
        1.  declare bien los puertos?
        2.  como hago para "invocar" el valor almacenado en la variable contador?
             
             
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 28 de Diciembre de 2013, 23:10:09
Gracias compañero por el aporte.. 
   Veo que estas mas familiarizado que yo en esto.

   Preguntas:
        1.  declare bien los puertos?
        2.  como hago para "invocar" el valor almacenado en la variable contador?
             
             

  1) ¿A que te refieres con "declare bien los puertos"? Si te refieres a que si están bien configurados, todo dependerá de tus necesidades. En este ejemplo en particular que sólo necesitas RC0 como entrada, sí está bien el valor del registro TRISC

  2) No entiendo que quieres decir con invocar. Si quieres compararlo con otro valor y otra variable es tan fácil como hacer algo así

Código: C
  1. if (contador != variable) // si contador distinto de variable
  2. o
  3. if (contador > 50) // si contador mayor a 50
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rojasfx en 29 de Diciembre de 2013, 02:01:56
Si con declarar puertos me refiero configurarlos es que lo que deseo es precionar un pulsador y que el contador vaya contando y este numero verlo en un display de 7 segmentos
  y que cuando el  contador llegue a cierto numero digamos 9 se resete y comienze de nuevo

Un asunto que le he estado dando y no entiendo porque me señala erron la linea __delay_ms (15); salen varios errores al copilar como que falta un ) y que error de sintaxis y ya defini el oscilador.. no entiendo porque..
Título: Re: Mini curso "Programación en XC8"
Publicado por: luisccl en 14 de Febrero de 2014, 00:01:01
alguien podria decirme donde encontrar nuevamente el turorial de suky acerca de PIC 18, que el link de la pagina mencionado en todos los post esta caido de hace muchos dias, y al parecer nadie dice nada al respecto :(
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 19 de Febrero de 2014, 13:26:56
  Subo una librería para LCD 2x16. Está basada en una que había hecho anteriormente para HiTech, sólo que esta vez cuenta con una función para crear caracteres y se puede utilizar con o sin el pin RW. Sólo la simulé en ISIS y funcionó bien, y como la versión anterior hubo gente del foro que la utilizó, imagino que ésta versión tendrá que funcionar también.

xclcd.h
Código: C
  1. #ifndef XCLCD_H
  2. #define XCLCD_H
  3.  
  4. #ifndef _XC_H_
  5. #include <xc.h>
  6. #endif
  7.  
  8. /******************************************************************************
  9.  *  Parametros configurables por el usuario                                   *
  10.  ******************************************************************************/
  11.  
  12. /*
  13.  * El valor de _XTAL_FREQ debe coincidir con el valor definido
  14.  * en el programa principal
  15.  */
  16.  
  17. /*
  18.  * LCDEN define el pin EN para el lcd
  19.  * LCDRS define el pin RS para el lcd
  20.  * LCDRW define el pin RW para el lcd
  21.  * LCDDATA define el puerto de datos
  22.  */
  23.  
  24. /*
  25.  * Si se utiliza un pic con resgistros LAT
  26.  * se pueden definir los pines utilizando LAT<x>bits.LAT<x><y>
  27.  * siendo <x> la letra del puerto correspondiente y <y> el bit
  28.  * Tambien se puede definir de la misma manera el puerto de datos
  29.  */
  30.  
  31. /*
  32.  * LCDTRISEN define el bit TRIS para el pin EN
  33.  * LCDTRISRS define el bit TRIS para el pin RS
  34.  * LCDTRISRW define el bit TRIS para el pin RW
  35.  * LCDTRIS define el TRIS correspondiente al puerto de datos
  36.  */
  37.  
  38. /*
  39.  * PROTOCOL4BIT define si se utiliza protocolo de 4 bits
  40.  * PROTOCOL8BIT define si se utiliza protocolo de 8 bits
  41.  */
  42.  
  43. /*
  44.  * En caso de utilizar protocolo de 4 bits
  45.  * UPPER define si se utiliza el nibble alto del puerto
  46.  * LOWER define si se utiliza el nibble bajo del puerto
  47.  */
  48.  
  49. /*
  50.  * En caso de utilizar el pin RW, hay que definir
  51.  * USE_RW
  52.  */
  53.  
  54. #ifndef _XTAL_FREQ
  55. #define _XTAL_FREQ 20000000
  56. #endif
  57.  
  58. #define LCDEN PORTBbits.RB0
  59. #define LCDRS PORTBbits.RB1
  60. #define LCDRW PORTBbits.RB2
  61. #define LCDTRISEN TRISBbits.TRISB0
  62. #define LCDTRISRS TRISBbits.TRISB1
  63. #define LCDTRISRW TRISBbits.TRISB2
  64. #define LCDDATA PORTB
  65. #define LCDTRIS TRISB
  66. #define PROTOCOL4BIT
  67. #define UPPER
  68. #define USE_RW
  69.  
  70.  
  71. /******************************************************************************
  72.  *  Definicion de valores para lcd_setdisplay                                 *
  73.  ******************************************************************************/
  74. /*
  75.  * Los valores se pueden combinar utilizando el operador |
  76.  */
  77.  
  78. #define DISPLAY_OFF 0b00001000
  79. #define DISPLAY_ON  0b00001100
  80. #define CURSOR_OFF  0b00001100
  81. #define CURSOR_ON   0b00001110
  82. #define BLINK_OFF   0b00001100
  83. #define BLINK_ON    0b00001101
  84.  
  85. /******************************************************************************
  86.  *  Definicion de valores para lcd_shift                                      *
  87.  ******************************************************************************/
  88. /*
  89.  * Los valores se pueden combinar utilizando el operador |
  90.  */
  91.  
  92. #define SHIFT_DISPLAY 0b00011000
  93. #define SHIFT_CURSOR  0b00010000
  94. #define SHIFT_LEFT    0b00010000
  95. #define SHIFT_RIGHT   0b00010100
  96.  
  97. /******************************************************************************
  98.  *  Definicion de valores para lcd_entrymode                                  *
  99.  ******************************************************************************/
  100. /*
  101.  * Los valores se pueden combinar utilizando el operador |
  102.  */
  103.  
  104. #define INCREMENT 0b00000110
  105. #define DECREMENT 0b00000100
  106. #define SHIFT_ON  0b00000101
  107. #define SHIFT_OFF 0b00000100
  108.  
  109.  
  110. /******************************************************************************
  111.  *  Definicion de funciones                                                   *
  112.  ******************************************************************************/
  113.  
  114. void lcd_init(void);
  115. void lcd_put(unsigned char, unsigned char);
  116. void lcd_puts(const unsigned char*);
  117. void lcd_gotoxy(unsigned char, unsigned char);
  118. bit lcd_busy(void);
  119. void lcd_putini(unsigned char);
  120. void lcd_createchar(unsigned char, const unsigned char*);
  121. void lcd_setdisplay(unsigned char);
  122. void lcd_shift(unsigned char);
  123. void lcd_entrymode(unsigned char);
  124.  
  125. #define lcd_putch(x) lcd_put(x,1)
  126. #define lcd_clear() lcd_put(0x01,0)
  127. #define lcd_home() lcd_put(0x02,0)
  128. #define lcd_off() lcd_put(0x08,0)
  129. #define lcd_on() lcd_put(0x0C,0)
  130.  
  131. #endif  /* XCLCD_H */


xclcd.c
Código: C
  1. #include "xclcd.h"
  2.  
  3. #if !defined(LCDEN) || !defined(LCDRS)
  4. #error Faltan definir los pines de control
  5. #elif !defined(LCDTRISEN) || !defined(LCDTRISRS)
  6. #error Falta definir la direccion de los pines de control
  7. #elif !defined(LCDDATA) || !defined(LCDTRIS)
  8. #error Falta definir el puerto y/o el tris de datos
  9. #elif !defined(PROTOCOL4BIT) && !defined(PROTOCOL8BIT)
  10. #error Falta definir el protocolo
  11. #elif defined(PROTOCOL4BIT) && !defined(UPPER) && !defined(LOWER)
  12. #error Falta definir el nibble
  13. #else
  14.  
  15. void lcd_init(void)
  16. {
  17.     unsigned char veces;
  18.  
  19.     LCDEN = 0;
  20.     LCDRS = 0;
  21.     LCDRW = 0;
  22.     LCDTRISRS = 0;
  23.     LCDTRISRW = 0;
  24.     LCDTRISEN = 0;
  25.     __delay_ms(15);
  26.     for (veces = 3; veces > 0; veces--)
  27.     {
  28.     lcd_putini(0x30);
  29.     __delay_ms(5);
  30.     }
  31. #if defined(PROTOCOL8BIT)
  32.     lcd_put(0x38,0);                          // Dos lineas, caracter 5x8
  33. #elif defined(PROTOCOL4BIT)
  34.     lcd_putini(0x20);                         // Protocolo de 4 bits
  35.     lcd_put(0x28,0);                          // Dos lineas, caracter 5x8
  36. #endif
  37.     lcd_put(0x08,0);                          // Apagar display, cursor, blink
  38.     lcd_put(0x01,0);                          // Borrar display
  39.     lcd_put(0x06,0);                          // Incrementa posicion, sin shift
  40. }
  41.  
  42. void lcd_putini(unsigned char data)
  43. {
  44.     unsigned char lasttris;
  45.  
  46.     lasttris = LCDTRIS;
  47. #if defined(PROTOCOL8BIT)
  48.     LCDTRIS = 0;
  49.     LCDDATA = data;
  50. #elif defined(PROTOCOL4BIT)
  51. #if defined(UPPER)
  52.     LCDTRIS &= 0x0F;
  53.     LCDDATA = (LCDDATA & 0x0F) | data;
  54. #elif defined(LOWER)
  55.     LCDTRIS &= 0xF0;
  56.     data = data >> 4;
  57.     LCDDATA = (LCDDATA & 0xF0) | data;
  58. #endif
  59. #endif
  60.     LCDEN = 1;
  61.     __delay_us(1);
  62.     LCDEN = 0;
  63.     LCDTRIS = lasttris;
  64. }
  65.  
  66. void lcd_put(unsigned char data, unsigned char reg)
  67. {
  68.     unsigned char lasttris;
  69.  
  70.     lasttris = LCDTRIS;
  71. #if defined (USE_RW)
  72.     while(lcd_busy() == 1);
  73. #else
  74.     __delay_ms(2);
  75. #endif
  76.     LCDRS = reg;
  77.     LCDRW = 0;
  78. #if defined(PROTOCOL8BIT)
  79.     LCDTRIS = 0;
  80.     LCDDATA = data;
  81.     LCDEN = 1;
  82.     __delay_us(1);
  83.     LCDEN = 0;
  84. #elif defined(PROTOCOL4BIT)
  85. #if defined(UPPER)
  86.     LCDTRIS &= 0x0F;
  87.     LCDDATA = (LCDDATA & 0x0F) | (data & 0xF0);
  88.     LCDEN = 1;
  89.     __delay_us(1);
  90.     LCDEN = 0;
  91.     __delay_us(1);
  92.     LCDDATA = (LCDDATA & 0x0F) | (data << 4);
  93.     LCDEN = 1;
  94.     __delay_us(1);
  95.     LCDEN = 0;
  96. #elif defined(LOWER)
  97.     LCDTRIS &= 0xF0;
  98.     LCDDATA = (LCDDATA & 0xF0) | (data >> 4);
  99.     LCDEN = 1;
  100.     __delay_us(1);
  101.     LCDEN = 0;
  102.     __delay_us(1);
  103.     LCDDATA = (LCDDATA & 0xF0) | (data & 0x0F);
  104.     LCDEN = 1;
  105.     __delay_us(1);
  106.     LCDEN = 0;
  107. #endif
  108.  
  109. #endif
  110.     LCDTRIS = lasttris;
  111. }
  112.  
  113.  
  114. bit lcd_busy(void)
  115. {
  116.     unsigned char lasttris;
  117.     unsigned char busy;
  118.  
  119.     lasttris = LCDTRIS;
  120.     LCDRS = 0;
  121.     LCDRW = 1;
  122. #if defined(PROTOCOL8BIT)
  123.     LCDTRIS = 0xFF;
  124.     LCDEN = 1;
  125.     __delay_us(1);
  126.     busy = LCDDATA;
  127.     LCDEN = 0;
  128. #elif defined(PROTOCOL4BIT)
  129. #if defined(UPPER)
  130.     LCDTRIS = (LCDTRIS & 0x0F) | 0xF0;
  131.     LCDEN = 1;
  132.     __delay_us(1);
  133.     busy = LCDDATA;
  134.     LCDEN = 0;
  135.     __delay_us(1);
  136.     LCDEN = 1;
  137.     __delay_us(1);
  138.     LCDEN = 0;
  139. #elif defined(LOWER)
  140.     LCDTRIS = (LCDTRIS & 0xF0) | 0x0F;
  141.     LCDEN = 1;
  142.     __delay_us(1);
  143.     busy = LCDDATA << 4;
  144.     LCDEN = 0;
  145.     __delay_us(1);
  146.     LCDEN = 1;
  147.     __delay_us(1);
  148.     LCDEN = 0;
  149. #endif
  150. #endif
  151.     LCDTRIS = lasttris;
  152.     if ((busy & 0x80) == 0x80) return 1;
  153.     else
  154.         return 0;
  155. }
  156.  
  157. void lcd_gotoxy(unsigned char x, unsigned char y)
  158. {
  159.     x--;
  160.     y--;
  161.     if (y == 0) lcd_put((0x80 + x),0);
  162.     else
  163.         lcd_put((0xC0 + x),0);
  164. }
  165.  
  166. void lcd_puts(const unsigned char* st)
  167. {
  168.     while (*st != 0)
  169.     {
  170.         lcd_put(*st,1);
  171.         st++;
  172.     }
  173. }
  174.  
  175. void lcd_createchar(unsigned char asciicode, const unsigned char* ascii)
  176. {
  177.     unsigned char line;
  178.     unsigned char caracter;
  179.  
  180.     for (line = 0; line < 7; line++)
  181.     {
  182.         caracter = ((asciicode & 0x07) << 3) | 0x40 + line;
  183.         lcd_put(caracter,0);
  184.         lcd_put(*ascii,1);
  185.         ascii++;
  186.     }
  187.     caracter = ((asciicode & 0x07) << 3) | 0x47;
  188.     lcd_put(caracter,0);
  189.     lcd_put(0,1);
  190.     lcd_clear();
  191. }
  192.  
  193. void lcd_setdisplay(unsigned char state)
  194. {
  195.     lcd_put(state,0);
  196. }
  197.  
  198. void lcd_shift(unsigned char state)
  199. {
  200.     lcd_put(state,0);
  201. }
  202.  
  203. void lcd_entrymode(unsigned char state)
  204. {
  205.     lcd_put(state,0);
  206. }
  207. #endif
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 19 de Febrero de 2014, 13:29:16
  Y aquí un programa de ejemplo. En este ejemplo definí el caracter ñ y muestro la palabra "Pequeño" y "Pequeno" para ver como queda el caracter representado en el LCD.

Código: C
  1. #include <xc.h>
  2.  
  3. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
  4. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  5. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  6. #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
  7. #pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
  8. #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
  9. #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
  10. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  11.  
  12. #define _XTAL_FREQ 20000000
  13.  
  14. #include "xclcd.h"
  15.  
  16. void main(void)
  17. {
  18.     unsigned char alfa[17] = "Peque";
  19.     const unsigned char letra[8] = {0b00000000,
  20.                                     0b00001110,
  21.                                     0b00000000,
  22.                                     0b00010110,
  23.                                     0b00011001,
  24.                                     0b00010001,
  25.                                     0b00010001};
  26.     unsigned char veces;
  27.  
  28.     CMCON = 7;
  29.     PORTA = 0;
  30.     TRISA = 0;
  31.     PORTB = 0;
  32.     TRISB = 0;
  33.     lcd_init();
  34.     lcd_createchar(1,letra);
  35.     lcd_setdisplay(DISPLAY_OFF);
  36.     lcd_puts("Pequeno");
  37.     lcd_gotoxy(1,2);
  38.     lcd_puts(alfa);
  39.     lcd_putch(1);
  40.     lcd_putch('o');
  41.     lcd_gotoxy(1,1);
  42.     lcd_setdisplay(CURSOR_ON);
  43.     while(1);
  44. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 19 de Febrero de 2014, 13:52:14
Gracias AngelGris por el aporte, ahora me toca estudiar.

 :5] QUE ENVIDIA me conformaria con saber una parte de lo que sabeis la mayoria de vosotros.

Miquel_S
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 19 de Febrero de 2014, 14:41:20
  Comparto tu opinión, que bueno sería saber aunque sea una mínima parte de lo que saben Nocturno, RedPic, Suky, Picuino y tantos otros... uno los sigue desde atrás pero en lugar de acortar la distancia, ésta se estira cada vez más  :oops:
Título: Re: Mini curso "Programación en XC8"
Publicado por: rotting79 en 21 de Febrero de 2014, 03:14:17
here is another library for LCD 2 x 16 on  XC8, may be helpful....

http://www.todopic.com.ar/foros/index.php?topic=41874.msg348245#msg348245
Título: Re: Mini curso "Programación en XC8"
Publicado por: freshdesing en 26 de Febrero de 2014, 07:26:40
TIMER 1 y TIMER 2 con 16F876A:

main.c

Código: C
  1. /******************************************************************************/
  2. /* Files to Include
  3.  *
  4.  * *****   TIMER 1   *****
  5.  * 16 bit  2x8bit TMR1H y TMR1L  0000h -> FFFFh
  6.  *
  7.  * TMR1ON: Star-Stop TIMER 1
  8.  * TMR1CS: Clock Source Timer/Counter
  9.  *      -T1SYNC: Syncronizacion
  10.  * T1OSCEN: enable-disable TIMER 1
  11.  * TMR1IE : Flag de interrupción
  12.  * T1CKPS1:T1CKPS0: Prescaler (1,2,4,8) -> Se borra al escribir en TMR1H o TMR1L
  13.  *
  14.  * (Registro PIR1)
  15.  * TMR1IF: Flag Overflow -> Borrar por software
  16.  *
  17.  * (Registro PIE1)
  18.  * TMR1IE: Enable interrupt TIMER 1
  19.  *
  20.  * (Registro INTCON)
  21.  * GIE: Activar interrupciones golobales
  22.  * PEIE: Activar interrupciones de perifericos
  23.  *
  24.  * Cuando esta funcionando: RC1 y RC0 son SALIDAS
  25.  *
  26.  * Interrupcion=4*TOSC*(65535-TMR1)*PRESCALER
  27.  *
  28.  *
  29.  * *****   TIMER 2   *****
  30.  * 8 bit  PR2 00h -> FFh
  31.  * Cuenta de 00h a PR2
  32.  * (Registro T2CON)
  33.  * TMR2ON: Star-Stop TIMER 2  (T2CON)
  34.  * T2CKPS1:T2CKPS0: Prescaler (1,4,16)
  35.  * TOUTPS3:TOUTPS0: Poscaler (1...16)
  36.  *
  37.  * (Registro PIR1)
  38.  * TMR2IF: Flag Overflow -> Borrar por software
  39.  *
  40.  * (Registro PIE1)
  41.  * TMR2IE: Enable interrupt TIMER 2
  42.  *
  43.  * (Registro INTCON)
  44.  * GIE: Activar interrupciones golobales
  45.  * PEIE: Activar interrupciones de perifericos
  46.  * Interrupcion=4*TOSC*(255-PR2)*PRESCALER*POSCALER
  47.  *
  48.  *
  49.  */
  50. /******************************************************************************/
  51. /* Interrupcion cada 100ms con el TIMER 1 (TMR1=53035)  LED RB0
  52. /* Interrupcion cada 50ms con el TIMER 2 (PR2=60) LED RB1
  53. /******************************************************************************/
  54.  
  55.  
  56. #include <xc.h>         /* XC8 General Include File */
  57.  
  58. #include <stdio.h>
  59. #include <stdint.h>        /* For uint8_t definition */
  60. #include <stdbool.h>       /* For true/false definition */
  61.  
  62.  
  63. #include "user.h"          /* User funct/params, such as InitApp */
  64. #include "configuration_bits.c"
  65. //#include "interrupts.c"
  66.  
  67. #define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro
  68. //#include <p16f876x.h>
  69. #define LED_B0 PORTBbits.RB0
  70. #define LED_B1 PORTBbits.RB1
  71. /******************************************************************************/
  72. /* User Global Variable Declaration  */
  73.  
  74.  
  75. /******************************************************************************/
  76.  
  77. /* i.e. uint8_t <variable_name>; */
  78.  
  79. void interrupt high_isr(void)
  80.     {
  81.     //Interrupcion TIMER 1
  82.     if(PIR1bits.TMR1IF == 1)
  83.         {
  84.         LED_B0 ^= 1;
  85.         TMR1H = 0xCF; // TIMER1 = 53035
  86.         TMR1L = 0x2B;
  87.         PIR1bits.TMR1IF = 0;      // Limpiamos bandera de desborde
  88.         }
  89.  
  90.     //Interrupcion TIMER 2
  91.     if(PIR1bits.TMR2IF == 1)
  92.         {
  93.         LED_B1 ^= 1;
  94.         PR2 = 195; //TIMER2 = 195
  95.         PIR1bits.TMR2IF = 0;      // Limpiamos bandera de desborde
  96.         }
  97.  
  98.     }
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107. /******************************************************************************/
  108. /* Main Program                                                               */
  109. /******************************************************************************/
  110.  
  111.     // FUNCION PRINCIPAL
  112. void main () {
  113.    TRISB = 0;                   // Puerto B como salidas
  114.    PORTB = 0;
  115.  
  116.    // Configuración del timer & interrupcion
  117.    
  118.    //Configuracion TIMER 1
  119.    T1CONbits.TMR1CS = 0 ;   //Internal Clock
  120.    T1CONbits.T1CKPS0 = 1;   //Prescaler = 8
  121.    T1CONbits.T1CKPS1 = 1;
  122.    PIE1bits.TMR1IE = 1;     //Habilitar interrupcion TIMER 1
  123.    PIR1bits.TMR1IF = 0;      // Limpiamos bandera de desborde
  124.    T1CONbits.TMR1ON = 1;    //TIMER 1 ON
  125.  
  126.    //Configuracion TIMER 2
  127.    T2CONbits.T2CKPS1 = 1;    //Prescaler = 16
  128.    T2CONbits.TOUTPS0 = 1;    //Postcale = 16
  129.    T2CONbits.TOUTPS1 = 1;
  130.    T2CONbits.TOUTPS2 = 1;
  131.    T2CONbits.TOUTPS3 = 1;
  132.    PIE1bits.TMR2IE = 1;     //Habilitar interrupcion TIMER 2
  133.    PIR1bits.TMR2IF = 0;      // Limpiamos bandera de desborde
  134.    T2CONbits.TMR2ON = 1;    //TIMER 2 ON
  135.  
  136.    //Configuracion interrupciones
  137.    INTCONbits.PEIE = 1;     //Peripheral Interrupt Enable bit
  138.    INTCONbits.GIE = 1;      //Global Interrupt Enable bit
  139.  
  140.  
  141.  
  142.  
  143.  
  144.    
  145.  
  146.  
  147.  
  148.    // Bucle infinito
  149.    while (1)
  150.    {
  151.  
  152.        
  153.    }
  154. }


configuration_bits.c

Código: C
  1. /******************************************************************************/
  2. /* Main Files to Include                                                      */
  3. /******************************************************************************/
  4.  
  5.  
  6. #include <xc.h>         /* XC8 General Include File */
  7.  
  8.  
  9. /******************************************************************************/
  10. /* Configuration Bits                                                         */
  11. /*                                                                            */
  12. /* Refer to your Hi-Tech User Manual in the PICC installation directory       */
  13. /* /doc folder for more information on filling in configuration bits.         */
  14. /* In addition, configuration bit mnemonics can be found in your              */
  15. /* PICC\version\include\<processor name>.h file for your device.  The XC8     */
  16. /* compiler contains documentation on the configuration bit macros within     */
  17. /* the compiler installation /docs folder in a file called                    */
  18. /* pic18_chipinfo.html.                                                       */
  19. /*                                                                            */
  20. /* For additional information about what the hardware configurations mean in  */
  21. /* terms of device operation, refer to the device datasheet.                  */
  22. /*                                                                            */
  23. /* A feature of MPLAB X is the 'Generate Source Code to Output' utility in    */
  24. /* the Configuration Bits window.  Under Window > PIC Memory Views >          */
  25. /* Configuration Bits, a user controllable configuration bits window is       */
  26. /* available to Generate Configuration Bits source code which the user can    */
  27. /* paste into this project.                                                   */
  28. /*                                                                            */
  29. /******************************************************************************/
  30.  
  31. /* TODO Fill in your config bits here.  Use the configuration bits generator/ */
  32. #include <xc.h>         /* XC8 General Include File */
  33. #include <stdint.h>        /* For uint8_t definition */
  34. #include <stdbool.h>       /* For true/false definition */
  35. #include <pic16f876a.h>
  36.  
  37.  
  38. // PIC16F876A Configuration Bit Settings
  39. #pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
  40. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  41. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  42. #pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
  43. #pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
  44. #pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
  45. #pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
  46. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

Cualquier mejora sera bienvenida.

Un saludo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Joe86 en 02 de Marzo de 2014, 22:42:25
Hola a todos, soy nuevo en el foro, ni siquiera sabía que ahora hay que decir que tiempo es el que se va estar dentro del Foro jejeje... He leído las respuestas y preguntas que muchos de ustedes han realizado a través de este tema, y Woao, no se, mi duda en algunos puntos se han aclarado, por ejemplo en los "Fuses" que no sabía que había que declararlos, yo vengo de Proton IDE y tengo ya más de 3 años que no agarro un PIC para programar, y simplemente por el uso de Software libre quise intentarlo usando las herramientas necesarias que existen para Ubuntu, cosa que MPLAB me suena bastante interesante y amigable, como bien dicen, se parece mucho a NetBeans para Java. En fin, lo único que busco es hacer un pequeño contador que muestre en 3 displays 7 segmentos, pero como quiero un PIC pequeño, procuro utilizar un Decodificador para ahorrarme unas patas del microcontrolador. Entonces mi gran duda es, por que cuando trato de activar un pin del microcontrolador a través de una variable, asignándole su respectiva posición, el compilador me da error?. Intento realizar algo como así:

char numeros[10] = {0,1,2,3,4,5,6,7,8,9};
char numero, i ;
numero = numeros ;

PORTBbits.RB0 = numero.0 ;
PORTBbits.RB1 = numero.1 ;
PORTBbits.RB2 = numero.2 ;
PORTBbits.RB3 = numero.3 ;

Esto debido a que numero debe ir cambiando ya que solo utilizo un solo decodificador y 3 displays, debido que la cifra más grande a mostrar posee 3 unidades, desde 0 a 250. No tengo todo el programa terminado, pero simplemente quería saber si el compilador no me daba error cuando trataba de modificar un bit del puerto del microcontrolador, pero no puedo hacerlo desde una variable, si me pudieran orientar mejor?, porque no recuerdo sinceramente si desde PROTON en Basic se podía realizar dicha modificaciones. O es que a juro necesito decirle que el valor es 0 o 1 para poder modificar el valor del pin del microcontrolador?... Gracias...
Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 03 de Marzo de 2014, 06:44:25
Hola a todos, soy nuevo en el foro, ni siquiera sabía que ahora hay que decir que tiempo es el que se va estar dentro del Foro jejeje... He leído las respuestas y preguntas que muchos de ustedes han realizado a través de este tema, y Woao, no se, mi duda en algunos puntos se han aclarado, por ejemplo en los "Fuses" que no sabía que había que declararlos, yo vengo de Proton IDE y tengo ya más de 3 años que no agarro un PIC para programar, y simplemente por el uso de Software libre quise intentarlo usando las herramientas necesarias que existen para Ubuntu, cosa que MPLAB me suena bastante interesante y amigable, como bien dicen, se parece mucho a NetBeans para Java. En fin, lo único que busco es hacer un pequeño contador que muestre en 3 displays 7 segmentos, pero como quiero un PIC pequeño, procuro utilizar un Decodificador para ahorrarme unas patas del microcontrolador. Entonces mi gran duda es, por que cuando trato de activar un pin del microcontrolador a través de una variable, asignándole su respectiva posición, el compilador me da error?. Intento realizar algo como así:

char numeros[10] = {0,1,2,3,4,5,6,7,8,9};
char numero, i ;
numero = numeros ;

PORTBbits.RB0 = numero.0 ;
PORTBbits.RB1 = numero.1 ;
PORTBbits.RB2 = numero.2 ;
PORTBbits.RB3 = numero.3 ;

Esto debido a que numero debe ir cambiando ya que solo utilizo un solo decodificador y 3 displays, debido que la cifra más grande a mostrar posee 3 unidades, desde 0 a 250. No tengo todo el programa terminado, pero simplemente quería saber si el compilador no me daba error cuando trataba de modificar un bit del puerto del microcontrolador, pero no puedo hacerlo desde una variable, si me pudieran orientar mejor?, porque no recuerdo sinceramente si desde PROTON en Basic se podía realizar dicha modificaciones. O es que a juro necesito decirle que el valor es 0 o 1 para poder modificar el valor del pin del microcontrolador?... Gracias...

Eso de numero.0 no es correcto en C, En el compilador XC8 se puede realizar PORTBbits.RB0 porque el compilador tiene definido PORTBbits como estructura, para poder acceder a los bits de una variable de forma similar a la que se accede a los pines del micro debe definir la variable de la siguiente forma:


Código: C
  1. union
  2. {
  3.     char value;
  4.     struct
  5.     {
  6.         unsigned bit0:1;
  7.         unsigned bit1:1;
  8.         unsigned bit2:1;
  9.         unsigned bit3:1;
  10.         unsigned bit4:1;
  11.         unsigned bit5:1;
  12.         unsigned bit6:1;
  13.         unsigned bit7:1;
  14.  
  15.     }bits;
  16.  
  17. }numero;

Una vez definida la variable de esa manera puede acceder a ella de la siguiente forma:

Código: C
  1. numero.value = numeros[i];
  2. PORTBbits.RB0 = numero.bits.bit0;

Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 20 de Marzo de 2014, 13:40:20
  Librería para manejo de teclado... Está pensada para teclado telefónico y Hexa. El puerto de las filas es la entrada y el de las columnas es la salida.
  La idea de funcionamientos es que primeramente están todas las salidas activas, para poder evaluar si hay alguna tecla presionada. Dentro de la función KBDGetKey() se hace un barrido secuencial de las columnas. Sólo una columna a la vez queda configurada como salida, el resto se configura como entrada para evitar posibles problemas.

xckbd.h
Código: C
  1. #ifndef XCKBD_H
  2. #define XCKBD_H
  3.  
  4.   #ifndef _XC_H_
  5.     #include <xc.h>
  6.   #endif
  7.   #include <stdint.h>
  8.  
  9.  /*****************************************************************************
  10.   *  Disposicion de los diferentes teclados                                   *
  11.   *****************************************************************************
  12.  
  13.   *****************************************************************************
  14.   *           PHONE_KEYPAD                        HEXA_KEYPAD                 *
  15.   *****************************************************************************
  16.   *        Out0   Out1   Out2                Out0   Out1   Out2   Out3        *
  17.   *          |      |      |                   |      |      |      |         *
  18.   *         ---    ---    ---                 ---    ---    ---    ---        *
  19.   *   In0--| 1 |--| 2 |--| 3 |          In0--| 0 |--| 1 |--| 2 |--| 3 |       *
  20.   *         ---    ---    ---                 ---    ---    ---    ---        *
  21.   *          |      |      |                   |      |      |      |         *
  22.   *         ---    ---    ---                 ---    ---    ---    ---        *
  23.   *   In1--| 4 |--| 5 |--| 6 |          In1--| 4 |--| 5 |--| 6 |--| 7 |       *
  24.   *         ---    ---    ---                 ---    ---    ---    ---        *
  25.   *          |      |      |                   |      |      |      |         *
  26.   *         ---    ---    ---                 ---    ---    ---    ---        *
  27.   *   In2--| 7 |--| 8 |--| 9 |          In2--| 8 |--| 9 |--| A |--| B |       *
  28.   *         ---    ---    ---                 ---    ---    ---    ---        *
  29.   *          |      |      |                   |      |      |      |         *
  30.   *         ---    ---    ---                 ---    ---    ---    ---        *
  31.   *   In3--| * |--| 0 |--| # |          In3--| C |--| D |--| E |--| F |       *
  32.   *         ---    ---    ---                 ---    ---    ---    ---        *
  33.   *                                                                           *
  34.   *****************************************************************************/
  35.  
  36.  
  37.   /****************************************************************************
  38.    *  Parametros configurables por el usuario                                 *
  39.    ****************************************************************************/
  40.  
  41.   /* Definir los puertos a utilizar */
  42.   #define KBD_COLUMN_PORT PORTB
  43.   #define KBD_ROW_PORT    PORTA
  44.  
  45.   /* Definir los TRIS correspondientes a los puertos utilizados */
  46.   #define KBD_COLUMN_TRIS TRISB
  47.   #define KBD_ROW_TRIS    TRISA
  48.  
  49.   /* Descomentar una de las siguientes lineas segun el teclado utilizado */
  50.   #define KBD_HEXA_KEYPAD
  51.   //#define KBD_PHONE_KEYPAD
  52.  
  53.  
  54.   /* Segun se utilicen resistencias de pullup o pulldown en el puerto de
  55.      las filas, descomentar la linea correspondiente */
  56.   //#define USE_KBD_PULLUP_RESISTOR
  57.   #define USE_KBD_PULLDOWN_RESISTOR
  58.  
  59.   /* Descomentar una de las siguientes lineas segun el nibble utilizado
  60.      para las filas */
  61.   #define USE_KBD_ROW_LOWER_NIBBLE
  62.   //#define USE_KBD_ROW_UPPER_NIBBLE
  63.  
  64.   /* Descomentar una de las siguientes lineas segun el primer bit utilizado
  65.      para las columnas */
  66.   //#define USE_KBD_FIRST_COLUMN_BIT 0
  67.   //#define USE_KBD_FIRST_COLUMN_BIT 1
  68.   #define USE_KBD_FIRST_COLUMN_BIT 4
  69.   //#define USE_KBD_FIRST_COLUMN_BIT 5
  70.  
  71.  
  72.   /****************************************************************************
  73.    *  Definicion de funciones                                                 *
  74.    ****************************************************************************/
  75.  
  76.   /*
  77.    * Inicializa los puertos para el teclado
  78.    */
  79.   void KBDInit(void);
  80.  
  81.   /*
  82.    * Devuelve 1 si hay alguna tecla presionada, o 0 si no hay tecla presionada
  83.    */
  84.   bit KBDIsKeyHit(void);
  85.  
  86.   /*
  87.    * Devuelve el codigo ascci de la tecla presionada
  88.    */
  89.   uint8_t KBDGetKey(void);
  90.  
  91.   /*
  92.    * Activa todas las salidas
  93.    */
  94.   void KBDSetColumn(void);
  95.  
  96. #endif  /* XCKBD_H */


xckbd.c
Código: C
  1. #include "xckbd.h"
  2. #if !defined(KBD_ROW_PORT) || !defined(KBD_COLUMN_PORT)
  3.   #error Falta definir los puertos
  4. #else
  5.  
  6.   /*
  7.    * Inicializa los puertos para el teclado
  8.    */
  9.   void KBDInit(void)
  10.   {
  11. #if defined(USE_KBD_ROW_LOWER_NIBBLE)
  12.       KBD_ROW_TRIS |= 0x0F;
  13. #elif defined(USE_KBD_ROW_UPPER_NIBBLE)
  14.       KBD_ROW_TRIS |= 0xF0;
  15. #endif
  16. #if defined(KBD_HEXA_KEYPAD)
  17. #if (USE_KBD_FIRST_COLUMN_BIT == 0)
  18.   #define KBD_COLUMN_TRIS_MASK 0xF0
  19.   #define KBD_COLUMN_DATA_MASK 0x0F
  20.   #define KBD_FIRST_BIT_MASK 0x01
  21. #elif (USE_KBD_FIRST_COLUMN_BIT == 4)
  22.   #define KBD_COLUMN_TRIS_MASK 0x0F
  23.   #define KBD_COLUMN_DATA_MASK 0xF0
  24.   #define KBD_FIRST_BIT_MASK 0x10
  25. #endif
  26. #define KBD_COLUMN_COUNT 4
  27. #elif defined(KBD_PHONE_KEYPAD)
  28. #if (USE_KBD_FIRST_COLUMN_BIT == 0)
  29.   #define KBD_COLUMN_TRIS_MASK 0xF8
  30.   #define KBD_COLUMN_DATA_MASK 0x07
  31.   #define KBD_FIRST_BIT_MASK 0x01
  32. #elif (USE_KBD_FIRST_COLUMN_BIT == 1)
  33.   #define KBD_COLUMN_TRIS_MASK 0xF1
  34.   #define KBD_COLUMN_DATA_MASK 0x0E
  35.   #define KBD_FIRST_BIT_MASK 0x02
  36. #elif (USE_KBD_FIRST_COLUMN_BIT == 4)
  37.   #define KBD_COLUMN_TRIS_MASK 0x8F
  38.   #define KBD_COLUMN_DATA_MASK 0x70
  39.   #define KBD_FIRST_BIT_MASK 0x10
  40. #elif (USE_KBD_FIRST_COLUMN_BIT == 5)
  41.   #define KBD_COLUMN_TRIS_MASK 0x1F
  42.   #define KBD_COLUMN_DATA_MASK 0xE0
  43.   #define KBD_FIRST_BIT_MASK 0x20
  44. #endif
  45. #define KBD_COLUMN_COUNT 3
  46. #endif
  47.       KBD_COLUMN_TRIS &= KBD_COLUMN_TRIS_MASK;
  48. #define KBD_ROW_COUNT 4
  49.   }
  50.  
  51.   /*
  52.    * Devuelve 1 si hay alguna tecla presionada, o 0 si no hay tecla presionada
  53.    */
  54.   bit KBDIsKeyHit(void)
  55.   {
  56.       uint8_t key;
  57.  
  58. #if defined(USE_KBD_PULLDOWN_RESISTOR)
  59.       key = KBD_ROW_PORT;
  60. #elif defined(USE_KBD_PULLUP_RESISTOR)
  61.       key = ~KBD_ROW_PORT;
  62. #endif
  63. #if defined(USE_KBD_ROW_LOWER_NIBBLE)
  64.       key = key & 0x0F;
  65. #elif defined(USE_KBD_ROW_UPPER_NIBBLE)
  66.       key = key >> 4;
  67. #endif
  68.       if (key != 0) return 1;
  69.       else
  70.           return 0;
  71.   }
  72.  
  73.   /*
  74.    * Activa todas las salidas
  75.    */
  76.   void KBDSetColumn(void)
  77.   {
  78. #if defined(USE_KBD_PULLDOWN_RESISTOR)
  79.       KBD_COLUMN_PORT |= KBD_COLUMN_DATA_MASK;
  80. #elif defined(USE_KBD_PULLUP_RESISTOR)
  81.       KBD_COLUMN_PORT &= ~KBD_COLUMN_DATA_MASK;
  82. #endif
  83.   }
  84.  
  85. #if defined(KBD_PHONE_KEYPAD)
  86.   const uint8_t asciiCode[KBD_ROW_COUNT][KBD_COLUMN_COUNT] = {'1','2','3',
  87.                                                               '4','5','6',
  88.                                                               '7','8','9',
  89.                                                               '*','0','#'};
  90. #elif defined(KBD_HEXA_KEYPAD)
  91.   const uint8_t asciiCode[KBD_ROW_COUNT][KBD_COLUMN_COUNT] = {'0','1','2','3',
  92.                                                               '4','5','6','7',
  93.                                                               '8','9','A','B',
  94.                                                               'C','D','E','F'};
  95. #endif
  96.  
  97.   /*
  98.    * Delvuelve el codigo ascii de la tecla presionada
  99.    */
  100.   uint8_t KBDGetKey(void)
  101.   {
  102.       uint8_t columnNumber;
  103.       uint8_t rowNumber;
  104.       uint8_t key;
  105.  
  106.       columnNumber = 0;
  107.       do
  108.       {
  109.           KBD_COLUMN_TRIS |= ~KBD_COLUMN_TRIS_MASK;
  110.           KBD_COLUMN_TRIS &= ~(KBD_FIRST_BIT_MASK << columnNumber);
  111. #if defined(USE_KBD_PULLDOWN_RESISTOR)
  112.           KBD_COLUMN_PORT |= (KBD_FIRST_BIT_MASK << columnNumber);
  113. #elif defined(USE_KBD_PULLUP_RESISTOR)
  114.           KBD_COLUMN_PORT &= ~(KBD_FIRST_BIT_MASK << columnNumber);
  115. #endif
  116.           columnNumber++;
  117.           key = KBD_ROW_PORT;
  118. #if defined(USE_KBD_ROW_UPPER_NIBBLE)
  119.           key = key >> 4;
  120. #endif
  121. #if defined(USE_KBD_PULLUP_RESISTOR)
  122.           key = ~key;
  123. #endif
  124.           key &= 0x0F;
  125.       }
  126.       while ((key == 0) && (columnNumber < KBD_COLUMN_COUNT));
  127.       switch (key)
  128.       {
  129.           case 1:
  130.           {
  131.               rowNumber = 0;
  132.               break;
  133.           }
  134.           case 2:
  135.           {
  136.               rowNumber = 1;
  137.               break;
  138.           }
  139.           case 4:
  140.           {
  141.               rowNumber = 2;
  142.               break;
  143.           }
  144.           case 8:
  145.           {
  146.               rowNumber = 3;
  147.               break;
  148.           }
  149.       }
  150.       KBD_COLUMN_TRIS &= KBD_COLUMN_TRIS_MASK;
  151.       KBDSetColumn();
  152.       if (key != 0) return asciiCode[rowNumber][columnNumber - 1];
  153.       else
  154.           return 0;
  155.   }
  156. #endif
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 20 de Marzo de 2014, 13:44:11
  Y aquí el ejemplo de uso de la librería del teclado... Utilizo el puertoC para mostrar el valor.

Código: C
  1. #include <xc.h>
  2.  
  3. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
  4. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  5. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  6. #pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
  7. #pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
  8. #pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
  9. #pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
  10. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  11.  
  12. #include <stdint.h>
  13. #include "xckbd.h"
  14.  
  15. #define _XTAL_FREQ 20000000
  16.  
  17. void main(void)
  18. {
  19.     uint8_t lastKeyHit;
  20.     uint8_t tecla;
  21.  
  22.     lastKeyHit = 0;
  23.     CMCON = 7;
  24.     ADCON1 = 7;
  25.     PORTC = 0;
  26.     TRISC = 0;
  27.     KBDInit();
  28.     KBDSetColumn();
  29.     while(1)
  30.     {
  31.         if ((lastKeyHit == 1) && (KBDIsKeyHit() == 0))
  32.             lastKeyHit = 0;
  33.         if ((lastKeyHit == 0) && (KBDIsKeyHit() == 1))
  34.         {
  35.             __delay_ms(10);
  36.             if (KBDIsKeyHit() == 1)
  37.             {
  38.                 lastKeyHit = 1;
  39.                 tecla = KBDGetKey();
  40.                 PORTC = tecla;
  41.             }
  42.         }
  43.     }
  44. }
Título: Re: Mini curso "Programación en XC8"
Publicado por: Micom en 24 de Marzo de 2014, 00:03:49
Me estoy iniciando con el CX8 y quería ver las ejecuciones paso a paso de algunos programitas sencillos que copie de este gran curso y no encuentro los archivos .cof, nose si el cx8 los genera o no?? o como se hace para generarlos. :huh:
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 24 de Marzo de 2014, 00:10:39
Me estoy iniciando con el CX8 y quería ver las ejecuciones paso a paso de algunos programitas sencillos que copie de este gran curso y no encuentro los archivos .cof, nose si el cx8 los genera o no?? o como se hace para generarlos. :huh:

  Los archivos .cof se generan al compilar los programas
Título: Re: Mini curso "Programación en XC8"
Publicado por: Micom en 24 de Marzo de 2014, 00:32:53
Gracias por responder Angel es que ya compile los programas de inicio y cargue a mis simulacion el archivo .hex y la simulacion corrio bien pero queria simularlo paso a pasoviendo el codigo y para eso queria el archivo .cof pero los busque dentro de la carpeta del proyecto y no los genera como se hara para generarlos
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 24 de Marzo de 2014, 09:39:29
  ¿Estás trabajando con MPLABX? ¿Revisaste todas las carpetas que se encuentran dentro de la carpeta del proyecto?
Título: Re: Mini curso "Programación en XC8"
Publicado por: Micom en 25 de Marzo de 2014, 01:31:41
Si trabajo con el mplabx, y he buscado deseperadamente los benditos archivos cof y no los encuentro en ninguna carpeta del proyecto no se si deba ajustarle algo al mplabx para wue se generen al compilar el proyecto
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 25 de Marzo de 2014, 08:53:56
Si trabajo con el mplabx, y he buscado deseperadamente los benditos archivos cof y no los encuentro en ninguna carpeta del proyecto no se si deba ajustarle algo al mplabx para wue se generen al compilar el proyecto

  Hasta donde yo sé, no hay que tocar nada. Siempre que la compilación me es exitosa, se genera el .cof. Dicho archivo aparece en

carpeta del proyecto/dist/default/production
Título: Re: Mini curso "Programación en XC8"
Publicado por: Micom en 25 de Marzo de 2014, 13:57:49
Si en esta carpeta proyecto/dist/default/production siempre lo encuentro pero cuando compilo con CCS ahora que compilo CX8 solo me aparecen 10 archivos con las siguientes extensiones: .cmf .elf .hex .hxl .lst .map .obj .rlf .sdb .sym . Ningún .cof creo que hay que ajustar algo voy a buscar documentación del CX8.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Micom en 25 de Marzo de 2014, 14:45:59
Bueno ya se porque no me genera los archivos cof  ;-) era un ajuste. Por si a alguien le pasa lo mismo voy a explicar brevemente que ajuste le hice al CX8 atreves del MPlabX.

Con tu proyecto abierto y compilado con el CX8 vamos a File/Project Properties(Nombre proyecto) y se abre la ventana de las propiedades del proyecto y en el menú de la izquierda buscas la opción XC8 global option la seleccionas se abre una subventana a la derecha y donde esta la opción de Ouput File Format cambias en la flechita, ELF/DWARF por COFF, aplicar aceptar y listo. Al compilar de nuevo el archivo .elf desaparece y se crea el .cof  :mrgreen:
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 25 de Marzo de 2014, 14:54:41
Si en esta carpeta proyecto/dist/default/production siempre lo encuentro pero cuando compilo con CCS ahora que compilo CX8 solo me aparecen 10 archivos con las siguientes extensiones: .cmf .elf .hex .hxl .lst .map .obj .rlf .sdb .sym . Ningún .cof creo que hay que ajustar algo voy a buscar documentación del CX8.

  Respondiste antes que yo...

  Veo que tú tienes archivos con extensión .CMF y .ELF en lugar del .COF que me aparece a mí. Estuve buscando en toda la configuración del proyecto y no encuentro nada que haga referencia ni a archivo .COF ni a archivos .CMF y .ELF

  Sabes, estoy usando la versión 1.60 de MPLABX en Linux y no me aparece ninguna subventana en la opción de "XC8 global".... pero ahora que lo nombras creo que sí, que en algún momento he cambiado algo, pero no logro saber como ya que no encuentro la opción.

  Como sea, que bueno que diste con la solución.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Micom en 28 de Marzo de 2014, 20:47:12
Este es mi primer programa con CX8  :)



Código: [Seleccionar]
/*
 * File:   Secuenciador de 8 leds
 * Author: Abel
 * Simula el funcionamiento de las luces del auto fantastico
 * Created on 25 de marzo de 2014, 12:27 PM
 */

#include <stdio.h>
#include <stdlib.h>
#include <xc.h> // Librería XC8

#define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro

#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// FUNCION PRINCIPAL

void main()
{
  TRISB = 0; // Configuro puerto B como salidas
  PORTB = 0; // borramos el puerto B

  while (1) // Bucle infinito
  {         //El primer bucle for deplaza la luz del bit 0 al bit 7 de portb
        for (PORTB=1; PORTB<128; PORTB=PORTB*2)
        {   // se visualiza por 200 milisegundos.
         __delay_ms(200);
        }   //El segundo bucle for desplaza la luz del bit 7 al bit 0 de portb
        for (PORTB=128; PORTB>1; PORTB=PORTB/2)
        {   // se visualiza por 200 milisegundos.
         __delay_ms(200);
        }
    }
}
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 10 de Abril de 2014, 10:41:36
Estoy haciendo un programa en XC8 y me estoy volviendo loco para conseguir un vector de reset.

Lo que quiero es hacer el programa compatible con un bootloader. Para eso en las 4 primeras direcciones de memoria debe haber un goto a la rutina que inicia el programa.

No consigo que haya un goto en la dirección de memoria 0

¿Cómo demonios se hace eso en XC8?

PD: Lo he intentado con la opción --CODEPAGE y ni caso

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 10 de Abril de 2014, 11:22:50
  Hola Picuino, aquí hay un link al foro de microchip, donde un usuario intenta un bootloader y encuentra que tiene que configurar una opción desde la ventana del linker en las opciones del proyecto. http://www.microchip.com/forums/m669220.aspx

  Recompile un proyecto haciendo los siguientes cambios. En XC8 linker --> Option categories seleccioné "additional options" y luego modifique la opción "Codeoffset" y le puse el valor 0x100. Para que mi programa comience en esa dirección de memoria.

 Y mirando el archivo .MAP veo lo siguiente...

reset_vec  100

intentry   104

  Supongo que serán los nuevos vectores de reset y de interrupción de mi aplicación.

  Imagino que si ya tienes un bootloader grabado, deberás saber cual tiene que ser el vector de reset de tu aplicación.

  No sé si estoy bien orientado o estoy hablando pavadas, ya que nunca utilicé un bootloader.
Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 10 de Abril de 2014, 11:30:46
Estoy haciendo un programa en XC8 y me estoy volviendo loco para conseguir un vector de reset.

Lo que quiero es hacer el programa compatible con un bootloader. Para eso en las 4 primeras direcciones de memoria debe haber un goto a la rutina que inicia el programa.

No consigo que haya un goto en la dirección de memoria 0

¿Cómo demonios se hace eso en XC8?

PD: Lo he intentado con la opción --CODEPAGE y ni caso

Saludos.

El XC8 trae la opcion Codeoffset, se encuentra en Additional Options en las opciones del Linker en las propiedades del proyecto, lo que hace  es desplazar el codigo hasta la direccion que indique, asi se puede reservar la posicion superior de la memoria para el bootloader.

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 10 de Abril de 2014, 11:41:33
Gracias, Sander

Me equivoqué cuando dije --CODEPAGE quise decir --CODEOFFSET

Ya lo he probado y el bootloader sigue dando error.

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 01 de Mayo de 2014, 01:01:58
hay algun include en xc8 que me permita usar las definiciones uint8_t, int16_t, etc?

saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 01 de Mayo de 2014, 08:36:20
hay algun include en xc8 que me permita usar las definiciones uint8_t, int16_t, etc?

saludos

  Sí, tienes que incluir el header stdint.h
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 08 de Junio de 2014, 18:00:56
Hola compañeros, no se si expongo la pregunta en el sitio correcto pero como hablamos de XC8 había pensado seguir aquí. El motivo es que estoy intentando capturar con el modulo CCP1 del Pic 16f88 la lectura del timer1, pero los resultados no se corresponden y no doy con el fallo, este es el código:
Código: C
  1. /*
  2.  * File:   CCP1_Modo_Captura.c
  3.  * Author: miquel
  4.  *
  5.  * Created on 28 de mayo de 2014, 09:12
  6.  */
  7.  
  8. #include <xc.h>
  9.  
  10. #define _XTAL_FREQ 20000000
  11. // #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/20000000.0)))
  12.  
  13. // #pragma config statements should precede project file includes.
  14.  
  15. // CONFIG1
  16. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
  17. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  18. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  19. #pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
  20. #pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
  21. #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
  22. #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
  23. #pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
  24. #pragma config CCPMX = RB0      // CCP1 Pin Selection bit (CCP1 function on RB0)
  25. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  26.  
  27. // CONFIG2
  28. #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
  29. #pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode disabled)
  30.  
  31.  
  32. #define PIN_DIR_CCP1 TRISB0
  33. #define INPUT 1
  34.  
  35. //----Variables Globales----
  36.  
  37.  
  38. //----Declaracion de Funciones
  39.  
  40.  
  41. //----Funcion Principal----
  42. void main(void)
  43. {
  44.     unsigned int high = 0;
  45.     unsigned int low = 0;
  46.    
  47.     PIN_DIR_CCP1 = INPUT;       // TRISB 0b00000001
  48.  
  49.     //****Configuracion del Modulo CCP1
  50.     CCP1CONbits.CCP1M3 = 0;         // Modo Captura con cada flanco ascendente en RB0/CCP1
  51.     CCP1CONbits.CCP1M2 = 1;
  52.     CCP1CONbits.CCP1M1 = 0;
  53.     CCP1CONbits.CCP1M0 = 1;
  54.  
  55.     //****Configuracion del Timer & Interrupcion
  56.     T1CONbits.T1CKPS1 = 0;
  57.     T1CONbits.T1CKPS0 = 0;          // 1:1 Prescale value
  58.     T1CONbits.TMR1CS = 0;           // Modo temporizador
  59.     PIR1bits.TMR1IF = 0;            // Borramos bandera overflow
  60.     T1CONbits.TMR1ON = 0;           // Timer1 OFF
  61.     TMR1H = 0x00;
  62.     TMR1L = 0x00;
  63.     T1CONbits.TMR1ON = 1;           // Timer1 ON
  64.     //INTCONbits.PEIE = 1;
  65.     //INTCONbits.GIE = 1;
  66.  
  67.     //****Bucle infinito
  68.     while(1)
  69.     {
  70.         if(PIR1bits.CCP1IF == 1)    // Preguntamos si se ha efectuado la captura
  71.         {
  72.             PIR1bits.CCP1IF = 0;
  73.             T1CONbits.TMR1ON = 0;
  74.             high = CCPR1H;
  75.             low = CCPR1L;
  76.             //TMR1H = 0x00;
  77.             //TMR1L = 0x00;
  78.             //T1CONbits.TMR1ON = 1;
  79.         }
  80.     }
  81. }
  82.  
  83. //----Funcion de Interrupcion----

Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 09 de Junio de 2014, 18:09:36
Hola de nuevo, sigo liado con el modulo CCP1, creo haber dado con el fallo al menos en parte, y es que el bit de overflow del Timer1 (TMR1IF) no se pone a 0 pero no se el porque, ya que si hago funcionar el Timer1 por separado no da fallo.
Timer1 funciona correctamente:
Código: C
  1. /*
  2.  * File:   TempTMR1.c
  3.  * Author: miquel
  4.  *
  5.  * Created on 28 de mayo de 2014, 20:12
  6.  */
  7.  
  8. #include <xc.h>
  9.  
  10. #define _XTAL_FREQ 20000000
  11. // #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/20000000.0)))
  12.  
  13. // #pragma config statements should precede project file includes.
  14.  
  15. // CONFIG1
  16. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
  17. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  18. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  19. #pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
  20. #pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
  21. #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
  22. #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
  23. #pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
  24. #pragma config CCPMX = RB0      // CCP1 Pin Selection bit (CCP1 function on RB0)
  25. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  26.  
  27. // CONFIG2
  28. #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
  29. #pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode disabled)
  30.  
  31.  
  32. #define CONFIG_ANSEL ANSEL
  33. #define PIN_DIR_LED TRISA0
  34. #define PIN_LED RA0
  35. #define OUTPUT 0
  36. #define OFF 0
  37.  
  38.  
  39. //----Funcion Principal----
  40. void main(void)
  41. {
  42.     CONFIG_ANSEL = 0x00;        // Configuramos todas las I/O digitales
  43.     PIN_DIR_LED = OUTPUT;       // TRISA 0b11111110
  44.  
  45.     //****Configuracion del Timer
  46.  
  47.     T1CONbits.T1CKPS1 = 1;
  48.     T1CONbits.T1CKPS0 = 1;          // 1:8 Prescale value
  49.     T1CONbits.TMR1CS = 0;           // Modo temporizador
  50.     PORTAbits.PIN_LED = OFF;        // Led Apagado
  51.     PIR1bits.TMR1IF = 0;            // Borramos bandera overflow
  52.     T1CONbits.TMR1ON = 0;           // Timer1 OFF
  53.     TMR1H = 0x85;                   // Inicializamos Timer1
  54.     TMR1L = 0xEE;
  55.     T1CONbits.TMR1ON = 1;           // Timer1 ON
  56.  
  57.     //****Bucle infinito
  58.     while(1)
  59.     {
  60.         if(PIR1bits.TMR1IF == 1)
  61.         {
  62.             PIR1bits.TMR1IF = 0;
  63.             PIN_LED ^=1;            // Complementamos pin RA0
  64.             T1CONbits.TMR1ON = 0;
  65.             TMR1H = 0x85;
  66.             TMR1L = 0xEE;
  67.             T1CONbits.TMR1ON = 1;
  68.         }
  69.     }
  70. }

Con el código del post anterior la bandera de overflow no se pone a 0.

Saludos y Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 09 de Junio de 2014, 18:48:20
    Miquel_S, en primer código que muestras no borras el flag del timer sino que estás borrando unicamente el flag de módulo CCP
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 10 de Junio de 2014, 03:09:36
Gracias AngelGris esto lo tengo presente, pero me he dado cuenta que en la instrucción que tengo casi al principio del main que si lo estoy borrando al simular paso a paso no se me pone a 0, y es aquí que no se el porque.
Título: Re: Mini curso "Programación en XC8"
Publicado por: storm67 en 13 de Junio de 2014, 21:27:52
Hola soy nuevo en MPLAB X y XC8 y trato de hacer un programa como practica para aprender a utilizar un PIC16F84A.   El programa es para un velocímetro digital que muestre la velocidad en 3 Diplays de 7 segmentos y la señal del sensor quiero ingresarla por el pin del RA4 como contador.
Creo que el funcionamiento se debe parecer al de un frecuencímetro ya que he la cantidad de pulsos que ingresan serán numéricamente igual a la velocidad.   Para esto, el periodo de tiempo debe ser de 555 ms .
¿Es correcto suponer que mientras espero que ocurra la interrupción para este período, se pueden contar los pulsos que ingresan por RA4 y procesarlos para separarlos en unidades, decenas y centenas y por medio de multiplexión los muestro en los displays?
Utilizaré 4 pines y un decodificador para los displays y tres pines para controlarlos, todos estos del puerto B.
Me gustaría saber si esta idea es correcta, si voy por el camino correcto.
Gracias por su ayuda!!!!
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 13 de Junio de 2014, 22:18:20
Hola soy nuevo en MPLAB X y XC8 y trato de hacer un programa como practica para aprender a utilizar un PIC16F84A.   El programa es para un velocímetro digital que muestre la velocidad en 3 Diplays de 7 segmentos y la señal del sensor quiero ingresarla por el pin del RA4 como contador.
Creo que el funcionamiento se debe parecer al de un frecuencímetro ya que he la cantidad de pulsos que ingresan serán numéricamente igual a la velocidad.   Para esto, el periodo de tiempo debe ser de 555 ms .
¿Es correcto suponer que mientras espero que ocurra la interrupción para este período, se pueden contar los pulsos que ingresan por RA4 y procesarlos para separarlos en unidades, decenas y centenas y por medio de multiplexión los muestro en los displays?
Utilizaré 4 pines y un decodificador para los displays y tres pines para controlarlos, todos estos del puerto B.
Me gustaría saber si esta idea es correcta, si voy por el camino correcto.
Gracias por su ayuda!!!!

  ¿Es un velocímetro o un tacómetro?
Título: Re: Mini curso "Programación en XC8"
Publicado por: storm67 en 14 de Junio de 2014, 00:22:42
Es un velocimetro que me encontré en una revista “Electronics projects”  el artículo se llama DIGITAL SPEEDOMETER que encontré en http://www.electronicsforu.com/electronicsforu/lab/ad.asp?url=www.electronicsforu.com/electronicsforu/circuitarchives/view_article.asp?sno=384&title=Digital%20Speedometer
Este artículo muestra unos cálculos para hacer que los pulsos del sensor sean numéricamente igual a la velocidad en km/h.
Quiero seguir el mismo principio pero cambiando los timers y contadores y latches por el pic.
Como es el primer pic que programaría escogí el PIC16F84A, espero que sea suficiente para lo que quiero.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 15 de Junio de 2014, 23:10:15
  En teoría se podría implementar.
  Creo que la base de tiempo sería más fácil implementarla con un 16f628A, ya que el timer1 lo puedes encender y apagar a voluntad. Además imagino que el 628A será más barato ya que el f84A está discontinuado hace rato
Título: Re: Mini curso "Programación en XC8"
Publicado por: storm67 en 16 de Junio de 2014, 19:15:53
Gracias AngelGris
vere la hoja de datos del 628A, aunque dejame decirte que el 84A aqui aun esta disponible, es muy comun para principiantes.  ¿es posible hacerlo en el 84A  :oops: ya lo compre¡¡¡¡¡¡
Título: Re: Mini curso "Programación en XC8"
Publicado por: storm67 en 16 de Junio de 2014, 19:23:31
Si mi primera lección aprendida.  revisar antes las hojas de datos antes de comprar los componentes!!!!!
Título: Re: Mini curso "Programación en XC8"
Publicado por: storm67 en 18 de Junio de 2014, 00:10:59
Hola.   Revisando diferentes aportaciones me surgieron varias preguntas las cuales son:
¿el RA4 y el TMR0 en el 16F84A, son mutuamente excluyentes, es decir, si uso RA4 como entrada de una señal cuadrada para contar sus pulsos, ya no podré usar TMR0 para generar interrupciones al mismo tiempo?
¿Puedo usar alguna otra entrada del puerto A como entrada de una señal cuadrada para contar los pulsos mientras espero una interrupción del TMR0?

ojalá alguien pueda sacarme de estas dudas.  Gracias de antemano.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Thulsa Doom en 18 de Junio de 2014, 09:26:06
Hola a todos, me estoy iniciando en el MPLABX y XC8, tengo algo de experiencia en MPLAB y C18, tengo algunas dudas.
¿XC8 trae librerías de manejo de periféricos como el compilador C18 pero para los pic inferiores a PIC18, ósea los PIC10/12/16?.
¿Los proyectos hechos con C18 y librerías valdrían a pelo sin modificar nada para XC8?
gracias
Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 18 de Junio de 2014, 16:11:03
Hola a todos, me estoy iniciando en el MPLABX y XC8, tengo algo de experiencia en MPLAB y C18, tengo algunas dudas.
¿XC8 trae librerías de manejo de periféricos como el compilador C18 pero para los pic inferiores a PIC18, ósea los PIC10/12/16?.
¿Los proyectos hechos con C18 y librerías valdrían a pelo sin modificar nada para XC8?
gracias

A la primera pregunta no, no trae librerias para los perifericos de los PIC de gama media y baja.

A la segunda es casi, hay algunas modificaciones que hay que hacer. por ejemplo los retardos se manejan de forma diferente.

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Thulsa Doom en 18 de Junio de 2014, 16:18:56
Pues vaya, me costará un poco adaptarme, creo que seguiré con C18 ya que si quisiera utilizar un conjunto de librerías como las de TCPIP sería un verdadero infierno adaptarlas.
saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 18 de Junio de 2014, 19:14:02
Pues vaya, me costará un poco adaptarme, creo que seguiré con C18 ya que si quisiera utilizar un conjunto de librerías como las de TCPIP sería un verdadero infierno adaptarlas.
saludos

  Tal vez deberías ver algún readme de la última edición de las librerías. Yo probé la de USB y ya contempla al compilador XC8, muy posiblemente para TCP/IP también pueda compilar con XC8.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 18 de Junio de 2014, 19:16:08
Hola.   Revisando diferentes aportaciones me surgieron varias preguntas las cuales son:
¿el RA4 y el TMR0 en el 16F84A, son mutuamente excluyentes, es decir, si uso RA4 como entrada de una señal cuadrada para contar sus pulsos, ya no podré usar TMR0 para generar interrupciones al mismo tiempo?
¿Puedo usar alguna otra entrada del puerto A como entrada de una señal cuadrada para contar los pulsos mientras espero una interrupción del TMR0?

ojalá alguien pueda sacarme de estas dudas.  Gracias de antemano.


  Efectivamente las posibles entradas para el TMR0 son o el clock interno o el pin RA4.... Podrías utilizar el pin RB0 (configurado para que genere interrupción) y así utilizar dicho pin como entrada para los pulsos del disco y el TMR0 como contador de tiempo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: storm67 en 19 de Junio de 2014, 01:23:53
Gracias AngelGris.  con ese dato se que puedo usar el F84A que ya tengo.  Usando el RB0 para generar interrupción y TMR0 para contar el tiempo entre pulsos. ´¿Estaría midiendo el tiempo entre pulsos? yo quiero realizar el otro método, el contar los pulsos en un periodo fijo de tiempo. Probablemente contando las interrupciones en RB0. El tiempo que necesito es de 0.555077 us  y debido a que el TMR0 solo cuenta hasta 256 usaré un valor de TMR0 de 39 para tener un perodo de 0.0555... y hacerlo dar 10 vueltas con un while y asi completarlo, entondes despues leer la cuenta de interrupciones de RB0 y mandarlas a displays despues de separarlas en unidades,, decenas y centenas.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Thulsa Doom en 19 de Junio de 2014, 04:49:14
Pues vaya, me costará un poco adaptarme, creo que seguiré con C18 ya que si quisiera utilizar un conjunto de librerías como las de TCPIP sería un verdadero infierno adaptarlas.
saludos

  Tal vez deberías ver algún readme de la última edición de las librerías. Yo probé la de USB y ya contempla al compilador XC8, muy posiblemente para TCP/IP también pueda compilar con XC8.

Vale, le echaré un vistazo, ahora estaba haciendo pruebas con librerías de C18 adaptándolas a XC8 y para los micros de gama media y con pocas modificaciones funcionan bien, voy a seguir estudiando
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 19 de Junio de 2014, 18:12:10
Gracias AngelGris.  con ese dato se que puedo usar el F84A que ya tengo.  Usando el RB0 para generar interrupción y TMR0 para contar el tiempo entre pulsos. ´¿Estaría midiendo el tiempo entre pulsos? yo quiero realizar el otro método, el contar los pulsos en un periodo fijo de tiempo. Probablemente contando las interrupciones en RB0. El tiempo que necesito es de 0.555077 us  y debido a que el TMR0 solo cuenta hasta 256 usaré un valor de TMR0 de 39 para tener un perodo de 0.0555... y hacerlo dar 10 vueltas con un while y asi completarlo, entondes despues leer la cuenta de interrupciones de RB0 y mandarlas a displays despues de separarlas en unidades,, decenas y centenas.

    Yo usaría el TMR0 para que cada interrupción incremente un contador (contador de tiempo). También la interrupción de RB0 para que incremente otro contador (contador de pulsos). Así cuando tu "contador de tiempo" llegue al valor requerido, lees el "contador de pulsos" y haces los cálculos necesarios.
    Tendrás que multiplexar los display, entonces creo que tendrías que buscar la forma de hacer eso dentro de tu ciclo while.
Título: Re: Mini curso "Programación en XC8"
Publicado por: CompSystems en 29 de Junio de 2014, 11:04:52
Hoy me he pasado de FRRESCALE a MICROCHIP  :-/, estoy usando MPLAB X ide 2.10, instalo los compiladores pero no aparecen cuando creo un nuevo proyecto, mientras instalaba los compiladores por ejemplo xc8-v1.32-windows-installer.exe sobre win8.1-OS genero un error que decía algo de MPLABXC8.dll pienso que aquí radica el problema aunque la intsalcion si ternina, deseo su colaboración para iniciarme en el mundo de MICROCHIP pues estoy "quieto" hasta solucionar esto  :(

Gracias

Mensaje que genera mientras se instala el compilador

/!\ Problem running post-install step. Installation may not complete correctly

Error running C:\Windows\systems32\regsvr32/s "C:\Program Files\Microchip\v1.32\bin\MPLABXC9.dll": Program ended with an error exit code
Título: Re: Mini curso "Programación en XC8"
Publicado por: EdoNork en 29 de Junio de 2014, 12:31:37
Hoy me he pasado de FREESCALE a MICROCHIP

Yo estoy pensando en hacer lo contrario... Con sus Kinetis te apañas para todo. Y no me parece una tontería utilize<ar un ARM de 32 bits para encender un led, costando poco más que un micro de 8 bits... Pero no nos salgamos del tema. Lo siento.
Título: Re: Mini curso "Programación en XC8"
Publicado por: CompSystems en 29 de Junio de 2014, 12:36:31
EL problema es que no existen foros en castellano de microcontroladores FREESCALE, y una comunidad (foro, blog) permite avanzar mas rápido en el autoaprendizaje, ademas existen cientos y miles de aficionados o expertos en micros MICROCHIP que colaboran en los foros, blogs, etc, mientras que los de FRESCALE trabajan para empresas y no son nada colaborativos. pienso que si desde un principio me hubiera enfocado en micros MICROCHIP en este momento tuviera un buen nivel de autoaprendizaje
Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 29 de Junio de 2014, 21:59:15
Hoy me he pasado de FRRESCALE a MICROCHIP  :-/, estoy usando MPLAB X ide 2.10, instalo los compiladores pero no aparecen cuando creo un nuevo proyecto, mientras instalaba los compiladores por ejemplo xc8-v1.32-windows-installer.exe sobre win8.1-OS genero un error que decía algo de MPLABXC8.dll pienso que aquí radica el problema aunque la intsalcion si ternina, deseo su colaboración para iniciarme en el mundo de MICROCHIP pues estoy "quieto" hasta solucionar esto  :(

Gracias

Mensaje que genera mientras se instala el compilador

/!\ Problem running post-install step. Installation may not complete correctly

Error running C:\Windows\systems32\regsvr32/s "C:\Program Files\Microchip\v1.32\bin\MPLABXC9.dll": Program ended with an error exit code

Alguna vez vi ese problema, puede probar hacer que el MPLAB X reconozca el compilador a mano. Para esto vaya al menu [Tools]->[Options], en esta ventana seleccione [embedded], en la pestaña [Build Tools] vera los compiladores que el MPLAB X reconocio, si el suyo no esta pruebe de adicionarlo usando el boton [Add].

Puede tambien de probar reinstalar el compilador.

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 28 de Julio de 2014, 04:26:06
Hola, alguien seria tan amable de compilar este código y simularlo para decirme cada cuanto tiempo cambia de estado el pin donde esta conectado el led.
En mi simulación cambia cada 16,38325ms pero según los cálculos debería cambiar cada 65ms, mis versiones del MPLABx son
Compiler: XC8 v1.32
IDE:    MPLABX v2.15
Código: C
  1. /**
  2.  *******************************************************************
  3.  *
  4.  *  PIC: 16F876A
  5.  *  Compiler: XC8 v1.32
  6.  *  IDE: MPLABX v2.15
  7.  *
  8.  *  Date: 25.07.2014
  9.  *
  10.  * *****************************************************************
  11.  */
  12.  
  13. #include <xc.h>                                     //PIC hardware mapping
  14. #define _XTAL_FREQ 4000000                         //Used by the XC8 delay_ms(x) macro
  15.  
  16. //#define DOWN                0
  17. //#define UP                  1
  18.  
  19. #define LED              PORTBbits.RB1
  20.  
  21. //#define PULL_UPS
  22.  
  23. // CONFIG
  24. #pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
  25. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  26. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  27. #pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
  28. #pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
  29. #pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
  30. #pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
  31. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  32.  
  33.  
  34.     /* -------------------LATB-----------------
  35.      * Bit#:  -7---6---5---4---3---2---1---0---
  36.      * LED:   -------------------|SV2|SV1|-----
  37.      *-----------------------------------------
  38.      */
  39.  
  40.  
  41. unsigned char cuenta = 0;                       //a global variable
  42.  
  43. void main(void)
  44. {
  45.     TRISB = 0b00000000;                         //all pins are outputs
  46.     PORTB = 0;                                   //init SERVOS in OFF state
  47.  
  48. //#ifdef PULL_UPS
  49.    
  50.  
  51. //#endif
  52.  
  53.      // Configuración del timer & interrupcion
  54.    TMR0 = 0;
  55.    OPTION_REGbits.PS0 = 1;
  56.    OPTION_REGbits.PS1 = 1;
  57.    OPTION_REGbits.PS2 = 1;
  58.    OPTION_REGbits.PSA = 0;
  59.    OPTION_REGbits.T0CS = 0;
  60.    INTCONbits.TMR0IE = 1;
  61.    INTCONbits.GIE = 1;
  62.  
  63.    // Bucle infinito
  64.    while (1){
  65.        if (cuenta == 1){
  66.            LED ^= 1;
  67.            cuenta = 0;
  68.        }
  69.    }
  70. }
  71.  
  72. void interrupt ISR(void)
  73. {
  74.    cuenta++;                   // Incremento variable
  75.    INTCONbits.TMR0IF = 0;      // Limpiamos bandera de desborde
  76. }

Gracias
Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 28 de Julio de 2014, 12:22:11
Si esta simulando en el simulador del MPLABX, tiene que configurar la velocidad de acuerdo a los MIPS, por ejemplo: 4M = 1 MIPS

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 28 de Julio de 2014, 12:37:27
Gracias sander por la respuesta, pero donde configuro los mips, solo se donde configurar la frecuencia del oscilador.
Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 28 de Julio de 2014, 12:49:24
Supongo que estas usando el simulador del MPLABX, buscas en las propiedades del proyecto, ahí te aparece las opciones para el simulador, buscas
Instruction execution frequency (Fcyc) y colocas el valor de cristal dividido entre cuatro, es decir los MIPS (la frecuencia real a la que se ejecutan las instrucciones)

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 28 de Julio de 2014, 13:32:05
Gracias de nuevo sander, yo ponía la frecuencia del cristal 4MHz.  :oops:
Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 28 de Julio de 2014, 14:27:24
Al principio tambien me confundia, porque en el MPLAB 8 se ponia la frecuencia del cristal.

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: alev2477 en 28 de Julio de 2014, 23:46:22
Supongo que estas usando el simulador del MPLABX, buscas en las propiedades del proyecto, ahí te aparece las opciones para el simulador, buscas
Instruction execution frequency (Fcyc) y colocas el valor de cristal dividido entre cuatro, es decir los MIPS (la frecuencia real a la que se ejecutan las instrucciones)

Saludos.

Saludos amigos,,

Un momento que me perdí.

Se coloca esa configuración para la simulación o también afecta al código real????
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 03 de Septiembre de 2014, 12:46:31
Otra vez necesito de vuestra ayuda, sigo liado con el modulo CCP en un pic 16f876A  por mucho que lo intento no me funciona correctamente, intento la captura del TMR1
pero nunca coincide el valor del timer con la pareja de registros del CCP, solo coincide la parte alta del timer.
Y a mi parecer tengo el codigo de forma correcta:
Código: C
  1. #include <xc.h>                                  //PIC hardware mapping
  2.  
  3. #define _XTAL_FREQ  20000000        //Used by the XC8 delay_ms(x) macro
  4.  
  5.  
  6. // CONFIG
  7. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
  8. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  9. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  10. #pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
  11. #pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
  12. #pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
  13. #pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
  14. #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
  15.  
  16. // Declaracion de funciones
  17. void main (void);
  18. void interrupt modulo_captura (void);
  19.  
  20. // Declaracion de Variables
  21.  
  22.  
  23. // FUNCION PRINCIPAL
  24. void main (void)
  25. {
  26.     TRISC = 0b00000100;
  27.  
  28. // Configuramos TMR1 & CCP1
  29.     CCP1CON = 0b00000000;
  30.     TMR1H = 0;
  31.     TMR1L = 0;
  32.     INTCON = 0b00000000;
  33.     PIE1 = 0b00000000;
  34.     PIR1 = 0b00000000;
  35.     CCP1CON = 0b00000101;
  36.     PIE1 = 0b00000100;
  37.     INTCON = 0b11000000;
  38.     T1CONbits.TMR1ON = 1;
  39.  
  40.     while(1)
  41.     {
  42.         continue;
  43.     }
  44. }
  45.  
  46. // Función modulo captura (CCP1)
  47. void interrupt modulo_captura (void)
  48. {
  49.     if(PIR1bits.CCP1IF)
  50.     {
  51.         PIR1bits.CCP1IF = 0;
  52.         TMR1H = 0;
  53.         TMR1L = 0;
  54.     }
  55. }
Captura simulacion (https://mega.co.nz/#!yMRxgCRJ!KszeH411TPg5Bfo6L-aJUgDLjbbvwZkgqfiHRnEfv5Y)
Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 03 de Septiembre de 2014, 13:20:09
Es normal. El timer sigue contando pulsos, mientras que el CCP mantiene el valor capturado del timer sin cambios.

¿Cómo ves los valores de los registros? ¿Qué frecuencia tiene la señal del timer?


Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 03 de Septiembre de 2014, 13:36:59
Es normal. El timer sigue contando pulsos, mientras que el CCP mantiene el valor capturado del timer sin cambios.

¿Cómo ves los valores de los registros? ¿Qué frecuencia tiene la señal del timer?


Saludos.
Hola Picuino podria ser lo que comentas, ya que el valor de la parte baja del TMR1 siempre es superior al CCPR1L. Los valores de los registros los veo a traves de la simulacion.
¿No hay manera de tener una lectura exacta del valor del TMR1?
He intentado parar el timer antes de cargarlo pero hace lo mismo.

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 03 de Septiembre de 2014, 18:02:22
La captura es la lectura exacta.

Puedes hacer una prueba:
Metes un tren de 10 pulsos
Una vez que han terminado los pulsos das un pulso de captura.
Lees los dos valores y deben ser ambos iguales a 10

Los pulsos puedes darles con el mismo pic conectando pines entre sí.

Saludos.

Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 03 de Septiembre de 2014, 18:07:31
También hay otro problema. Si el micro no tiene la lectura de ambos CCPR1 sincronizada (no he mirado el datasheet), entonces es mucho más dificil en el mundo real.

Para sincronizarles debes leer el HIGH luego el LOW y luego otra vez el HIGH. A partir de esas 3 lecturas hay que programar todos los posibles casos.
Puede que prefieras pasarte a otro micro que sincronize por hardware las dos lecturas HIGH y LOW

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 04 de Septiembre de 2014, 04:15:43
Gracias Picuino por la info, aunque estas volando muy por encima de mi  :shock: pero intento aprender, de ser como tu dices las mediciones que se puedan hacer con el sensor HC-SR04 no son reales.
Lo digo por lo del eco del sensor que al ser recibido captura los valores del timer, pero si el timer tiene unos valores y el CCP otros no es real.
¿ O me equivoco?

Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 04 de Septiembre de 2014, 09:23:47
No te estoy contando cosas muy complicadas. Si te parece así es que no me he explicado bien o que no me has entendido.

Vamos a empezar por el principio.
En el módulo de captura hay dos señales:
   La primera es el reloj que hace que el timer cuente y aumente su valor.
   La segunda es la señal de captura, que hace que el modulo de captura lea el valor del timer y lo almacene.

¿Cuáles son estas dos señales en tu circuito?


Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 04 de Septiembre de 2014, 16:48:10
Para medir la duración de pulso de ese sensor, lo mejor es poner como señal de reloj al propio reloj del sistema con un preescaler para reducir su frecuencia a unos 200kHz.
La captura del valor del timer puedes hacerla por soft sin el módulo de captura porque ese sensor tiene un incertidumbre grande, de +-10us.

En cuanto a tu programa, es bastante difícil de entender porque no se pueden ver los bits individuales que activas en la configuración.
Luego subo un programa Python interesante que he programado para solucionarlo.

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 04 de Septiembre de 2014, 17:45:59
Para medir la duración de pulso de ese sensor, lo mejor es poner como señal de reloj al propio reloj del sistema con un preescaler para reducir su frecuencia a unos 200kHz.
La captura del valor del timer puedes hacerla por soft sin el módulo de captura porque ese sensor tiene un incertidumbre grande, de +-10us.

En cuanto a tu programa, es bastante difícil de entender porque no se pueden ver los bits individuales que activas en la configuración.
Luego subo un programa Python interesante que he programado para solucionarlo.

Saludos.
:shock: :shock: :shock: :shock: :shock: Te cuento, yo la electrónica no se si por suerte o desgracia la tengo como un hobby,  y como tengo un montón de proyectos sin terminar por quedarme estancado y no saber solucionarlo, he decidido coger un pic en este caso un 16f876A
y no dejarlo hasta saber como funciona como mínimo en un 80%.
Y ahora le toca al CCP en modo captura, y lo único que intento es poner el timer1 a contar y al recibir un pulso en RC2 me haga la captura del timer, luego ya veremos que hago con todo lo que haya aprendido  :D

Saludos y gracias por tu tiempo.
Miquel.
Título: Re: Mini curso "Programación en XC8"
Publicado por: elgarbe en 04 de Septiembre de 2014, 21:48:09
Miguel, es como dice Picuino.

El timer está contando e inncrementando constantemente  los registros TMR1L y TMR1H. Cuando se da la condicion de captura (y se produce la interrupcion) se almacena de forma inmediata los valores de TMR1L y TMR1H en los registros CCPR1L y CCPR1H, pero ni bien se ejecute una instruccion más, el registro TMR1 irá cambiando. Por lo que no debes preocuparte porque no coincidan, nunca (creo) vas a poder ver en pantalla que coincidan. Lo que sí tenes que estar seguro es que en CCPR1 tendras los 16 bits del timer al momento de producirse la condicion de captura.

Para ese sensor, si queres usar el CCP, lo que debería hacer configurar el CCP para que interrumpa en el RISING EDGE, luego poner en 1 el pin correspondiente a TRG, hacer un delay de unos uSeg, poner a 0 el TRG. En la interrupcion del CCP almacenas los valores de CCPR1 en una variable global, configuras para que interrumpa nuevamente el CCP en el falling edge y sales de la interrupcion. Cuando el sensor detecte el TRIGER, luego de unos mseg pondrá él solo la señal de ECO en 1 y cuando reciba el Eco de la señal de US pondrá en 0 dicha señal con lo que se disparará por segunda vez la interrupcion y ahi deberás restar el contenido de CCPR1 a la variable global.

Escrito así es complicado, pero analizalo un poco!

saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 05 de Septiembre de 2014, 04:08:07
Gracias elgarbe por la excelente explicación, voy a ver si entre lo tuyo y la explicación de Picuino consigo hacer algo.

De nuevo gracias a los dos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Picuino en 05 de Septiembre de 2014, 12:05:10
Hola Miquel, prueba a programar los registros con este código:

http://www.todopic.com.ar/foros/index.php?topic=43374.msg359161#msg359161

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 05 de Septiembre de 2014, 14:54:37
Gracias Picuino revisare el post que me ofreces.

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: illusionista_86 en 12 de Octubre de 2014, 22:34:31
a petición de un compañero voy a poner unos ejemplos que he realizado para la utilización del "timer0" para el control de servos.

en el siguiente ejemplo se controlan 6 servos, pero es fácilmente ampliable hasta unos 10 servos.

el principio de funcionamiento es, para cada servo se necesitan 20ms para que funcione, pues durante estos 20ms puedo activar tantos servos como pueda, suponiendo que como máximo cada servos en tiempo alto esta 2ms, me caben unos 10 servos en el peor de los casos. Los servos se activan sucesivamente, uno detrás de otro, dentro de estos 20 ms, al llegar al último servo, se vuelve a empezar, eso si, teniendo en cuenta que si la suma de todos los tiempos en alto no llega a los 20ms, se calcula el tiempo que queda para llegar a los 20ms y se dejan todos los servos a 0 durante ese tiempo, aquí el código:

Código: C
  1. /*
  2.  * File:   prueva_servos.c
  3.  * Author: Enrique
  4.  *
  5.  * Created on 11 de octubre de 2014, 18:54
  6.  */
  7.  
  8. #include <p18f2550.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <delays.h>
  12. #include <string.h>
  13. #include <usart.h>
  14. #include <math.h>
  15. #include <float.h>
  16.  
  17.  
  18. #pragma config FOSC=XT_XT, FCMEN=OFF,IESO=OFF,CPUDIV=OSC1_PLL2
  19. #pragma config PWRT=ON,BOR=OFF,BORV=0,WDT=OFF,WDTPS=32768
  20. #pragma config MCLRE=ON,LPT1OSC=OFF,PBADEN=OFF,CCP2MX=OFF
  21. #pragma config STVREN=OFF,LVP=OFF,XINST=OFF,DEBUG=OFF
  22. #pragma config CP0=OFF,CP1=OFF,CP2=OFF,CPB=OFF,CPD=OFF
  23. #pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF
  24. #pragma config WRTB=OFF,WRTC=OFF,WRTD=OFF
  25. #pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTRB=OFF
  26.  
  27. #define _XTAL_FREQ 8000000
  28. #define LED PORTAbits.RA3
  29. #define SERVO0 PORTBbits.RB2
  30. #define SERVO1 PORTBbits.RB3
  31. #define SERVO2 PORTBbits.RB4
  32. #define SERVO3 PORTBbits.RB5
  33. #define SERVO4 PORTBbits.RB6
  34. #define SERVO5 PORTBbits.RB7
  35. #define _RAND_MAX 180;
  36. #define _RAND_MIN 0;
  37.  
  38. unsigned long T_ON[]={0,0,0,0,0,0},T_OFF=0;
  39. float ms_ton[]={0.0,0.0,0.0,0.0,0.0,0.0};
  40. float ms_toff=0;
  41. float m;
  42. int servo=0;
  43. int pos[]={0,0,0,0,0,0};
  44. float b=0.5;
  45. float pendiente;
  46.  
  47. void calc_tiempos(int grados[]){
  48.  
  49.     pendiente=(2.5-b)/(180.0-0.0);
  50.     for (int i=0;i<6;i++){
  51.         ms_ton[i]=pendiente*(float)grados[i]+0.5;
  52.         T_ON[i]=65536-(unsigned long)((ms_ton[i]/1000.0)*(_XTAL_FREQ)/4.0); // 62556
  53.     }
  54.     ms_toff=20.0-ms_ton[0]-ms_ton[1]-ms_ton[2]-ms_ton[3]-ms_ton[4]-ms_ton[5];
  55.     T_OFF=65536-(unsigned long)((ms_toff/1000.0)*(_XTAL_FREQ)/4.0); // 28516
  56.     printf("Grados 0: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[0],T_ON[0],ms_ton[0],pendiente);
  57.     printf("Grados 1: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[1],T_ON[1],ms_ton[1],pendiente);
  58.     printf("Grados 2: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[2],T_ON[2],ms_ton[2],pendiente);
  59.     printf("Grados 3: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[3],T_ON[3],ms_ton[3],pendiente);
  60.     printf("Grados 4: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[4],T_ON[4],ms_ton[4],pendiente);
  61.     printf("Grados 5: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",grados[5],T_ON[5],ms_ton[5],pendiente);
  62.     printf("T_OFF=%lu, ms_toff=%.2f, pendiente=%.4f\n\r",T_OFF,ms_toff,pendiente);
  63. }
  64.  
  65.  
  66. void putch(unsigned char byte)
  67. {
  68.             TXSTA=0x26;
  69.             SPEN=1;
  70.             TXREG=byte;            /* transmit a character to Serial IO */
  71.             while(!TXIF)continue;
  72.             TXIF=0;
  73. }
  74.  
  75. void interrupt timer0(void){
  76.  
  77.     if(INTCONbits.TMR0IF){
  78.  
  79.         if (servo==0){
  80.             SERVO0=1;
  81.             SERVO1=0;SERVO2=0;SERVO3=0;SERVO4=0;SERVO5=0;
  82.             WriteTimer0(T_ON[0]);
  83.             servo=1;
  84.         }else if(servo==1){
  85.             SERVO1=1;
  86.             SERVO0=0;SERVO2=0;SERVO3=0;SERVO4=0;SERVO5=0;
  87.             WriteTimer0(T_ON[1]);
  88.             servo=2;
  89.         }else if(servo==2){
  90.             SERVO2=1;
  91.             SERVO1=0;SERVO0=0;SERVO3=0;SERVO4=0;SERVO5=0;
  92.             WriteTimer0(T_ON[2]);
  93.             servo=3;
  94.         }else if(servo==3){
  95.             SERVO3=1;
  96.             SERVO1=0;SERVO2=0;SERVO0=0;SERVO4=0;SERVO5=0;
  97.             WriteTimer0(T_ON[3]);
  98.             servo=4;
  99.         }else if(servo==4){
  100.             SERVO4=1;
  101.             SERVO1=0;SERVO2=0;SERVO3=0;SERVO0=0;SERVO5=0;
  102.             WriteTimer0(T_ON[4]);
  103.             servo=5;
  104.         }else if(servo==5){
  105.             SERVO5=1;
  106.             SERVO1=0;SERVO2=0;SERVO3=0;SERVO4=0;SERVO0=0;
  107.             WriteTimer0(T_ON[5]);
  108.             servo=6;
  109.         }else if(servo==6){
  110.             SERVO0=0;SERVO1=0;SERVO2=0;SERVO3=0;SERVO4=0;SERVO5=0;
  111.             WriteTimer0(T_OFF);
  112.             servo=0;
  113.         }
  114.         INTCONbits.TMR0IF=0;
  115.     }
  116.  
  117.  
  118. }
  119.  
  120. void main(void) {
  121.  
  122.     ADCON1 = 0xFF;      // Deshabilita las entradas analogas.
  123.     TRISA=0b000110000;
  124.     TRISB=0b00000011;
  125.     TRISC = 0b11110011; //Coil in RC2 (PWM) and RC3
  126.  
  127.     OpenUSART(USART_TX_INT_OFF &
  128.             USART_RX_INT_ON &       //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
  129.             USART_ASYNCH_MODE &     //Modo asincrono (fullduplex)
  130.             USART_EIGHT_BIT &       //8 bits de datos
  131.             USART_CONT_RX &         //Recepción continua
  132.             USART_BRGH_HIGH, 51);  //9600 Baudios
  133.  
  134.     OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_1);
  135.     // TiempoTMR0 = (4/Fosc)*(2^bits - ValorTMR0)*Prescaler
  136.     // TiempoTMR0 = (4/8000000)*(2^16 - ValorTMR0)*1
  137.     RCONbits.IPEN = 1;          // Enable interrupt priorities
  138.     INTCONbits.GIE = 1;         // Globally enable interrupts
  139.     INTCONbits.PEIE = 1;
  140.  
  141.     printf("Prueba servos con T0\r\n");
  142.     pos[0]=90;pos[1]=90;pos[2]=90;
  143.     pos[3]=90;pos[4]=90;pos[5]=90;
  144.     calc_tiempos(pos);
  145.     servo=6;
  146.     WriteTimer0(T_OFF);
  147. //    T_ON=62556;
  148. //    T_OFF=28516;
  149.  
  150.  
  151.     while(1){
  152.         if  (PORTAbits.RA4==0){
  153.             pos[0]=rand()%180;pos[1]=rand()%180;pos[2]=rand()%180;
  154.             pos[3]=rand()%180;pos[4]=rand()%180;pos[5]=rand()%180;
  155.             calc_tiempos(pos);
  156.  
  157.             while (PORTAbits.RA4==0){
  158.                    Delay1KTCYx(1);
  159.             }
  160.         }
  161.     }
  162. }

tambien he colgado en el foro los archivos del proyecto y el proteus:
http://www.todopic.com.ar/foros/index.php?topic=43560.0
Título: Re: Mini curso "Programación en XC8"
Publicado por: illusionista_86 en 12 de Octubre de 2014, 22:41:05
dejo otro ejemplo de utilización del timer0 para el control de servos,

en el ejemplo utilizao 6 servos, pero es fácil ampliarlo a tantos servos como se desee.

en este caso TODOS los servos se activan a la vez, de forma que se van desactivado conforme se termine su tiempo en alto, para ello se ordenan los servos según el tiempo en alto, de menor a mayor, y se calcula la diferencia entre el actual menos el anterior, es decir, el primer servo tiene que estar en alto durante 1ms y el segundo durante 1.2ms, con lo cual se calcula el primero para un tiempo de 1ms, el segundo para 0.2ms, y así sucesivamente... en el primer instante se escribe a WriteTimer0 con el valor de 1ms, al desbordar, apaga el servo correspondiente y se vuelve a activar con el valor de 0.2ms, al desbordar desactiva este segundo servo y carga el siguiente.... y asi hasta llegar al final....

con esto podemos poner tantos servos como salidas tengamos en nuestro pic, el código es fácil de modificar.

Código: C
  1. /*
  2.  * File:   prueva_servos.c
  3.  * Author: Enrique
  4.  *
  5.  * Created on 11 de octubre de 2014, 18:54
  6.  */
  7.  
  8. #include <p18f2550.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <delays.h>
  12. #include <string.h>
  13. #include <usart.h>
  14. #include <math.h>
  15. #include <float.h>
  16.  
  17.  
  18. #pragma config FOSC=XT_XT, FCMEN=OFF,IESO=OFF,CPUDIV=OSC1_PLL2
  19. #pragma config PWRT=ON,BOR=OFF,BORV=0,WDT=OFF,WDTPS=32768
  20. #pragma config MCLRE=ON,LPT1OSC=OFF,PBADEN=OFF,CCP2MX=OFF
  21. #pragma config STVREN=OFF,LVP=OFF,XINST=OFF,DEBUG=OFF
  22. #pragma config CP0=OFF,CP1=OFF,CP2=OFF,CPB=OFF,CPD=OFF
  23. #pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF
  24. #pragma config WRTB=OFF,WRTC=OFF,WRTD=OFF
  25. #pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTRB=OFF
  26.  
  27. #define _XTAL_FREQ 20000000
  28. #define LED PORTAbits.RA3
  29. #define SERVO0 PORTBbits.RB2
  30. #define SERVO1 PORTBbits.RB3
  31. #define SERVO2 PORTBbits.RB4
  32. #define SERVO3 PORTBbits.RB5
  33. #define SERVO4 PORTBbits.RB6
  34. #define SERVO5 PORTBbits.RB7
  35. #define _RAND_MAX 180;
  36. #define _RAND_MIN 0;
  37.  
  38. unsigned long T_ON[]={0,0,0,0,0,0},T_OFF=0;
  39. float ms_ton[]={0.0,0.0,0.0,0.0,0.0,0.0};
  40. float ms_toff=0;
  41. int servo=0;
  42. // tenemos 6 servos más una dimensión mas para el tiempo en off, de la posición
  43. // 0 a la 5, son las posiciones de los 6 servos, la posición 7, siempre será 0, de
  44. // la posición 8 a la 13 son los índices de los servos, que se inicializarán siempre
  45. // de la misma forma como la actual. será como una matriz de 2x7
  46. int pos[2][7]={0,0,0,0,0,0,0,0,1,2,3,4,5,6};
  47. float b=0.5; // coeficiente "b" de la recta.
  48. float pendiente; // pendiente de la recta para pasar la posición a "ms".
  49. int cont=0; // variable para saber qué tiempo estamos activando.
  50.  
  51. void ordenar(){
  52.     // ordenamos la variable "pos" de menor a mayor grado, en cada columna tendremos
  53.     // la posición del motor en la primera fila, y el número del servo al que corresponde
  54.     // en la segunda fila.
  55.     int comp1,comp2,index1,index2;
  56.     for (int i=0;i<6;i++){
  57.         comp1=pos[0][i];
  58.         index1=pos[1][i];
  59.         for (int j=(i+1);j<6;j++){
  60.             comp2=pos[0][j];
  61.             index2=pos[1][j];
  62.             if (comp1>comp2){      
  63.                 pos[0][i]=comp2;
  64.                 pos[1][i]=index2;
  65.                 pos[0][j]=comp1;
  66.                 pos[1][j]=index1;
  67.                 comp1=comp2;
  68.                 index1=index2;
  69.             }
  70.         }
  71.     }
  72. }
  73.  
  74. void calc_tiempos(){
  75.  
  76.     float time_ant;
  77.  
  78.     ordenar();
  79.    
  80.     pendiente=(2.5-b)/(180.0-0.0);
  81.     time_ant=0.0;
  82.     for (int i=0;i<6;i++){
  83.         // con la variable de las posiciones ordenadas, calculamos los tiempos en
  84.         // "ms" de cada una de estas posiciones, como vamos a activar todos los servos
  85.         // a la vez, cremamos una variable "time_ant" que corresponde con el tiempo
  86.         // que esta activado anteriormente ese servo. Por ejemplo: el primer servo se activa
  87.         // durante 0.8 ms, y el segundo 1 ms, con lo cual, el segundo estará 0.2 ms
  88.         // más tiempo encendido que el primero, con lo cual, este 0.2 es el que tenemos
  89.         // que almacenar, ya que los dos servos se han activado a la vez, de igual
  90.         // forma para el resto de servos.
  91.         ms_ton[i]=(pendiente*(float)pos[0][i]+b)-time_ant;
  92.         time_ant=time_ant+ms_ton[i];
  93.         // aqui el valor del TMR0 a escrivir cada vez.
  94.         T_ON[i]=65536-(unsigned long)((ms_ton[i]/1000.0)*(_XTAL_FREQ)/8.0); // 62556
  95.     }
  96.     // el tiempo en off será de 20 ms menos el tiempo del servo que este activo mas tiempo.
  97.     ms_toff=20.0-time_ant;
  98.     T_OFF=65536-(unsigned long)((ms_toff/1000.0)*(_XTAL_FREQ)/8.0); // 28516
  99. //
  100. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][0],pos[0][0],T_ON[0],ms_ton[0],pendiente);
  101. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][1],pos[0][1],T_ON[1],ms_ton[1],pendiente);
  102. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][2],pos[0][2],T_ON[2],ms_ton[2],pendiente);
  103. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][3],pos[0][3],T_ON[3],ms_ton[3],pendiente);
  104. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][4],pos[0][4],T_ON[4],ms_ton[4],pendiente);
  105. //    printf("Grados %d: %d, T_on=%lu, ms_on=%.2f, pendiente=%.4f\n\r",pos[1][5],pos[0][5],T_ON[5],ms_ton[5],pendiente);
  106. //    printf("T_OFF=%lu, ms_toff=%.2f, pendiente=%.4f\n\r",T_OFF,ms_toff,pendiente);
  107. //    printf("----------------------------------\n\r");
  108.  
  109. }
  110.  
  111.  
  112. void putch(unsigned char byte)
  113. {
  114.             TXSTA=0x26;
  115.             SPEN=1;
  116.             TXREG=byte;            /* transmit a character to Serial IO */
  117.             while(!TXIF)continue;
  118.             TXIF=0;
  119. }
  120.  
  121. void interrupt timer0(void){
  122.  
  123.     if(INTCONbits.TMR0IF){
  124.  
  125.         // inicializamos con "cont=0" para que todos los servos se activen.
  126.         // en este instante accedemos a "pos" (variable ordenada), y leemos la
  127.         // posición "cont=0" de las variables "T_ON[cont]" y "pos[1][cont], de
  128.         // esta forma accedemos a la posición del servo que menos tiempo tiene que
  129.         // estar activo, en "servo" guardamos el num del servo, y en "WriteTimer0"
  130.         // escribimos el tiempo en ON de este servo. y aumentamos la variable "cont"
  131.  
  132.         // cuando se active este primer timer, accedemos a la sección de este "servo"
  133.         // ponemos a "0" la salida de dicho servo, y escrivimos en "WriteTimer0" el valor
  134.         // del siguiente servo menos activo, y guardamos en "servo" el valor del
  135.         // siguiente servo correspondiente al tiempo activado. aumentamos la variable
  136.         // "cont".... y así hasta el final.
  137.         if (cont==0){
  138.             SERVO0=1;SERVO1=1;SERVO2=1;SERVO3=1;SERVO4=1;SERVO5=1;
  139.             WriteTimer0(T_ON[cont]);
  140.             servo=pos[1][cont];
  141.             cont++;
  142.         }else if (servo==0){
  143.             SERVO0=0;
  144.             WriteTimer0(T_ON[cont]);
  145.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  146.             servo=pos[1][cont];
  147.             cont++;
  148.         }else if(servo==1){
  149.             SERVO1=0;
  150.             WriteTimer0(T_ON[cont]);
  151.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  152.             servo=pos[1][cont];
  153.             cont++;
  154.         }else if(servo==2){
  155.             SERVO2=0;
  156.             WriteTimer0(T_ON[cont]);
  157.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  158.             servo=pos[1][cont];
  159.             cont++;
  160.  
  161.         }else if(servo==3){
  162.             SERVO3=0;
  163.             WriteTimer0(T_ON[cont]);
  164.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  165.             servo=pos[1][cont];
  166.             cont++;
  167.         }else if(servo==4){
  168.             SERVO4=0;
  169.             WriteTimer0(T_ON[cont]);
  170.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  171.             servo=pos[1][cont];
  172.             cont++;
  173.         }else if(servo==5){
  174.             SERVO5=0;
  175.             WriteTimer0(T_ON[cont]);
  176.             //printf(" servo %d, %ul\n\r",servo,T_ON[cont]);
  177.             servo=pos[1][cont];
  178.             cont++;
  179.         }else if(servo==6){
  180.             SERVO0=0;SERVO1=0;SERVO2=0;SERVO3=0;SERVO4=0;SERVO5=0;
  181.             //printf("todos servos a 0 ------------------\n\r");
  182.             WriteTimer0(T_OFF);
  183.             cont=0;
  184.         }
  185.         INTCONbits.TMR0IF=0;
  186.     }
  187. }
  188.  
  189. void print_servos(void){
  190.     // imprimimos las posiciones de los servos, antes de ser ordenados.
  191.     printf("Servo 0: %d grados.\r\n",pos[0][0]);
  192.     printf("Servo 1: %d grados.\r\n",pos[0][1]);
  193.     printf("Servo 2: %d grados.\r\n",pos[0][2]);
  194.     printf("Servo 3: %d grados.\r\n",pos[0][3]);
  195.     printf("Servo 4: %d grados.\r\n",pos[0][4]);
  196.     printf("Servo 5: %d grados.\r\n",pos[0][5]);
  197.     printf("-------------------\r\n");
  198. }
  199. void main(void) {
  200.  
  201.     ADCON1 = 0xFF;      // Deshabilita las entradas analogas.
  202.     TRISA=0b000110000;
  203.     TRISB=0b00000011;
  204.     TRISC = 0b11110011; //Coil in RC2 (PWM) and RC3
  205.  
  206.     // inicializamos la USART
  207.     OpenUSART(USART_TX_INT_OFF &
  208.             USART_RX_INT_ON &       //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
  209.             USART_ASYNCH_MODE &     //Modo asincrono (fullduplex)
  210.             USART_EIGHT_BIT &       //8 bits de datos
  211.             USART_CONT_RX &         //Recepción continua
  212.             USART_BRGH_HIGH, 129);  //9600 Baudios
  213.             // 12-77,20-129,
  214.  
  215.     // inizializamos el TIMER0;
  216.     OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_2);
  217.     // TiempoTMR0 = (4/Fosc)*(2^bits - ValorTMR0)*Prescaler
  218.     // TiempoTMR0 = (4/20000000)*(2^16 - ValorTMR0)*4
  219.     RCONbits.IPEN = 1;          // Enable interrupt priorities
  220.     INTCONbits.GIE = 1;         // Globally enable interrupts
  221.     INTCONbits.PEIE = 1;
  222.  
  223.     printf("Prueba servos con T0\r\n");
  224.     // inicializamos la variable "pos" con unoas valores aleatorios.
  225.     pos[0][0]=20;pos[0][1]=130;pos[0][2]=5;
  226.     pos[0][3]=100;pos[0][4]=90;pos[0][5]=4;
  227.     // recordad que siempre que modifiqueis las variables de las posiciones,
  228.     // estas siguientes variables se han de inicializar de igual manera.
  229.     pos[1][0]=0;pos[1][1]=1;pos[1][2]=2;
  230.     pos[1][3]=3;pos[1][4]=4;pos[1][5]=5;
  231.  
  232.     // imprimimos los valores iniciales sin ordenar
  233.     print_servos();
  234.  
  235.     // calculamos los tiempos para el "writetimer0"
  236.     calc_tiempos();
  237.  
  238.     // inicializamos "WriteTimer0"
  239.     servo=6;
  240.     cont=0;
  241.     WriteTimer0(T_OFF);
  242.  
  243.     while(1){
  244.         if  (PORTAbits.RA4==0){
  245.             // random para cada uno de los 6 servos,
  246.             pos[0][0]=rand()%180;pos[0][1]=rand()%180;pos[0][2]=rand()%180;
  247.             pos[0][3]=rand()%180;pos[0][4]=rand()%180;pos[0][5]=rand()%180;
  248.             // inicalizamos los índices de los servos.
  249.             pos[1][0]=0;pos[1][1]=1;pos[1][2]=2;
  250.             pos[1][3]=3;pos[1][4]=4;pos[1][5]=5;
  251.  
  252.             // imprimimos los servos
  253.             print_servos();
  254.  
  255.             // calculamos los tiempos.
  256.             calc_tiempos();
  257.            
  258.             while (PORTAbits.RA4==0){
  259.                    Delay1KTCYx(1);
  260.             }
  261.         }
  262.     }
  263. }


los archivos del proyecto y la simulación en proteus lo pueden encontrar en el enlace:
http://www.todopic.com.ar/foros/index.php?topic=43560.0
Título: Re: Mini curso "Programación en XC8"
Publicado por: illusionista_86 en 12 de Octubre de 2014, 22:48:22
un ejemplo del uso de i2c, me parece interesante porque es entro dos pics, en este caso dos 18f2550 y la utilización de enteros.

codigo del maestro:

Código: C
  1. /*
  2.  * File:   prueba_lcd.c
  3.  * Author: Enrique
  4.  *
  5.  * Created on 6 de octubre de 2014, 20:15
  6.  */
  7. #include <p18f2550.h>
  8. #include <delays.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <i2c.h>
  12. #include <usart.h>
  13. #include <stdio.h>
  14. #include <math.h>
  15. #include "i2c_func.h"
  16.  
  17. #pragma config FOSC=XT_XT, FCMEN=OFF,IESO=OFF,CPUDIV=OSC1_PLL2
  18. #pragma config PWRT=ON,BOR=OFF,BORV=0,WDT=OFF,WDTPS=32768
  19. #pragma config MCLRE=ON,LPT1OSC=OFF,PBADEN=OFF,CCP2MX=OFF
  20. #pragma config STVREN=OFF,LVP=OFF,XINST=OFF,DEBUG=OFF
  21. #pragma config CP0=OFF,CP1=OFF,CP2=OFF,CPB=OFF,CPD=OFF
  22. #pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF
  23. #pragma config WRTB=OFF,WRTC=OFF,WRTD=OFF
  24. #pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTRB=OFF
  25.  
  26. #define _RAND_MAX 10;
  27.  
  28. unsigned char ebuffer[30];
  29. unsigned char ebuffer2[2];
  30. unsigned long long value[10];
  31. char MensajeTx[] = "Pruba Comunicacion I2C maestro: \n\r";
  32. int cont;
  33.  
  34. void putch(unsigned char byte)
  35. {
  36.             TXSTA=0x26;
  37.             SPEN=1;
  38.             TXREG=byte;            /* transmit a character to Serial IO */
  39.             while(!TXIF)continue;
  40.             TXIF=0;
  41. }
  42.  
  43. void main(void){
  44.  
  45.     ADCON1 = 0xFF;      // Deshabilita las entradas analogas.
  46.     TRISA=0b00010000;
  47.     TRISB=0b00000011;
  48.     TRISCbits.TRISC6=0; TRISCbits.TRISC7=1;
  49.     OpenUSART(USART_TX_INT_OFF &
  50.             USART_RX_INT_ON &       //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
  51.             USART_ASYNCH_MODE &     //Modo asincrono (fullduplex)
  52.             USART_EIGHT_BIT &       //8 bits de datos
  53.             USART_CONT_RX &         //Recepción continua
  54.             USART_BRGH_HIGH, 51);  //9600 Baudios
  55.     OpenI2C( MASTER, SLEW_OFF);
  56.     // Clock = FOSC/(4 * (SSPADD + 1)) // 100 KHz = 8E6/4*20 = 100 KHz.
  57.     // SSPADD=(FOSC/(Clock*4))-1; Para Clock=50Khz. -> SSPADD=(8000000/(4*100000))-1=19
  58.     SSPADD = 19;
  59.     PORTAbits.RA3=0;
  60.  
  61.     putsUSART(MensajeTx);
  62.     cont=1;
  63.     value[0]=9;
  64.     value[1]=25;
  65.     value[2]=480;
  66.     value[3]=3124;
  67.     value[4]=48215;
  68.     value[5]=147348;
  69.     value[6]=3648975;
  70.     value[7]=12473587;
  71.     value[8]=318974698;
  72.     value[9]=1475286934;
  73.  
  74.     while(1){
  75.  
  76.         Delay1KTCYx(2);
  77.         PORTAbits.RA3=~PORTAbits.RA3;
  78.         if  (PORTAbits.RA4==0){
  79. //            value=rand();
  80.             for (int i=0;i<10;i++){
  81.                 printf("Dato %d enviado: %llu\n\r",cont,value[i]);
  82.                 Empezar_i2c(0x0A);
  83.                 Escribir_int_i2c(value[i]);
  84.                 Cerrar_i2c();
  85.                 cont++;
  86.                 Delay1KTCYx(20);
  87.                 while (PORTAbits.RA4==0){
  88.                     Delay1KTCYx(1);
  89.                 }
  90.             }
  91.         }
  92.     }
  93. }

codigo del esclavo:

Código: C
  1. /*
  2.  * File:   prueba_lcd.c
  3.  * Author: Enrique
  4.  *
  5.  * Created on 6 de octubre de 2014, 20:15
  6.  */
  7. #include <p18f2550.h>
  8. #include <delays.h>
  9. #include <string.h>
  10. #include <i2c.h>
  11. #include <usart.h>
  12. #include <stdio.h>
  13. #include <math.h>
  14. #include <stdarg.h>
  15. #include "i2c_func.h"
  16. #include <stdlib.h>
  17.  
  18. #pragma config FOSC=XT_XT, FCMEN=OFF,IESO=OFF,CPUDIV=OSC1_PLL2
  19. #pragma config PWRT=ON,BOR=OFF,BORV=0,WDT=OFF,WDTPS=32768
  20. #pragma config MCLRE=ON,LPT1OSC=OFF,PBADEN=OFF,CCP2MX=OFF
  21. #pragma config STVREN=OFF,LVP=OFF,XINST=OFF,DEBUG=OFF
  22. #pragma config CP0=OFF,CP1=OFF,CP2=OFF,CPB=OFF,CPD=OFF
  23. #pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF
  24. #pragma config WRTB=OFF,WRTC=OFF,WRTD=OFF
  25. #pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTRB=OFF
  26.  
  27. unsigned char ebuffer[15];
  28. unsigned char ebuffer2[5];
  29. int kbit,cont;
  30. char adress;
  31. unsigned long long reciv;
  32.  
  33. char MensajeTx[] = "Pruba Comunicacion I2C esclavo: \n\r";
  34.  
  35. // para que funcione "printf" en la USART
  36. //void putch(char data) {
  37. //while( ! TXIF)
  38. //continue;
  39. //TXREG = data;
  40. //}
  41. void putch(unsigned char byte)
  42. {
  43.             TXSTA=0x26;
  44.             SPEN=1;
  45.             TXREG=byte;            /* transmit a character to Serial IO */
  46.             while(!TXIF)continue;
  47.             TXIF=0;
  48. }
  49.  
  50. void interrupt isr(void)
  51. {
  52.  
  53.     if (PIR1bits.SSPIF) {        // Check for SSP interrupt
  54.         kbit=1;
  55.         adress = ReadI2C();
  56.         IdleI2C();
  57.  
  58.         reciv=Recibir_int_i2c();
  59.         IdleI2C();
  60.  
  61.         PIR1bits.SSPIF = 0;  // Clear the interrupt flag
  62.  
  63.        
  64.     }
  65.     return;
  66. }
  67.  
  68.  
  69. void main(void){
  70.  
  71.    
  72.     ADCON1 = 0xFF;      // Deshabilita las entradas analogas.
  73.     TRISA=0;
  74.     TRISB=0b00000011;
  75.     TRISCbits.TRISC6=0; TRISCbits.TRISC7=1;  
  76.     OpenUSART(USART_TX_INT_OFF &
  77.             USART_RX_INT_ON &       //Activar la interrupcion por la recepcion de dato del buffer de Rx del USART
  78.             USART_ASYNCH_MODE &     //Modo asincrono (fullduplex)
  79.             USART_EIGHT_BIT &       //8 bits de datos
  80.             USART_CONT_RX &         //Recepción continua
  81.             USART_BRGH_HIGH, 51);  //9600 Baudios
  82.     OpenI2C( SLAVE_7, SLEW_OFF);
  83.     // Clock = FOSC/(4 * (SSPADD + 1)) // 100 KHz = 8E6/4*20 = 100 KHz.
  84.     // SSPADD=(FOSC/(Clock*4))-1; Para Clock=50Khz. -> SSPADD=(4000000/(4*100000))-1=19
  85.     SSPADD = 0x0A;
  86.     RCONbits.IPEN = 1;          // Enable interrupt priorities
  87.     INTCONbits.GIE = 1;             // Globally enable interrupts
  88.     PIE1bits.SSPIE = 1;         // Enable SSP interrupt
  89.     IPR1bits.SSPIP = 1;         // Set SSP interrupt priority to high
  90.     INTCONbits.PEIE = 1;
  91.  
  92.     PORTAbits.RA2=0;
  93.     PORTAbits.RA3=0;
  94.     putsUSART(MensajeTx);
  95.     cont=1;
  96.     while(1){
  97.         PORTAbits.RA3=~PORTAbits.RA3;
  98.         Delay1KTCYx(5);
  99.         if (kbit==1){
  100.             printf("Dato %d recivido: %llu\n\r",cont,reciv);
  101.             cont++;
  102.             kbit=0;
  103.         }
  104.     }
  105.  
  106.  
  107.  
  108.  
  109. }


libreria utilizada para enviar los datos:

Código: C
  1. /*
  2.  * File:   i2c_func.h
  3.  * Author: Enrique
  4.  *
  5.  * Created on 10 de octubre de 2014, 15:27
  6.  */
  7.  
  8. #ifndef I2C_FUNC_H
  9. #define I2C_FUNC_H
  10.  
  11. #include <i2c.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15.  
  16. int Escribir_dato_i2c(char Address, char Data) // Escribe un byte a un esclavo en I2C
  17.  {
  18.     IdleI2C();                          // ensure module is idle
  19.     StartI2C();                         // initiate START condition
  20.     while ( SSPCON2bits.SEN );          // wait until start condition is over
  21.     WriteI2C( Address );                        // Selecciona el dispositivo esclavo
  22.     IdleI2C();                          // Asegura que el modulo este desocupado
  23.     if ( SSPCON2bits.ACKSTAT )          // Prueba por la condicion de ACK, si es recibida
  24.     {
  25.             StopI2C();                  // send STOP condition
  26.             while ( SSPCON2bits.PEN );  // wait until stop condition is over
  27.             return 1;
  28.     }
  29.     WriteI2C( Data );
  30.     IdleI2C();
  31.     AckI2C();
  32.     StopI2C();                  // send STOP condition
  33.     while ( SSPCON2bits.PEN );  // wait until stop condition is over
  34.     return 0;
  35.  }
  36.  
  37. void Escribir_int_i2c(unsigned long long value) // Escribe un byte a un esclavo en I2C
  38.  {
  39.     unsigned char buff_leng[2];
  40.     unsigned char buff_value[10];
  41.     int leng;
  42.  
  43.     ltoa(buff_value,value,10);
  44.     leng=strlen(buff_value);
  45.     leng=leng-1;
  46.     itoa(buff_leng,leng,10);
  47.  
  48.     IdleI2C();
  49.     putsI2C(buff_leng);
  50.     IdleI2C();
  51.     putsI2C(buff_value);
  52.     IdleI2C();    
  53.  }
  54.  
  55. unsigned long long int Recibir_int_i2c(void) // Escribe un byte a un esclavo en I2C
  56. {
  57.     unsigned char buff_leng[2];
  58.     unsigned char buff_value[15];
  59.     int leng;
  60.     unsigned long long reciv;
  61.  
  62.     getsI2C(buff_leng,1);
  63.     IdleI2C();
  64.     leng=(atoi(buff_leng)+1);
  65.     getsI2C(buff_value,leng);
  66.     IdleI2C();
  67.     reciv=atol(buff_value);
  68.  
  69.     return reciv;
  70.  }
  71.  
  72. void Empezar_i2c(char Address) // Escribe un byte a un esclavo en I2C
  73.  {
  74.     IdleI2C();                          // ensure module is idle
  75.     StartI2C();                         // initiate START condition
  76.     while ( SSPCON2bits.SEN );          // wait until start condition is over
  77.     WriteI2C( Address );                        // Selecciona el dispositivo esclavo
  78.     IdleI2C();                          // Asegura que el modulo este desocupado
  79.     if ( SSPCON2bits.ACKSTAT )          // Prueba por la condicion de ACK, si es recibida
  80.     {
  81.             StopI2C();                  // send STOP condition
  82.             while ( SSPCON2bits.PEN );  // wait until stop condition is over
  83.     }
  84. }
  85.  
  86. void Cerrar_i2c(void) // Escribe un byte a un esclavo en I2C
  87. {
  88.     IdleI2C();
  89.     AckI2C();
  90.     StopI2C();                  // send STOP condition
  91.     while ( SSPCON2bits.PEN );  // wait until stop condition is over
  92. }
  93. #endif  /* I2C_FUNC_H */


los archivos del proyecto en mplabX y proteus en el enlace:
http://www.todopic.com.ar/foros/index.php?topic=43560.0
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 18 de Octubre de 2014, 17:51:57
Hola alguien puede explicarme esta parte de código de la librería xlcd.h:
Código: [Seleccionar]
/* 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   LATBbits.LATC6   /* PORT for RW */
 #define TRIS_RW  TRISBbits.TRISC6     /* TRIS for RW */

 #define RS_PIN   LATBbits.LATC5   /* PORT for RS */
 #define TRIS_RS  TRISBbits.TRISC5     /* TRIS for RS */

 #define E_PIN    LATBbits.LATC4   /* PORT for E  */
 #define TRIS_E   TRISBbits.TRISC4     /* TRIS for E  */

Entiendo que si quiero usar el Puerto B escribo:
Código: [Seleccionar]
#define DATA_PORT         PORTB
#define TRIS_DATA_PORT TRISB
Lo que no entiendo es la parte de control que pone por ejemplo: RS_PIN  LATBbits.LATC5 que es LATB o LATC.

Gracias.

Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 18 de Octubre de 2014, 18:45:26
Los PIC18F traen tres registros para manejar cada puerto, TRISx(para configurar), PORTx(para leer del puerto) y LATx(para escribir en el puerto), aumentaron el registro LAT para solucionar algunos problemas que podrian ocurrir en los PIC16F al acceder a los puertos con las instrucciones bcf , bsf y otras mas, ya que estas instrucciones realmente no trabajan sobre los bits individuales del puesto, si no que leen todo el puerto, modifican el bit requerido y vuelven escribir en el puerto, esto a veces hacia que se cambien otros valores del puerto accidentalmente.

Este problema esta bastante documentado rmw effect. (http://www.microchip.com/forums/m478014.aspx)

Resumiendo en los PIC16F1 y PIC18F usar PORT para leer y LAT para escribir.

Saludos.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 18 de Octubre de 2014, 18:50:53
Lo siento pero sigo sin saber donde modificar para usar un determinado bit de un determinado puerto.

Gracias
Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 18 de Octubre de 2014, 19:02:18
Lo siento pero sigo sin saber donde modificar para usar un determinado bit de un determinado puerto.

Gracias

Pero preguntaste que es LATB y LATC  :?

Bueno,
Código: C
  1. //si quieres usar el pin RB5 como salida  usas
  2. #define RS PIN  LATBbits.LATB5
  3. // si quieres usar el pin RC0 para escribir usas
  4. #define RS PIN LATCbits.LATC0
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 18 de Octubre de 2014, 19:12:42
Perdón no hice la pregunta bien, lo que queria preguntar era que como esta escrito:
Código: [Seleccionar]
#define RS_PIN   LATBbits.LATC5    /* PORT for RS */
 #define TRIS_RS  TRISBbits.TRISC5    /* TRIS for RS */
esta mezclando LATBbits con LATC5 y TRISBbits con LATC5 y eso es lo que no entendia pero sera que hay un error.

Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: sander en 18 de Octubre de 2014, 19:22:30
Si eso esta equivocado, deberia salirle error al compilar.

Saludos
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 18 de Octubre de 2014, 19:40:43
Gracias por la ayuda sander, al compilar no salia ningún error.

Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 18 de Octubre de 2014, 20:57:27
Alguien seria tan amable de revisar este código y decirme si tengo algún error, lo digo porque me salen caracteres extraños y así poder descartar que sea el código.
main.c
Código: [Seleccionar]
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "my_xlcd.h"
#include <plib/delays.h>


#pragma config PLLDIV = 5       // PLL Prescaler Selection bits (Divide by 5 (20 MHz oscillator input))
#pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
#pragma config USBDIV = 2       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes from the 96 MHz PLL divided by 2)
#pragma config FOSC = HSPLL_HS  // Oscillator Selection bits (HS oscillator, PLL enabled (HSPLL))
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = ON         // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
#pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)
#pragma config CCP2MX = ON      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM is not write-protected)
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)


#define _XTAL_FREQ 48000000

//Retardos requeridos por la librería XLCD
void DelayFor18TCY(void);
void DelayPORXLCD(void);
void DelayXLCD(void);

void main(void)
{
 ADCON1 = 0b1111;
 //Configurando LCD 4 bits mutilínea
 OpenXLCD(FOUR_BIT & LINES_5X7);
 //Esperar hasta que el display esté disponible.
 while(BusyXLCD());
 //Mover cursor a la derecha...
 WriteCmdXLCD(0x06);
 //Desactivando el cursor.
 WriteCmdXLCD(0x0C);

 while(1)
 {
 //Primera línea
 SetDDRamAddr(0x00);
 putrsXLCD("HOLA");
 //Segunda línea
 SetDDRamAddr(0x40);
 putrsXLCD("MUNDO");
 }

}
void DelayFor18TCY(void)
{
 Delay10TCYx(120);
 return;
}

void DelayPORXLCD(void)
{
 Delay1KTCYx(180);
 return;
}

void DelayXLCD(void)
{
 Delay1KTCYx(60);
 return;
}
my_xlcd.h
Código: [Seleccionar]
#ifndef __XLCD_H
#define __XLCD_H
#include "p18cxxx.h"
/* PIC18 XLCD peripheral routines.
 *
 *   Notes:
 *      - These libraries routines are written to support the
 *        Hitachi HD44780 LCD controller.
 *      - The user must define the following items:
 *          - The LCD interface type (4- or 8-bits)
 *          - If 4-bit mode
 *              - whether using the upper or lower nibble
 *          - The data port
 *              - The tris register for data port
 *              - The control signal ports and pins
 *              - The control signal port tris and pins
 *          - The user must provide three delay routines:
 *              - DelayFor18TCY() provides a 18 Tcy delay
 *              - DelayPORXLCD() provides at least 15ms delay
 *              - DelayXLCD() provides at least 5ms delay
 */

/* Interface type 8-bit or 4-bit
 * For 8-bit operation uncomment the #define BIT8
 */
/* #define BIT8 */

/* When in 4-bit interface define if the data is in the upper
 * or lower nibble.  For lower nibble, comment the #define UPPER
 */
/* #define UPPER */

/* DATA_PORT defines the port to which the LCD data lines are connected */
 #define DATA_PORT      PORTB
 #define TRIS_DATA_PORT TRISB

/* CTRL_PORT defines the port where the control lines are connected.
 * These are just samples, change to match your application.
 */
 #define RW_PIN   LATBbits.LATB2    /* PORT for RW */
 #define TRIS_RW  TRISBbits.TRISB2    /* TRIS for RW */

 #define RS_PIN   LATBbits.LATB0    /* PORT for RS */
 #define TRIS_RS  TRISBbits.TRISB0    /* TRIS for RS */

 #define E_PIN    LATBbits.LATB1  /* PORT for E  */
 #define TRIS_E   TRISBbits.TRISB1    /* TRIS for E  */

/* Display ON/OFF Control defines */
#define DON         0b00001111  /* Display on      */
#define DOFF        0b00001011  /* Display off     */
#define CURSOR_ON   0b00001111  /* Cursor on       */
#define CURSOR_OFF  0b00001101  /* Cursor off      */
#define BLINK_ON    0b00001111  /* Cursor Blink    */
#define BLINK_OFF   0b00001110  /* Cursor No Blink */

/* Cursor or Display Shift defines */
#define SHIFT_CUR_LEFT    0b00000100  /* Cursor shifts to the left   */
#define SHIFT_CUR_RIGHT   0b00000101  /* Cursor shifts to the right  */
#define SHIFT_DISP_LEFT   0b00000110  /* Display shifts to the left  */
#define SHIFT_DISP_RIGHT  0b00000111  /* Display shifts to the right */

/* Function Set defines */
#define FOUR_BIT   0b00101100  /* 4-bit Interface               */
#define EIGHT_BIT  0b00111100  /* 8-bit Interface               */
#define LINE_5X7   0b00110000  /* 5x7 characters, single line   */
#define LINE_5X10  0b00110100  /* 5x10 characters               */
#define LINES_5X7  0b00111000  /* 5x7 characters, multiple line */

#ifdef _OMNI_CODE_
#define PARAM_SCLASS
#else
#define PARAM_SCLASS auto
#endif

#ifndef MEM_MODEL
#ifdef _OMNI_CODE_
#define MEM_MODEL
#else
#define MEM_MODEL far  /* Change this to near for small memory model */
#endif
#endif

/* OpenXLCD
 * Configures I/O pins for external LCD
 */
void OpenXLCD(PARAM_SCLASS unsigned char);

/* SetCGRamAddr
 * Sets the character generator address
 */
void SetCGRamAddr(PARAM_SCLASS unsigned char);

/* SetDDRamAddr
 * Sets the display data address
 */
void SetDDRamAddr(PARAM_SCLASS unsigned char);

/* BusyXLCD
 * Returns the busy status of the LCD
 */
unsigned char BusyXLCD(void);

/* ReadAddrXLCD
 * Reads the current address
 */
unsigned char ReadAddrXLCD(void);

/* ReadDataXLCD
 * Reads a byte of data
 */
char ReadDataXLCD(void);

/* WriteCmdXLCD
 * Writes a command to the LCD
 */
void WriteCmdXLCD(PARAM_SCLASS unsigned char);

/* WriteDataXLCD
 * Writes a data byte to the LCD
 */
void WriteDataXLCD(PARAM_SCLASS char);

/* putcXLCD
 * A putc is a write
 */
#define putcXLCD WriteDataXLCD

/* putsXLCD
 * Writes a string of characters to the LCD
 */
void putsXLCD(PARAM_SCLASS char *);

/* putrsXLCD
 * Writes a string of characters in ROM to the LCD
 */
void putrsXLCD(const char *);

/* User defines these routines according to the oscillator frequency */
extern void DelayFor18TCY(void);
extern void DelayPORXLCD(void);
extern void DelayXLCD(void);

#endif


Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: illusionista_86 en 20 de Octubre de 2014, 11:04:25
Miquel_s, en la libreria tuya de XLCD, creo que estas poniendo E, RW y RS en la parte baja del puerto B, pues si te fijas mas arriba de tu codigo hay una parte donde pone:

/* When in 4-bit interface define if the data is in the upper
 * or lower nibble.  For lower nibble, comment the #define UPPER
 */
/* #define UPPER */

la tienes comentada, con lo cual se esta utilizando tambien la parte baja para los datos, descomentala para ver que pasa.

esto te lo digo de forma rapida, no tengo mucho tiempo de ver mas cosas ahora, si no funciona, lo dices...

y yo de normal para ir a una posicion dada de la pantalla utilizao "lcd_gotoXY()", tambien suelo definir los delays en el mismo archivo que esta el "main" de mi proyecto, al igual que la funcion "command"
Título: Re: Mini curso "Programación en XC8"
Publicado por: rotting79 en 21 de Octubre de 2014, 01:45:36
Hey there

try this one....

http://www.todopic.com.ar/foros/index.php?topic=41874.msg348245#msg348245
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 21 de Octubre de 2014, 05:28:28
Thanks rotting79, I will review your program.

Greetings.
Título: Re: Mini curso "Programación en XC8"
Publicado por: illusionista_86 en 23 de Octubre de 2014, 12:08:00
el siguiente codigo no deveria de ir aqui porque es para CCS, pero es un ejemplo que he realizado utilizando la filosofia que he comentado para el control de servos, en este caso son 8 servos, y ademas he realizado una aplicacion en visual basic 2013 para controlar los 8 servos desde el pc, conectando la placa entrenadora al pc por el puerto com.


Código: C
  1. ////////////////////////////////////////////////////////////////////
  2. //TITULO: CONTROL DE 8 SERVOMOTORES PARA HITEC                            //////
  3. //AUTOR: illusionista_86                                                      //////
  4. //FECHA: 20 - 04 - 11                                                                     //////
  5. //DESCRIPCION: POR MEDIO DEL PROGRAMA CONTROL DE 8 SERVOS.EXE //////
  6. //                         CONTROLARAS POR MEDIO DE BARRAS QUE TE INDICARA//////
  7. //                         EL GRADO Y EL SERVO A CONTROLAR.               //////
  8. ////////////////////////////////////////////////////////////////////
  9. ////////////////////////////////////////////////////////////////////
  10.  
  11. #include<16F628A.H>
  12. #include <string.h>
  13. #fuses HS,NOWDT,NOLVP,MCLR,NOPROTECT
  14.  
  15. //HS: CRISTAL DE HIGH SPEED 20MHZ
  16. //NOWDT: NO SE UTILIZA EL PERRO GUARDIAN
  17. //NOLVP: SE DESACTIVA ESTA OPCION DE PROGRAMACION
  18. //MCLR:ACTIVAMOS EL MASTER CLEAN
  19. //NOPROTECT: NO SE PROTEGE EL CODIGO()
  20.  
  21. #use delay(clock=20000000)                      //CRISTAL DE 20MHZ
  22. #use rs232(uart1,baud=9600,parity=N,bits=8,stop=1)                      //PIN_B1->RX,PIN_B2->TX
  23. //#use rs232(uart1,baud=9600)
  24. #use fast_io(A)                                         //RAPIDA INTERVENCION DEL PUERTO A
  25. #use fast_io(B)                                         // ''          ''         PUERTO B
  26. #priority timer1,rda                            //Es mas primordial que se atienda la interrupcion
  27.                                                                         //en el timer1
  28. //CONSTANTES DE ENCENDIDO
  29.  
  30. int MODO=10;
  31. unsigned int baudrate_config=7;
  32. //VARIABLES A CONTROLAR
  33.  
  34. unsigned long tick;                     //E
  35. unsigned int servo=0;           //ES EL NUMERO DEL SERVO A CONTRLAR MAXIMO CONTAR DE 0 A 7
  36.  
  37. short FLAG=0;                           //ACTUALIZADOR
  38. unsigned int NSERVO=0;          //NUMERO DE SERVO SELECCIONADO
  39. unsigned int i;
  40. int ini=0;
  41. unsigned int pos2[]={0,0,0,0,0,0,0,0,0,0};
  42. //VARIABLE DE CONTROL DE PULSO DE ALTO Y BAJO PARA LOS 8 SERVOS
  43. //COLOCADO COMO UN ARREGLO
  44.  
  45. unsigned long T_ON[]={0,0,0,0,0,0,0,0},T_OFF=0;
  46. float ms_ton[]={0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
  47. float ms_toff=0;
  48.  
  49.  
  50. void config(void){
  51.  
  52.                 output_a(0x00);
  53.                 output_b(0x00);
  54.                 set_tris_a(0xA0);
  55.                 set_tris_b(0x02);
  56.                 //output_bit(PIN_B3,1);
  57.                 setup_comparator(NC_NC_NC_NC);                  //Comparadores APAGADO
  58.                 setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //Tick de 0.0002ms
  59.                 set_timer1(tick);
  60.                 disable_interrupts(INT_TIMER1);
  61.                 disable_interrupts(INT_RDA);
  62.                 disable_interrupts(GLOBAL);
  63. }
  64.  
  65.  
  66. void calc_tiempos(int grados[]){
  67.  
  68.     ms_toff=20.0;
  69.     //((2.5-0.5)/(180.0-0.0))
  70.     for (int i=0;i<8;i++){
  71.         ms_ton[i]=0.01111*(float)grados[i]+0.5;
  72.         ms_toff=ms_toff-ms_ton[i];
  73.         T_ON[i]=65536-(unsigned long)((ms_ton[i]/1000.0)*5000000.0); // 62556
  74.     }
  75.     T_OFF=65536-(unsigned long)((ms_toff/1000.0)*5000000.0); // 28516
  76.  
  77. }
  78.  
  79. #INT_RDA
  80. void Interrupcion_X_recepcion(void){
  81.  
  82.                 //disable_interrupts(INT_TIMER1);//DESACTIVA EL TIMER 1
  83.                 if(kbhit()){                                    //HAY INFORMACION A CAPTAR
  84.  
  85.                         MODO=getc();
  86.  
  87.                         if (MODO==0){
  88.                                         //enable_interrupts(INT_TIMER1);
  89.                         }else if(MODO==1){
  90.  
  91.                                         pos2[0]=getc();
  92.                                         pos2[1]=getc();
  93.                                         pos2[2]=getc();
  94.                                         pos2[3]=getc();
  95.                                         pos2[4]=getc();
  96.                                         pos2[5]=getc();
  97.                                         pos2[6]=getc();
  98.                                         pos2[7]=getc();
  99.  
  100.                         }else if(MODO==2){
  101.                             output_toggle(PIN_B3);
  102.                                         NSERVO=getc();
  103.                                         pos2[NSERVO-1]=getc();
  104.  
  105.                         }else if (MODO==3){
  106.                                         NSERVO=getc();
  107.                         }else if (MODO==4){
  108.                                 baudrate_config=getc();
  109.                         }
  110.                 }
  111.                 FLAG=1; //ESTE PARAMETRO TE INDICA QUE SE A EFECTUADO UN CAMBIO EN UN DE LOS
  112.                                 //SERVOMOTORES
  113.                                                                                         //PARA QUE SIGA DONDE SE QUEDO...
  114. }
  115.  
  116. void config_baud_uart(unsigned int baudrate){
  117.  
  118.  
  119.         switch (baudrate)
  120.         {
  121.                 case 0: set_uart_speed(1200);
  122.                                 break;
  123.                 case 1: set_uart_speed(2400);
  124.                                 break;
  125.                 case 2: set_uart_speed(4800);
  126.                                 break;
  127.                 case 3: set_uart_speed(9600);
  128.                                 break;
  129.                 case 4: set_uart_speed(19200);
  130.                                 break;
  131.                 case 5: set_uart_speed(38400);
  132.                                 break;
  133.                 case 6: set_uart_speed(57600);
  134.                                 break;
  135.                 case 7: set_uart_speed(115200);
  136.                                 break;
  137.         }
  138.  
  139. }
  140.  
  141. void set_servos(int s1,int s2, int s3, int s4, int s5, int s6, int s7, int s8){
  142.     output_bit(PIN_A0,s1);output_bit(PIN_A1,s2);output_bit(PIN_A2,s3);output_bit(PIN_A3,s4);
  143.     output_bit(PIN_B4,s5);output_bit(PIN_B5,s6);output_bit(PIN_B6,s7);output_bit(PIN_B7,s8);
  144.     set_timer1(T_ON[servo]);
  145. }
  146.  
  147. #INT_TIMER1
  148. void Interrupcion_timer1(void){
  149.  
  150.         if (servo==0){
  151.             set_servos(1,0,0,0,0,0,0,0);
  152.             servo=1;
  153.         }else if(servo==1){
  154.             set_servos(0,1,0,0,0,0,0,0);
  155.             servo=2;
  156.         }else if(servo==2){
  157.             set_servos(0,0,1,0,0,0,0,0);
  158.             servo=3;
  159.         }else if(servo==3){
  160.             set_servos(0,0,0,1,0,0,0,0);
  161.             servo=4;
  162.         }else if(servo==4){
  163.             set_servos(0,0,0,0,1,0,0,0);
  164.             servo=5;
  165.         }else if(servo==5){
  166.             set_servos(0,0,0,0,0,1,0,0);
  167.             servo=6;
  168.         }else if(servo==6){
  169.             set_servos(0,0,0,0,0,0,1,0);
  170.             servo=7;
  171.         }else if(servo==7){
  172.             set_servos(0,0,0,0,0,0,0,1);
  173.             servo=8;
  174.         }else if(servo==8){
  175.             output_bit(PIN_A0,0);output_bit(PIN_A1,0);output_bit(PIN_A2,0);output_bit(PIN_A3,0);
  176.             output_bit(PIN_B4,0);output_bit(PIN_B5,0);output_bit(PIN_B6,0);output_bit(PIN_B7,0);
  177.             set_timer1(T_OFF);
  178.         }                               //ESTABLECE EL TIMER PARA MANTENER EL PUSLO ALTO
  179.                                                                                 //O BAJO PARA EL PIN QUE CORRESPONDA
  180. }
  181.  
  182.  
  183. void main(void){
  184.  
  185.     config();
  186.     output_bit(PIN_B3,1);
  187.     enable_interrupts(GLOBAL);
  188.     enable_interrupts(INT_RDA);
  189.  
  190.     while(TRUE){
  191.  
  192.         delay_ms(50);
  193.  
  194.         if (FLAG==1){
  195.             if (MODO==1){
  196.                     output_bit(PIN_B3,1);
  197.                     for(int i=0;i<=7;i++){
  198.                             printf("%u\n",pos2[i]);
  199.                     }
  200.                     calc_tiempos(pos2);
  201.                     if (ini==0){
  202.                             enable_interrupts(INT_TIMER1);
  203.                             ini=1;
  204.                     }
  205.             }else if (MODO==2){
  206.                 output_toggle(PIN_B0);
  207.                     printf("%u\n",MODO);
  208.                     printf("%u\n",NSERVO);
  209.                     printf("%u\n",pos2[NSERVO-1]);
  210.                     calc_tiempos(pos2);
  211.             }else if (MODO==3){
  212.                     printf("%u\n",MODO);
  213.                     printf("%u\n",NSERVO);
  214.                     printf("%u\n",pos2[NSERVO-1]);
  215.  
  216.             }else if (MODO==4){
  217.                     printf("%u\n",baudrate_config);
  218.                     config_baud_uart(baudrate_config);
  219.             }
  220.             FLAG=0;MODO=10;
  221.         }
  222.  
  223.     }
  224. }

en el siguiente enlace se encuentra la aplicacion en cuestion para ser instalada, el proyecto en mplabX utilizando CCS, y el archivo proteus para silumar, y el esquematico de la placa realizada para tal fin.


https://www.dropbox.com/sh/9syipx78rjcmbj2/AACtP84Yz9OSzsaIS3wGoC7ua?dl=0

adjunto una imagen de la aplicacion.


PD: perdon por los acentos, estoy utilizando un teclado de EEUU que no los llevan (o no se como ponerlos, jejej)

Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 24 de Octubre de 2014, 19:55:51
Sigo sin lograr hacer funcionar el Lcd y no soy capaz de dar con el error, si alguien fuera tan amable de revisar el código lo agradecería, el problema es que no consigo visualizar nada en el Lcd.
El Lcd esta conectado de la siguiente manera:
RB3  ---->  E
RB2  ---->  RS
RB4  ---->  D4
RB5  ---->  D5
RB6  ---->  D6
RB7  ---->  D7

my_xlcd
Código: [Seleccionar]
#ifndef __XLCD_H
#define __XLCD_H
#include "p18f2550.h"
/* PIC18 XLCD peripheral routines.
 *
 *   Notes:
 *      - These libraries routines are written to support the
 *        Hitachi HD44780 LCD controller.
 *      - The user must define the following items:
 *          - The LCD interface type (4- or 8-bits)
 *          - If 4-bit mode
 *              - whether using the upper or lower nibble
 *          - The data port
 *              - The tris register for data port
 *              - The control signal ports and pins
 *              - The control signal port tris and pins
 *          - The user must provide three delay routines:
 *              - DelayFor18TCY() provides a 18 Tcy delay
 *              - DelayPORXLCD() provides at least 15ms delay
 *              - DelayXLCD() provides at least 5ms delay
 */

/* Interface type 8-bit or 4-bit
 * For 8-bit operation uncomment the #define BIT8
 */
/* #define BIT8 */

/* When in 4-bit interface define if the data is in the upper
 * or lower nibble.  For lower nibble, comment the #define UPPER
 */
 //#define UPPER

/* DATA_PORT defines the port to which the LCD data lines are connected */
 #define DATA_PORT       PORTB
 #define TRIS_DATA_PORT TRISB

/* CTRL_PORT defines the port where the control lines are connected.
 * These are just samples, change to match your application.
 */
 #define RW_PIN   LATBbits.LATB1   /* PORT for RW */
 #define TRIS_RW  TRISBbits.TRISB1     /* TRIS for RW */

 #define RS_PIN   LATBbits.LATB2   /* PORT for RS */
 #define TRIS_RS  TRISBbits.TRISB2     /* TRIS for RS */

 #define E_PIN    LATBbits.LATB3   /* PORT for D  */
 #define TRIS_E   TRISBbits.TRISB3     /* TRIS for E  */

/* Display ON/OFF Control defines */
#define DON         0b00001111  /* Display on      */
#define DOFF        0b00001011  /* Display off     */
#define CURSOR_ON   0b00001111  /* Cursor on       */
#define CURSOR_OFF  0b00001101  /* Cursor off      */
#define BLINK_ON    0b00001111  /* Cursor Blink    */
#define BLINK_OFF   0b00001110  /* Cursor No Blink */

/* Cursor or Display Shift defines */
#define SHIFT_CUR_LEFT    0b00000100  /* Cursor shifts to the left   */
#define SHIFT_CUR_RIGHT   0b00000101  /* Cursor shifts to the right  */
#define SHIFT_DISP_LEFT   0b00000110  /* Display shifts to the left  */
#define SHIFT_DISP_RIGHT  0b00000111  /* Display shifts to the right */

/* Function Set defines */
#define FOUR_BIT   0b00101100  /* 4-bit Interface               */
#define EIGHT_BIT  0b00111100  /* 8-bit Interface               */
#define LINE_5X7   0b00110000  /* 5x7 characters, single line   */
#define LINE_5X10  0b00110100  /* 5x10 characters               */
#define LINES_5X7  0b00111000  /* 5x7 characters, multiple line */

#ifdef _OMNI_CODE_
#define PARAM_SCLASS
#else
#define PARAM_SCLASS auto
#endif

#ifndef MEM_MODEL
#ifdef _OMNI_CODE_
#define MEM_MODEL
#else
#define MEM_MODEL far  /* Change this to near for small memory model */
#endif
#endif

/* OpenXLCD
 * Configures I/O pins for external LCD
 */
void OpenXLCD(PARAM_SCLASS unsigned char);

/* SetCGRamAddr
 * Sets the character generator address
 */
void SetCGRamAddr(PARAM_SCLASS unsigned char);

/* SetDDRamAddr
 * Sets the display data address
 */
void SetDDRamAddr(PARAM_SCLASS unsigned char);

/* BusyXLCD
 * Returns the busy status of the LCD
 */
unsigned char BusyXLCD(void);

/* ReadAddrXLCD
 * Reads the current address
 */
unsigned char ReadAddrXLCD(void);

/* ReadDataXLCD
 * Reads a byte of data
 */
char ReadDataXLCD(void);

/* WriteCmdXLCD
 * Writes a command to the LCD
 */
void WriteCmdXLCD(PARAM_SCLASS unsigned char);

/* WriteDataXLCD
 * Writes a data byte to the LCD
 */
void WriteDataXLCD(PARAM_SCLASS char);

/* putcXLCD
 * A putc is a write
 */
#define putcXLCD WriteDataXLCD

/* putsXLCD
 * Writes a string of characters to the LCD
 */
void putsXLCD(PARAM_SCLASS char *);

/* putrsXLCD
 * Writes a string of characters in ROM to the LCD
 */
void putrsXLCD(const char *);

/* User defines these routines according to the oscillator frequency */
extern void DelayFor18TCY(void);
extern void DelayPORXLCD(void);
extern void DelayXLCD(void);

#endif
He probado dejando comentado //#define UPPER y sin comentar y no funciona

main
Código: [Seleccionar]
#include <xc.h>                 //PIC hardware mapping
#include <plib/delays.h>
#include "my_xlcd.h"
#include <stdlib.h>
#include <stdio.h>

#define _XTAL_FREQ  48000000        //Used by the XC8 delay_ms(x) macro

// CONFIG1L
#pragma config PLLDIV = 5       // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
#pragma config USBDIV = 1       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)

// CONFIG1H
#pragma config FOSC = HSPLL_HS     // Oscillator Selection bits (XT oscillator (XT))
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = ON         // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
#pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)

// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = ON      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM is not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)

/* Retardos requeridos por la libreria XLCD */
void DelayFor18TCY(void);
void DelayPORXLCD(void);
void DelayXLCD(void);

//*********************************************************
/* FUNCIONES DE RETARDOS REQUERIDOS POR LA LIBRERIA LCD  */
//*********************************************************
void DelayFor18TCY(void)
{
    Delay10KTCYx(120);      /* Retardo de 18 TCY */
    return;
}
void DelayPORXLCD(void)
{
    Delay1KTCYx(180);       /* Retardo de 15ms */
    return;
}
void DelayXLCD(void)
{
    Delay1KTCYx(60);        /* Retardo de 5ms */
    return;
}


//*********************************************************
/* FUNCION PRINCIPAL */
//*********************************************************

int main ()
{
    /* Set RB<4:0> as digital I/O pins (required if config bit PBADEN is set */
    ADCON1 = 0x0E;
    /* Configure external LCD */
    OpenXLCD( FOUR_BIT & LINES_5X7 );
    /* Esperamos a que el display este disponible */
    while(BusyXLCD());
    WriteCmdXLCD( BLINK_ON );
    WriteCmdXLCD( SHIFT_DISP_LEFT );
     while(1)
     {
     //Primera línea
     SetDDRamAddr(0x00);
     putrsXLCD("HOLA");
     //Segunda línea
     SetDDRamAddr(0x40);
     putrsXLCD("MUNDO");
     }
}

Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 26 de Octubre de 2014, 16:19:36
Me doy por vencido despues de 12 dias intentando visualizar hola en el lcd, otro de tantos a la basura.

Miquel_S
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 26 de Octubre de 2014, 16:28:00
Antes de tirar la Pcb a la basura es necesario tener el pin RW conectado al micro o puedo ponerlo directo a masa como es el caso.
Título: Re: Mini curso "Programación en XC8"
Publicado por: AngelGris en 26 de Octubre de 2014, 16:35:50
  Si quieres chequear el estado del LCD será necesario conectar el pin RW al micro. Si no lo conectas debes utilizar retardos largos para asegurarte que no envías información al LCD mientras el mismo está ocupado con la instrucción anterior.

  Aquí está la librería que subí, para manejo de LCD... podrías intentar con ella para ver que ocurre.


http://www.todopic.com.ar/foros/index.php?topic=40649.180

  ¿Tu programa lo has simulado en ISIS? De ser así, ¿ha funcionado?
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 26 de Octubre de 2014, 18:13:11
Si lo he simulado en Proteus y tampoco me funciona, voy ha revisar la librería.

Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 26 de Octubre de 2014, 18:43:11
He desconectado el pin RW de la masa y lo he conectado al pic y sigo con el mismo problema.

Gracias
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 09 de Noviembre de 2014, 14:13:00
He conseguido hacerlo funcionar en proteus pero con una configuracion diferente al hardware que tengo montado, y no comprendo el porque mi configuracion no me funciona.

Funciona:
RS ----> RB5
RW ---->RB6
E ----> RB4

Mi configuracion no funciona en proteus ni montado en fisico:
RS ----> RB6
RW ----> RB5
E ----> RB7

¿Que tiene de especial el pin RB7 porque segun he leido en el datasheet ni siquiera es analogico?

Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 11 de Noviembre de 2014, 15:33:49
Por favor nadie sabe lo que puede estar pasando.

Miquel_S
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 11 de Noviembre de 2014, 16:01:41
Por favor nadie sabe lo que puede estar pasando.

Miquel_S

Es raro, pero bueno empecemos....
Se elimino todo problema de software ? Es decir, con los otros pines funciona SI o SI ?


lo que se me ocurre que en CONFIG4L tenes:

bit 7 DEBUG(negado): Background Debugger Enable bit
1 = Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
0 = Background debugger enabled, RB6 and RB7 are dedicated to In-Circuit Debug

Por default viene en 1, pero no se.. de todas formas no andaria RB6.

Para ir limando el problema y tratar de encontrarlo, probaste modificar la salida del RB7 a mano ?
Es decir podes poner a 1 RB7 o a 0 a tu voluntad? Aunque sea con un programita simple. Si es asi estaria mirando ya al codigo de esa libreria, veo que algunos tienen problemas con eso por mala inicializacion etc.

Antes de tirar la Pcb a la basura es necesario tener el pin RW conectado al micro o puedo ponerlo directo a masa como es el caso.

Esto unicamente si queres leer del LCD, yo lo hice funcionar con el RW conectado a GND, y siendo el LCD de 5V y el micro de 3.3v
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 11 de Noviembre de 2014, 16:35:17
Gracias KILLERJC primero después de cenar voy a probar una solución del compañero illusionista_86 y os contare.

Gracias!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 11 de Noviembre de 2014, 17:56:11
Aquí lo dejo no me funciona ni simulado ni montado en Pcb, si alguien es tan amable de ayudarme lo agradeceré sino no pasa nada ya estoy acostumbrado a no terminar ninguno, despues de un par de años a día de hoy solo se encender un led.

Saludos!

PD: No cuento esto por dar pena a nadie pero creedme es frustrante.

Título: Re: Mini curso "Programación en XC8"
Publicado por: illusionista_86 en 11 de Noviembre de 2014, 18:19:08
esta noche lo pruebo, para mi es todavia medio dia... jejej
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 11 de Noviembre de 2014, 18:47:56
Yo tengo el problema que no poseo la libreria de microchip la que poseen las funciones OpenXLCD() por ejemplo, eso queria ver :).

Por que encuentro de todo menos esas funciones, lo cual no se si es una libreria creada por alguien o de microchip, vi un pdf de microchip y habla de XLCDInit() y no esa funcion que tenes ahi.

Si usas esta: http://www.todopic.com.ar/foros/index.php?topic=40649.msg339676#msg339676

Veo que cuando inicia usa el pin RW.

Aquí lo dejo no me funciona ni simulado ni montado en Pcb, si alguien es tan amable de ayudarme lo agradeceré sino no pasa nada ya estoy acostumbrado a no terminar ninguno, despues de un par de años a día de hoy solo se encender un led.

Probaste lo que te dije? intentar poner a 1 o 0 el pin RB7 ( por mas que no tengas nada conectado ) Si es asi, entonces miraria la libreria.
Título: Re: Mini curso "Programación en XC8"
Publicado por: illusionista_86 en 11 de Noviembre de 2014, 21:46:42
ya esta solucionado:

1- en headers files tienes varios archivos: borralos todos incluso el tuyo de "myXLCD"

2- cambia en el main.x la cabecera correspondiente al xlcd : <xlcd.h>

3- ve a la ruta: C:\Program Files (x86)\Microchip\xc8\v1.33\sources\pic18\plib\XLCD y copia todos los archivos que hay aqui dentro a la carpeta de tu proyecto: "lcd2x16.x"

4- en el proyecto en mplabX, selecciona source files, boton derecho y selecciona add items.... agrega todos y cada uno de los archivos copiados a la carpeta de tu proyecto.

5- una vez agregados, modifica el archivo original xlcd.h, puedes comentar las lineas originales y modificar una copia de ellas:

 #define RW_PIN   LATBbits.LATB5         /* PORT for RW */
 #define TRIS_RW  TRISBbits.TRISB5       /* TRIS for RW */

 #define RS_PIN   LATBbits.LATB6         /* PORT for RS */
 #define TRIS_RS  TRISBbits.TRISB6       /* TRIS for RS */

 #define E_PIN    LATBbits.LATB7        /* PORT for D  */
 #define TRIS_E   TRISBbits.TRISB7       /* TRIS for E  */

6- compila el proyecto y a funcionar....


esto es lo que te dige al principio, que copiaras todos los archivos de XLCD a tu proyecto y modificaras la libreria xlcd.h....

pongo un link al archivo porque el foro no me deja subir mas de 250kb. en dos dias quito el link.

https://www.dropbox.com/s/8lkmrqf3yxfv1ij/Lcd2x16.X.rar?dl=0
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 11 de Noviembre de 2014, 21:52:47
En fin un problema de libreria ? por eso preguntaba sobre la libreria :/
Título: Re: Mini curso "Programación en XC8"
Publicado por: illusionista_86 en 11 de Noviembre de 2014, 23:12:21
Si, para poder modificar la librería xlc y que se compile de nuevo, todos los archivos de la librería XLCD hay que copiarlos en la carpeta del proyecto, añadirlas al proyecto en MPLABX, modificar el xlcd.h original, comentando si queréis las líneas originales, y compilar el proyecto, así es cuando surten efecto las modificaciones en el archivo XLCD.h.
Título: Re: Mini curso "Programación en XC8"
Publicado por: illusionista_86 en 11 de Noviembre de 2014, 23:15:55
Killerjc, tu caso es diferente.. Que programa usas? Que compilador? El MPLABX utilizando el XC8 debería de encontrarte la librería XLCD y sus funciones, están en la ruta que e puesto antes, si no están ahí es porque algo tienes mal instalado o estas utilizando un compilador o programa diferente.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 12 de Noviembre de 2014, 05:22:43
Lo primero dar las gracias a illusionista_86 por haberse molestado en perder parte de su tiempo haciendo el trabajo y de paso enseñarme como debía de hacerlo, y perdón por mi ignorancia yo había entendido que debía copiar el archivo XLCD.h dentro del proyecto pero no entendí que debía copiar todos sus archivos.
Gracias de nuevo illusionista_86 y todos los que habéis aportado vuestro granito de arena.

Miquel Servera.
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 12 de Noviembre de 2014, 10:34:28
Killerjc, tu caso es diferente.. Que programa usas? Que compilador? El MPLABX utilizando el XC8 debería de encontrarte la librería XLCD y sus funciones, están en la ruta que e puesto antes, si no están ahí es porque algo tienes mal instalado o estas utilizando un compilador o programa diferente.

Usaba MPLAB X + XC8 o XC16, pero hacia tiempo que no lo tocaba y limpie mi particion de linux borrandolo, y como me meti de lleno con un ARM no lo instale mas xD, pero C es C y los PICs son PICs, por lo que puedo saber de C y notar un error de programacion o puedo saber por que no funciona una cosa del PIC si esta mal configurada, pero cuando entro una libreria a la cual no tenia acceso al codigo se me complico, Intente buscarla por internet pero usaban otros nombres de funciones. Ahi se me complico mas xD Ya baje los archivos del MPLAB + XC8 por otra cosa que quiero hacer.

De todas formas uno podria linkear el .c no creo que exista necesidad de copiar y pegar el archivo. Al menos asi lo hago con el CSS de TI (basado en eclipse), si no lo encuentra te deberia dar un error el linker.
Título: Re: Mini curso "Programación en XC8"
Publicado por: illusionista_86 en 12 de Noviembre de 2014, 12:58:58
Miquel_s, no hay de que, para eso estamos, hoy por ti, manyana por mi...

killerjc, no se si linkeando el .c funciona, pero como tu dices, deberia... por ahora he probado la forma que he comentado, y creo que es la que todos usan y es la que funciona.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 16 de Noviembre de 2014, 14:53:36
 :oops: Hola de nuevo, sigo con el lcd pero avanzando, tengo un error en el programa el cual desearía resolver antes de seguir y no doy con la solución.
Código: [Seleccionar]
/* DECLARACION DE FUNCIONES */
void Menu_Inicio(void);
void Menu_Principal(void);

/* FUNCIONES DE TEMPORIZACION */
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)
{
    ADCON1 = 0b00001111;
    TRISA = 0x01;
    OpenXLCD(FOUR_BIT & LINES_5X7);     // Iniciamos Lcd
    comandXLCD(0x06);       // Nos aseguramos incremento de direccion, display fijo
    comandXLCD(0x0C);       // Encendemos Lcd
    Menu_Inicio();               // Llamamos a la funcion del menu de inicio.
    Menu_Principal();            // Llamamos a la funcion del menu principal.


    while(1)
    {
        if(PORTAbits.RA0){
            Menu_Principal();   // Retorna al menu principal
        }
        Delay1KTCYx(15);
    }
}

/* FUNCIONES PARA EL USO DEL MENU CICLICO */

/* Funcion menu de inicio */
void Menu_Inicio(void){
    putrsXLCD("Robot Minisumo");
    gotoxyXLCD(6,2);
    putrsXLCD("PANCHO");
    Delay10KTCYx(0);
}

/* Funcion menu principal */
void Menu_Principal(void){
    WriteCmdXLCD(CLEAR);
    gotoxyXLCD(2,1);
    putrsXLCD("MENU1");
    gotoxyXLCD(2,2);
    putrsXLCD("MENU2");
    gotoxyXLCD(10,1);
    putrsXLCD("MENU3");
    gotoxyXLCD(10,2);
    putrsXLCD("MENU4");
}

En la función Menu_Principal donde dice gotoxyXLCD(2,1); por mucho que cambie el valor de x siempre empieza en la posición 1 y no se porque ya que los demás si funcionan correctamente.

Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Rseliman en 02 de Abril de 2015, 21:40:28
Hola amigos ...hace ya un tiempo que no me daba una vuelta ...habia dejado un poco de programar , ahora retornando quisiera pedirles un consejo ...

que mas me conviene usar con un pic cualquiera ...para enviar por internet una orden a una pagina de apretar un boton de ok ....no se si me explico ....o sea que apretando un boton conectado al pic , este mismo este conectado a la red , a esa pagina , y haga lo mismo que si fuese yo a la pagina con una pc  ingrese un numero y le de ok con el mouse o sea el dispositivo tendria un lcd para ver el numero que ingreso y un boton para darle ok ...obviamente conectado a la red logueado en ese servidor o pagina ...

Muchas gracias a todos !!!!
Título: Re: Mini curso "Programación en XC8"
Publicado por: leo_gladiador en 29 de Agosto de 2015, 16:18:59
hola una consulta,como realizo pausas extensas(de horas) en xc8 ,es decir lo que quiero hacer es presionar un botón  y que cambie el estado de un pin  luego de un tiempo(1hora) determinado vuelva a cero.

Esta funcion no se si es eficiente  para realizar lo que quiero hacer

void pausa(unsigned int tiempo)
{
  unsigned int __tiempo;
  for (__tiempo = tiempo; __tiempo > 0; __tiempo--)
  {
    __delay_ms(1000);
  }
}


saludos  :-/
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 29 de Agosto de 2015, 16:33:55
Hola leo_gladiator intenta no preguntar lo mismo en dos apartados diferentes.

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Thulsa Doom en 30 de Agosto de 2015, 07:12:12
hola una consulta,como realizo pausas extensas(de horas) en xc8 ,es decir lo que quiero hacer es presionar un botón  y que cambie el estado de un pin  luego de un tiempo(1hora) determinado vuelva a cero.

Esta funcion no se si es eficiente  para realizar lo que quiero hacer

void pausa(unsigned int tiempo)
{
  unsigned int __tiempo;
  for (__tiempo = tiempo; __tiempo > 0; __tiempo--)
  {
    __delay_ms(1000);
  }

}

saludos  :-/

Hola, mala idea emplear bucles para retardos, la razón es que el micro no podrá hacer nada más hasta que termine el bucle y si tienes un retardo de una hora pues el micro no podrá seguir ejecutando su programa hasta una hora después, con lo cual es inviable.
Para contar tiempos lo mejor es utilizar el timer 0 y una interrupción, hay una librería llamada Tick.c que se encuentra en las librerías TCP/IP de microchip que hace eso que tu buscas, es para C18 pero puede ser adaptada para XC8.
ya nos cuentas como te va
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 06 de Septiembre de 2015, 14:38:23
Buenas tardes, tengo un pequeño problema con un programa para visualizar un mensaje en el LCD, me visualiza el mensaje pero al cabo de unos segundos desaparece y aparecen caracteres extraños desplazándose por la pantalla, he descartado problemas de hardware ya que en ASM el LCD funciona de forma correcta.
Código: C
  1. /*
  2.  * PIC: 18F2550
  3.  * Compiler: XC8 v1.34
  4.  * IDE: MPLABX v3.05
  5.  */
  6.  
  7. #include <xc.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <plib/xlcd.h>
  11. #include <plib/delays.h>
  12.  
  13. #define _XTAL_FREQ 48000000     //Used by the XC8 delay_ms(x) macro
  14.  
  15. // CONFIG1L
  16. #pragma config PLLDIV = 5       // PLL Prescaler Selection bits (Divide by 5 (20 MHz oscillator input))
  17. #pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
  18. #pragma config USBDIV = 1       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)
  19.  
  20. // CONFIG1H
  21. #pragma config FOSC = HSPLL_HS  // Oscillator Selection bits (HS oscillator, PLL enabled (HSPLL))
  22. #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
  23. #pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
  24.  
  25. // CONFIG2L
  26. #pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
  27. #pragma config BOR = OFF        // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
  28. #pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
  29. #pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)
  30.  
  31. // CONFIG2H
  32. #pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
  33. #pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)
  34.  
  35. // CONFIG3H
  36. #pragma config CCP2MX = ON      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
  37. #pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
  38. #pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
  39. #pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
  40.  
  41. // CONFIG4L
  42. #pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
  43. #pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
  44. #pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
  45.  
  46. // CONFIG5L
  47. #pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
  48. #pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
  49. #pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
  50. #pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)
  51.  
  52. // CONFIG5H
  53. #pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
  54. #pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)
  55.  
  56. // CONFIG6L
  57. #pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
  58. #pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
  59. #pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
  60. #pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)
  61.  
  62. // CONFIG6H
  63. #pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
  64. #pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
  65. #pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM is not write-protected)
  66.  
  67. // CONFIG7L
  68. #pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
  69. #pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
  70. #pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
  71. #pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)
  72.  
  73. // CONFIG7H
  74. #pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)
  75.  
  76.  
  77.  
  78. //Retardos requeridos por la libreria XLCD
  79. void DelayFor18TCY(void);
  80. void DelayPORXLCD(void);
  81. void DelayXLCD(void);
  82.  
  83. void main(void)
  84. {
  85. /* Set RB<4:0> as digital I/O pins (required if config bit PBADEN is set */
  86.     ADCON1 = 0x0E;
  87.     /* Configure external LCD */
  88.     OpenXLCD( FOUR_BIT & LINES_5X7 );
  89.     /* Esperamos a que el display este disponible */
  90.     while(BusyXLCD());
  91.     WriteCmdXLCD( BLINK_ON );
  92.     WriteCmdXLCD( SHIFT_DISP_LEFT );
  93.      while(1)
  94.      {
  95.      //Primera línea
  96.      SetDDRamAddr(0x00);
  97.      putrsXLCD("HOLA");
  98.      //Segunda línea
  99.      SetDDRamAddr(0x40);
  100.      putrsXLCD("MUNDO");
  101.      }
  102. }
  103.  
  104. void DelayFor18TCY(void)
  105. {
  106.     Delay10TCYx(120);
  107. }
  108. void DelayPORXLCD(void)
  109. {
  110.     Delay1KTCYx(180);
  111.     return;
  112. }
  113. void DelayXLCD(void)
  114. {
  115.     Delay1KTCYx(60);
  116.     return;
  117. }

Gracias por cualquier ayuda aportada.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Thulsa Doom en 06 de Septiembre de 2015, 15:49:37
Hola, puede ser problema de la velocidad en el driver del XC8, a mi me pasaba con C18 y después de muchas pruebas era esa la causa
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 06 de Septiembre de 2015, 16:03:00
Gracias Thulsa Doom por tu respuesta, he encontrado parte del fallo pero no se el porque, el problema es el LCD que por algún motivo a dejado de funcionar siendo nuevo, de todos modos voy a volver a probarlo con el programa que tengo en ASM para poder descartar que no sea problema del programa mas arriba posteado.

Saludos!
Título: Re: Mini curso "Programación en XC8"
Publicado por: Miquel_S en 06 de Septiembre de 2015, 16:21:16
Bueno, después de hacer pruebas tengo lo siguiente:

LCD mod: QC1602A v2.0
Controlador mod: HD44780
Funciona correctamente con programa escrito en ASM.
Funciona de forma errónea con programa escrito en C.  (Código del post anterior)

LCD mod: WM-C1602M
Controlador mod: HD44780
Funciona correctamente con programa escrito en ASM.
Funciona correctamente con programa escrito en C.  (Código del post anterior)

Alguna idea, Gracias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 06 de Septiembre de 2015, 21:21:12
Tienen el mismo controlador, asi que no deberia haber diferencias.
Pero si podrian ser tiempos, en el que uno sea un poquito mas rapido y no tenga problemas, y el otro no. Los datos que se mandan son iguales asi que tampoco es eso.

Otra explicacion realmente no se me cruza por la cabeza. Aunque si fuera por tiempo podria fallar tambien en la primera pero ocurre a los segundos. Asi que ya con eso va mas a un error del controlador. tal ves se cuelga o algo por el estitlo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: Thulsa Doom en 07 de Septiembre de 2015, 18:57:40
También me ha pasado que de entrada funciona bien y cuando llega a una sección del programa empieza a salir caracteres raros, en mi caso era por una estructura que machacó una parte del programa y ocurría eso pero creo que ese no es tu caso. lo digo como curiosidad quien sabe en un futuro lo que pueda pasar  :lol:
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 30 de Septiembre de 2015, 12:09:57
una pregunta estoy tratando de configurar la lcd 2x16 para pic 24fj64gb002 pero he tenido problemas no escribe se ubica en la posicion pero a momento de escribir no lo hace me he ayudado con este tema de xc8 pero estoy utilizando xc16 y he tratado de adaptarlo al compilador las ddiferentes librerias de este curso pero no ha dado resultado por favor si me pudieran ayudar aqui les dejo el programa :
Código: [Seleccionar]
[pre]#include <p24FJ64GB002.h>
#include <stdio.h>
#include <stdlib.h>
#include <libpic30.h>

 //config2
//#pragma config POSCMOD = HS             // Primary Oscillator Select (HS Oscillator mode selected)
#pragma config PLL96MHZ = ON            // 96MHz PLL Startup Select (96 MHz PLL Startup is enabled automatically on start-up)
#pragma config PLLDIV = DIV5            // USB 96 MHz PLL Prescaler Select (Oscillator input divided by 5 (20 MHz input))
//config1
#pragma config FWDTEN = OFF             // Watchdog Timer (Watchdog Timer is disabled)
#pragma config GWRP = OFF               // General Segment Write Protect (Writes to program memory are allowed)
#pragma config GCP = OFF                // General Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = ON              // JTAG Port Enable (JTAG port is enabled)

#define _XTAL_FREQ 20000000
#define __delay_ms(x) __delay32((unsigned long)((x)*(_XTAL_FREQ/10000.0))) 
#define __delay_us(x) __delay32((unsigned long)((x)*(_XTAL_FREQ/10000000.0)))
#define LED PORTAbits.RA1     
#define ra0 PORTAbits.RA0
#include "xclcd.h"
 
void main(void)
{
    unsigned char alfa[17] = "Peque";
 
    const unsigned char letra[8] = {0b00000000,
                                    0b00001110,
                                    0b00000000,
                                    0b00010110,
                                    0b00011001,
                                    0b00010001,
                                    0b00010001};
     
    unsigned char veces;
       
   
    PORTA = 0;
    TRISA = 0;
  //  PORTB = 0;
  //  TRISB = 0;
 
  lcd_init();
   
        __delay_ms(1500);
    lcd_createchar(1,letra);

        __delay_ms(1500);
    lcd_setdisplay(DISPLAY_OFF);

        __delay_ms(1500);
    lcd_puts("Pequeno");
        __delay_ms(1500);
    lcd_gotoxy(1,2);
        __delay_ms(1500);
    lcd_puts(alfa);
        __delay_ms(1500);
    lcd_putch(1);
        __delay_ms(1500);
    lcd_putch('o');
 
        __delay_ms(1500);

    lcd_setdisplay(CURSOR_ON);

        __delay_ms(1500);

        lcd_puts("hola");

        __delay_ms(1500);
        lcd_gotoxy(1,2);
        __delay_ms(1500);
    lcd_setdisplay(CURSOR_ON);     
__delay_ms(1500);
    lcd_puts("fino");
    while(1)
    {
        LED=1;
        __delay_ms(500);
        LED=0;
        __delay_ms(500);
     
    }
}[/pre]

librerias de angel gris publicado en este post  XCLCD.h

Código: [Seleccionar]
#ifndef XCLCD_H
#define XCLCD_H
 
#ifndef _XC_H_
#include <p24FJ64GB002.h>
#endif
 
/******************************************************************************
 *  Parametros configurables por el usuario                                   *
 ******************************************************************************/
 
/*
 * El valor de _XTAL_FREQ debe coincidir con el valor definido
 * en el programa principal
 */
 
/*
 * LCDEN define el pin EN para el lcd
 * LCDRS define el pin RS para el lcd
 * LCDRW define el pin RW para el lcd
 * LCDDATA define el puerto de datos
 */
 
/*
 * Si se utiliza un pic con resgistros LAT
 * se pueden definir los pines utilizando LAT<x>bits.LAT<x><y>
 * siendo <x> la letra del puerto correspondiente y <y> el bit
 * Tambien se puede definir de la misma manera el puerto de datos
 */
 
/*
 * LCDTRISEN define el bit TRIS para el pin EN
 * LCDTRISRS define el bit TRIS para el pin RS
 * LCDTRISRW define el bit TRIS para el pin RW
 * LCDTRIS define el TRIS correspondiente al puerto de datos
 */
 
/*
 * PROTOCOL4BIT define si se utiliza protocolo de 4 bits
 * PROTOCOL8BIT define si se utiliza protocolo de 8 bits
 */
 
/*
 * En caso de utilizar protocolo de 4 bits
 * UPPER define si se utiliza el nibble alto del puerto
 * LOWER define si se utiliza el nibble bajo del puerto
 */
 
/*
 * En caso de utilizar el pin RW, hay que definir
 * USE_RW
 */
 
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 20000000
#endif
 
#define LCDEN PORTBbits.RB13
#define LCDRS PORTBbits.RB15
#define LCDRW PORTBbits.RB14
#define LCDTRISEN TRISBbits.TRISB13
#define LCDTRISRS TRISBbits.TRISB15
#define LCDTRISRW TRISBbits.TRISB14
#define LCDDATA PORTB
#define LCDTRIS TRISB
#define LCDLAT LATB
#define PROTOCOL4BIT
#define LOWER
#define USE_RW
 
 
/******************************************************************************
 *  Definicion de valores para lcd_setdisplay                                 *
 ******************************************************************************/
/*
 * Los valores se pueden combinar utilizando el operador |
 */
 
#define DISPLAY_OFF 0b00001000
#define DISPLAY_ON  0b00001100
#define CURSOR_OFF  0b00001100
#define CURSOR_ON   0b00001110
#define BLINK_OFF   0b00001100
#define BLINK_ON    0b00001101
 
/******************************************************************************
 *  Definicion de valores para lcd_shift                                      *
 ******************************************************************************/
/*
 * Los valores se pueden combinar utilizando el operador |
 */
 
#define SHIFT_DISPLAY 0b00011000
#define SHIFT_CURSOR  0b00010000
#define SHIFT_LEFT    0b00010000
#define SHIFT_RIGHT   0b00010100
 
/******************************************************************************
 *  Definicion de valores para lcd_entrymode                                  *
 ******************************************************************************/
/*
 * Los valores se pueden combinar utilizando el operador |
 */
 
#define INCREMENT 0b00000110
#define DECREMENT 0b00000100
#define SHIFT_ON  0b00000101
#define SHIFT_OFF 0b00000100
 
 
/******************************************************************************
 *  Definicion de funciones                                                   *
 ******************************************************************************/
 
void lcd_init(void);
void lcd_put(unsigned char, unsigned char);
void lcd_puts(const unsigned char*);
void lcd_gotoxy(unsigned char, unsigned char);
int  lcd_busy(void);
void lcd_putini(unsigned char);
void lcd_createchar(unsigned char, const unsigned char*);
void lcd_setdisplay(unsigned char);
void lcd_shift(unsigned char);
void lcd_entrymode(unsigned char);
 
#define lcd_putch(x) lcd_put(x,1)
#define lcd_clear() lcd_put(0x01,0)
#define lcd_home() lcd_put(0x02,0)
#define lcd_off() lcd_put(0x08,0)
#define lcd_on() lcd_put(0x0C,0)
 
#endif /* XCLCD_H */

y aqui XCLCD.c
Código: [Seleccionar]
#include <p24FJ64GB002.h>
#include "xclcd.h"
#define _XTAL_FREQ 20000000
#define __delay_ms(x) __delay32((unsigned long)((x)*(_XTAL_FREQ/10000.0))) 
#define __delay_us(x) __delay32((unsigned long)((x)*(_XTAL_FREQ/10000000.0)))
#if !defined(LCDEN) || !defined(LCDRS)
#error Faltan definir los pines de control
#elif !defined(LCDTRISEN) || !defined(LCDTRISRS)
#error Falta definir la direccion de los pines de control
#elif !defined(LCDDATA) || !defined(LCDTRIS)
#error Falta definir el puerto y/o el tris de datos
#elif !defined(PROTOCOL4BIT) && !defined(PROTOCOL8BIT)
#error Falta definir el protocolo
#elif defined(PROTOCOL4BIT) && !defined(UPPER) && !defined(LOWER)
#error Falta definir el nibble
#else
 

void lcd_putini(unsigned char data)
{
    unsigned char lasttris;
 
    lasttris = LCDTRIS;
#if defined(PROTOCOL8BIT)
    LCDTRIS = 0;
    LCDDATA = data;
#elif defined(PROTOCOL4BIT)
#if defined(UPPER)
    LCDTRIS &= 0x0F;
    LCDDATA = (LCDDATA & 0x0F) | data;
#elif defined(LOWER)
    LCDTRIS &= 0xF0;
    data = data >> 4;
    LCDDATA = (LCDDATA & 0xF0) | data;
#endif
#endif
    LCDEN = 1;
    __delay_us(1);
    LCDEN = 0;
    LCDTRIS = lasttris;
}
 
void lcd_put(unsigned char data, unsigned char reg)
{
    unsigned char lasttris;
 
    lasttris = LCDTRIS;
#if defined (USE_RW)
    while(lcd_busy() == 1);
#else
    __delay_ms(2);
#endif
    LCDRS = reg;
    LCDRW = 0;
#if defined(PROTOCOL8BIT)
    LCDTRIS = 0;
    LCDDATA = data;
    LCDEN = 1;
    __delay_us(1);
    LCDEN = 0;
#elif defined(PROTOCOL4BIT)
#if defined(UPPER)
    LCDTRIS &= 0x0F;
    LCDDATA = (LCDDATA & 0x0F) | (data & 0xF0);
    LCDEN = 1;
    __delay_us(1);
    LCDEN = 0;
    __delay_us(1);
    LCDDATA = (LCDDATA & 0x0F) | (data << 4);
    LCDEN = 1;
    __delay_us(1);
    LCDEN = 0;
#elif defined(LOWER)
    LCDTRIS &= 0xF0;
    LCDDATA = (LCDDATA & 0xF0) | (data >> 4);
    LCDEN = 1;
    __delay_us(1);
    LCDEN = 0;
    __delay_us(1);
    LCDDATA = (LCDDATA & 0xF0) | (data & 0x0F);
    LCDEN = 1;
    __delay_us(1);
    LCDEN = 0;
#endif
 
#endif
    LCDTRIS = lasttris;
}
 
void lcd_init(void)
{
    unsigned char veces;
 
    LCDEN = 0;
    LCDRS = 0;
    LCDRW = 0;
    LCDTRISRS = 0;
    LCDTRISRW = 0;
    LCDTRISEN = 0;
   
    __delay_ms(15);
   
    for (veces = 3; veces > 0; veces--)
    {
    lcd_putini(0x30);
    __delay_ms(5);
    }
#if defined(PROTOCOL8BIT)
    lcd_put(0x38,0);                          // Dos lineas, caracter 5x8
#elif defined(PROTOCOL4BIT)
    lcd_putini(0x20);                         // Protocolo de 4 bits
    lcd_put(0x28,0);                          // Dos lineas, caracter 5x8
#endif
    lcd_put(0x08,0);                          // Apagar display, cursor, blink
    lcd_put(0x01,0);                          // Borrar display
    lcd_put(0x06,0);                          // Incrementa posicion, sin shift
}
 

int lcd_busy(void)
{
    unsigned char lasttris;
    unsigned char busy;
 
    lasttris = LCDTRIS;
    LCDRS = 0;
    LCDRW = 1;
#if defined(PROTOCOL8BIT)
    LCDTRIS = 0xFF;
    LCDEN = 1;
    __delay_us(1);
    busy = LCDDATA;
    LCDEN = 0;
#elif defined(PROTOCOL4BIT)
#if defined(UPPER)
    LCDTRIS = (LCDTRIS & 0x0F) | 0xF0;
    LCDEN = 1;
    __delay_us(1);
    busy = LCDDATA;
    LCDEN = 0;
    __delay_us(1);
    LCDEN = 1;
    __delay_us(1);
    LCDEN = 0;
#elif defined(LOWER)
    LCDTRIS = (LCDTRIS & 0xF0) | 0x0F;
    LCDEN = 1;
    __delay_us(1);
    busy = LCDDATA << 4;
    LCDEN = 0;
    __delay_us(1);
    LCDEN = 1;
    __delay_us(1);
    LCDEN = 0;
#endif
#endif
    LCDTRIS = lasttris;
    if ((busy & 0x80) == 0x80) return 1;
    else
        return 0;
}
 
void lcd_gotoxy(unsigned char x, unsigned char y)
{
    x--;
    y--;
    if (y == 0) lcd_put((0x80 + x),0);
    else
        lcd_put((0xC0 + x),0);
}
 
void lcd_puts(const unsigned char *st)
{
    while (*st != 0)
    {
        lcd_put(*st,1);
        st++;
    }
}
 
void lcd_createchar(unsigned char asciicode, const unsigned char* ascii)
{
    unsigned char line;
    unsigned char caracter;
 
    for (line = 0; line < 7; line++)
    {
        caracter = (((asciicode & 0x07) << 3) | (0x40 + line));
        lcd_put(caracter,0);
        lcd_put(*ascii,1);
        ascii++;
    }
    caracter = ((asciicode & 0x07) << 3) | 0x47;
    lcd_put(caracter,0);
    lcd_put(0,1);
    lcd_clear();
}
 
void lcd_setdisplay(unsigned char state)
{
    lcd_put(state,0);
}
 
void lcd_shift(unsigned char state)
{
    lcd_put(state,0);
}
 
void lcd_entrymode(unsigned char state)
{
    lcd_put(state,0);
}
#endif

agradeceria muchisimo la ayuda
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 30 de Septiembre de 2015, 13:41:18
Primero que nada la libreria esta realizado para un dispositivo con registros de 8 bits. Entonces cuando modifica los TRIS son con valores de 0x0F o 0xF0 que si lo transportas a 16bits quedarian 0x000F y 0x00F0, pero como ese ultimo valor esta mal ya que deberia haber sido 0xFFF0. Vas a tener que adaptar la libreria al pic24, para eso vas a tener inevitablemente que aprender como es que se comunica con el LCD. Rara ves una libreria sacada de internet te va a funcionar.


En mi opinion personal: Usar un pic24 ya no estas para hacer eso de copiar y pegar, ya debes aprender a hacerte tus propias librerias, entender como funciona, leerte los datasheet, podes apoyarte sobre una libreria hecha lo que hace que sea mas facil hacerla por vos mismo, pero ahi vas a aprender como hacer las cosas y vas a encontrar los problemas. Esto no es un problema de sintaxis, esta todo bien, sino un problema de programacion o portabilidad. Si alguno te quiere dar una mano y te pasa un codigo, excelente. Pero lo que respecta a mi, y mi consejo hacia vos, es que aprendas a hacerte tus propias librerias.
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 30 de Septiembre de 2015, 17:54:22
bueno por lo menos ya se por que no me daba entonces dices tu que por datasheet ? puedo sacar la comunicacion con la lcd y conexion usb y creo mi propia libreria ? muchas gracias por responder estaba acostumbrado a ccs pero me cambia a xc16 cojn mplab x para la comunicacion usb y acceder mejor a los registros... En ccs se me hizo facil configurar la lcd por la libreria que trae pero pense q la libreria de lcd me serviria pero no tenia acceso a los registros del usb no encontre como y segun he visto xc16 es mejor programa... deberian hacer un foro mini curso " Programacion en XC16" seria bastante ayuda ....... una pregunta entonces para configurar los pines de entrada y salida en el pic24f
Código: [Seleccionar]
#define TRISB TRISB
extern volatile unsigned int  TRISB __attribute__((__sfr__));
typedef struct tagTRISBBITS {
  unsigned TRISB0:1;
  unsigned TRISB1:1;
  unsigned TRISB2:1;
  unsigned TRISB3:1;
  unsigned TRISB4:1;
  unsigned TRISB5:1;
  unsigned :1;
  unsigned TRISB7:1;
  unsigned TRISB8:1;
  unsigned TRISB9:1;
  unsigned TRISB10:1;
  unsigned TRISB11:1;
  unsigned :1;
  unsigned TRISB13:1;
  unsigned TRISB14:1;
  unsigned TRISB15:1;
} TRISBBITS;

lo hago si voy a configurar el pin RB0 como entrada
Código: [Seleccionar]
TRISB = 0x0001;
PORTB = 0;
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 30 de Septiembre de 2015, 18:20:53
Es que XC16 es lo mismo que XC8, es igual. es C. no hay diferencias. la unica diferencia que puede haber es como poner el nombre de una interrupcion o algo asi.
XC8/16/32 ofrece el .h con todos los registros (que creo que al poner el include xc.h ya te lo agrega), por eso mismo podes usar cosas como PORTBbits.PORTB1 y creo que lo que copiaste es justamente eso. Por que en ese .h estan definidos. Pero esto es igual para micros de 8 bits o 16 bits.



Para solucionarte un poco mas la vida y que encontres la solucion. Normalmente en las librerias de los LCD (o podria decir cualquier libreria) podes encontrar lo siguiente:

- 1 funcion de inicio, esto permite una configuracion inicial de los puertos etc. Poner los valores iniciales de los pines y luego iniciar el modulo.

Citar
void lcd_init(void)
{
    unsigned char veces;
  // Set inicial de valores de los pines y configuracion de los mismo
    LCDEN = 0;
    LCDRS = 0;
    LCDRW = 0;
    LCDTRISRS = 0;
    LCDTRISRW = 0;
    LCDTRISEN = 0;


    // Comienzo de inicio del modulo    
    __delay_ms(15);
    
    for (veces = 3; veces > 0; veces--)
    {
    lcd_putini(0x30);
    __delay_ms(5);
    }
#if defined(PROTOCOL8BIT)
    lcd_put(0x38,0);                          // Dos lineas, caracter 5x8
#elif defined(PROTOCOL4BIT)
    lcd_putini(0x20);                         // Protocolo de 4 bits
    lcd_put(0x28,0);                          // Dos lineas, caracter 5x8
#endif
    lcd_put(0x08,0);                          // Apagar display, cursor, blink
    lcd_put(0x01,0);                          // Borrar display
    lcd_put(0x06,0);                          // Incrementa posicion, sin shift
}

- Luego hay 1/2 o 3 funciones que son las encargadas de modificar los puertos, y las demas funciones usan esas, como ves en el caso de lcd_init que usa las funciones lcd_put y lcd_putini.

Las funciones que tocan el puerto son:

lcd_put()
lcd_putini()
lcd_busy()

- Las demas funciones son facilidades para usar el LCD, si vos envias un string esta la funcion lcd_puts() que va a enviar 1 por 1 los caracteres al string, haciendo uso de las funciones que nombre anteriormente.

Entonces si sabes que el codigo funciona, y no funciona por que cambiaste de PIC, lo unico que puede afectar eso es como se manejan los puertos o como se leen, o que no estan configurados realmente como se debe.
De esa forma las unicas funciones que deberias "estudiar" e intentar modificar para adaptarla a el PIC24 son esas 3 que nombre antes, y lcd_init() en la parte de la configuracion si es que necesita de algo mas (ejemplo de pasarlo a digital cuando estaban en analogicas, etc )


Eso ya va a disminuir la cantidad de cosas que tenes que revisar y realmente centrarte en lo que necesitas cambiar. Espero que me entiendas a que me refiero. De tener que hacerlo yo tendria que leerme como funciona los puertos del PIC24 que tenes, y proceder a hacer los cambios, que no son muchos (imagino). Espero que lo que dije disminuya la carga de estudiar todo el codigo y te sirva para saber a donde apuntar para modificarlo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 01 de Octubre de 2015, 08:53:52
muchas gracias KILLERJC gracias por responder me pondre a estudiar esa parte si el include xc.h me permite eso puerdo ver todos los registros de mi pic es un 24fj64gb002
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 02 de Octubre de 2015, 12:38:33
//// Que esta ocurriendo cuando en xc8 defino:

 #define _XTAL_FREQ 1000000
 #define delay_ms(x)   _delay((unsigned long)((x)*( _XTAL_FREQ/1000.0)))

//// y me da este error y no puedo usar los delay :

LCD.c:35: error: (1098) conflicting declarations for variable "__delay" (C:\Program Files (x86)\Microchip\xc8\v1.35\include\pic.h:150)
(908) exit status = 1

///// como si el _delay no existiera y le doy ctrl + enter y no hay nada sale error como si al compilador le fatara una libreria pero no tengo idea si me pudieran ayudar




Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 02 de Octubre de 2015, 13:31:04
el _delay, se incluye cuando agregas el xc.h (que seguro lo tenes en el main, pero esto no se extiende a la libreria.), creo que es tu libreria el archivo LCD.h, si en tu libreria no esta definida la funcion entonces va a tirar error.
Eso o hay 2 definiciones de lo mismo.
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 02 de Octubre de 2015, 15:34:18
si era eso muchisimas gracias KILLERJC ya me da la simulacion,........ otra preguntica si quiero simular en proteus el pic 24fj64gb002 como hago para descargar las librerias del pic lo estaba buscando y no sale
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 02 de Octubre de 2015, 15:47:53
estoy utilizando: ISIS Profesional = labcenter electronics 1989-2010. Release 7.9 SP1 (Build 11535) with Advanced Simulation
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 02 de Octubre de 2015, 15:48:39
No se como actualizar las VSM de Proteus sin necesidad de instalar la ultima version de las mismas. Podrias buscar en internet si hay forma de actualizarlas ( suponiendo que no pida exactamente la nueva version )
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 02 de Octubre de 2015, 16:34:20
una pregunta para que sirve este comando :

ANSEL = 0x00;

xq si le quito eso no me da la simulacion en la lcd y si lo pongo si da ue tiene q ver ese comando
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 02 de Octubre de 2015, 16:49:52
En algunos PIC el registro ANSEL sirve para seleccionar si la entrada es digital o analogica.

Y puede incluso funcionar distinto entre PICs, hay PIC que con solo configurar el TRIS como salida ya no hace falta mas nada.
En otros es necesario si o si modificar el ANSEL para que quede como digital.
En tu PIC es distinto:

Citar
10.2     Configuring Analog Port Pins

The AD1PCFG and TRIS registers control the operation of the A/D port pins. Setting a port pin as an analog input also requires that the corresponding TRIS bit be set. If the TRIS bit is cleared (output), the digital output level (VOH or VOL) will be converted.
When reading the PORT register, all pins configured as analog input channels will read as cleared (a low level). Pins configured as digital inputs will not convert an analog input. Analog levels on any pin that is defined as a digital input (including the ANx pins) may cause the
input buffer to consume current that exceeds the device specifications

El regisotr AD1PCFG esta en el pagina 261

1 =  Pin for corresponding analog channel is configured in Digital mode; I/O port read enabled
0 =  Pin configured in Analog mode; I/O port read disabled, A/D samples pin voltage

Y comienza con valores en 0. es decir si esta como entrada ( TRIS en 1 ), va a estar en modo analogico y si lees el PORT vas a leer un 0 siempre, para pasarlo a digital tenes que poner un 1 en el bit que corresponda de ese registro

o ponerlos todos digital con

AD1PCFG |= 0xFFF;
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 02 de Octubre de 2015, 17:19:44
muchismasssss gracias  :-/ KILLERJC ya vi el registro no lo habia visto lo probare por esa razon seguro no leia los puertos como digitales lo probare
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 05 de Octubre de 2015, 11:08:32
buenisimo KILLERJC ese era el error ya me funciona la lcd pero encontre otro problema que como yo configuro que funcione a 48MHZ para el usb no funcionaba la lcd asi que fui acomodando los delay hasta q me mostrara el mensaje en pantalla si hice eso se desconfiguro los 48 MHZ ?

mis configuraciones del clock
Código: [Seleccionar]
#pragma config POSCMOD = HS               // Primary Oscillator Select (HS Oscillator mode selected)
#pragma config FCKSM = CSDCMD     
#pragma config FNOSC = PRIPLL           // Initial Oscillator Select (Primary Oscillator with PLL module (XTPLL, HSPLL, ECPLL))
#pragma config PLL96MHZ = ON            // 96MHz PLL Startup Select (96 MHz PLL Startup is enabled automatically on start-up)
#pragma config PLLDIV = DIV5            // USB 96 MHz PLL Prescaler Select (Oscillator input divided by 5 (20 MHz input))
#pragma config IESO = OFF               // Internal External Switchover (IESO mode (Two-Speed Start-up) disabled)
modificacion del delay para que mostrara la lcd el mensaje
Código: [Seleccionar]
#define _XTAL_FREQ 20000000
#define __delay_ms(x) __delay32((unsigned long)((x)*(_XTAL_FREQ/800.0)))
#define __delay_us(x) __delay32((unsigned long)((x)*(_XTAL_FREQ/800000.0)))
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 05 de Octubre de 2015, 12:39:37
ahora estoy tratando de configurar la cominicacion spi compre un modulo enc28j60 spi - ethernet y quiero configurar mi pic24fj64gb002 para enviarle un dato a un PLC allen bradley si alguien lo ha hecho antes me podria guiar por donde ? descargue las librerias de MLA de microchip y salen unas de tcp/ip pero no se usarlas
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 05 de Octubre de 2015, 18:07:28
Primero que nada, felicidades por haber logrado portar la libreria, parece algo simple, tal ves no lo es, pero esto te va a ayudar en cualquier otra libreria


Tu codigo original
Código: C
  1. #define _XTAL_FREQ 20000000
  2. #define __delay_ms(x) __delay32((unsigned long)((x)*(_XTAL_FREQ/10000.0)))  
  3. #define __delay_us(x) __delay32((unsigned long)((x)*(_XTAL_FREQ/10000000.0)))


Bueno no voy a meterme demasiado con el tema del oscilador.
En el PLL debe entrar 4Mhz, asi que supongo que tenes un cristal de 20Mhz. Esto general 96Mhz los cuales tenes 48Mhz para el USB y como maximo 32Mhz en tu CPU
Esos 32 es por hay hay un postscaler fijo de 1:3 ( divido 3 )

http://ww1.microchip.com/downloads/en/DeviceDoc/39700c.pdf

Entonces por un lado el USB tiene 48Mhz, por el otro tu CPU tiene 32Mhz (suponiendo que no lo dividas aun mas, y que es el maximo), esto quiere decir que la frecuencia que entra a la CPU es:

Código: C
  1. #define _XTAL_FREQ 32000000

Y solo eso deberias cambiar (entonces cuando cambias de frecuencia en tu programa solo tocas eso). Microchip provee las funcion __delay_ms() y __delay_us().
Lo primero que haria es comentar esos 2 macros y probarlo. Si aun asi no funciona. Vamos a crear los macros para estos PICs

Una instruccion en un PIC16/18 tarda 4/Fosc , en ejecutarse, mientras que en un PIC24/dsPIC lo hace en 2/Fosc.
Entonces para 32Mhz, 1us en ciclos seria:

1us / ( 2/Fosc) = 16 ciclos
3us  = 16 ciclos * 3 =48 ciclos

Podriamos modificar un poco mas nuestra formula, ya que 1us y 2 son constantes, y nuestra unica "variable" seria Fosc

1us / (2/Fosc) = 1*10^-6 / ( 2/Fosc ) = Fosc / 2*1*10^6 = Fosc / 2000000
Eso por cada microsegundos

Código: C
  1. #define __delay_us(x) __delay32((unsigned long)((x)*(_XTAL_FREQ/2000000.0)))

Si usamos la formula y quiero 3 microsegundos quedaria:   3  *( 32000000 / 2000000.0)   =   3 *  ( 16 ) = 48, que es exactamente lo que necesitabamos y decirle con __delay32() que espere 48 ciclos.
De la misma forma podemos hacer la otra para los milisegundos, en ese caso lo unico que cambia es nuestra formula que tenemos 1ms ( 1*10^-3 ) en ves de 1us, la relacion entre 1ms/1us = 1000
Por lo tanto lo unico que cambia es que no vamos a tener 2.000.000 sino 2.000 en el denominador

Código: C
  1. #define __delay_us(x) __delay32((unsigned long)((x)*(_XTAL_FREQ/2000.0)))

Felicidades si es que Microchip no te dio las funciones, ( que creo que te las da por que __delay32 es una de ellas) entonces podes crear tus propias.
Solo recordar que _delay32 no acepta menos de 12 ciclos.

--------------------------------

Si por alguna razon decidis dividir la frecuencia que entra a la CPU o por ejemplo utilizas un cristal de 20Mhz directo por que no te importa el USB, lo unico que debes cambiar es
Código: C
  1. #define _XTAL_FREQ 20000000

Por la frecuencia que entra en la CPU.
Título: Re: Mini curso "Programación en XC8"
Publicado por: marcoj2560456* en 05 de Octubre de 2015, 18:53:04
que excelente gracias por la explicación KILLERJC gracias por toda la ayuda de verdad ...  :-/
Título: Re: Mini curso "Programación en XC8"
Publicado por: KILLERJC en 05 de Octubre de 2015, 19:05:33
Una cosa que quedo escondida y que no me di cuenta de ponerlo antes es la siguiente:

Como dije __delay32() el minimo es de 12 ciclos.

Segun la formula calculada

ciclos = Fosc / 2000000

tenemos una frecuencia limite en la cual va a ser valido tener 1us, y que es:

12 * 2000000 = 24Mhz

Es decir por debajo de 24Mhz es imposible crear un delay de 1us con esa funcion, y tal ves tarde 1.4, 2us en ves de 1. Aunque la formula sigue siendo valida. Esto por si termian tardando un poco mas de lo que debe el delay
El minimo tiempo que puede lograrse con __delay32() es 12 * 2 / Fosc

0.75us para 32 Mhz
1.2us para 20Mhz
2.4us para 10Mhz
3us para 8Mhz
6us para 4Mhz

Es algo que debes tener en cuenta:

Si entra 20Mhz , __delay_us(1); va a tardar 1.2us
Si entra 10Mhz , __delay_us(1); va a tardar 2.4us, __delay_us(2); va a tardar 2.4us, __delay_us(3); va a tardar 3us
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 05 de Diciembre de 2015, 20:31:57
Alguien puede decirme el porque de este error
(http://www.todopic.com.ar/foros/imgtiny/nlzhvr.png)
He probado de añadir la librería timers.h al proyecto pero me sigue dando error.

Gracias.
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 05 de Diciembre de 2015, 20:41:31
Tiene pinta de ser un fallo de haber borrado un fichero, y el makefile te lo esta pidiendo.

Por otro lado:

Citar
/opt/microchip/xc8/v1.34/include/plib/timers.h:31: error: (141) can't open include file "pconfig.h": No such file or directory

En las versiones de XC32 como la v1.34 ya no sirven las plib, hace mucho que no uso xc8 ¿pasa lo mismo en xc8?

Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 05 de Diciembre de 2015, 21:35:47
Tiene pinta de ser un fallo de haber borrado un fichero, y el makefile te lo esta pidiendo.

Por otro lado:

Citar
/opt/microchip/xc8/v1.34/include/plib/timers.h:31: error: (141) can't open include file "pconfig.h": No such file or directory

En las versiones de XC32 como la v1.34 ya no sirven las plib, hace mucho que no uso xc8 ¿pasa lo mismo en xc8?


Hola juaperser1 el fichero no ha sido borrado se encuentra en la carpeta include/plib, lo que no se el porque no lo abre, he probado de incluirlo en el código pero sigue sin abrirlo.
Si pasa lo mismo en xc8 la verdad no lo se.
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 05 de Diciembre de 2015, 21:51:20
Parece mas un error de direcciones de include. (Aunque estoy mas que seguro que es eso )

Me explico... La direccion de include esta en:

/opt/microchip/xc8/v1.34/include/

Entonces vos cuando haces un include lo haces a partir de esa direccion. Pero dentro del fichero timers.h existe un #include <pconfig.h>
es decir no tiene el plib/, esto hace que lo busque como:

/opt/microchip/xc8/v1.34/include/pconfig.h

La idea es si podes agregar como direccion de include (propiedades del pryecto -> XC8 Compiler -> Include directories):

/opt/microchip/xc8/v1.34/include/plib/

Esperemos que no pida archivos de otros lados tambien  :(
Si agregas esa direccion de ruta, en tu proyecto principal podes hacer

#include <timers.h>

Aunque realmente a veces esas rutas de include funcionan con "timers.h" , con comillas y  no <> , pero bueno. Es tan dependiente del compilador que no se que decirte.
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 05 de Diciembre de 2015, 21:57:38
Puede ser lo que dice killer, pruebalo incluyendo la ruta de búsqueda en las opciones de tu proyecto.

Un saludo.

Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 06 de Diciembre de 2015, 06:56:38
Siento dar por c..o otra vez, después de probar lo que dice KILLERJC que se me soluciono el problema del include/plib, me sale otro error y por mucho que busque no encuentro donde esta, y al darle clic encima no me enseña donde esta el error.
(http://www.todopic.com.ar/foros/imgtiny/t5r3aw.png)
Este es el codigo:
Código: C
  1. #define _XTAL_FREQ 4000000  //The speed of your internal(or)external oscillator
  2.  
  3. #define USE_AND_MASKS
  4. #include <xc.h>
  5. #include "config.h"
  6. #include <plib/timers.h>
  7.  
  8. unsigned char Timer0Config;
  9.  
  10. void main(void)
  11. {
  12.     TRISBbits.RB0 = 0;  //Seteamos RB0 como salida
  13.     LATB0 = 1;  //RB0 a nivel alto
  14.    
  15.     Timer0Config = TIMER_INT_ON & T0_8BIT & T0_SOURCE_INT & T0_PS_1_1;
  16.     OpenTimer0(Timer0Config);
  17.     WriteTimer0(0xFF);
  18.    
  19.     INTCONbits.TMR0IF = 0;  //Reseteamos el flag de la interrupcion
  20.    
  21.     ei();
  22.    
  23.     while(1)    //Bucle infinito
  24.     {
  25.        
  26.     }
  27. }
  28.  
  29. void interrupt TimerOverflow()
  30. {
  31.     if(INTCONbits.TMR0IF == 1)
  32.     {
  33.         LATB0 = ~LATB0;
  34.         INTCONbits.TMR0IF = 0;
  35.         WriteTimer0(0xFF);
  36.     }
  37. }

Gracias.
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 06 de Diciembre de 2015, 07:52:05
Lo interesante es que yo quite el config.h y probe tu codigo sin cambiar la ruta de include y....

BUILD SUCCESSFUL (total time: 1s)

Luego use este:

Código: C
  1. #define USE_AND_MASKS
  2. #include <xc.h>
  3. #include <plib.h>

Es decir solo le pido que incluya el plib.h y ya eso agrega el timers.h por si solo. Igual como dije probe tu codigo ( copy & paste de aca ) y solo le quite la linea del #include "config.h" (por que tengo un archivo llamado config.c dentro de la carpeta source con esas declaraciones) y compilo sin errores.

Una parte:
Código: [Seleccionar]
Microchip MPLAB XC8 C Compiler (--- Mode) V1.33
Part Support Version: 1.33 (A)
Copyright (C) 2014 Microchip Technology Inc.
License type: Node Configuration

:: advisory: (1233) Employing 18F2550 errata work-arounds:
:: advisory: (1234)  * Corrupted fast interrupt shadow registers

Memory Summary:
    Program space        used    84h (   132) of  8000h bytes   (  0.4%)
    Data space           used     9h (     9) of   800h bytes   (  0.4%)
    Configuration bits   used     7h (     7) of     7h words   (100.0%)
    EEPROM space         used     0h (     0) of   100h bytes   (  0.0%)
    ID Location space    used     8h (     8) of     8h bytes   (100.0%)
    Data stack space     used     0h (     0) of   7A0h bytes   (  0.0%)

make[2]: Leaving directory 'F:/CCS/MPLABx/Prueba/Prueba.X'
make[1]: Leaving directory 'F:/CCS/MPLABx/Prueba/Prueba.X'

BUILD SUCCESSFUL (total time: 1s)
Loading symbols from F:/CCS/MPLABx/Prueba/Prueba.X/dist/default/production/Prueba.X.production.elf...
Loading code from F:/CCS/MPLABx/Prueba/Prueba.X/dist/default/production/Prueba.X.production.hex...
Loading completed

Incluso hice click derecho sobre la funcion WriteTimer0() y le di a Ir a declaracion y me abrio correctamente el timers.h en ambos casos, con plib.h y con el codigo tuyo


-- Si esto sigue asi intenta crear un proyecto de 0, se abra tocado algo sin querer imagino.
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 06 de Diciembre de 2015, 08:10:15
Gracias KILLERJC también había probado con el include de plib.h y me daba el mismo error, voy a probar de crear un proyecto nuevo.

Gracias.
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 06 de Diciembre de 2015, 08:29:15
Sigo con el mismo error, de todos modos veo que estas usando una versión diferente, no se si probar a actualizar a la versión 1.35.

Saludos!
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 06 de Diciembre de 2015, 09:52:01
Sigo con el mismo error, de todos modos veo que estas usando una versión diferente, no se si probar a actualizar a la versión 1.35.

Saludos!

Estas incluyendo las rutas de búsqueda en las opciones de proyecto? Incluye solo el xc.h y las plib no incluyas ninguna mas o puede que te de error de que lo tienes duplicado.De toda maneras, bajate el compilador 1.31 el 1.34 a mi me dio problemas.

Un saludo.
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 06 de Diciembre de 2015, 09:58:22
No voy a estar cerca del ordenador en todo el dia, quizá esta noche, si quieres puedes mandarme el proyecto por privado y le echo un vistazo a la configuración a ver porque no compila.

Puede ser que hayan cambiado las rutas al cambiar de ubicación el proyecto, o cualquier tontería, porque parece eso, la típica tontería que te da dolor de cabeza y luego no es nada.


Un saludo.
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 06 de Diciembre de 2015, 11:11:34
Gracias juaperser1,  primero voy a probar con otra versión anterior del compilador ya que la v1.35 por no llevar no lleva ni las librerías. Si no consigo que funcione tendré que seguir con ASM aunque me hubiera gustado aprender ASM y C conjuntamente.

Saludos!
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 06 de Diciembre de 2015, 18:06:33
Al final he podido compilar con la versión v1.33

Gracias a los dos por la ayuda.
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 07 de Diciembre de 2015, 09:27:00
Citar
Al final he podido compilar con la versión v1.33

Pfff cada vez van peor de verdad, no me gusta que este tipo de cosas te hagan perder tiempo de desarrollo, te da dolor de cabeza intentando ver donde te has equivocado y resulta que la culpa no es tuya...

Me alegro que lo hayas arreglado.

Un saludo
Título: Re: Mini curso "Programación en XC8"
Publicado por: fernandogomav en 09 de Diciembre de 2015, 18:45:40
Interrupciones de alta y baja prioridad.

 En este programa vamos a utilizar las interrupciones externas del pic18F4550 en los pines RB0, RB1 y RB2
   configurando lso flancos de subida para INT0, INT1, e INT2.

  En el 4550 la INT0 es siempre de alta prioridad. No se puede setear como de baja prioridad
   Las INT1 e INT2 las configuramos en baja prioridad.

   Cada vez que se produzca una interrupción en INT0 cambiará el estado del pin RA0
   Cada vez que se produzca una interrupción en INT1 cambiará el estado del pin RA1
   Cada vez que se produzca una interrupción en INT2 cambiará el estado del pin RA2

        Saludos.
              Jukinch

Código: C
  1. File:   main.c
  2.    Author: JUKINCH
  3.  
  4.    Created on 31 de mayo de 2013, 14:49
  5.  
  6.    PRUEBA DE INTERRUPCIONES en baja y alta prioridad
  7.    EN INT0 (RB0) INT1 (RB1) E INT2 (RB2)
  8.  
  9.  
  10.    pic: 18f4550
  11.    crystal: NO
  12.    CPU: 8Mhz (valor establecido dentro de main cambiando los bits IRCF2, IRCF1 e IRCF0 del registro OSCCON)
  13.         en RA6 sale la frecuencia de Fosc/4   ------->   8Mhz/4 = 2Mhz
  14.  
  15.    FUSES: los bits de configuración se establecen en el archivo "configuracion_de_fuses.c"
  16.  
  17.    CONEXIONES entrenadora FELIXLS:
  18.     1 módulo conectado en IDC(RB0) en modo botón
  19.     1 módulo conectado en IDC(RA0) en modo leds
  20.     los cambios se pueden hacer en el archivo configuracion_hard.c
  21.  
  22.  */
  23.  
  24.  
  25.  
  26. /*Includes globales*/
  27. #include <xc.h>
  28. #include <delays.h> /* Para utilizar demoras en nuestro código*/
  29.  
  30. /*Includes locales*/
  31. #include "configuracion_de_fuses.c"
  32. #include "configuracion_hard.c"
  33.  
  34.  
  35.  
  36.  
  37.  
  38. volatile int myVolatileVariable=0;//variable para utilizar con las interrupciones
  39.  
  40.  
  41. //******************************************************//
  42. // Rutina de Interrupcion de Alta Prioridad
  43. //******************************************************//
  44. //
  45.  
  46. void interrupt interrupcionDeAlta(void)//prototipo de la interrupción de alta prioridad
  47.         {
  48.             if(INTCONbits.INT0IF)          //pregunta por bandera de interrupción en rb0
  49.                     {
  50.                     LED0 = ~LED0;          // invierto estado del led
  51.                     myVolatileVariable++;
  52.                     INTCONbits.INT0IF = 0; //limpia bandera y salimos
  53.                     }
  54.         }
  55.  
  56.  
  57. //
  58. //******************************************************//
  59. // Rutina de Interrupcion de baja prioridad
  60. //******************************************************//
  61. //
  62. void interrupt low_priority   interrupcionDeBaja(void)//prototipo de la interrupción de baja prioridad
  63.         {
  64.             if(INTCON3bits.INT1IF)       //pregunta por bandera de interrupción
  65.                 {
  66.                 LED1 = ~LED1;            // invierto estado del led
  67.                 myVolatileVariable++;
  68.                 INTCON3bits.INT1IF = 0;  //limpia bandera y salimos
  69.                 }
  70.  
  71.  
  72.             if(INTCON3bits.INT2IF)       //pregunta por bandera de interrupción
  73.                 {
  74.                 LED2 = ~LED2;            // invierto estado del led
  75.                 myVolatileVariable++;
  76.                 INTCON3bits.INT2IF = 0;  //limpia bandera y salimos
  77.                 }
  78.         }
  79.  
  80.  
  81.  
  82.  
  83.  
  84. //******************************************************//
  85. // Programa Principal
  86. //******************************************************//
  87. void main(void)
  88. {
  89. ADCON0 = 0X00,ADCON1 = 0X0F,CMCON = 0X07; //puerto A con todos los pines digitales
  90.  
  91. PINLED0=0; // Configuración de pines como salida para los leds
  92. PINLED1=0;
  93. PINLED2=0;
  94. PINBOTON0=1; // Configuración de pines como entrada para los botones
  95. PINBOTON1=1;
  96. PINBOTON2=1;
  97.  
  98. LATA = 0X00; // todo el puerto A a cero.
  99.  
  100.  
  101. RCONbits.IPEN = 1; // Activa modo alta y baja prioridad
  102. INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
  103. INTCONbits.GIEH = 1;// permitimos interrupciones de alta prioridad (Global Interrupt Enable High)
  104. INTCON2bits.INTEDG0 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB0
  105. INTCON2bits.INTEDG1 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB1
  106. INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
  107.  
  108. INTCONbits.INT0IE=1; // activa la interrupción externa por flanco del pin RB0
  109.                      // La Int0 es siempre de alta prioridad. No se puede setear como de baja prioridad
  110.  
  111. INTCON3bits.INT1IE=1; // activa la interrupción externa por flanco del pin RB1
  112. INTCON3bits.INT1IP=0; // selecciona la interrupción de baja prioridad del pin RB1
  113.  
  114. INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
  115. INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2
  116.  
  117. //*******************************************************
  118. //*******************************************************
  119.  
  120.  
  121. while (1);
  122.  
  123.  
  124.  
  125. }
  126. //*******************************************************
  127. //*******************************************************

HOLA JUKINCH, tengo un problema con las interrupciones, estoy utilizando un 4550 en XC8 y proteus, y me guie de este ejemplo para hacer la interrupcion, les cuento lo que hago y que me pasa:

tengo un led en RA4 que se prende si tengo un estado dentro del programa activo, luego que esta encendido el led quiero poder apagarlo con un pulsador.

el pulsador lo monte en RB2, interrupcion de baja prioridad, y la interrupcion por flanco de subida o colocando el alto en el pin.

en el VOID MAIN defino esto:

    RCONbits.IPEN = 1; // Activa modo alta y baja prioridad
    INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
    INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
    INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
    INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2


tambien tengo definida esas patas como entradas y salidas:

    TRISB=0x1F; // RB2 entrada pulsado para silenciar alarma
    TRISA=0x6F; // RA4 SALIDA DE ALARMA

luego defino la funcion de interrupcion y variable volatil:

volatile int myVolatileVariable=0;//variable para utilizar con las interrupciones


    void interrupt isr (void)//prototipo de la interrupción de baja prioridad
    {
        if(INTCON3bits.INT2IF==1)       //pregunta por bandera de interrupción
          {
           LATAbits.LATA4= ~LATAbits.LATA4;            // invierto estado del led
           myVolatileVariable++;
           INTCON3bits.INT2IF = 0;  //limpia bandera y salimos
          }
    }


EStoy haciendo esto y no quiere apagar el led en RA4, el programa copila bien y no arroja ningun error pero nose que pasa, si pueden ayudarme estaria muy agradecido.
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 09 de Diciembre de 2015, 19:05:23
Tal ves te falta configurar las entradas RB4:0 Como digitales, en especial si tus fuses estan puestos para que puedan ser digital o analogicos esos

ADCON1 = 0X0F

Tambien intenta primero activar las interrupciones del modulo y como punto final activar las interrupciones globales, no activar la interrrupcion global y lluego configurar el modulo
Título: Re:Mini curso "Programación en XC8"
Publicado por: fernandogomav en 09 de Diciembre de 2015, 19:15:46
Tal ves te falta configurar las entradas RB4:0 Como digitales, en especial si tus fuses estan puestos para que puedan ser digital o analogicos esos

ADCON1 = 0X0F

Tambien intenta primero activar las interrupciones del modulo y como punto final activar las interrupciones globales, no activar la interrrupcion global y lluego configurar el modulo

tengo una pregunta con lo primero queme dices killer:

en el puerto A tengo todas entradas menos RA4 que es la salida del led

y la tengo digital como puse TRISA=0x6F; // RA4 SALIDA DE ALARMA
lo que me dices lo deberia poner asi:

ADCON1 = 0XEF ???

y lo otro que me dices seria solo dejar las las interrupciones del modulo osea estas:
INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
    INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
    INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 09 de Diciembre de 2015, 20:15:06
El PORTA ( en su mayoria) + PORTB 4 a 0, son analogicos por defecto.

Es decir ante un reset, esos puertos se configuran como entradas todos (RA4 es una excepcion y queda como salida) y como analogicos. Si los tratas como digitales y queres leer, siempre vas a leer un 0, por lo tanto no funcionaria como "entrada". Para pasarlos a digital deberias modificar el valor de ADCON1, podes buscarlo en el datasheet y veras que con un 0x0F pondrias todos los posibles ANx como digitales, es decir: Configurados como entradas Y digitales. Tenes una tabla en el datasheet sobre eso

Tambien en ese PIC, hay un fuse que pone RB4 a 0 como digitales ignorando el valor del ADCON1. El fuse es : PBADEN de CONFIG3H

Distinto es cuando lo configuras como salida, al configurarlo como salida ignora los bits de ADCON1 y presenta a la salida el valor de LATx ( esto ocurre en estos PICs, los PIC16 por ahi es necesario ponerlos digital por igual, aunque no puedo hablar por todos los PIC16 )

Citar
y lo otro que me dices seria solo dejar las las interrupciones del modulo osea estas:

Sobre las interrupciones comente por que habias puesto esto:

Código: [Seleccionar]
    RCONbits.IPEN = 1; // Activa modo alta y baja prioridad
    INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
    INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
    INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
    INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2

Cuando deberia ser algo asi:

Código: [Seleccionar]
    RCONbits.IPEN = 1; // Activa modo alta y baja prioridad

    INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
    INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
    INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2

    INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)

Es decir habilitar las interrupciones LUEGO de configurar las interrupciones que necesites
Título: Re:Mini curso "Programación en XC8"
Publicado por: fernandogomav en 09 de Diciembre de 2015, 21:51:54
gracias de nuevo KILLERJC, algo que no te comente esque estoy utilizando todo el puerto A como entradas, (AN0, AN1, AN2, AN3, AN4 y las dos entradas del cristal OSC1 y OSC2) y la RA4 es la única salida, y bueno si esta configurada como una salida porque si me prende el LED cuando me tiene que prender, el problema es que pareciera que no hace efecto la interrupción, ya modifique la configuración que me dijiste por prioridades, pero nada que puedo apagarlo, nose si de todos modos tengo que agregar el registro ADCON1 que me estas diciendo....
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 09 de Diciembre de 2015, 23:06:21
A ver si me explico mejor. Si lo tenes como analogico no va a pasar de 0 a 1 o de 1 a 0 el pin, siempre va a leer 0. Por eso no entra a la interrupcion.
Ponelo como digital y va a poder realizarse eso. asi que si no usas el ADC directamente ponelo a todos como digitales con el registro ADCON1.
Título: Re:Mini curso "Programación en XC8"
Publicado por: fernandogomav en 12 de Diciembre de 2015, 19:16:00
A ver si me explico mejor. Si lo tenes como analogico no va a pasar de 0 a 1 o de 1 a 0 el pin, siempre va a leer 0. Por eso no entra a la interrupcion.
Ponelo como digital y va a poder realizarse eso. asi que si no usas el ADC directamente ponelo a todos como digitales con el registro ADCON1.

HOLA KILLERJC, de nuevo gracias.

Ya funciona la interrupcion, tenia que poner el fuse PBADEN en OFF como me recomendaste, tambien me faltaba poner en 1 el registro GILH de las interrupciones, me tuve que fijar en el diagrama de compuertas en el datasheet.

la interrupcion ya funciona =), pero tengo un nuevo problema....

EL PROGRAMA SE CUELGA cuando presiono el pulsador que activa la interrupción, (la pantalla lcd no muestra nada) y me muestra este warnning en proteus:

(PIC18 STACK)PC=0X30AE. Stack overflow is forcing device reset.

me parece que esto es porque cuando activo la interrupcion el programa se queda en la función de la interrupcion y no entra de nuevo al main, intente ponerle un return a la funcion de interrupcion para que se saliera pero nada, si pueden ayudarme estare muy agradecido....
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 12 de Diciembre de 2015, 19:25:08
Podrias pasar de nuevo el codigo?.

Mas que eso es como si se llamara continuamente a una funcion y nunca se volviera, interrupcion dentro de otra interrupcion, muchas veces seguidas, lo cual es absurdo ya que al entrar se deshabilitan las mismas.
Y es C, con lo cual el tema de CALL - RETURN se manejan solos. Te piedo el codigo para probarlo yo en mi PC y ver cual es el problema.
Título: Re:Mini curso "Programación en XC8"
Publicado por: fernandogomav en 12 de Diciembre de 2015, 19:46:06
Podrias pasar de nuevo el codigo?.

Mas que eso es como si se llamara continuamente a una funcion y nunca se volviera, interrupcion dentro de otra interrupcion, muchas veces seguidas, lo cual es absurdo ya que al entrar se deshabilitan las mismas.
Y es C, con lo cual el tema de CALL - RETURN se manejan solos. Te piedo el codigo para probarlo yo en mi PC y ver cual es el problema.

mira lo que encontre en el datasheet en la parte final de interrupciones KILLERJC

Context Saving During Interrupts:

During interrupts, the return PC address is saved on
the stack. Additionally, the WREG, STATUS and BSR
registers are saved on the Fast Return Stack. If a fast
return from interrupt is not used (see Section 5.3
“Data Memory Organization”), the user may need to
save the WREG, STATUS and BSR registers on entry
to the Interrupt Service Routine. Depending on the
user’s application, other registers may also need to be
saved. Example 9-1 saves and restores the WREG,
STATUS and BSR registers during an Interrupt Service
Routine.

pero ni idea de como habilitar el fast return stack... sigo leyendo un poco y dice que es con el registro MOVLB y MOVFF, sabes algo de esto? ya te paso el codigo igual...
Título: Re:Mini curso "Programación en XC8"
Publicado por: fernandogomav en 12 de Diciembre de 2015, 19:47:05
Podrias pasar de nuevo el codigo?.

Mas que eso es como si se llamara continuamente a una funcion y nunca se volviera, interrupcion dentro de otra interrupcion, muchas veces seguidas, lo cual es absurdo ya que al entrar se deshabilitan las mismas.
Y es C, con lo cual el tema de CALL - RETURN se manejan solos. Te piedo el codigo para probarlo yo en mi PC y ver cual es el problema.


// PIC18F4550 Configuration Bit Settings

// 'C' source line config statements

#include <xc.h>
#include "LCD_4bits.h"
#include <stdio.h>
#include "adc_4550.h"


// #pragma config statements should precede project file includes.
// Use project enums instead of#define for ON and OFF.

// CONFIG1L
#pragma config PLLDIV = 1       // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
#pragma config USBDIV = 1       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)

// CONFIG1H
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator (HS))
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = ON         // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
#pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)

// CONFIG2H
#pragma config WDT = ON         // Watchdog Timer Enable bit (WDT enabled)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = ON      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF      // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config ICPRT = OFF      // Dedicated In-Circuit Debug/Programming Port (ICPORT) Enable bit (ICPORT disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM is not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)

void main (void)
{
   

    float presion1, presion2, presion3, presion4, presion5;
    float presion1_anterior = 0, presion2_anterior = 0, presion3_anterior = 0, presion4_anterior = 0, presion5_anterior = 0; // para que solo escriba en pantalla si cambia la presion
    char T[17]; // cadena de 16 caracteres incluyendo el final \0

    //TRISCbits.RC0=0;
    //TRISC=0X00;
    TRISB=0x1F; // RB2 entrada pulsado para silenciar alarma
    TRISA=0x6F; // RA4 SALIDA DE ALARMA
    //TRISE=0x0F; //entrada analogica #6 en RE1

    LCD_init();
   
    ADC_init(0x09  | ADC_10bit | ADC_FOSC32 | ADC_02TAD ); // 6 entradas analogicas

//ADC_init(ADC_AN01  | ADC_10bit | ADC_FOSC32 | ADC_02TAD );
   
//ADC_init(ADC_AN02 | ADC_10bit | ADC_FOSC32 | ADC_02TAD );

//ADC_init(ADC_AN03 | ADC_10bit | ADC_FOSC32 | ADC_02TAD );

//ADC_init(ADC_AN04 | ADC_10bit | ADC_FOSC32 | ADC_02TAD );

// ADC_init(ADC_AN05 | ADC_10bit | ADC_FOSC32 | ADC_02TAD );

    /*CONFIGURACION INTERRUPCION EN RB2*/

    RCONbits.IPEN = 1; // Activa modo alta y baja prioridad
    INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
    INTCONbits.GIEH=1;  //alto en ultima compuerta
    INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2

    INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
    INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2
   
   

    /*CONFIGURACION INTERRUPCION EN RB2*/
   
    LCD_clear();

    while (1)
    {
     //presion = (float)ADC_get(0);  calculo de numero binario para voltaje analogico (se utilizo para hallar el numero binario para cada voltaje analogico

     

     presion1=(((float)ADC_get(0)/203.7221)-0.5)/0.01333333333;
     if (presion1<30)
     {
         if(presion1 != presion1_anterior)
         {
          sprintf(T, "%03.1f %c ", presion1, 0x3C);
          LCD_gotoxy(0,0);
          LCD_puts(T);
          presion1 = presion1_anterior;
          LATBbits.LATB5=1;
          LATAbits.LATA4=1;
         
         }
     }
     else if (presion1 >= 30 && presion1 <=40)
     {
         if(presion1 != presion1_anterior)
         {
          sprintf(T, "%03.1f %c", presion1, 0x2D);
          LCD_gotoxy(0,0);
          LCD_puts(T);
          presion1 = presion1_anterior;
          LATBbits.LATB6=1;
          LATBbits.LATB5=0;
          LATBbits.LATB7=0;
         }
     }
      else
      {
         if(presion1 != presion1_anterior)
         {
          sprintf(T, "%03.1f %c", presion1, 0x3E);
          LCD_gotoxy(0,0);
          LCD_puts(T);
          presion1 = presion1_anterior;
          LATBbits.LATB7=1;
         
         }
      }


     presion2=(((float)ADC_get(1)/203.7221)-0.5)/0.01333333333;
     if (presion2<30)
     {
         if(presion2 != presion2_anterior)
         {
          sprintf(T, "%03.1f %c ", presion2, 0x3C);
          LCD_gotoxy(0,1);
          LCD_puts(T);
          presion2 = presion2_anterior;
          LATBbits.LATB5=1;
         
         }
     }
     else if (presion2 >= 30 && presion2 <=40)
     {
         if(presion2 != presion2_anterior)
         {
          sprintf(T, "%03.1f %c", presion2, 0x2D);
          LCD_gotoxy(0,1);
          LCD_puts(T);
          presion2 = presion2_anterior;
          LATBbits.LATB6=1;
          LATBbits.LATB5=0;
          LATBbits.LATB7=0;
         }
     }
      else
      {
         if(presion2 != presion2_anterior)
         {
          sprintf(T, "%03.1f %c", presion2, 0x3E);
          LCD_gotoxy(0,1);
          LCD_puts(T);
          presion2 = presion2_anterior;
          LATBbits.LATB7=1;
         
         }
      }
     
     presion3=(((float)ADC_get(2)/203.7221)-0.5)/0.01333333333;
     if (presion3<30)
     {
         if(presion3 != presion3_anterior)
         {
          sprintf(T, "%03.1f %c ", presion3, 0x3C);
          LCD_gotoxy(0,2);
          LCD_puts(T);
          presion3 = presion3_anterior;
          LATBbits.LATB5=1;
         
         }
     }
     else if (presion3 >= 30 && presion3 <=40)
     {
         if(presion3 != presion3_anterior)
         {
          sprintf(T, "%03.1f %c", presion3, 0x2D);
          LCD_gotoxy(0,2);
          LCD_puts(T);
          presion3 = presion3_anterior;
          LATBbits.LATB6=1;
          LATBbits.LATB5=0;
          LATBbits.LATB7=0;
         }
     }
      else
      {
         if(presion3 != presion3_anterior)
         {
          sprintf(T, "%03.1f %c", presion3, 0x3E);
          LCD_gotoxy(0,2);
          LCD_puts(T);
          presion3 = presion3_anterior;
          LATBbits.LATB7=1;
         
         }
      }

     presion4=(((float)ADC_get(3)/203.7221)-0.5)/0.01333333333;
     if (presion4<30)
     {
         if(presion4 != presion4_anterior)
         {
          sprintf(T, "%03.1f %c ", presion4, 0x3C);
          LCD_gotoxy(0,3);
          LCD_puts(T);
          presion4 = presion4_anterior;
          LATBbits.LATB5=1;
         
         }
     }
     else if (presion4 >= 30 && presion4 <=40)
     {
         if(presion4 != presion4_anterior)
         {
          sprintf(T, "%03.1f %c", presion4, 0x2D);
          LCD_gotoxy(0,3);
          LCD_puts(T);
          presion4 = presion4_anterior;
          LATBbits.LATB6=1;
          LATBbits.LATB5=0;
          LATBbits.LATB7=0;
         }
     }
      else
      {
         if(presion4 != presion4_anterior)
         {
          sprintf(T, "%03.1f %c", presion4, 0x3E);
          LCD_gotoxy(0,3);
          LCD_puts(T);
          presion4 = presion4_anterior;
          LATBbits.LATB7=1;
         
         }
      }

     presion5=(((float)ADC_get(4)/203.7221)-0.5)/0.01333333333;
     if (presion5<30)
     {
         if(presion5 != presion5_anterior)
         {
          sprintf(T, "%03.1f %c ", presion5, 0x3C);
          LCD_gotoxy(9,0);
          LCD_puts(T);
          presion5 = presion5_anterior;
          LATBbits.LATB5=1;
         
         }
     }
     else if (presion5 >= 30 && presion5 <=40)
     {
         if(presion5 != presion5_anterior)
         {
          sprintf(T, "%03.1f %c", presion5, 0x2D);
          LCD_gotoxy(9,0);
          LCD_puts(T);
          presion5 = presion5_anterior;
          LATBbits.LATB6=1;
          LATBbits.LATB5=0;
          LATBbits.LATB7=0;
         }
     }
      else
      {
         if(presion5 != presion5_anterior)
         {
          sprintf(T, "%03.1f %c", presion5, 0x3E);
          LCD_gotoxy(9,0);
          LCD_puts(T);
          presion5 = presion5_anterior;
          LATBbits.LATB7=1;
         }

      }
    /*LCD_gotoxy(0,0);
    LCD_puts("linea 1");
    LCD_gotoxy(0,1);
    LCD_puts("linea 2");
    LCD_gotoxy(0,2);
    LCD_puts("linea 3");
    LCD_gotoxy(0,3);
    LCD_puts("linea 4");*/
}
   
   
}

//volatile int myVolatileVariable=0;//variable para utilizar con las interrupciones


    void interrupt isr (void)//prototipo de la interrupción de baja prioridad
    {
        if(INTCON3bits.INT2IF==1)       //pregunta por bandera de interrupción
          {
           LATAbits.LATA4= 0;            // invierto estado del led
          //myVolatileVariable++;
           INTCON3bits.INT2IF = 0;  //limpia bandera y salimos
          }
        //return;
    }
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 13 de Diciembre de 2015, 10:30:35
Bueno.. Ahi mire el programa y lo probe, solo probe la parte del sprintf, y todo lo del micro, nada de ADC/LCD, estos son los problemas que encontre, aunque voy a ir con tu problema primero:

- La interrupcion esta como "alta velocidad" ( le falta el low_priority), pero vos tenes definida la interrupcion como baja prioridad. Ademas tenes habilitada las 2 interrupciones, las de alta y las de baja cuando solo usarias la de baja:

Código: C
  1. INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
  2.     INTCONbits.GIEH=1;  //alto en ultima compuerta

En si el problema es el siguiente. la interrupcion de alta prioridad se encuentra en 0x0008 y la de baja en 0x0018, MPLAB no se por que pone todo el codigo a partir de la direccion 0x800 tal ves esperando un bootloader. Entonces cuando ocurre una interrupcion, catalogada como baja prioridad va a 0x0018, PERO tu call a la funcion de interrupcion se da en 0x0008, de esta forma primero que nada estas ejecutando NOP hasta que vuelve a las instrucciones de reset ( va de 0x0018 a 0x0800 ejecutando NOPs), lo feo es que si se habia ejecutado un CALL por ejemplo ( como para comparar los flotantes ) y se produce la interrupcion, ese CALL, nunca ejecuta un RETURN. LLenando el STACK poco a poco ya que jamas se saca nada, y eso termina en el STACK OVERFLOW que tenes.

- Mas problemas con tu programa:

- Comparacion:

Código: C
  1. presion1 = presion1_anterior;

Eso no tiene sentido por que siempre asignaria un 0 a presion1 y jamas daria igualdad entre lo anterior y presion1 e imagino que quisiste hacerlo al reves, es decir:

Código: C
  1. presion1_anterior = presion1;

- Repeticion de codigo... es terrible la cantidad de codigo que se repite y algunas condiciones que tampoco tienen sentido.
Podrias haber realizado con un for, todo eso, para cada una de las entradas, pero hiciste una por 1, tambien comprobas cosas que habias comprobado antes, como es el ejemplo de ver que es menos de 30 y luego en el else comparar si es mayor o igual, si ya hiciste antes esa comparacion, ¿por que nuevamente?. La otra tambien es la de preguntar siempre si es igual o no que el valor anterior. Un solo if fuera y esta listo.

Tu programa:

Código: C
  1. float presion[5], presion_anterior[5] = 0; // para que solo escriba en pantalla si cambia la presion
  2.     char T[17], terminacion; // cadena de 16 caracteres incluyendo el final \0
  3.     int i;

Código: C
  1. while (1)
  2.     {
  3.  
  4.         for(i=0;i<5;i++)
  5.         {
  6.             presion[i]=(((float)ADC_get(i)/203.7221)-0.5)/0.01333333333;
  7.             if(presion[i] != presion_anterior[i])
  8.             {
  9.                 terminacion = 0x3C;
  10.                 if (presion[i]<30)
  11.                 {
  12.                     LATBbits.LATB5=1;
  13.                     if(!i) LATAbits.LATA4=1;        //Solo para canal0
  14.                 }
  15.                 else if (presion[i] <=40)
  16.                 {
  17.                     LATBbits.LATB6=1;
  18.                     LATBbits.LATB5=0;
  19.                     LATBbits.LATB7=0;
  20.                     terminacion = 0x2D;
  21.                 }
  22.                 else
  23.                 {
  24.                     LATBbits.LATB7=1;
  25.                 }
  26.                 sprintf(T, "%03.1f %c ", presion[i], terminacion);
  27.                 if (i==4) LCD_gotoxy(9,0);
  28.                 else LCD_gotoxy(0,i);
  29.                 LCD_puts(T);
  30.                 presion_anterior[i] = presion[i];
  31.             }
  32.          }
  33.     }

Incluso si tenes que hacer una salida por cada uno seguiria asi el ejemplo. nomas que usaria otra funcion mas aparte de eso.

Creo que la reduccion es poca, ya que lo que mas ocupa son otras cosas como lo de float y sprintf pero tenes:

    Program space        used  1642h (  5698) of  8000h bytes   ( 17.4%)

versus un 20%+ ocupado como lo tenias en tu programa. Y tal ves no sea necesario calcular todo, solo cuando sea necesario ademas, tenes que darte cuenta que la coma flotante para que se produzca una igualdad es bastante complejo. Por gusto probe con enteros :)

Código: C
  1. int presion[5], presion_anterior[5]; // para que solo escriba en pantalla si cambia la presion
  2.     float resultado;
  3.     char T[17], terminacion; // cadena de 16 caracteres incluyendo el final \0
  4.     short int i;

Código: C
  1. for(i=0;i<5;i++)
  2.         {
  3.             presion[i]=ADC_get(i);
  4.             if(presion[i] != presion_anterior[i])
  5.             {
  6.                 presion_anterior[i] = presion[i];
  7.                 terminacion = 0x3C;
  8.                 if (presion[i]<183)
  9.                 {
  10.                     LATBbits.LATB5=1;
  11.                     if(!i) LATAbits.LATA4=1;        //Solo para canal0
  12.                 }
  13.                 else if (presion[i] <=210)
  14.                 {
  15.                     LATBbits.LATB6=1;
  16.                     LATBbits.LATB5=0;
  17.                     LATBbits.LATB7=0;
  18.                     terminacion = 0x2D;
  19.                 }
  20.                 else
  21.                 {
  22.                     LATBbits.LATB7=1;
  23.                 }
  24.                 resultado=(((float)presion[i]/203.7221)-0.5)/0.01333333333;
  25.                 sprintf(T, "%03.1f %c ", resultado , terminacion);
  26.                 if (i==4) LCD_gotoxy(9,0);
  27.                 else LCD_gotoxy(0,i);
  28.                 LCD_puts(T);
  29.             }
  30.          }

Una curiosidad que encontre.

Tiempos:

Comparacion, activar saidas, etc: 89 a 120 ciclos
Calculo: 1960 a 2000 ciclos ( Solo la linea con la matematica )
Pasarlo a texto: 11600 a 13800 ciclos ( Solo la linea del sprintf )

-------------------------

Una mejora para el calculo, simplificandolo:

Código: C
  1. resultado=((float)(test/2.71629)-37.5);

Ocupa 900 ciclos menos aproximadamente.
Floats de 24 bits, no de 32! Pero suficiente para la precision que estas buscando.
Título: Re:Mini curso "Programación en XC8"
Publicado por: fernandogomav en 13 de Diciembre de 2015, 21:27:14
Bueno.. Ahi mire el programa y lo probe, solo probe la parte del sprintf, y todo lo del micro, nada de ADC/LCD, estos son los problemas que encontre, aunque voy a ir con tu problema primero:

- La interrupcion esta como "alta velocidad" ( le falta el low_priority), pero vos tenes definida la interrupcion como baja prioridad. Ademas tenes habilitada las 2 interrupciones, las de alta y las de baja cuando solo usarias la de baja:

Código: C
  1. INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
  2.     INTCONbits.GIEH=1;  //alto en ultima compuerta

En si el problema es el siguiente. la interrupcion de alta prioridad se encuentra en 0x0008 y la de baja en 0x0018, MPLAB no se por que pone todo el codigo a partir de la direccion 0x800 tal ves esperando un bootloader. Entonces cuando ocurre una interrupcion, catalogada como baja prioridad va a 0x0018, PERO tu call a la funcion de interrupcion se da en 0x0008, de esta forma primero que nada estas ejecutando NOP hasta que vuelve a las instrucciones de reset ( va de 0x0018 a 0x0800 ejecutando NOPs), lo feo es que si se habia ejecutado un CALL por ejemplo ( como para comparar los flotantes ) y se produce la interrupcion, ese CALL, nunca ejecuta un RETURN. LLenando el STACK poco a poco ya que jamas se saca nada, y eso termina en el STACK OVERFLOW que tenes.

- Mas problemas con tu programa:

- Comparacion:

Código: C
  1. presion1 = presion1_anterior;

Eso no tiene sentido por que siempre asignaria un 0 a presion1 y jamas daria igualdad entre lo anterior y presion1 e imagino que quisiste hacerlo al reves, es decir:

Código: C
  1. presion1_anterior = presion1;

- Repeticion de codigo... es terrible la cantidad de codigo que se repite y algunas condiciones que tampoco tienen sentido.
Podrias haber realizado con un for, todo eso, para cada una de las entradas, pero hiciste una por 1, tambien comprobas cosas que habias comprobado antes, como es el ejemplo de ver que es menos de 30 y luego en el else comparar si es mayor o igual, si ya hiciste antes esa comparacion, ¿por que nuevamente?. La otra tambien es la de preguntar siempre si es igual o no que el valor anterior. Un solo if fuera y esta listo.

Tu programa:

Código: C
  1. float presion[5], presion_anterior[5] = 0; // para que solo escriba en pantalla si cambia la presion
  2.     char T[17], terminacion; // cadena de 16 caracteres incluyendo el final \0
  3.     int i;

Código: C
  1. while (1)
  2.     {
  3.  
  4.         for(i=0;i<5;i++)
  5.         {
  6.             presion[i]=(((float)ADC_get(i)/203.7221)-0.5)/0.01333333333;
  7.             if(presion[i] != presion_anterior[i])
  8.             {
  9.                 terminacion = 0x3C;
  10.                 if (presion[i]<30)
  11.                 {
  12.                     LATBbits.LATB5=1;
  13.                     if(!i) LATAbits.LATA4=1;        //Solo para canal0
  14.                 }
  15.                 else if (presion[i] <=40)
  16.                 {
  17.                     LATBbits.LATB6=1;
  18.                     LATBbits.LATB5=0;
  19.                     LATBbits.LATB7=0;
  20.                     terminacion = 0x2D;
  21.                 }
  22.                 else
  23.                 {
  24.                     LATBbits.LATB7=1;
  25.                 }
  26.                 sprintf(T, "%03.1f %c ", presion[i], terminacion);
  27.                 if (i==4) LCD_gotoxy(9,0);
  28.                 else LCD_gotoxy(0,i);
  29.                 LCD_puts(T);
  30.                 presion_anterior[i] = presion[i];
  31.             }
  32.          }
  33.     }

Incluso si tenes que hacer una salida por cada uno seguiria asi el ejemplo. nomas que usaria otra funcion mas aparte de eso.

Creo que la reduccion es poca, ya que lo que mas ocupa son otras cosas como lo de float y sprintf pero tenes:

    Program space        used  1642h (  5698) of  8000h bytes   ( 17.4%)

versus un 20%+ ocupado como lo tenias en tu programa. Y tal ves no sea necesario calcular todo, solo cuando sea necesario ademas, tenes que darte cuenta que la coma flotante para que se produzca una igualdad es bastante complejo. Por gusto probe con enteros :)

Código: C
  1. int presion[5], presion_anterior[5]; // para que solo escriba en pantalla si cambia la presion
  2.     float resultado;
  3.     char T[17], terminacion; // cadena de 16 caracteres incluyendo el final \0
  4.     short int i;

Código: C
  1. for(i=0;i<5;i++)
  2.         {
  3.             presion[i]=ADC_get(i);
  4.             if(presion[i] != presion_anterior[i])
  5.             {
  6.                 presion_anterior[i] = presion[i];
  7.                 terminacion = 0x3C;
  8.                 if (presion[i]<183)
  9.                 {
  10.                     LATBbits.LATB5=1;
  11.                     if(!i) LATAbits.LATA4=1;        //Solo para canal0
  12.                 }
  13.                 else if (presion[i] <=210)
  14.                 {
  15.                     LATBbits.LATB6=1;
  16.                     LATBbits.LATB5=0;
  17.                     LATBbits.LATB7=0;
  18.                     terminacion = 0x2D;
  19.                 }
  20.                 else
  21.                 {
  22.                     LATBbits.LATB7=1;
  23.                 }
  24.                 resultado=(((float)presion[i]/203.7221)-0.5)/0.01333333333;
  25.                 sprintf(T, "%03.1f %c ", resultado , terminacion);
  26.                 if (i==4) LCD_gotoxy(9,0);
  27.                 else LCD_gotoxy(0,i);
  28.                 LCD_puts(T);
  29.             }
  30.          }

Una curiosidad que encontre.

Tiempos:

Comparacion, activar saidas, etc: 89 a 120 ciclos
Calculo: 1960 a 2000 ciclos ( Solo la linea con la matematica )
Pasarlo a texto: 11600 a 13800 ciclos ( Solo la linea del sprintf )

-------------------------

Una mejora para el calculo, simplificandolo:

Código: C
  1. resultado=((float)(test/2.71629)-37.5);

Ocupa 900 ciclos menos aproximadamente.
Floats de 24 bits, no de 32! Pero suficiente para la precision que estas buscando.

Primero que todo KILLERJC agradecerte porque el problema esta solucionado, ya la interrupción actúa y puedo apagar el LED con el pulsador, como dijiste me faltaba declarar la funcion de interrupcion como low_priority!! algo que queria comentarte, intente robarla sin el GIEH=1 y no funciona, solo funciona habilitando esa tambien.

-con lo de la comparacion:

presion1 = presion1_anterior;

aqui lo que trato de hacer es que no escriba en pantalla continuamente, es decir, que no realize el printf a menos que la presion cambie, osea el valor de la entrada analogica, esto es lo que trato de hacer, tu me diras si si esta bien o se puede hacer de otra manera, ademas tienes razon en que son coma flotante y es dificil que se cumpla la igualdad, mas bien creo que ese codigo esta de mas...

lo que me preguntas del porque volver a evaluar términos entre 30 y 40 y no solamente menores a 40, es porque es un ejemplo de el intervalo en donde las presiones se pueden considerar normales, por eso tengo tres intervalos..osea presiones menores a 30 realiza ciertas cosas, entre 30 y 40 esta normal y mayores a 40 altos...

te agradezco muchisimo el codigo de ejemplo que pones, pues veo que realiza lomismo pero en muchisimas menos lineas, bueno ya ves q no tengo tanta experiencia programando, voy aprediendo...=)

en mi programa, el que te pase, todas las presiones tienen los mismos intervalos pero era solo para probarlas, en realidad cada presion tiene intervalos diferentes porque medire diferentes gases, con los gases diferentes ya no podria aplicar el codigo con el for o si???

lo podria aplicar a los que sean iguales y a los diferentes como lo tenia no?'
me dijsite esto: Incluso si tenes que hacer una salida por cada uno seguiria asi el ejemplo. nomas que usaria otra funcion mas aparte de eso, eso fue lo que entendi...

ahora lo que hiciste en el segundo código que probaste con enteros, tendría que ver el valor digital del get(x) para el valor de mi presion, entiendo por esto que estar trabajando directamente en los intervalos con el valor digital de la conversión...no?

ahora lo de el printf una sola vez y el calculo de presion una sola vez con la variable terminacion para el caracter, es simplemente codigo en su estado puro, creo que hubiese necesitado unos meses mas para llegar a eso, de verdad muchas gracias KILLERJC..



y la verdad ya me estaba empezando a preocupar que se llena la memoria y me falta mucho por programar aun....


Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 13 de Diciembre de 2015, 22:09:28
Citar
presion1 = presion1_anterior;

aqui lo que trato de hacer es que no escriba en pantalla continuamente, es decir, que no realize el printf a menos que la presion cambie, osea el valor de la entrada analogica, esto es lo que trato de hacer, tu me diras si si esta bien o se puede hacer de otra manera, ademas tienes razon en que son coma flotante y es dificil que se cumpla la igualdad, mas bien creo que ese codigo esta de mas...

2 cosas ahi:

Estas haciendo:

presion1 <- presion1_anterior

en ves de al reves, eso intente hacerte notar, como presion1_anterior inicializa a 0 y vos jamas lo cambias ( ya que tu asignacion estaba al reves, era lo mismo que poner:

presion1 = 0;

Con respecto a los flotantes, siempre que los uses, trata de jamas usar igualdades, siempre menor a o mayor a, es algo que me traje de python pero creo que se aplica aca tambien. Las representaciones binarias no son exactas y bueno puede parecer que son iguales pero que dentro en la representacion no lo son.

Citar
en mi programa, el que te pase, todas las presiones tienen los mismos intervalos pero era solo para probarlas, en realidad cada presion tiene intervalos diferentes porque medire diferentes gases, con los gases diferentes ya no podria aplicar el codigo con el for o si???

Si podes hacerlo. Suponete que fijamos 2 valores por cada "presion", podes utilizar un array de esta forma:

Código: C
  1. const int limites_presion[5][2] = {{10,20},{30,40},{50,60},{700,1000},{80,200}};

El const, te lo pone en flash, pero si ves que esta muy llena tu flash se lo sacas para que quede almacenado en la RAM. y reemplazas los valores de los if:

Código: C
  1. if (presion[i]<30)
  2.                 else if (presion[i] <=40)

por

Código: C
  1. if (presion[i] < limites_presion[i][0])
  2.                 else if (presion[i] <= limites_presion[i][1])

Con respecto a las salidas ya se complica un poco mas.
Voy a suponer por un momento que cada condicion.. es decir: Minimo, Medio, Maximo de cada presion son distintos.
Voy a intentar hacer un codigo facil para que te sea facil verlo. OJO! hay muchas formas mas de hacerlo, esto es solo para que veas una forma y se pueda ver facilmente. todo va a depender de que tan complejas sean tus funciones.

Código: C
  1. for(i=0;i<5;i++)
  2.         {
  3.             presion[i]=ADC_get(i);
  4.             if(presion[i] != presion_anterior[i])
  5.             {
  6.                 presion_anterior[i] = presion[i];
  7.                 terminacion = 0x3C;
  8.                 salida = i*3;
  9.                 if (presion[i] > limite_presion[i][0] && presion[i] <= limite_presion[i][1])
  10.                 {
  11.                         salida++
  12.                         terminacion = 0x2D;
  13.                 }
  14.                 else
  15.                 {
  16.                         salida+=2;
  17.                 }
  18.                 Cambiar_salida(salida);
  19.                 resultado=(((float)presion[i]/203.7221)-0.5)/0.01333333333;
  20.                 sprintf(T, "%03.1f %c ", resultado , terminacion);
  21.                 if (i==4) LCD_gotoxy(9,0);
  22.                 else LCD_gotoxy(0,i);
  23.                 LCD_puts(T);
  24.             }
  25.          }
  26.  
  27.  
  28.  
  29.  
  30. void Cambiar_salida(short valor_salida)
  31. {
  32.         switch(valor_salida)
  33.         {
  34.  
  35.         // i = 0
  36.         case 0:
  37.                 //Valor minimo (presion[0] < limite_presion[0][0])
  38.                 break;
  39.         case 1:
  40.                 //Valor medio (limite_presion[0][0] < presion[0] <= limite_presion[0][1])
  41.                 break;
  42.         case 2:
  43.                 //Valor maximo (presion[0] > limite_presion[0][1])
  44.                 break;
  45.  
  46.         // i = 1
  47.         case 3:
  48.                 //Valor minimo (presion[i] < limite_presion[i][0])
  49.                 break;
  50.         case 4:
  51.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  52.                 break;
  53.         case 5:
  54.                 //Valor maximo (presion[i] > limite_presion[i][1])
  55.                 break;
  56.  
  57.         // i = 2
  58.         case 6:
  59.                 //Valor minimo (presion[i] < limite_presion[i][0])
  60.                 break;
  61.         case 7:
  62.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  63.                 break;
  64.         case 8:
  65.                 //Valor maximo (presion[i] > limite_presion[i][1])
  66.                 break;
  67.  
  68.         // i = 3
  69.         case 9:
  70.                 //Valor minimo (presion[i] < limite_presion[i][0])
  71.                 break;
  72.         case 10:
  73.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  74.                 break;
  75.         case 11:
  76.                 //Valor maximo (presion[i] > limite_presion[i][1])
  77.                 break;
  78.  
  79.         // i = 4
  80.         case 12:
  81.                 //Valor minimo (presion[i] < limite_presion[i][0])
  82.                 break;
  83.         case 13:
  84.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  85.                 break;
  86.         case 14:
  87.                 //Valor maximo (presion[i] > limite_presion[i][1])
  88.                 break;
  89.  
  90.         default:
  91.                 // Aca entra si existe un error. Deberia desactivar todo.
  92.  
  93.         }
  94.  
  95. }
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 17 de Diciembre de 2015, 15:37:40
Hola compañeros, ¿Podéis decirme porque este simple código no me funciona correctamente? En la simulación solo cambian los 8 bits de la parte baja del Timer y en consecuencia nunca se desborda.
Código: C
  1. #define _XTAL_FREQ 20000000
  2. #include <xc.h>
  3. #include <pic18f2550.h>
  4. #include "config.h"
  5.  
  6. void main(void)
  7. {
  8.     TRISBbits.RB0 = 0;  //Configuramos RB0 como salida
  9.     LATB0 = 0;  //Empezamos con el led apagado
  10.    
  11.     //CONFIGURAMOS TIMER1
  12.     INTCONbits.GIE = 0; //Desabilitamos todas las interrupciones
  13.     T1CONbits.RD16 = 1; //16 bit
  14.     T1CONbits.T1RUN = 0;
  15.     T1CONbits.T1CKPS1 = 0;  //Seleccionamos
  16.     T1CONbits.T1CKPS0 = 0;  //prescaler 1:1
  17.     T1CONbits.T1OSCEN = 0;  // Timer 1 Osc Enable: 0 = off, 1 = on
  18.     T1CONbits.T1SYNC = 0;
  19.     T1CONbits.TMR1CS = 0;   //Internal clock (Fosc/4)
  20.     T1CONbits.TMR1ON = 1;   //Enable Timer1
  21.     TMR1H = 0x00;
  22.     TMR1L = 0x00;
  23.     PIR1bits.TMR1IF = 0;     //Reset the interrupt flag
  24.    
  25.     while(!PIR1bits.TMR1IF){
  26.         LATB0 =~ LATB0;  
  27.     }
  28.     T1CONbits.TMR1ON = 0;   //Stop Timer1
  29. }

Saludos!
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 17 de Diciembre de 2015, 17:05:31
hola miguel, antes de nada decirte que te falta en tu programa un bucle principal, un while (1); si no lo tienes se ejecutara una vez y se acabo, por lo tanto debes agregarlo.


por otro lado cada vez que salta la interrupción debes recargar los registros y limpiar el flag de interrupcion.

es decir cada vez que se desborde debes reiniciarlo

Código: [Seleccionar]
TMR1IF=0;
TMR1 = (lo que le quieras poner, en tu caso 0) ;

o

Código: [Seleccionar]
TMR1IF=0;
TMR1H = 0;
TMR1L=0;

y ya de paso habilita su interrupción, si no me equivoco, eran los registros PIE1, TMR1IE

por cierto los fuses los has colocado en algún lado?

un saludo
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 17 de Diciembre de 2015, 17:53:23
hola miguel, antes de nada decirte que te falta en tu programa un bucle principal, un while (1); si no lo tienes se ejecutara una vez y se acabo, por lo tanto debes agregarlo.


por otro lado cada vez que salta la interrupción debes recargar los registros y limpiar el flag de interrupcion.

es decir cada vez que se desborde debes reiniciarlo

Código: [Seleccionar]
TMR1IF=0;
TMR1 = (lo que le quieras poner, en tu caso 0) ;

o

Código: [Seleccionar]
TMR1IF=0;
TMR1H = 0;
TMR1L=0;

y ya de paso habilita su interrupción, si no me equivoco, eran los registros PIE1, TMR1IE

por cierto los fuses los has colocado en algún lado?

un saludo
Hola Juan José ante todo gracias, lo del bucle infinito lo se, se que sin el solo se ejecuta una vez pero es que ni siquiera llega a una vez, en la simulación me he dado cuenta que los registros del Timer TMR1H y TMR1L solo se incrementa el low el high siempre esta a 0.
Si quiero que trabaje como temporización sin crear una función de interrupción ¿El bit TMR1IE debe estar habilitado?
Los fuses los tengo en un archivo aparte pero no es problema de fuses ya que probé con elos en el programa.

Saludos!

 
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 17 de Diciembre de 2015, 18:09:27
Código: [Seleccionar]
#define _XTAL_FREQ 20000000
#include <xc.h>
#include <pic18f2550.h>
#include "config.h"
 
void main(void)
{
    TRISBbits.RB0 = 0;  //Configuramos RB0 como salida
    LATB0 = 0;  //Empezamos con el led apagado
   
    //CONFIGURAMOS TIMER1
    INTCONbits.GIE = 0; //Desabilitamos todas las interrupciones
    T1CONbits.RD16 = 1; //16 bit
    T1CONbits.T1RUN = 0;
    T1CONbits.T1CKPS1 = 0;  //Seleccionamos
    T1CONbits.T1CKPS0 = 0;  //prescaler 1:1
    T1CONbits.T1OSCEN = 0;  // Timer 1 Osc Enable: 0 = off, 1 = on
    T1CONbits.T1SYNC = 0;
    T1CONbits.TMR1CS = 0;   //Internal clock (Fosc/4)
    TMR1H = 0x00;
    TMR1L = 0x00;
    PIR1bits.TMR1IF = 0;     //Reset the interrupt flag
    T1CONbits.TMR1ON = 1;   //Enable Timer1
   

    while(1)
    {
          if(PIR1bits.TMR1IF)
          {
                 LATB0 =~ LATB0;
                 TMR1IF=0;
                 TMR1H = 0;
                 TMR1L=0;
          }         
    }
}

prueba eso, eso te debe dar una señal cuadrada y si debe cargar la parte superior del registro.

Citar
¿El bit TMR1IE debe estar habilitado?

creo que no, ya que no recurres a ninguna interrupcion, por eso esta linera tampoco es necesaria:

Código: [Seleccionar]
INTCONbits.GIE = 0; //Desabilitamos todas las interrupciones
un saludo


EDITO cambia de posición las lineas de carga y encendido del timer como he puesto yo
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 17 de Diciembre de 2015, 18:40:11
Gracias voy a probar a tu manera, pero ya sera mañana que si no las 6 de la mañana se me hace temprano.

Miquel_S
Título: Re:Mini curso "Programación en XC8"
Publicado por: fernandogomav en 19 de Diciembre de 2015, 12:59:25
Citar
presion1 = presion1_anterior;

aqui lo que trato de hacer es que no escriba en pantalla continuamente, es decir, que no realize el printf a menos que la presion cambie, osea el valor de la entrada analogica, esto es lo que trato de hacer, tu me diras si si esta bien o se puede hacer de otra manera, ademas tienes razon en que son coma flotante y es dificil que se cumpla la igualdad, mas bien creo que ese codigo esta de mas...

2 cosas ahi:

Estas haciendo:

presion1 <- presion1_anterior

en ves de al reves, eso intente hacerte notar, como presion1_anterior inicializa a 0 y vos jamas lo cambias ( ya que tu asignacion estaba al reves, era lo mismo que poner:

presion1 = 0;

Con respecto a los flotantes, siempre que los uses, trata de jamas usar igualdades, siempre menor a o mayor a, es algo que me traje de python pero creo que se aplica aca tambien. Las representaciones binarias no son exactas y bueno puede parecer que son iguales pero que dentro en la representacion no lo son.

Citar
en mi programa, el que te pase, todas las presiones tienen los mismos intervalos pero era solo para probarlas, en realidad cada presion tiene intervalos diferentes porque medire diferentes gases, con los gases diferentes ya no podria aplicar el codigo con el for o si???

Si podes hacerlo. Suponete que fijamos 2 valores por cada "presion", podes utilizar un array de esta forma:

Código: C
  1. const int limites_presion[5][2] = {{10,20},{30,40},{50,60},{700,1000},{80,200}};

El const, te lo pone en flash, pero si ves que esta muy llena tu flash se lo sacas para que quede almacenado en la RAM. y reemplazas los valores de los if:

Código: C
  1. if (presion[i]<30)
  2.                 else if (presion[i] <=40)

por

Código: C
  1. if (presion[i] < limites_presion[i][0])
  2.                 else if (presion[i] <= limites_presion[i][1])

Con respecto a las salidas ya se complica un poco mas.
Voy a suponer por un momento que cada condicion.. es decir: Minimo, Medio, Maximo de cada presion son distintos.
Voy a intentar hacer un codigo facil para que te sea facil verlo. OJO! hay muchas formas mas de hacerlo, esto es solo para que veas una forma y se pueda ver facilmente. todo va a depender de que tan complejas sean tus funciones.

Código: C
  1. for(i=0;i<5;i++)
  2.         {
  3.             presion[i]=ADC_get(i);
  4.             if(presion[i] != presion_anterior[i])
  5.             {
  6.                 presion_anterior[i] = presion[i];
  7.                 terminacion = 0x3C;
  8.                 salida = i*3;
  9.                 if (presion[i] > limite_presion[i][0] && presion[i] <= limite_presion[i][1])
  10.                 {
  11.                         salida++
  12.                         terminacion = 0x2D;
  13.                 }
  14.                 else
  15.                 {
  16.                         salida+=2;
  17.                 }
  18.                 Cambiar_salida(salida);
  19.                 resultado=(((float)presion[i]/203.7221)-0.5)/0.01333333333;
  20.                 sprintf(T, "%03.1f %c ", resultado , terminacion);
  21.                 if (i==4) LCD_gotoxy(9,0);
  22.                 else LCD_gotoxy(0,i);
  23.                 LCD_puts(T);
  24.             }
  25.          }
  26.  
  27.  
  28.  
  29.  
  30. void Cambiar_salida(short valor_salida)
  31. {
  32.         switch(valor_salida)
  33.         {
  34.  
  35.         // i = 0
  36.         case 0:
  37.                 //Valor minimo (presion[0] < limite_presion[0][0])
  38.                 break;
  39.         case 1:
  40.                 //Valor medio (limite_presion[0][0] < presion[0] <= limite_presion[0][1])
  41.                 break;
  42.         case 2:
  43.                 //Valor maximo (presion[0] > limite_presion[0][1])
  44.                 break;
  45.  
  46.         // i = 1
  47.         case 3:
  48.                 //Valor minimo (presion[i] < limite_presion[i][0])
  49.                 break;
  50.         case 4:
  51.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  52.                 break;
  53.         case 5:
  54.                 //Valor maximo (presion[i] > limite_presion[i][1])
  55.                 break;
  56.  
  57.         // i = 2
  58.         case 6:
  59.                 //Valor minimo (presion[i] < limite_presion[i][0])
  60.                 break;
  61.         case 7:
  62.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  63.                 break;
  64.         case 8:
  65.                 //Valor maximo (presion[i] > limite_presion[i][1])
  66.                 break;
  67.  
  68.         // i = 3
  69.         case 9:
  70.                 //Valor minimo (presion[i] < limite_presion[i][0])
  71.                 break;
  72.         case 10:
  73.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  74.                 break;
  75.         case 11:
  76.                 //Valor maximo (presion[i] > limite_presion[i][1])
  77.                 break;
  78.  
  79.         // i = 4
  80.         case 12:
  81.                 //Valor minimo (presion[i] < limite_presion[i][0])
  82.                 break;
  83.         case 13:
  84.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  85.                 break;
  86.         case 14:
  87.                 //Valor maximo (presion[i] > limite_presion[i][1])
  88.                 break;
  89.  
  90.         default:
  91.                 // Aca entra si existe un error. Deberia desactivar todo.
  92.  
  93.         }
  94.  
  95. }
HOLA KILLERJC, primero que todo gracias por tus respuestas y consejos, estuve toda la semana arreglando el codigo y entendiendo todo lo que me explicabas...

ya arregle lo de presion1_anterior=presion1, claro tenias toda la razon la estaba poniendo en 0 todo el tiempo...

fije los limetes de presion como me dijiste y cambie los if de cada entrada por un for para todos como me mandaste el codigo, copilo y simulo EXCELENTE  muchisimas gracias, cada vez aprendo mas programar =)...

ahora el codigo pesa 32% y sumandole mas codigo aparte del que me pasaste que sustituí y agregue otras cosas, versus un 36% que tenia solo con los intervalos if para cada gas =)

agradecido... PROBLEMA SOLUCIONADO
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 20 de Diciembre de 2015, 12:51:07
Código: [Seleccionar]
#define _XTAL_FREQ 20000000
#include <xc.h>
#include <pic18f2550.h>
#include "config.h"
 
void main(void)
{
    TRISBbits.RB0 = 0;  //Configuramos RB0 como salida
    LATB0 = 0;  //Empezamos con el led apagado
   
    //CONFIGURAMOS TIMER1
    INTCONbits.GIE = 0; //Desabilitamos todas las interrupciones
    T1CONbits.RD16 = 1; //16 bit
    T1CONbits.T1RUN = 0;
    T1CONbits.T1CKPS1 = 0;  //Seleccionamos
    T1CONbits.T1CKPS0 = 0;  //prescaler 1:1
    T1CONbits.T1OSCEN = 0;  // Timer 1 Osc Enable: 0 = off, 1 = on
    T1CONbits.T1SYNC = 0;
    T1CONbits.TMR1CS = 0;   //Internal clock (Fosc/4)
    TMR1H = 0x00;
    TMR1L = 0x00;
    PIR1bits.TMR1IF = 0;     //Reset the interrupt flag
    T1CONbits.TMR1ON = 1;   //Enable Timer1
   

    while(1)
    {
          if(PIR1bits.TMR1IF)
          {
                 LATB0 =~ LATB0;
                 TMR1IF=0;
                 TMR1H = 0;
                 TMR1L=0;
          }         
    }
}

prueba eso, eso te debe dar una señal cuadrada y si debe cargar la parte superior del registro.

Citar
¿El bit TMR1IE debe estar habilitado?

creo que no, ya que no recurres a ninguna interrupcion, por eso esta linera tampoco es necesaria:

Código: [Seleccionar]
INTCONbits.GIE = 0; //Desabilitamos todas las interrupciones
un saludo


EDITO cambia de posición las lineas de carga y encendido del timer como he puesto yo
Hola después de muchas pruebas con el timer consigo las temporizaciones según la formula del Timer1, pero sigo con fallos en la simulación con el IDE, por lo cual puedo asegurar que el MPLAB X IDE v3.10 me esta fallando mas que una escopeta de feria  :5]

Miquel_S
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 20 de Diciembre de 2015, 13:36:52
Citar
Hola después de muchas pruebas con el timer consigo las temporizaciones según la formula del Timer1, pero sigo con fallos en la simulación con el IDE, por lo cual puedo asegurar que el MPLAB X IDE v3.10 me esta fallando mas que una escopeta de feria  :5]

Miquel_S

Hasta ahora el unico fallo que tuve con el MPLAB X es de que se me corrompiera un proyecto y no me compilara, pase el codigo entero a otro proyecto y funcionando. Fue el unico, en simulacion no tuve problemas, incluso cuando hice los codigos para los PIC18 y dsPIC
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 20 de Diciembre de 2015, 14:30:56
Citar
Hola después de muchas pruebas con el timer consigo las temporizaciones según la formula del Timer1, pero sigo con fallos en la simulación con el IDE, por lo cual puedo asegurar que el MPLAB X IDE v3.10 me esta fallando mas que una escopeta de feria  :5]

Miquel_S

Hasta ahora el unico fallo que tuve con el MPLAB X es de que se me corrompiera un proyecto y no me compilara, pase el codigo entero a otro proyecto y funcionando. Fue el unico, en simulacion no tuve problemas, incluso cuando hice los codigos para los PIC18 y dsPIC
Gracias KILLERJC voy a seguir probando y ya os contare, de momento necesito hacer una temporizacion de 5 seg para que se ejecute antes del inicio del programa.

Saludos!
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 20 de Diciembre de 2015, 18:55:53
Y sigo liado, estoy intentando una temporización de 5 segundos y no consigo que me funcione la interrupción en RB0 y no veo el porque ¿Podéis ayudarme?
Código: C
  1. #define _XTAL_FREQ 20000000
  2. #include <xc.h>
  3. //#include "config.h"
  4. #include <delays.h>
  5.  
  6. /*
  7.  *
  8.  */
  9.  
  10. // CONFIG1L
  11. #pragma config PLLDIV = 1       // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
  12. #pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
  13. #pragma config USBDIV = 1       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)
  14.  
  15. // CONFIG1H
  16. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator (HS))
  17. #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
  18. #pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
  19.  
  20. // CONFIG2L
  21. #pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
  22. #pragma config BOR = ON         // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
  23. #pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
  24. #pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)
  25.  
  26. // CONFIG2H
  27. #pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
  28. #pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)
  29.  
  30. // CONFIG3H
  31. #pragma config CCP2MX = ON      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
  32. #pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
  33. #pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
  34. #pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
  35.  
  36. // CONFIG4L
  37. #pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
  38. #pragma config LVP = OFF         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
  39. #pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
  40.  
  41. // CONFIG5L
  42. #pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
  43. #pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
  44. #pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
  45. #pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)
  46.  
  47. // CONFIG5H
  48. #pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
  49. #pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)
  50.  
  51. // CONFIG6L
  52. #pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
  53. #pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
  54. #pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
  55. #pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)
  56.  
  57. // CONFIG6H
  58. #pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
  59. #pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
  60. #pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM is not write-protected)
  61.  
  62. // CONFIG7L
  63. #pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
  64. #pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
  65. #pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
  66. #pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)
  67.  
  68. // CONFIG7H
  69. #pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)
  70.  
  71. unsigned char i=0;  //Variable usada en la temporizacion
  72.  
  73. void main(void)
  74. {
  75.     TRISBbits.RB0 = 1;  //Configuramos RB0 como entrada
  76.     TRISBbits.RB1 = 0;  //Configuramos RB3 como salida
  77.     LATB1 = 0;  //Robot parado
  78.    
  79.     //Configuramos INT0
  80.     INTCONbits.INT0IE = 1;  //Habilitamos interrupcion en RB0
  81.     INTCON2bits.INTEDG0 = 1;    //Flanco ascendente
  82.     INTCONbits.GIE = 1;     //Habilitamos todas las interrupciones
  83.    
  84. while(1){
  85.     //Iniciamos secuencia
  86.     if(INTCONbits.INT0IF == 1){
  87.         //Temporizamos 5seg antes del inicio del robot
  88.         for(i=0; i<=10; i++){
  89.             Delay10KTCYx(226);
  90.         INTCONbits.INT0IF = 0;  //Borramos flag de interrupcion en RB0
  91.         INTCONbits.INT0IE = 0;  //Desabilitamos interrupcion en RB0
  92.         INTCONbits.GIE = 0;     //Desabilitamos interrupciones
  93.         LATB1 = 1;  //Inicia escaneo
  94.         }
  95.     }else{
  96.         LATB1 = 0;  //Robot parado
  97.     }
  98. }
  99. }
Otro favor, alguien puede simularlo que a mi no me corre como debería la simulación y no sabré que tiempo a transcurrido cuando pongo a nivel alto RB1.

Gracias y perdón por las molestias.
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 20 de Diciembre de 2015, 19:10:21
Hola Miguel, ¿exactamente que es lo que deseas hacer?

No me gusta ese delay y como esta quedando el código (no quiero Criticarte ni nada por el estilo, no te lo tomes a mal), si me dices que quieres hacer,  puedo escribirte un codigo que haga lo que quieres.

Y ya lo modificas tu como quieras.

Te lo haría mañana, hoy ya no puedo, dime que micro estas usando, compilador, etc

Un saludo.
Título: Re:Mini curso "Programación en XC8"
Publicado por: sander en 20 de Diciembre de 2015, 19:24:00
Y sigo liado, estoy intentando una temporización de 5 segundos y no consigo que me funcione la interrupción en RB0 y no veo el porque ¿Podéis ayudarme?
Código: C
  1. #define _XTAL_FREQ 20000000
  2. #include <xc.h>
  3. //#include "config.h"
  4. #include <delays.h>
  5.  
  6. /*
  7.  *
  8.  */
  9.  
  10. // CONFIG1L
  11. #pragma config PLLDIV = 1       // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
  12. #pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
  13. #pragma config USBDIV = 1       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)
  14.  
  15. // CONFIG1H
  16. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator (HS))
  17. #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
  18. #pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
  19.  
  20. // CONFIG2L
  21. #pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
  22. #pragma config BOR = ON         // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
  23. #pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
  24. #pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)
  25.  
  26. // CONFIG2H
  27. #pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
  28. #pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)
  29.  
  30. // CONFIG3H
  31. #pragma config CCP2MX = ON      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
  32. #pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
  33. #pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
  34. #pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
  35.  
  36. // CONFIG4L
  37. #pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
  38. #pragma config LVP = OFF         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
  39. #pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
  40.  
  41. // CONFIG5L
  42. #pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
  43. #pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
  44. #pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
  45. #pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)
  46.  
  47. // CONFIG5H
  48. #pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
  49. #pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)
  50.  
  51. // CONFIG6L
  52. #pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
  53. #pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
  54. #pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
  55. #pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)
  56.  
  57. // CONFIG6H
  58. #pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
  59. #pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
  60. #pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM is not write-protected)
  61.  
  62. // CONFIG7L
  63. #pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
  64. #pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
  65. #pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
  66. #pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)
  67.  
  68. // CONFIG7H
  69. #pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)
  70.  
  71. unsigned char i=0;  //Variable usada en la temporizacion
  72.  
  73. void main(void)
  74. {
  75.     TRISBbits.RB0 = 1;  //Configuramos RB0 como entrada
  76.     TRISBbits.RB1 = 0;  //Configuramos RB3 como salida
  77.     LATB1 = 0;  //Robot parado
  78.    
  79.     //Configuramos INT0
  80.     INTCONbits.INT0IE = 1;  //Habilitamos interrupcion en RB0
  81.     INTCON2bits.INTEDG0 = 1;    //Flanco ascendente
  82.     INTCONbits.GIE = 1;     //Habilitamos todas las interrupciones
  83.    
  84. while(1){
  85.     //Iniciamos secuencia
  86.     if(INTCONbits.INT0IF == 1){
  87.         //Temporizamos 5seg antes del inicio del robot
  88.         for(i=0; i<=10; i++){
  89.             Delay10KTCYx(226);
  90.         INTCONbits.INT0IF = 0;  //Borramos flag de interrupcion en RB0
  91.         INTCONbits.INT0IE = 0;  //Desabilitamos interrupcion en RB0
  92.         INTCONbits.GIE = 0;     //Desabilitamos interrupciones
  93.         LATB1 = 1;  //Inicia escaneo
  94.         }
  95.     }else{
  96.         LATB1 = 0;  //Robot parado
  97.     }
  98. }
  99. }
Otro favor, alguien puede simularlo que a mi no me corre como debería la simulación y no sabré que tiempo a transcurrido cuando pongo a nivel alto RB1.

Gracias y perdón por las molestias.

Hola Miguel_S, tengo una duda, porque habilitas las interrupciones y revisas la bandera INTCONbits.INT0IF mediante un while, cuando quieres utilizar interrupciones tienes que trabajar mediante el vector de interrupcion , en el caso de la interrupcion por RB0 el vector de interrupciones de alta prioridad.
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 20 de Diciembre de 2015, 19:26:06
Exactamente, no queda claro que estas intentando hacer, te voy a explicar el por que no funciona tu codigo.

Tenes activada la interrupcion y no tenes funcion de interrupcion. No es que el simulador este funcionando mal, sino que el programa esta mal.

Tambien te falta ponerlos como digital, si das una mejor idea que tiene que hacer como dijo juanjo va a ser mas facil darte una solucion.

PD: esto intentaste hacer, eso si, 5s de delay es demasiado, se toma un buen tiempo la PC hasta llegar ahi haciendo nada.

Código: C
  1. void main(void)
  2. {
  3.     unsigned char i = 0;  //Variable usada en la temporizacion
  4.  
  5.     TRISBbits.RB0 = 1;  //Configuramos RB0 como entrada
  6.     TRISBbits.RB1 = 0;  //Configuramos RB1 como salida
  7.     ADCON1 = 0x0F;
  8.     LATB1 = 0;  //Robot parado
  9.  
  10.     //Configuramos INT0
  11.     INTCON2bits.INTEDG0 = 1;    //Flanco ascendente
  12.     INTCONbits.INT0IF = 0;
  13.  
  14.     while(1)
  15.     {
  16.         //Iniciamos secuencia
  17.         if(INTCONbits.INT0IF == 1)
  18.         {
  19.             //Temporizamos 5seg antes del inicio del robot
  20.             for (i=0;i<250;i++) __delay_ms(20);
  21.             INTCONbits.INT0IF = 0;  //Borramos flag de interrupcion en RB0
  22.             LATB1 = 1;  //Inicia escaneo
  23.         }
  24.         else
  25.         {
  26.             LATB1 = 0;  //Robot parado
  27.         }
  28.     }
  29. }
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 20 de Diciembre de 2015, 19:45:18
Gracias, tengo un compañero de mi hijo que se ha propuesto hacerse un minisumo y me pregunto si me gustaria echarle una mano con ello y eso es lo que intento, la temporización de 5 segundos es el tiempo de espera antes de que el robot empiece a moverse.
Hola Miguel, ¿exactamente que es lo que deseas hacer?

No me gusta ese delay y como esta quedando el código (no quiero Criticarte ni nada por el estilo, no te lo tomes a mal), si me dices que quieres hacer,  puedo escribirte un codigo que haga lo que quieres.

Y ya lo modificas tu como quieras.

Te lo haría mañana, hoy ya no puedo, dime que micro estas usando, compilador, etc

Un saludo.
Gracias Juan José por la intención y para nada me lo tomo a mal pero aunque sea con ayuda de ustedes tengo que intentar hacerlo yo mismo que si no no aprendo.

Nuevamente gracias a todos.
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 20 de Diciembre de 2015, 20:32:35
Citar
tengo que intentar hacerlo yo mismo que si no no aprendo

de acuerdo lo comprendo y eso te honra.

Bueno pues si no he entendido mal, lo que quieres hacer, es que al pulsar un pulsador el robot haga una espera de 5 segundos y empiece a moverse ¿no?

pues entonces te recomiendo, que te olvides de las interrupciones externas y que hagas una función por pulling y evitando rebotes para detectar la pulsación, así te quitas de encima las interrupciones externas y puedes elegir el pin que quieras.

para ello lo primero es hacer lo que dice killer, configurar los pines (Esto hay que hacerlo en casi todo los programas y de las primeras cosas).

Si esta espera no va a interferir en el resto del programa, puedes hacerla con delay_ms() y for como te indica killer y para el pulsador un while para que no pase de ahí hasta que se pulse, pero ojo, esto solo si no va a interferir con el resto del programa.

es decir si solo se va a ejecutar una vez, de lo contrario deberás evitar el uso de delay y de while.

prueba a hacerlo así (o si los compañeros tienen otra idea mas fácil) ¿Qué te parece?

un saludo.

Título: Re:Mini curso "Programación en XC8"
Publicado por: sander en 21 de Diciembre de 2015, 09:38:19
Gracias, tengo un compañero de mi hijo que se ha propuesto hacerse un minisumo y me pregunto si me gustaria echarle una mano con ello y eso es lo que intento, la temporización de 5 segundos es el tiempo de espera antes de que el robot empiece a moverse.
Hola Miguel, ¿exactamente que es lo que deseas hacer?

No me gusta ese delay y como esta quedando el código (no quiero Criticarte ni nada por el estilo, no te lo tomes a mal), si me dices que quieres hacer,  puedo escribirte un codigo que haga lo que quieres.

Y ya lo modificas tu como quieras.

Te lo haría mañana, hoy ya no puedo, dime que micro estas usando, compilador, etc

Un saludo.
Gracias Juan José por la intención y para nada me lo tomo a mal pero aunque sea con ayuda de ustedes tengo que intentar hacerlo yo mismo que si no no aprendo.

Nuevamente gracias a todos.

Si es como comenta, tambien puede poner un retardo siempre al inicio, y usar el reset como el pulsador de inicio, es decir cada vez que el micro se encienda, o resetee, 5 seg de espera y luego se ejecuta el programa principal. No tiene ni que usar interrupciones, ni configurar puertos :D, solamente dejar el reset habilitado
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 21 de Diciembre de 2015, 10:03:02
imagino que lo quiere aplicar a un boton, y que sea para comenzar la pelea. es decir entre que se presiona el boton que pasen 5 segundos y "choquen" ambos luchadores de sumo. Lo que no se es si necesita ademas que haga otra cosa dentro de esos 5s. Sino lo mas seguro es ir por interrupciones
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 21 de Diciembre de 2015, 12:48:47
Gracias de nuevo por sus respuestas, estos 5 segundos es tiempo de espera antes de iniciar la pelea el cual el robot  no hace nada mas que esperar que pasen los 5 segundos, por lo cual creo se puede hacer con un delay.

Saludos!
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 21 de Diciembre de 2015, 19:10:28
Avanzando pero poco a poco, de esta manera me funciona el inicio pero ¿Es la forma correcta de hacerlo?
Código: C
  1. #define _XTAL_FREQ 20000000
  2. #include <xc.h>
  3. #include "config.h"
  4. #include <delays.h>
  5.  
  6. /*
  7.  *
  8.  */
  9.  
  10. unsigned char i=0;  //Variable usada en la temporizacion
  11.  
  12. void main(void)
  13. {
  14. /* CONFIGURACION DE PINES */
  15.     ADCON1bits.PCFG3 = 1;   //Configuramos
  16.     ADCON1bits.PCFG2 = 1;   //RA0:RA1 analogicos
  17.     ADCON1bits.PCFG1 = 0;   //el resto de pines
  18.     ADCON1bits.PCFG0 = 1;   //digitales
  19.     TRISAbits.RA2 = 1;  //Configuramos RA2 como entrada
  20.     TRISAbits.RA3 = 0;  //Configuramos RA3 como salida
  21.     LATA3 = 0;  //Empezamos con el robot parado
  22.    
  23. /* COMPRUEBA PULSADOR Y DE SER LIBERADO EMPIEZA TEMPORIZACION */
  24.     while(1)
  25.     {
  26.         while(!PORTAbits.RA2 == 1)
  27.         {
  28.             //Bucle para delay de 5 segundos
  29.             for(i=0; i<=10; i++)
  30.             {
  31.                 Delay10KTCYx(226);
  32.             }
  33.             LATA3 = 1;  //Inicia el escaneo del tatami
  34.         }
  35.         LATA3 = 0;  //Robot parado
  36.     }
  37. }

Gracias.
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 21 de Diciembre de 2015, 20:51:50
Hola Miguel, no tengo la hoja de datos a mano (escribo desde el móvil), así que no me voy a meter si has configurado bien los pines.

Pero por ejemplo, primero (supongo que el pulsador tiene lógica positiva) el programa comienza, y estara poniendo el LATA3 a 0 constantemente hasta que se pulse el pulsador.

Este método no evita los rebotes por lo tanto, la pulsación deberá de durar menos de 5 segundos o volverá a entrar.

Cuando pulsas, se hace la espera, y se pone LATA3 a 1, lo malo es que inmediatamente después se pondrá a 0 al salir del bucle while y el robot se parara tan pronto como empiece a moverse. Por lo tanto te recomiendo el uso de banderas, para ir marcando cuando empieza a escanear, cuando termina etc.

Delay10KTCYx(226);

Esta instrucción no la había visto nunca, pero supongo que tu la conoces y la has calculado bien, pero veo mas intuitiva delay_ms().

Te recomiendo también meter la variable i dentro del main si no la vas a usar en otros ficheros.

Y que hagas un define para el pin RA2, le puedes llamar "pulsador" por ejemplo, luego s mas fácil para leer el código, por ejemplo el while seria:

while(!pulsador)

Estas últimas cosas solo son consejos pero que son de buena práctica.

Pero el problema del LATA3 debes arreglarlo.

Un saludo.




Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 21 de Diciembre de 2015, 22:01:21
Yo no voy a hablar del codigo todavia, solo voy a decir que no se puede darte una muy buena respuestas por que todavia no has especificado exactametne que debe hacer el robot. El estado que estabam si debe responder a algo mas, si debe repetirse eso la condicion de pelea mientras pasan por otras partes del programa, etc.
Hasta que no puedas definir exactamente todas las variables , condiciones, estados que puedas tener es imposible darte una solucion que finalmente satisfaga tu necesidad.

Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 22 de Diciembre de 2015, 05:42:52
Buenos días, vamos a intentar explicar la idea:
Una vez colocados los robots en el Dohyo (tatami) mantienes pulsado el switch de inicio hasta que se de el aviso para empezar el combate, momento en el cual se suelta el switch para empezar a contar los 5 segundos reglamentarios cosa que solo ocurre al principio de cada combate, motivo por el cual creo que esta temporización puede hacerse por delay ya que el robot no hace nada mas que esperar que pasen los 5 segundos. Una vez transcurridos los 5 segundos el robot debe empezar a moverse y intentar localizar al oponente a través de los sensores y una vez localizado empujarlo hasta sacarlo fuera del dohyo.
Delay10KTCYx(226);

Esta instrucción no la había visto nunca, pero supongo que tu la conoces y la has calculado bien, pero veo mas intuitiva delay_ms().
Hola Juan José te dejo como funciona dicha instrucción, no entiendo que quieres decir con que Cuando pulsas, se hace la espera, y se pone LATA3 a 1, lo malo es que inmediatamente después se pondrá a 0 al salir del bucle while y el robot se parara tan pronto como empiece a moverse ¿No puede estar todo el código dentro de dicho bucle? con el código que he dejado en el post anterior y colocando un led en el lugar del motor una vez transcurrido el tiempo de espera dicho led se enciende y no vuelve a apagarse hasta que no quitas la alimentación al circuito.
Voy a seguir tus consejos con los defines y la variable.

Gracias.
 - Tienes que ingresar para ver archivos adjuntos -
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 22 de Diciembre de 2015, 08:58:58
hola miguel, puedes meter todo en el bucle while, pero eso no es una forma adecuada de hacer las cosas, recuerda, que funcione no quiere decir que este bien.

te recomiendo que pienses en tu sistema como una maquina de estados y no de una forma secuencial. Es como están pensados muchisimos programas, y por ejemplo si utilizas las harmony para generar el código, te crea automaticamente una maquina de estados.

te ayuda a estructurar la manera de pensar y te puede ayudar a hacerte una mejor idea, y ha utilizar las banderas para cambiar de los estados, mediante condiciones if o switch case.

el robot siempre debe de estar en un estado.

(lo he hecho en paint xd :D :D, y ademas de manera muy resumida con solo 3 estados)

 - Tienes que ingresar para ver archivos adjuntos -

Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 22 de Diciembre de 2015, 11:13:09
Bueno cambio un poco el panorama, ahora decis que cuando se suelte espere los 5s. Esto puede traer aparejado un par de problemas por los rebotes, por que se toca y se suelta etc.

La forma de hacerlo con un delay va a implicar que apenas se detecte un cambio peuda dispararse el tema del robot, imaginate un menor teniendo el boton que se mueve de un lado para el otro y que por ahi el boton no haga contacto como debe podria suceder. y deberia reiniciarse el tiempo. Si se presiona nuevamente dentro de los 5 segundos que pasaria ?
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 22 de Diciembre de 2015, 11:58:26
Gracias a los dos, a seguir estudiando y buscar la manera de hacerlo para que funcione correctamente, en un principio el arranque, pero si eso ya se me complica no quiero ni pensar el la estrategia del combate.

Saludos!
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 22 de Diciembre de 2015, 12:08:24
Gracias a los dos, a seguir estudiando y buscar la manera de hacerlo para que funcione correctamente, en un principio el arranque, pero si eso ya se me complica no quiero ni pensar el la estrategia del combate.

Saludos!

los primeros pasos son dificiles, luego se te va haciendo la forma de pensar y te va resultando cada vez mas facil, animo ;-)
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 23 de Diciembre de 2015, 05:49:13
te recomiendo que pienses en tu sistema como una maquina de estados y no de una forma secuencial. Es como están pensados muchisimos programas, y por ejemplo si utilizas las harmony para generar el código, te crea automaticamente una maquina de estados.
Estoy empezando a mirar lo de las maquinas de estado y se ve una cosa interesante, había oído sobre ellas pero nunca hacer uso de ellas, lo de las harmony podéis aconsejarme algún software para probar.

Gracias.
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 23 de Diciembre de 2015, 07:23:53
Perdona Miguel me explique mal, lo de las harmony era solo un ejemplo, creo que de momento solo se pueden usar en pic32, pero nada te impide hacer un ejemplo con xc32 y harmony y estudiarlo, aunque no te lo recomiendo porque es un generador de código y ya sabemos lo que pasa con eso, además la maquina de estados que hace es muy liosa hay muchas mas maneras de hacer una maquina de estados.

Hay muchos ejemplos sencillitos, si quieres puedo buscarte algún ejemplo o hacerte algún ejemplo para que lo veas.

Una maquina de estados compleja, lleva muchas veces el uso de tablas y normas para no dejarte ninguna condicion ni estado. Pero es una muy buena técnica de programación para muchos casos.

Un saludo
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 23 de Diciembre de 2015, 09:14:40
Precisamente lo preguntaba porque solo habia encontrado para XC32, de todos modos voy a estudiarme lo de la maquina de estados y buscar ejemplos.

Gracias.
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 25 de Diciembre de 2015, 15:21:59
Hola estoy intentando lo de la maquina de estados finitos y no me funciona y no consigo ver el porque:
Código: C
  1. #define _XTAL_FREQ 20000000
  2. #include <xc.h>
  3. #include "config.h"
  4. #include <delays.h>
  5.  
  6. #define pulsador_ini   PORTAbits.RA2  //pulsador_ini conectado en RA2
  7. #define motor_izq   PORTAbits.RA3  //motor izquierdo conectado en RA3
  8. #define motor_dcho  PORTAbits.RA4  //motor derecho conectado en RA4
  9.  
  10. /* DECLARACION DE FUNCIONES */
  11. void pausa_5seg(void);
  12.  
  13. /* ENUMERAMOS LOS TIPOS DE ESTADOS */
  14. enum eEstados{
  15.     Detenido,Inicio
  16. }estado;
  17.  
  18. /* FUNCION PRINCIPAL */
  19. void main(void)
  20. {
  21. /* CONFIGURACION DE PINES */
  22.     ADCON1bits.PCFG3 = 1;   //Configuramos
  23.     ADCON1bits.PCFG2 = 1;   //RA0:RA1 analogicos
  24.     ADCON1bits.PCFG1 = 0;   //el resto de pines
  25.     ADCON1bits.PCFG0 = 1;   //digitales
  26.     TRISAbits.RA2 = 1;  //Configuramos RA2 como entrada
  27.     TRISAbits.RA3 = 0;  //Configuramos RA3 como salida
  28.     TRISAbits.RA4 = 0;  //Configuramos RA4 como salida
  29.    
  30.     //estado = Detenido;  //Empezamos con el robot parado
  31.    
  32.     while(1)
  33.     {
  34.         switch(estado)
  35.         {
  36.             case Detenido:
  37.                 if(pulsador_ini == 0){
  38.                 motor_izq = 0;
  39.                 motor_dcho = 0;
  40.                 }
  41.             break;
  42.                
  43.             case Inicio:
  44.                 if(pulsador_ini){
  45.                     pausa_5seg();
  46.                 }
  47.                 motor_izq = 1;
  48.                 motor_dcho = 1;
  49.             break;
  50.         }
  51.     }
  52. }
  53.  
  54. void pausa_5seg(void){
  55.     unsigned char i = 0;
  56.     for(i=0; i<=10; i++){
  57.         Delay10KTCYx(226);
  58.     }
  59. }

Gracias.
Título: Re:Mini curso "Programación en XC8"
Publicado por: sander en 25 de Diciembre de 2015, 16:39:41
Hola estoy intentando lo de la maquina de estados finitos y no me termina de funcionar como debería, con este código:
Código: C
  1. #define _XTAL_FREQ 20000000
  2. #include <xc.h>
  3. #include "config.h"
  4. #include <delays.h>
  5.  
  6. #define pulsador_ini   PORTAbits.RA2  //pulsador_ini conectado en RA2
  7. #define motor_izq   PORTAbits.RA3  //motor izquierdo conectado en RA3
  8. #define motor_dcho  PORTAbits.RA4  //motor derecho conectado en RA4
  9.  
  10. /* ENUMERAMOS LOS TIPOS DE ESTADOS */
  11. enum eEstados{
  12.     Detenido
  13. }estado;
  14.  
  15. /* FUNCION PRINCIPAL */
  16. void main(void)
  17. {
  18.     unsigned char i=0;  //Variable usada en la temporizacion de 5 segundos
  19.    
  20. /* CONFIGURACION DE PINES */
  21.     ADCON1bits.PCFG3 = 1;   //Configuramos
  22.     ADCON1bits.PCFG2 = 1;   //RA0:RA1 analogicos
  23.     ADCON1bits.PCFG1 = 0;   //el resto de pines
  24.     ADCON1bits.PCFG0 = 1;   //digitales
  25.     TRISAbits.RA2 = 1;  //Configuramos RA2 como entrada
  26.     TRISAbits.RA3 = 0;  //Configuramos RA3 como salida
  27.     TRISAbits.RA4 = 0;  //Configuramos RA4 como salida
  28.    
  29.     estado = Detenido;  //Empezamos con el robot parado
  30.    
  31.     while(1)
  32.     {
  33.         switch(estado)
  34.         {
  35.             case Detenido:
  36.                 if(pulsador_ini)
  37.                 {
  38.                     for(i=0; i<=10; i++)
  39.                     {
  40.                         Delay10KTCYx(226);
  41.                     }
  42.                         motor_izq = 1;
  43.                         motor_dcho = 1;
  44.                 }else{
  45.                     motor_izq = 0;
  46.                     motor_dcho = 0;
  47.                 }
  48.             break;
  49.            
  50.             default:
  51.                 Detenido;
  52.                 break;
  53.         }
  54.     }
  55. }
me pasa que si antes de alimentar el circuito mantengo pulsado el switch de inicio y después lo alimento, hasta que no lo dejo de pulsar los motores permanecen parados, pero si doy corriente al circuito sin mantener el pulsador los motores se alimentan al momento como si entrara en el if pero sin contar los 5 segundos, y lo siento pero no veo el error.

Gracias.

Ha probado con apagar los motores antes de entrara al ciclo while(1), es decir antes de entrar el while poner
 motor_izq = 0;
 motor_dcho = 0;

los pines del micro no empiezan necesariamente en cero.

Por cierto, si esta usando un PIC18F debe utilizar el registro LATA si los pines estan configurados como salida

Saludos,
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 25 de Diciembre de 2015, 17:02:07
Hola sander lo siento pero te has dado mas prisa tu en contestar que yo modificar el codigo  :D ahora estoy probando este codigo pero ni siquiera enciende los led's que tengo conectados en el lugar de los motores.

Código: C
  1. #define _XTAL_FREQ 20000000
  2. #include <xc.h>
  3. #include "config.h"
  4. #include <delays.h>
  5.  
  6. #define pulsador_ini   PORTAbits.RA2  //pulsador_ini conectado en RA2
  7. #define motor_izq   LATA3  //motor izquierdo conectado en RA3
  8. #define motor_dcho  LATA4 //motor derecho conectado en RA4
  9.  
  10. /* DECLARACION DE FUNCIONES */
  11. void pausa_5seg(void);
  12.  
  13. /* ENUMERAMOS LOS TIPOS DE ESTADOS */
  14. enum eEstados{
  15.     Detenido,Inicio
  16. }estado;
  17.  
  18. /* FUNCION PRINCIPAL */
  19. void main(void)
  20. {
  21. /* CONFIGURACION DE PINES */
  22.     ADCON1bits.PCFG3 = 1;   //Configuramos
  23.     ADCON1bits.PCFG2 = 1;   //RA0:RA1 analogicos
  24.     ADCON1bits.PCFG1 = 0;   //el resto de pines
  25.     ADCON1bits.PCFG0 = 1;   //digitales
  26.     TRISAbits.RA2 = 1;  //Configuramos RA2 como entrada
  27.     TRISAbits.RA3 = 0;  //Configuramos RA3 como salida
  28.     TRISAbits.RA4 = 0;  //Configuramos RA4 como salida
  29.    
  30.     //estado = Detenido;  //Empezamos con el robot parado
  31.    
  32.     while(1)
  33.     {
  34.         switch(estado)
  35.         {
  36.             case Detenido:
  37.                 if(pulsador_ini == 0){
  38.                 motor_izq = 0;
  39.                 motor_dcho = 0;
  40.                 }
  41.             break;
  42.                
  43.             case Inicio:
  44.                 if(pulsador_ini){
  45.                     pausa_5seg();
  46.                 }
  47.                 motor_izq = 1;
  48.                 motor_dcho = 1;
  49.             break;
  50.         }
  51.     }
  52. }
  53.  
  54. void pausa_5seg(void){
  55.     unsigned char i = 0;
  56.     for(i=0; i<=10; i++){
  57.         Delay10KTCYx(226);
  58.     }
  59. }

Saludos!
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 25 de Diciembre de 2015, 17:14:11
hola miguel:

prueba esto:

Código: [Seleccionar]
#define _XTAL_FREQ 20000000
#include <xc.h>
#include "config.h"
#include <delays.h>
 
#define pulsador_ini   PORTAbits.RA2  //pulsador_ini conectado en RA2
#define motor_izq   LATAbits.LA3  //motor izquierdo conectado en RA3
#define motor_dcho  LATAbits.LA4  //motor derecho conectado en RA4
 
/* DECLARACION DE FUNCIONES */
void pausa_5seg(void);
 
/* ENUMERAMOS LOS TIPOS DE ESTADOS */
enum eEstados{
    Detenido,Inicio,Espera
}estado;
 
/* FUNCION PRINCIPAL */
void main(void)
{
/* CONFIGURACION DE PINES */
    estado = Detenido;  //Empezamos con el robot parado
    ADCON1bits.PCFG3 = 1;   //Configuramos
    ADCON1bits.PCFG2 = 1;   //RA0:RA1 analogicos
    ADCON1bits.PCFG1 = 0;   //el resto de pines
    ADCON1bits.PCFG0 = 1;   //digitales
    TRISAbits.RA2 = 1;  //Configuramos RA2 como entrada
    TRISAbits.RA3 = 0;  //Configuramos RA3 como salida
    TRISAbits.RA4 = 0;  //Configuramos RA4 como salida
   
    while(1)
    {
        switch(estado)
        {
            case Detenido:
            {
                motor_izq = 0;
                motor_dcho = 0;
                if(pulsador_ini == 1)
                {
                    estado = Espera;
                }
            }
            break;
            case Espera:
            {
                pausa_5seg();
                estado=Inicio;
            }
            break;
            case Inicio:
            {
                motor_izq = 1;
                motor_dcho = 1;
            }
            break;
        }
    }
}
 
void pausa_5seg(void){
    unsigned char i = 0;
    for(i=0; i<=10; i++){
        Delay10KTCYx(226);
    }
}


no se te encienden los led por que estabas utilizando porta y no lata, ademas, el compilador si no la inicializacion del estado al principio hace cosas raras.A ver si asi te funciona

un saludo
Título: Re:Mini curso "Programación en XC8"
Publicado por: Miquel_S en 25 de Diciembre de 2015, 18:15:45
Gracias Juan José me has abierto los ojos, ahora tengo mas claro como implementar la maquina de estados. Perdón una pregunta ¿Si usamos la instrucción switch debemos seguir el mismo orden que seguiríamos en el diagrama de la maquina de estados, o sea un estado detrás de otro?
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 25 de Diciembre de 2015, 18:24:39
Gracias Juan José me has abierto los ojos, ahora tengo mas claro como implementar la maquina de estados. Perdón una pregunta ¿Si usamos la instrucción switch debemos seguir el mismo orden que seguiríamos en el diagrama de la maquina de estados, o sea un estado detrás de otro?

no ni mucho menos, al igual que si lo implementaras con if, el código entrará en el case que corresponda. por lo tanto puedes poner el primer case el "inicio", el segundo "Detenido" y el tercero "Espera" por ejemplo, lo importante es que no haya incongruencia en las condiciones, ni posibilidad de que ejecute dos estados "al mismo tiempo".

esta es solo una manera de hacer una maquina de estados puedes implementarla de otras maneras como por ejemplo usando if-else.

ya lo que a ti te venga mejor.

un saludo
Título: Re:Mini curso "Programación en XC8"
Publicado por: lmtreser en 08 de Enero de 2016, 00:02:46
Volví !!! Totalmente alejado del XC8 retome un poco el tema. Estuve leyendo y googleando y estoy medio perdido con el tema de librerías. De forma oficial Microchip lanzo algún paquete con LCD, I2C, SPI, 1-Wire, Modbus, USB????

Por el momento estoy jugando con un RTC DS1307 y un sensor DS18B20, y no encuentro mucha información. Estoy buscando mal, o hay que laburar para implementar estos dispositivos?

Saludos y buen año!!!
Título: Re:Mini curso "Programación en XC8"
Publicado por: Rseliman en 09 de Enero de 2016, 09:39:15
Hola Como estas , no he probado ninguno de los dos , pero googleando me he encontrado con cosas para los dos dispositivos , el 1307 se lee con I2C si mal no recuerdo , tengo unas librerias andando para pic16 de i2c ..con las cuales manejaba un bmp085 , es mas creo que nadan por aca por el foro dando vueltas , y del 18b20 estoy seguro de haber visto info en google , si encuentro algo te lo envio o lo posteo

Saludos



Volví !!! Totalmente alejado del XC8 retome un poco el tema. Estuve leyendo y googleando y estoy medio perdido con el tema de librerías. De forma oficial Microchip lanzo algún paquete con LCD, I2C, SPI, 1-Wire, Modbus, USB????

Por el momento estoy jugando con un RTC DS1307 y un sensor DS18B20, y no encuentro mucha información. Estoy buscando mal, o hay que laburar para implementar estos dispositivos?

Saludos y buen año!!!
Título: Re:Mini curso "Programación en XC8"
Publicado por: juaperser1 en 09 de Enero de 2016, 09:50:20
Citar
De forma oficial Microchip lanzo algún paquete con LCD, I2C, SPI, 1-Wire, Modbus, USB????

De capa física vas a encontrar de todos sus periféricos, es decir, de i2c, usb, spi etc.
pero de modbus y otros protocolos de comunicación no vas a encontrar nada oficial, a no ser que sea propiedad de microchip.

Un saludo
Título: Re:Mini curso "Programación en XC8"
Publicado por: lmtreser en 09 de Enero de 2016, 11:39:18
Usando una rutina I2C que encontré ya puse en marcha el DS1307. Cuando depure el código lo comparto. Saludos!
Título: Re:Mini curso "Programación en XC8"
Publicado por: c@Lic_0 en 20 de Febrero de 2016, 13:58:17
Buenos Dias, si alguien me puede ayudar estoy usando la verasion 1.36 del XC8, y al agregar la libreria del SPI:

#include <spi.h>

me aparece marcado como error, entro en el disco C: donde tengo instalado el xc8, especificamente a la carpeta include, y efectivamente no se encuentra el archivo spi.h, buscando en internet, encontre que estas librerias estan en la carpeta >include>plib, ahi deberia de estar el archivo spi.h, pero no tengo la carpeta plib instalada.

No se si el XC8 se instalo mal o cual es el error que estoy cometiendo

De antemano gracias por su ayuda.
 
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 20 de Febrero de 2016, 14:13:58
Las plib vienen por defecto en XC8. No estoy muy seguro si es que xc.h te las agrega solo, sino intenta agregar plib.h
Título: Re:Mini curso "Programación en XC8"
Publicado por: elvisnoria en 21 de Febrero de 2016, 18:26:00
Buenas, soy un novato en esto y necesito su ayuda en una práctica simulada en proteus. tengo que hacer que el pic me genere una frecuencia de 25KHz como salida en un pin. Tengo que usar un pic16f887.

Me he informado en paginas web y veo que es un largo proceso y no manejo muy bien lo de los registros del pic y esas cosas. el pic que tengo.

Alguien podria ayudarme?
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 21 de Febrero de 2016, 20:24:17
Buenas, soy un novato en esto y necesito su ayuda en una práctica simulada en proteus. tengo que hacer que el pic me genere una frecuencia de 25KHz como salida en un pin. Tengo que usar un pic16f887.

Me he informado en paginas web y veo que es un largo proceso y no manejo muy bien lo de los registros del pic y esas cosas. el pic que tengo.

Alguien podria ayudarme?

Utiliza el ejemplo de un led pero cambiarle el delay a un valor de 39/40 microsegundos. Y tenes tu programa, darte mas seria hacerte el proyecto por vos.

http://www.todopic.com.ar/foros/index.php?topic=40649.msg338216#msg338216

Es decir usa __delay_us(29) , en ves de __delay_ms()

Un PIC16F887 tiene mas registros.. y tenes que configurarlos, te sugiero que leas el datasheet del PIC en el puerto que deseas usar. Y seguro lo tenes funcionando.
Título: Re:Mini curso "Programación en XC8"
Publicado por: jorge garcia en 29 de Febrero de 2016, 21:38:53
Muy interesante tu minicurso, recién estoy aprendiendo a programar en C y el compilador que tengo es el Mikro C pro for PIC. Cómo puedo saber que instrucciones acepta y cuáles no.
Gracias por tu tiempo y tu respuesta. Saludos amigo
Jorge
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 29 de Febrero de 2016, 21:46:20
Consejo, si comenzas para mi lo mejor es XC8. Por que vas a aprender a manejar registro por registro lo que es el PIC, y lo demas es aprender C. O mejor dicho, si lees el datasheet, el mismo te indica paso a paso que registros tenes que modificar para activar un modulo y se traduce casi literalmente ese "paso a paso" a XC8.

En cambio mikro C / CCS tienen funciones incluidas dentro del compilador, y tenes que estar con un manual al lado hasta que aprendes cada una. Esto no quita que puedas hacer o tengas las mismas funciones en XC8. Ademas XC8 es gratuito y soporta todos los micros. XC8 usa el IDE: MPLAB X.

Si aun asi quisieras seguir con Mikro C, deberias ir a la pagina del compilador y buscar el manual de las funciones que soporta.
Con respecto a C, es comun a todos, es decir los for/while/if, como declarar varaibles, funciones, etc. Todo eso es comun a C.
Título: Re:Mini curso "Programación en XC8"
Publicado por: NIN en 07 de Mayo de 2016, 23:55:44
Buenas noches. Soy un novato . Ya realize muchos de los ejemplos que realizaron al principio. Gracias a todos. Ayudan un monton.

Ahora bien. Quiero realizar Un PWM pero no quiero usar las librerias, sino hacerlo desde los registros.

Los datos son los siguientes:

Frecuencia de oscilacion = 4MHz
Periodo de oscilacion = 0.25us
Duty_cicle= 250
Prescale = 16
PR2 = 124

Ya realize los calculos, Es para obtener un PWM : Periodo =2ms; Duty_cicle = 1ms. Algo asi :
   _______
   |           |
   |           |
   |           |
   |           |______
   
   <-DC->
   <----Periodo--->

...

Quiero mostrarles el codigo que realize (despues de mucho esfuerzo, lo tengo que admitir), sin embargo todavia no puedo generar la salida PWM:

Código: [Seleccionar]
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <pic16f88.h>

#pragma config FOSC = HS  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

void main ()
{
   
     while (1)
     {
         TRISB &= ~(1 << 3); /*limpiar bit RB3/CCP1 en TRISB, hacer PORTB3/CCP1 como salida*/
            CCP1CON = 0x2C; /*activar PWM */
            PR2 = 0x7C;    /*124 (DECIMAL)*/
            T2CON = 0X06; /*prescale 16 */
            CCPR1L = 0X3E;
           
     }   
}

Todavia no me sale. Yo se que hay varios ejemplos (incluso en este post hay uno) sin embargo quiero saber porque el mio todavia no sale.

Agradeceria muchisimo alguna ayuda que me puedan dar. Ya no se que hacer.



Sinceramente
NIN.

Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 08 de Mayo de 2016, 02:30:57
Empecemos primero por la forma del programa, Voy a escribir masomenos como estan formados todos los main.c:


Código: C
  1. // Aca los #include
  2.  
  3. // Aca los FUSES
  4.  
  5. // Prototipos de funciones y variables
  6.  
  7. void main(void)
  8. {
  9.         // Aca la configuracion de cada modulo que se vaya a usar
  10.  
  11.         while(1)                // Loop infinito, el unico loop infinito que hay en todo el programa.
  12.         {
  13.                 //Aca el programa en cuestion
  14.         }
  15. }
  16.  
  17. // Otras funciones si es que es el caso

Ahora vamos adentro de la funcion main y veamos como quedaria el codigo:

El CCP del PIC16F88 utiliza el timer 2, si observas al final de la parte de PWM ahi estan TODOS los regsotrs y bits que estan involucrados con el PWM, algunos registros solo tiene 1 bit como es PIE1 por ejemplo que corresponde al PWM. Voy a usar valores obtenidos de una calculadora online. Igual lo explico en el comentario, si tenes alguna duda podes ver el diagrama del PWM, observa que solo basta configurar el PWM y darle arranque al TMR2, luego de ahi no tenes que hacer mas nada.


Código: C
  1. void main(void)
  2. {
  3.  
  4.         //Aca configuracion de modulos
  5.  
  6.         // Puertos
  7.  
  8.         TRISB = 0;              // Todas salidas por ahora nomas, la salida PWM puede estar en RB0 o RB3 segun el fuse que se elija.
  9.         PORTB = 0;              // Apagamos todos
  10.  
  11.  
  12.         // CCP
  13.  
  14.         CCP1CON = 0x1C;         // En PWM, y los ultimos 2 bits ( de los 10 del duty ) es 01
  15.         PR2 = 0x7C;             // Periodo va estar dado por PR2, y como este el timer2 configurado, 0x7C = 124, pero se crea virtualmente 2 bits mas, resultado periodo igual a 496
  16.         T2CON = 0x07;           // T2CON, postscaler = 1, prescaler = 16, TMR2 ON. Periodo : (PR2+1)*4*Tosc*(Prescaler) = (124+1)*4*Tosc*16 = 8000 * 0.250us = 2ms
  17.         CCPR1L = 0x3E;          // Valor real de duty que con los 2 bits del CCP1CON es 0xF9 = 249, virtualmente el PWM hace llegar al timer hasta 496, un duty de 50% 496 * 0.5 = 248
  18.  
  19.         while(1)
  20.         {
  21.         }
  22.  
  23. }


2 cosas mas, usa FOSC = XT para 4Mhz o menos y HS para cuando tenes mas de 4Mhz, y... no hace falta que agregues tantos includes, con el de xc.h se agrega el del pic16f88 por si solo. es decir solo necesitas este include:

Código: C
  1. #include <xc.h>

Aunque a veces da problemas igual..

Y el MPLAB X tiene una forma facil de generar codigo para crearte los fuses
Título: Re:Mini curso "Programación en XC8"
Publicado por: NIN en 08 de Mayo de 2016, 22:12:50
Empecemos primero por la forma del programa, Voy a escribir masomenos como estan formados todos los main.c:


Código: C
  1. // Aca los #include
  2.  
  3. // Aca los FUSES
  4.  
  5. // Prototipos de funciones y variables
  6.  
  7. void main(void)
  8. {
  9.         // Aca la configuracion de cada modulo que se vaya a usar
  10.  
  11.         while(1)                // Loop infinito, el unico loop infinito que hay en todo el programa.
  12.         {
  13.                 //Aca el programa en cuestion
  14.         }
  15. }
  16.  
  17. // Otras funciones si es que es el caso

Ahora vamos adentro de la funcion main y veamos como quedaria el codigo:

El CCP del PIC16F88 utiliza el timer 2, si observas al final de la parte de PWM ahi estan TODOS los regsotrs y bits que estan involucrados con el PWM, algunos registros solo tiene 1 bit como es PIE1 por ejemplo que corresponde al PWM. Voy a usar valores obtenidos de una calculadora online. Igual lo explico en el comentario, si tenes alguna duda podes ver el diagrama del PWM, observa que solo basta configurar el PWM y darle arranque al TMR2, luego de ahi no tenes que hacer mas nada.


Código: C
  1. void main(void)
  2. {
  3.  
  4.         //Aca configuracion de modulos
  5.  
  6.         // Puertos
  7.  
  8.         TRISB = 0;              // Todas salidas por ahora nomas, la salida PWM puede estar en RB0 o RB3 segun el fuse que se elija.
  9.         PORTB = 0;              // Apagamos todos
  10.  
  11.  
  12.         // CCP
  13.  
  14.         CCP1CON = 0x1C;         // En PWM, y los ultimos 2 bits ( de los 10 del duty ) es 01
  15.         PR2 = 0x7C;             // Periodo va estar dado por PR2, y como este el timer2 configurado, 0x7C = 124, pero se crea virtualmente 2 bits mas, resultado periodo igual a 496
  16.         T2CON = 0x07;           // T2CON, postscaler = 1, prescaler = 16, TMR2 ON. Periodo : (PR2+1)*4*Tosc*(Prescaler) = (124+1)*4*Tosc*16 = 8000 * 0.250us = 2ms
  17.         CCPR1L = 0x3E;          // Valor real de duty que con los 2 bits del CCP1CON es 0xF9 = 249, virtualmente el PWM hace llegar al timer hasta 496, un duty de 50% 496 * 0.5 = 248
  18.  
  19.         while(1)
  20.         {
  21.         }
  22.  
  23. }


2 cosas mas, usa FOSC = XT para 4Mhz o menos y HS para cuando tenes mas de 4Mhz, y... no hace falta que agregues tantos includes, con el de xc.h se agrega el del pic16f88 por si solo. es decir solo necesitas este include:

Código: C
  1. #include <xc.h>

Aunque a veces da problemas igual..

Y el MPLAB X tiene una forma facil de generar codigo para crearte los fuses

Muchisimas gracias KILLER. Exactamente este era el tipo de respuesta que queria. Que no modificara tanto mi programa y saber cuales eran mis errores.

Quisiera que me ayudes en mi camino, porque te puedo asegurar que voy a tener muchisimas dudas con este aprendizaje

Sinceramente
NIN.
Título: Re:Mini curso "Programación en XC8"
Publicado por: NIN en 26 de Junio de 2016, 22:45:42
Buenas noches. Esta pregunta es muy basica pero en serio no me sale la compilacion. Vamos por un programa simple para que se entienda.

Tengo este programa que prende el led mediante un funcion llamada " prender" :

Código: [Seleccionar]
#include <xc.h>

#define _XTAL_FREQ 10000

#pragma config WDTE = OFF
#pragma config FOSC = XT
#pragma config CCPMX = RB0

void prender ()
{
    PORTBbits.RB1 = 1;
   
}
void main()
{
    TRISB = 0b00000001;
    PORTB = 0b00000001;
   
   
        while (PORTBbits.RB0 == 1)
        {
            prender();
        }
   
}

Funciona perfectamente.

Ahora supongamos que quiero realizar mi propia libreria externa llamada "prender" hago los siguiente:

Creo mi libreria llamada "prender.h", y esta tiene una funcion llamada "luz" (para que prenda el led)

 - Tienes que ingresar para ver archivos adjuntos -

A su vez llamo a esta libreria desde el programa principal con el "#include<prender.h>":

 - Tienes que ingresar para ver archivos adjuntos -

pero me sale error de compilacion. Que podria hacer para eliminar ese error.Muchas gracias.

Sinceramente NIN.



Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 26 de Junio de 2016, 22:58:49
main.c
Código: C
  1. #include <xc.h>
  2. #include "prender.h"
  3.  
  4. #pragma config WDTE = OFF
  5. #pragma config FOSC = XT
  6. #pragma config CCPMX = RB0
  7.  
  8. void main()
  9. {
  10.     TRISB = 0b00000001;
  11.     PORTB = 0b00000001;
  12.    
  13.    
  14.         while (PORTBbits.RB0 == 1)
  15.         {
  16.             Luz();
  17.         }
  18. }

prender.h
Código: C
  1. #ifndef PRENDER_H
  2. #define PRENDER_H
  3.  
  4. void luz(void);
  5.  
  6. #endif // PRENDER_H

prender.c
Código: C
  1. #include <xc.h>
  2. #include "prender.h"
  3.  
  4. void Luz(void)
  5. {
  6.       PORTBbits.RB1 = 1;
  7. }

Primero que nada no poner codigo en los .h, aunque se puede hacer.
Pusiste la parte del .h dentro de la seccion para C++, cosa que no se usa en XC8, podras observar que yo no lo puse en mi .h. Si sacaras tu codigo afuera funcionaria, pero violaria lo de antes.
Otra cosa mas, es que inclui en el prender.c a xc.h nuevamente, para poder usar el "PORTBbits"
Título: Re:Mini curso "Programación en XC8"
Publicado por: NIN en 27 de Junio de 2016, 05:28:13
main.c
Código: C
  1. #include <xc.h>
  2. #include "prender.h"
  3.  
  4. #pragma config WDTE = OFF
  5. #pragma config FOSC = XT
  6. #pragma config CCPMX = RB0
  7.  
  8. void main()
  9. {
  10.     TRISB = 0b00000001;
  11.     PORTB = 0b00000001;
  12.    
  13.    
  14.         while (PORTBbits.RB0 == 1)
  15.         {
  16.             Luz();
  17.         }
  18. }

prender.h
Código: C
  1. #ifndef PRENDER_H
  2. #define PRENDER_H
  3.  
  4. void luz(void);
  5.  
  6. #endif // PRENDER_H

prender.c
Código: C
  1. #include <xc.h>
  2. #include "prender.h"
  3.  
  4. void Luz(void)
  5. {
  6.       PORTBbits.RB1 = 1;
  7. }

Primero que nada no poner codigo en los .h, aunque se puede hacer.
Pusiste la parte del .h dentro de la seccion para C++, cosa que no se usa en XC8, podras observar que yo no lo puse en mi .h. Si sacaras tu codigo afuera funcionaria, pero violaria lo de antes.
Otra cosa mas, es que inclui en el prender.c a xc.h nuevamente, para poder usar el "PORTBbits"

Como siempre Killer muchisimas gracias. Las cosas que me cuesta demasiado hacer tu me ayudas un monton. Habia buscado muchisimo como hacer tengo varios dias intentandolo y tu me ayudas demasiado.

Sinceramente NIN
Título: Medidor de distancia HC-SR04 y 5110 nokia
Publicado por: Rseliman en 01 de Julio de 2016, 19:06:15
Hola Amigos , hace un tiempo que no escribo nada por aca , estuve haciendo unas pruebas con un HC_SR04 y un 5110 en xc8 y como no hay nada sobre estos dos temas en la red , queria compartirlo con UDS !!! espero les sirva use un pic 16f648 ...

Saludos a todos

Código: [Seleccionar]
user.h

void LCDWrite(unsigned char data_or_command, unsigned char data);
void gotoXY(int x, int y);
void LCDBitmap(char my_array[]);
void LCDCharacter(char character);
void LCDString(char *characters);
void LCDClear(void);
void LCDInit(void) ;
void LCDNumero(long num );
const unsigned char ramiro[];

void InitApp(void);         /* I/O and Peripheral Initialization */


Código: [Seleccionar]
user.c

/*
 * File:   user.c
 * Author: Ramiro
 *
 * Created on 20 de junio de 2016, 9:44
 */

/******************************************************************************/
/* Files to Include                                                           */
/******************************************************************************/

#if defined(__XC)
    #include <xc.h>         /* XC8 General Include File */
#elif defined(HI_TECH_C)
    #include <htc.h>        /* HiTech General Include File */
#endif

#include <stdint.h>         /* For uint8_t definition */
#include <stdbool.h>
#include <pic16f628a.h>        /* For true/false definition */

#include "user.h"

/******************************************************************************/
/* User Functions                                                             */
/******************************************************************************/

#define LCD_CLK PORTBbits.RB5
#define LCD_DIN PORTBbits.RB4
#define LCD_DC PORTBbits.RB3
#define LCD_CE PORTBbits.RB2
#define LCD_RST PORTBbits.RB7


//The DC pin tells the LCD if we are sending a command or data
#define LCD_COMMAND 0
#define LCD_DATA  1

//You may find a different size screen, but this one is 84 by 48 pixels
#define LCD_X     84
#define LCD_Y     48

//------------------------------------------------------------------------------
// File generated by LCD Assistant
// http://en.radzio.dxp.pl/bitmap_converter/
//------------------------------------------------------------------------------

const unsigned char ramiro[] = {
0x80, 0xE0, 0xF0, 0xF8, 0xF8, 0xFC, 0x7C, 0x7E, 0x3E, 0x3E, 0x3E, 0x1F, 0x1F, 0x1F, 0x1F, 0x9F,
0x9F, 0x9F, 0x1F, 0x1F, 0x9F, 0x9F, 0x9F, 0x1F, 0x1F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x1F,
0x1F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x1F, 0x1F, 0x1F, 0x9F, 0x9F, 0x1F, 0x1F, 0x9F, 0x9F,
0x9F, 0x9F, 0x9F, 0x9F, 0x1F, 0x1F, 0x1F, 0x1F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x1F, 0x1F, 0x1F,
0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x1F, 0x1F, 0x1F, 0x3E, 0x3E, 0x3E, 0x7E, 0x7C, 0xFC, 0xF8,
0xF8, 0xF0, 0xE0, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7F, 0x7F, 0x0F, 0x7C, 0x7C, 0x0F, 0x7F, 0x7F, 0x00, 0x00, 0x7F, 0x7F, 0x6D,
0x6D, 0x6D, 0x6D, 0x00, 0x00, 0x7F, 0x7F, 0x61, 0x61, 0x61, 0x7F, 0x3F, 0x00, 0x00, 0x7F, 0x7F,
0x00, 0x00, 0x7F, 0x7F, 0x61, 0x61, 0x61, 0x7F, 0x3F, 0x00, 0x00, 0x3F, 0x7F, 0x61, 0x61, 0x61,
0x7F, 0x3F, 0x00, 0x00, 0x7F, 0x7F, 0x0D, 0x0D, 0x3D, 0x7F, 0x67, 0x40, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFC, 0xF8, 0xF8, 0xF0, 0xE0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x18, 0x18, 0x18,
0xF8, 0xF0, 0x00, 0x00, 0xF8, 0xF8, 0xD8, 0xD8, 0xD8, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFC, 0xF8,
0xF8, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x87, 0x8F, 0x8F, 0x8F, 0x0F, 0x0F, 0x0F, 0x8F,
0x8F, 0x07, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x87,
0x87, 0x86, 0x06, 0x06, 0x07, 0x83, 0x80, 0x80, 0x07, 0x07, 0x06, 0x06, 0x86, 0x86, 0x00, 0x00,
0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x07, 0x0F, 0x0F, 0x8F, 0x8F,
0x0F, 0x0F, 0x0F, 0x0F, 0x87, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x61, 0x61, 0x61, 0x7F,
0x3F, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x67, 0x67, 0x6D, 0x6D, 0x7D, 0x39, 0x10, 0x01, 0x01,
0x01, 0x7F, 0x7F, 0x01, 0x01, 0x01, 0x40, 0x78, 0x7E, 0x37, 0x33, 0x3F, 0x7E, 0x78, 0x40, 0x00,
0x7F, 0x7F, 0x07, 0x1E, 0x38, 0x7F, 0x7F, 0x00, 0x00, 0x3F, 0x7F, 0x61, 0x61, 0x61, 0x73, 0x33,
0x00, 0x00, 0x7F, 0x7F, 0x00, 0x40, 0x78, 0x7E, 0x37, 0x33, 0x3F, 0x7E, 0x78, 0x40, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x3F, 0x3E, 0x7E, 0x7C, 0x7C, 0x7C,
0x7C, 0x7C, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7E,
0x3E, 0x3F, 0x3F, 0x1F, 0x0F, 0x0F, 0x07, 0x01,
};




/* <Initialize variables in user.h and insert code for user algorithms.> */
const unsigned char ASCII[][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00} // 20
,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 ?
,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 ?
,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d ?
,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c <
,{0x14, 0x14, 0x14, 0x14, 0x14} // 3d =
,{0x00, 0x41, 0x22, 0x14, 0x08} // 3e >
,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c "\"
,{0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
,{0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
,{0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
,{0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j
,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
,{0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
,{0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
,{0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ~
,{0x78, 0x46, 0x41, 0x46, 0x78} // 7f DEL
};

void setup(void) {
  LCDInit(); //Init the LCD
}

void loop(void) {
  LCDClear();
 // LCDBitmap(SFEFlame);
 // delay(1000);

 // LCDClear();
 // LCDBitmap(SFEFlameBubble);
 /// delay(1000);

//  LCDClear();
 // LCDBitmap(awesome);
 // delay(1000);

  //LCDClear();
  LCDString("Hello World!");
 // delay(1000);
}

void gotoXY(int x, int y) {
  LCDWrite(0, 0x80 | x);  // Column.
  LCDWrite(0, 0x40 | y);  // Row.  ?
}

//This takes a large array of bits and sends them to the LCD
void LCDBitmap(char my_array[]){
  for (int index = 0 ; index < (LCD_X * LCD_Y / 8) ; index++)
    LCDWrite(LCD_DATA, my_array[index]);
}

//This function takes in a character, looks it up in the font table/array
//And writes it to the screen
//Each character is 8 bits tall and 5 bits wide. We pad one blank column of
//pixels on each side of the character for readability.
void LCDCharacter(char character) {
  LCDWrite(LCD_DATA, 0x00); //Blank vertical line padding

  for (int index = 0 ; index < 5 ; index++)
    LCDWrite(LCD_DATA, ASCII[character - 0x20][index]);
    //0x20 is the ASCII character for Space (' '). The font table starts with this character

  LCDWrite(LCD_DATA, 0x00); //Blank vertical line padding
}

//Given a string of characters, one by one is passed to the LCD
void LCDString(char *characters) {
  while (*characters)
  {
    LCDCharacter(*characters);
    *characters++;
  }
}

//Clears the LCD by writing zeros to the entire screen
void LCDClear(void) {
  for (int index = 0 ; index < (LCD_X * LCD_Y / 8) ; index++)
    LCDWrite(LCD_DATA, 0x00);

  gotoXY(0, 0); //After we clear the display, return to the home position
}

//This sends the magical commands to the PCD8544
void LCDInit(void) {

  //Configure control pins
    TRISBbits.TRISB3=0;
    TRISBbits.TRISB4=0;
    TRISBbits.TRISB5=0;
    TRISBbits.TRISB6=0;
    TRISBbits.TRISB7=0;

    LCD_DIN=0;
    LCD_CLK=0;
    LCD_DC=0;

//  pinMode(PIN_SCE, OUTPUT);
//  pinMode(PIN_RESET, OUTPUT);
//  pinMode(PIN_DC, OUTPUT);
//  pinMode(PIN_SDIN, OUTPUT);
//  pinMode(PIN_SCLK, OUTPUT);

  //Reset the LCD to a known state
 // digitalWrite(PIN_RESET, LOW);
  LCD_RST=0;
  //  digitalWrite(PIN_RESET, HIGH);
  LCD_RST=1;

  LCDWrite(LCD_COMMAND, 0x21); //Tell LCD that extended commands follow
  LCDWrite(LCD_COMMAND, 0xBB); //Set LCD Vop (Contrast): Try 0xB1(good @ 3.3V) or 0xBF if your display is too dark
  LCDWrite(LCD_COMMAND, 0x04); //Set Temp coefficent
  LCDWrite(LCD_COMMAND, 0x14); //LCD bias mode 1:48: Try 0x13 or 0x14

  LCDWrite(LCD_COMMAND, 0x20); //We must send 0x20 before modifying the display control mode
  LCDWrite(LCD_COMMAND, 0x0C); //Set display control, normal mode. 0x0D for inverse
}

//There are two memory banks in the LCD, data/RAM and commands. This
//function sets the DC pin high or low depending, and then sends
//the data byte
void LCDWrite(unsigned char data_or_command, unsigned char data) {
  unsigned char i,d;

  d=data;
  if(data_or_command==0)LCD_DC=0;
  else LCD_DC=1;
  //data_or_command; //Tell the LCD that we are writing either to data or a command

  //Send the data
  LCD_CE=0;
//  digitalWrite(PIN_SCE, LOW);

  for(i=0;i<8;i++)
  {
  LCD_DIN=0;
  if(d&0x80)LCD_DIN=1;
  LCD_CLK=1;
  d<<=1;
  LCD_CLK=0;
  }
//  shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
  LCD_CE=1;
//  digitalWrite(PIN_SCE, HIGH);
}

void InitApp(void)
{
    /* TODO Initialize User Ports/Peripherals/Project here */

    /* Setup analog functionality and port direction */
   
    /* Initialize peripherals */
    // OPTION_REG=0x80;
    /* Enable interrupts */
    TMR0IE=1;
    GIE=1;

}


Código: [Seleccionar]

system.h

/******************************************************************************/
/* System Level #define Macros                                                */
/******************************************************************************/

/* TODO Define system operating frequency */

/* Microcontroller MIPs (FCY) */
#define SYS_FREQ        400000L
#define FCY             SYS_FREQ/4

extern unsigned char spk_bit;
extern unsigned char led_bit;
extern unsigned char spk_enable,spk_enable2;
extern unsigned int led_counter;

/******************************************************************************/
/* System Function Prototypes                                                 */
/******************************************************************************/

/* Custom oscillator configuration funtions, reset source evaluation
functions, and other non-peripheral microcontroller initialization functions
go here. */

void ConfigureOscillator(void); /* Handles clock switching/osc initialization */



Código: [Seleccionar]
system.c

/*
 * File:   System.c
 * Author: Ramiro
 *
 * Created on 20 de junio de 2016, 9:42
 */

/******************************************************************************/
/*Files to Include                                                            */
/******************************************************************************/

#if defined(__XC)
    #include <xc.h>         /* XC8 General Include File */
#elif defined(HI_TECH_C)
    #include <htc.h>        /* HiTech General Include File */
#endif

#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */

#include "system.h"

/* Refer to the device datasheet for information about available
oscillator configurations. */
void ConfigureOscillator(void)
{
    /* TODO Add clock switching code if appropriate.  */

    /* Typical actions in this function are to tweak the oscillator tuning
    register, select new clock sources, and to wait until new clock sources
    are stable before resuming execution of the main project. */
}





Código: [Seleccionar]
main.c


#define _XTAL_FREQ 4000000

#include <xc.h>
#include <pic16f628a.h>
#include <stdio.h>
#include <stdlib.h>
#include "confbits.h"
#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */
#include "user.h"
#include "system.h" /* System funct/params, like osc/peripheral config */
                      /* User funct/params, such as InitApp */
#define triger PORTBbits.RB0
#define echo PORTBbits.RB1

/******************************************************************************/
/* User Global Variable Declaration                                           */
/******************************************************************************/

unsigned char led_bit,spk_bit,spk_enable,spk_enable2;
unsigned int led_counter,a;
char salida[20] ;
/* i.e. uint8_t <variable_name>; */

/******************************************************************************/
/* Main Program                                                               */
/******************************************************************************/
/************************/


void main(void)

{
      // **********************inicializo el micro
      // ******************** inicializacion cpu *************************** 
     
      PCONbits.OSCF;// reloj en 4 mhz
      CMCON = 0X07 ; //apaga los comparadores y habilita los pines de I/O
      TRISA = 0x00;
      PORTA = 0X00;
      TRISB = 0x00;
      TRISBbits.TRISB1 = 1;
     
   

    /* Configure the oscillator for the device */
    ConfigureOscillator();

    /* Initialize I/O and Peripherals for application */
    InitApp();
         
    led_counter=0;
    spk_bit=0;
    led_bit=0;
      LCDInit();
      LCDClear();
      gotoXY(0,0);
      LCDBitmap(ramiro);
     
      __delay_ms(5000);
      LCDClear();
             
    while(1)
    {
   
        T1CONbits.TMR1CS = 0;
       
        TMR1H = 0;                  //Sets the Initial Value of Timer
        TMR1L = 0;                  //Sets the Initial Value of Timer

       
        triger = 1; // disparo el triger del distanciometro
        __delay_us(10); // espero 10 us
       
        triger = 0; // apago el triger
       
       
           
       
       
       
       while(!echo);           //Waiting for Echo
       T1CONbits.TMR1ON = 1;              //Timer Starts
       while(echo);            //Waiting for Echo goes LOW
        T1CONbits.TMR1ON = 0;            //Timer Stops

       
               a = (TMR1L | (TMR1H<<8));   //Reads Timer Value
               a = a/58.82;                //Converts Time to Distance
                             //Distance Calibration
               itoa(salida,a,10);
               if(a>=2 && a<=400)          //Check whether the result is valid or not
               {
                LCDClear();
                gotoXY(15,2);

                LCDString("DISTANCIA");
                gotoXY(25,4);
                LCDString(salida);
                LCDString(" cm");
               }
               else
                {
                LCDClear;
                gotoXY(0,5);
                LCDString("out of range");
                }
                 __delay_ms(300);
                   
     //   if(spk_bit==1)
       //  {
         //   if((spk_enable==1)&&(spk_enable2==1))
           //  TRISBbits.TRISB6=1;
        // }  else TRISBbits.TRISB6=0;
             
    }
}
Título: Re:Mini curso "Programación en XC8"
Publicado por: NIN en 06 de Julio de 2016, 02:29:21
Buenas noches de nuevo. Realmente he aprendido mucho gracias a sus valiosisimas ayudas. (Sobre todo gracias a KILLER). Sin su ayuda creo que me hubiera desanimado y hubiera dejado esto botado.

Al grano.

Resulta que tengo esta configuracion:

 - Tienes que ingresar para ver archivos adjuntos -

Simplemente es :

Si aprieto RA0 se prende RB0
Si aprieto RA1 se prende RB1
Si aprieto RA2 se prende RA2.

Ya realice el codigo con "if...else" anidados. Este es el codigo que realice :

Código: [Seleccionar]
#include <xc.h>

#pragma config WDTE = OFF
#pragma config FOSC = XT
#pragma config CCPMX = RB0


void main()
{
    TRISA = 0b00000111;
    PORTA = 0b00000111;
    TRISB = 0b00000000;
    PORTB = 0b00000000;
    ANSEL = 0b00000000;   
    while(1)
    {
             
        if (PORTAbits.RA0==1)
        {
            PORTBbits.RB0=1;
        }
        else if (PORTAbits.RA1==1)
        {
            PORTBbits.RB1=1;
        }
        else if (PORTAbits.RA2==1)
        {
            PORTBbits.RB2=1;
        }
        else
        {
            PORTB = 0b00000000;
        }
    }
}

Me salio a la perfeccion. Pero ahora lo quiero hacer con las sentencia "switch...case". aqui empiezan mis problemas:

Código: [Seleccionar]
#include <xc.h>

#pragma config CCPMX = RB0
#pragma config WDTE = OFF

 void main (void)
{
     TRISA = 0b00000111;
    PORTA = 0b00000111;
    TRISB = 0b00000000;
    PORTB = 0b00000000;
    ANSEL = 0b00000000;
     
     unsigned char input ;
     
     while(1)
     {
         switch (input)
         {
             case :
             
         }
         
     }
         
   
}



El principal problema al que le busco  solucion es como puedo almacenar el estado de un puerto (boton pulsado o boton sin pulsar) en una variable en el xc8. (en este caso yo le puse "input"). En GCC es con "scanf()", pero como se puede hacer aqui ?

Saque esto del manual. Sin embargo el manual no dice nada sobre almacenamiento de variables para hacer match con el "case"

Código: [Seleccionar]
int a;
switch(input) {
case a: /* oops!
cannot use variable as part of a case label */
input++;
}

Bueno espero su ayuda.

Sinceramente,
NIN.
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 06 de Julio de 2016, 08:59:02
Código: C
  1. void main (void)
  2. {
  3.         unsigned char input ;
  4.  
  5.         TRISA = 0b00000111;
  6.         PORTA = 0b00000111;
  7.         TRISB = 0b00000000;
  8.         PORTB = 0b00000000;
  9.         ANSEL = 0b00000000;
  10.      
  11.    
  12.         while(1)
  13.         {
  14.                 input = PORTA & 0b111;          // Me aseguro que solo queden los valores de RA0, RA1 y RA2
  15.                 switch (input)
  16.                 {
  17.                 case 0b001:
  18.                         //RA0
  19.                         PORTBbits.RB0=1;
  20.                         break:
  21.                 case 0b010:
  22.                         PORTBbits.RB1=1;
  23.                         //RA1
  24.                         break:
  25.                 case 0b100:
  26.                         //RA2
  27.                         PORTBbits.RB2=1;
  28.                         break:
  29.                 default:
  30.                         //Cualquier otra combinacion ejemplo RA2 y RA1 juntos, etc.
  31.                         PORTB = 0;
  32.                         break;
  33.          }
  34.          
  35.      }
  36. }

EL switch case solo admite valores numericos, es decir 0x12 , 30 , 0b1213 , 'a' , o algun enum

Vas a observar que si presionas 2 juntos sea cual sea va a poner a 0 el puerto completo, por que al no estar el case con el numero que debe, entra en "default".
Título: Re:Mini curso "Programación en XC8"
Publicado por: AcoranTf en 20 de Julio de 2016, 21:51:07
Hola gente, necesito las librerias perifericas de XC8. Las encontre en un archivo instalador de windows, pero yo utilizo Linux y no me deja extraerlas de ahi.
¿Alguien las tiene o sabe de donde descargarlas en un formato compatible Linux?.

Saludos.
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 20 de Julio de 2016, 22:42:22
Realmente en 8 bits nunca me maneje con una libreria, creo ni siquiera dan el codigo, distinto a XC16 en adelante que si te dan el codigo de los perifericos y ademas deberias tener un PDF.

Por que la mayoria de los modulos son 2/3 registros como maximo.

PD: Yo uso el MPLAB en Linux
Título: Re:Mini curso "Programación en XC8"
Publicado por: AngelGris en 20 de Julio de 2016, 23:15:18
Hola gente, necesito las librerias perifericas de XC8. Las encontre en un archivo instalador de windows, pero yo utilizo Minux y no me deja extraerlas de ahi.
¿Alguien las tiene o sabe de donde descargarlas en un formato compatible Linux?.

Saludos.

  Hola AcoranTf, ¿A qué te refieres, a las de ADC, por ejemplo?
De ser así, las hay. Pero creo que sólo para las familias 18xxxxx
En Debian Jessie las tengo en "/opt/microchip/xc8/v1.33/sources/pic18/plib"
Título: Re:Mini curso "Programación en XC8"
Publicado por: AcoranTf en 20 de Julio de 2016, 23:29:57
Realmente en 8 bits nunca me maneje con una libreria, creo ni siquiera dan el codigo, distinto a XC16 en adelante que si te dan el codigo de los perifericos y ademas deberias tener un PDF.

Por que la mayoria de los modulos son 2/3 registros como maximo.

PD: Yo uso el MPLAB en Linux

Hola KILLERJC, principalmente las quiero para ver el codigo y aprender a hacer a "mano" algunas de sus funciones. El PDF al que te refieres no esta en mi instalacion, ya habia visto buscando por google que lo citan en algunos sitios, pero en mi PC no esta ese PDF.
Gracias de todos modos.


Hola gente, necesito las librerias perifericas de XC8. Las encontre en un archivo instalador de windows, pero yo utilizo Minux y no me deja extraerlas de ahi.
¿Alguien las tiene o sabe de donde descargarlas en un formato compatible Linux?.

Saludos.

  Hola AcoranTf, ¿A qué te refieres, a las de ADC, por ejemplo?
De ser así, las hay. Pero creo que sólo para las familias 18xxxxx
En Debian Jessie las tengo en "/opt/microchip/xc8/v1.33/sources/pic18/plib"

Hola Angel Gris, si me referia a esas y otras mas, son un monton de ellas para manejar los perifericos, aunque como le contestaba a KILLERJC, las quiero sobretodo para tener info de como se hacen algunas cosas. Y si se que solo valen para los PIC18. En esa carpeta ya mire y no hay nada, no se si sera porque la instalacion que yo hice es la que se descarga gratuitamente de Microchip y parece ser, segun lei que no incluye esas librerias. En la carpeta que citas yo solo tengo 21 archivos y dos carpetas, que no incluyen esas lñibrerias.
Gracias igualmente por tu respuesta.

Saludos.

Título: Re:Mini curso "Programación en XC8"
Publicado por: AcoranTf en 20 de Julio de 2016, 23:30:56
Lo borre por estar repetido.
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 20 de Julio de 2016, 23:38:17
Asi como dice AngelGris, es justamente para PIC18, pero no se si estan todas las funciones a simple vista

.../Microchip/xc8/v1.xx/docs/MPLAB_XC8_Peripheral_Libraries.pdf
.../Microchip/xc8/v1.xx/include/plib/...
.../Microchip/xc8/v1.xx/sources/pic18/plib/...

De todas formas creo mas facil usar el datasheet del micro, y al final de cada modulo te aparece que registros son los necesarios. Incluso te sule poner un paso a paso sobre como configurar el modulo.
En las librerias vas a ver muchas mas cosas de las que necesitas, si es que realmente queres aprenderlo.
Título: Re:Mini curso "Programación en XC8"
Publicado por: AcoranTf en 21 de Julio de 2016, 00:12:35
Asi como dice AngelGris, es justamente para PIC18, pero no se si estan todas las funciones a simple vista

.../Microchip/xc8/v1.xx/docs/MPLAB_XC8_Peripheral_Libraries.pdf
.../Microchip/xc8/v1.xx/include/plib/...
.../Microchip/xc8/v1.xx/sources/pic18/plib/...

De todas formas creo mas facil usar el datasheet del micro, y al final de cada modulo te aparece que registros son los necesarios. Incluso te sule poner un paso a paso sobre como configurar el modulo.
En las librerias vas a ver muchas mas cosas de las que necesitas, si es que realmente queres aprenderlo.

Entiendo lo que comentas, lo que ocurre es que pense que sria mas sencillo verlo en las librerias y mas si contienen comentarios, pero tienes razon, todo es ponerse tranquilamente con la documentacion del PIC.

Saludos.
Título: Re:Mini curso "Programación en XC8"
Publicado por: AngelGris en 21 de Julio de 2016, 09:39:08
  Yo también instalé la versión gratis. Ahora no estoy en casa, pero recuerdo que hay una carpeta por periférico. Me vienen a la mente, ADC, I2C, SPI, UART, CCPM, I2C por software.... a la noche me fijo en case y te paso el listado de las carpetas.

Título: Re:Mini curso "Programación en XC8"
Publicado por: AcoranTf en 21 de Julio de 2016, 12:39:15
  Yo también instalé la versión gratis. Ahora no estoy en casa, pero recuerdo que hay una carpeta por periférico. Me vienen a la mente, ADC, I2C, SPI, UART, CCPM, I2C por software.... a la noche me fijo en case y te paso el listado de las carpetas.

OK, eso no esta en mi instalacion, no se si lo habran cambiado. Voy a preparar una cuenta de FTP en mi servidor y te pasare los datos para que me envies todas esas carpetas comprimidas, si te parece bien.

Saludos.
Título: Re:Mini curso "Programación en XC8"
Publicado por: AngelGris en 21 de Julio de 2016, 13:53:51
  Yo también instalé la versión gratis. Ahora no estoy en casa, pero recuerdo que hay una carpeta por periférico. Me vienen a la mente, ADC, I2C, SPI, UART, CCPM, I2C por software.... a la noche me fijo en case y te paso el listado de las carpetas.

OK, eso no esta en mi instalacion, no se si lo habran cambiado. Voy a preparar una cuenta de FTP en mi servidor y te pasare los datos para que me envies todas esas carpetas comprimidas, si te parece bien.

Saludos.

  Dale, no hay ningún problema
Título: Re:Mini curso "Programación en XC8"
Publicado por: AcoranTf en 21 de Julio de 2016, 14:06:19

  Dale, no hay ningún problema

Te acabo de enviar un MP.

Título: Re:Mini curso "Programación en XC8"
Publicado por: AKENAFAB en 07 de Octubre de 2016, 19:45:37
Les comparto esta rutina para pwm 10bits.

La utilizo con los pic12F1840,16F

Código: C
  1. void PWM_set_DC(uint16_t pwm_DC); // duty cycle 10bits pwm

Código: C
  1. /**************************************************************/
  2.     void PWM_set_DC(uint16_t pwm_DC){
  3.    
  4.         uint8_t auxt = 0;
  5.         uint8_t ccp_temp = 0;
  6.        
  7.         auxt = pwm_DC << 4;     // swap byte
  8.         auxt &= 0b00110000;     // Enmascara dcb1:dcb0 LSB bits
  9.         ccp_temp = CCP1CON & 0b11001111; //Prepara registro temporal
  10.         ccp_temp |= auxt;   // cargno nuevos bits a variable temporal
  11.         CCPR1L = pwm_DC >> 2;   //MSB actualizo la parte alta
  12.         CCP1CON = ccp_temp;    // LSB actualizo 2bits parte baja
  13.        
  14.     }// pwm_set
  15.  
  16. /**************************************************************/

Código: C
  1. uint16_t duty_cycle;
  2.  
  3. int main(void) {
  4.  
  5.     while(1){
  6.          
  7.         for(duty_cycle = 0; duty_cycle < 512;duty_cycle++){ // 0 t0 50%
  8.        
  9.             PWM_set_DC(duty_cycle);             // establecer valor pwm
  10.  
  11.             __delay_ms(10);             // 10ms delay
  12.         }//for duty
  13.  
  14.     }//while loop
  15. }//main
Título: Re:Mini curso "Programación en XC8"
Publicado por: Sebas1010 en 04 de Noviembre de 2018, 10:30:42
Buenas hace tiempo que estoy en el foro pero nunca comente nada, generalmente empece a utilizar el CCS para programar en C los micros. Hace poco empece a meterme en el mundo de Mplab x C8 realice dos librerías para el LCD(16x2/20x4) y el ADC(10bits) para los pic 16f8xxx.
A medida que realice nuevas librerías las iré compartiendo.



Código: [Seleccionar]
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * File: LCD 16x2 y LCD 20x4                                                                             
 * Author: Sebas                                                                                 
 * Comments: Gama de pic 16f8XX                                                         
 * Revision history: 1.0a                                                                         
 * Descripcion: LCD HD44780 o equivalente                             
 * -Lcd_int();//Inicializacion del LCD                                 
 * -Lcd_printf();//Funcion para imprimir lo que queremos ver en el LCD
 * -Lcd_clear();//Funcion para limpiar pantalla                       
 * -Lcd_printf_String();//Funcion para imprimir un string             
 * -Lcd_gotoxy();//Funcion de la posicion de posicion en el LCD                                                                                                                                                                                           
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */                                                                   


#ifndef LCD20x4
#define LCD20x4
       
#define PIN_RS    PORTBbits.RB0
#define TRISBRS   TRISBbits.TRISB0

#define PIN_EN    PORTBbits.RB1
#define TRISBEN   TRISBbits.TRISB1

#define LCD_D4    PORTBbits.RB4
#define LCD_D4_T  TRISBbits.TRISB4

#define LCD_D5    PORTBbits.RB5
#define LCD_D5_T  TRISBbits.TRISB5

#define LCD_D6    PORTBbits.RB6
#define LCD_D6_T  TRISBbits.TRISB6

#define LCD_D7    PORTBbits.RB7
#define LCD_D7_T  TRISBbits.TRISB7
 
/*Declaracion de funciones*/

void Lcd_int();
void Lcd_control_cmd(char);
void Lcd_port(char);
void Lcd_write_data_port(char);
void Lcd_printf(char*);
void Lcd_clear();
void Lcd_printf_String(char*);
void Lcd_gotoxy(char , char);

/*Funciones*/

void Lcd_int() //configuracion para inicializar el LCD
{
    PIN_RS = 0;
    PIN_EN = 0;
    TRISBRS = 0;
    TRISBEN = 0;
    LCD_D4 = 0; 
    LCD_D4_T = 0;

    LCD_D5 = 0; 
    LCD_D5_T = 0;

    LCD_D6 = 0;   
    LCD_D6_T = 0;

    LCD_D7 = 0;
    LCD_D7_T = 0;
   
   
    Lcd_port(0x00);
    __delay_ms(20);
    Lcd_control_cmd(0x03);
    __delay_ms(5);
    Lcd_control_cmd(0x03);
__delay_ms(11);
    Lcd_control_cmd(0x03);
 
    Lcd_control_cmd(0x02);
    Lcd_control_cmd(0x02);
    Lcd_control_cmd(0x08);
    Lcd_control_cmd(0x00);
    Lcd_control_cmd(0x0C);
    Lcd_control_cmd(0x00);
    Lcd_control_cmd(0x06);
   
}

void Lcd_control_cmd(char data) //pines de control para LCD
{
  PIN_RS = 0;             
  Lcd_port(data);
  PIN_EN  = 1;             
  __delay_ms(4);
  PIN_EN  = 0;     
}

void Lcd_port(char data) //
{
if(data & 1)
    {   
LCD_D4 = 1;
    }   
else
    {   
LCD_D4 = 0;
    }   

if(data & 2)
    {   
LCD_D5 = 1;
    }   
else
    {   
LCD_D5 = 0;
    }   
if(data & 4)
    {   
LCD_D6 = 1;
    }   
else
{
        LCD_D6 = 0;
    }
if(data & 8)
    {   
LCD_D7 = 1;
    }   
else
    {   
LCD_D7 = 0;
    }   
}


void Lcd_write_data_port(char data)//Modo de 4 bits LCD
{
    char var;
    char y;
   var = (data & 0x0F);
   y = (data & 0xF0);
   PIN_RS = 1;             
   Lcd_port(y>>4);           
   PIN_EN = 1;
   __delay_us(40);
   PIN_EN = 0;
   Lcd_port(var);
   PIN_EN = 1;
   __delay_us(40);
   PIN_EN = 0;
   
}

void Lcd_printf(char *data)//Funcion para imprimir lo que queremos ver en el LCD
{
    while (*data) // Mientras no sea Null
    {
        Lcd_write_data_port(*data); // Envio el dato al LCD
        data++; // Incrementa el buffer de dato
    }
}
void Lcd_gotoxy(char x, char y)//Funcion de la posicion de posicion en el LCD
{
char temp;
    char dato1;
    char dato2;
if(y == 1)
{
  temp = 0x80 + x - 1;
dato1 = temp >> 4;
dato2 = temp & 0x0F;
        Lcd_control_cmd(dato1);
Lcd_control_cmd(dato2);
}
if(y == 2)
{
temp = 0xC0 + x - 1;
dato1 = temp >> 4;
dato2 = temp & 0x0F;
Lcd_control_cmd(dato1);
    Lcd_control_cmd(dato2);
}
    if(y == 3)
    {
        temp = 0x94 + x - 1;
dato1 = temp >> 4;
dato2 = temp & 0x0F;
Lcd_control_cmd(dato1);
    Lcd_control_cmd(dato2);
    }
    if(y == 4)
    {
        temp = 0xD4 + x - 1;
dato1 = temp >> 4;
dato2 = temp & 0x0F;
Lcd_control_cmd(dato1);
    Lcd_control_cmd(dato2);
    }
}
       

void Lcd_clear()//Funcion para limpiar pantalla
{
    Lcd_control_cmd(0);
    Lcd_control_cmd(1);
}
   
 void Lcd_printf_String(char *data)//Funcion imprime string
{
int i;
for(i=0;data[i]!='\0';i++)
  Lcd_write_data_port(data[i]);
}
 
 /*
 * Guardar caracteres especiales. en la CGRAM
 */
void lcd_put_caracter(char adress, char caracter[]) {
    int i;
    Lcd_control_cmd(0x40 + (adress * 8));
    for (i = 0; i < 8; i++) {
        Lcd_write_data_port(caracter[i]);
    }
}

void Lcd_Shift_Right()
{
    Lcd_control_cmd(0);
    Lcd_control_cmd(1);
Lcd_control_cmd(0x0C);
}

void Lcd_Shift_Left()
{
Lcd_control_cmd(0);
    Lcd_control_cmd(1);
Lcd_control_cmd(0x08);
}

#endif

ADC
Código: [Seleccionar]
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * File: ADC                                                       *             
 * Author: Sebas                                                   *
 * Comments: Gama de pic 16f8XX                                    *
 * Revision history: 1.0a                                          *
 * Descripcion: ADC de resolucion 10bits                           *
 * -ADC_Setup();//Elegir E/analagicas y REF interna o externar     *
 * -ADC_Selec_Fosc();//Seleccion de reloj                          *
 * -ADC_Result_Format_Select();//Justificacion del formato         *
 * -ADC_ON_OFF();//Activa o desactiva el ADC                       *                 
 * -ADC_READ();//Obtiene y calcula el valor del ADC y canal        *
 *  Esta descripta las opciones para elegir en los                 *
 *  #define AN_All_VDD_VSS (ejmplo)                                *                                                                                                                                   
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */                                                                   

#ifndef ADC_H
#define ADC_H

#define AN_All_VDD_VSS  1   
#define AN_ALL_VREFPOS_VSS 2
#define AN4_AN3_AN2_AN1_AN0_VDD_VSS 3
#define AN4_AN3_AN2_AN1_AN0_VREFPOS_VSS 4
#define AN3_AN1_AN0_VDD_VSS 5
#define AN1_AN0_VRESFPOS_VSS 6
#define ALL_SHUT_DOWN_AN 7
#define AN_ALL_VREFPOS_VREFNEG 8
#define AN5_AN4_AN3_AN2_AN1_AN0_VDD_VSS 9
#define AN5_AN4_AN2_AN1_AN0_VREFPOS_VSS 10
#define AN5_AN4_VREFPOS_VREFNEG_AN1_AN0 11
#define AN4_VREFPOS_VRESNEG_AN1_AN0 12
#define VREFPOS_VREFNEG_AN1_AN0 13
#define AN0_VDD_VSS 14
#define AN0_VRREFPOS_VREFNEG 15
#define FOSC2 1
#define FOSC8 2
#define FOSC32 3
#define FRC 4
#define FOSC4 5
#define FOSC16 6
#define FOSC64 7
#define FRC2 8
#define RIGHT 1
#define LETF 0
#define ON 1
#define OFF 2


/*Declaracion de funciones*/
void ADC_Setup(char);
unsigned int ADC_READ(unsigned char);
void ADC_Selec_Fosc(char);
void ADC_Result_Format_Select(char);
void ADC_ON_OFF(char);


void ADC_Setup(char set)
{
    if(set == 1)//Referencia Ref+:Vdd y Ref-:Vss
    {                     
       ADCON1bits.PCFG0 = 0;
       ADCON1bits.PCFG1 = 0;
       ADCON1bits.PCFG2 = 0;
       ADCON1bits.PCFG3 = 0;
       
    }
    if(set == 2)//Referencia Ref+:Vdd y Ref-:Vss
    {
       ADCON1bits.PCFG0 = 0;
       ADCON1bits.PCFG1 = 0;
       ADCON1bits.PCFG2 = 0;
       ADCON1bits.PCFG3 = 1;
    }
    if(set == 3)//Analogicos de AN4 a AN0 con VDD y VSS referencia interna
    {
       ADCON1bits.PCFG0 = 0;
       ADCON1bits.PCFG1 = 0;
       ADCON1bits.PCFG2 = 1;
       ADCON1bits.PCFG2 = 0;   
    }
    if(set == 4)//Analogicos de AN4 a AN0 con Ref externa +(AN3) y VSS referencia interna
    {
       ADCON1bits.PCFG0 = 0;
       ADCON1bits.PCFG1 = 0;
       ADCON1bits.PCFG2 = 1;
       ADCON1bits.PCFG3 = 1;   
    }
    if(set == 5)//Analogicos de AN3, AN1 y AN0 con ref interna VDD y VSS
    {
       ADCON1bits.PCFG0 = 0;
       ADCON1bits.PCFG1 = 1;
       ADCON1bits.PCFG2 = 0;
       ADCON1bits.PCFG3 = 0;   
    }
    if(set == 6)//Analogicos de AN1 y AN0 con Ref externa +(AN3) y VSS referencia interna
    {
       ADCON1bits.PCFG0 = 0;
       ADCON1bits.PCFG1 = 1;
       ADCON1bits.PCFG2 = 0;
       ADCON1bits.PCFG3 = 1;   
    }
    if(set == 7)//Apaga todas las entradas analogicas
    {
       ADCON1bits.PCFG0 = 0;
       ADCON1bits.PCFG1 = 1;
       ADCON1bits.PCFG2 = 1;
       ADCON1bits.PCFG3 = 0;   
    }
    if(set == 8)//Todas analogias pero AN3 es ref positivo y AN2 ref negativa
    {
       ADCON1bits.PCFG0 = 1;
       ADCON1bits.PCFG1 = 0;
       ADCON1bits.PCFG2 = 0;
       ADCON1bits.PCFG3 = 0;   
    }
    if(set == 9)//AN5 a AN0 con referencia VDD y VSS
    {
       ADCON1bits.PCFG0 = 1;
       ADCON1bits.PCFG1 = 0;
       ADCON1bits.PCFG2 = 0;
       ADCON1bits.PCFG3 = 1;   
    }
    if(set == 10)//AN5, AN4, AN2, AN1 y AN0 Ref positovo en AN3 y VSS
    {
       ADCON1bits.PCFG0 = 0;
       ADCON1bits.PCFG1 = 1;
       ADCON1bits.PCFG2 = 0;
       ADCON1bits.PCFG3 = 1;   
    }
    if(set == 11)//AN5, AN4, AN1 y AN0 Ref positovo en AN3 y AN2 Ref negativo
    {
       ADCON1bits.PCFG0 = 1;
       ADCON1bits.PCFG1 = 0;
       ADCON1bits.PCFG2 = 1;
       ADCON1bits.PCFG3 = 1;   
    }
    if(set == 12)//AAN4, AN1 y AN0 Ref positovo en AN3 y AN2 Ref negativo
    {
       ADCON1bits.PCFG0 = 1;
       ADCON1bits.PCFG1 = 1;
       ADCON1bits.PCFG2 = 0;
       ADCON1bits.PCFG3 = 0;   
    }
    if(set == 13)//AN1 y AN0, Ref positovo en AN3 y AN2 Ref negativo
    {
       ADCON1bits.PCFG0 = 1;
       ADCON1bits.PCFG1 = 1;
       ADCON1bits.PCFG2 = 0;
       ADCON1bits.PCFG3 = 1;   
    }
    if(set == 14)//AN0, Referencia VDD y VSS
    {
       ADCON1bits.PCFG0 = 1;
       ADCON1bits.PCFG1 = 1;
       ADCON1bits.PCFG2 = 1;
       ADCON1bits.PCFG3 = 0;   
    }
    if(set == 15)//AN0, Ref positovo en AN3 y AN2 Ref negativo
    {
       ADCON1bits.PCFG0 = 1;
       ADCON1bits.PCFG1 = 1;
       ADCON1bits.PCFG2 = 1;
       ADCON1bits.PCFG3 = 1;   
   }   
}

void ADC_Selec_Fosc(char set2)
{

    if (set2 == 1)
    {       
       ADCON1bits.ADCS2 = 0; 
       ADCON0bits.ADCS1 = 0;
       ADCON0bits.ADCS0 = 0;
    }
    if (set2 == 2)
    {       
       ADCON1bits.ADCS2 = 0; 
       ADCON0bits.ADCS1 = 0;
       ADCON0bits.ADCS0 = 1;
    }
    if (set2 == 3)
    {       
       ADCON1bits.ADCS2 = 0; 
       ADCON0bits.ADCS1 = 1;
       ADCON0bits.ADCS0 = 0;
    }
    if (set2 == 4)
    {       
       ADCON1bits.ADCS2 = 0; 
       ADCON0bits.ADCS1 = 1;
       ADCON0bits.ADCS0 = 1;
    }
    if (set2 == 5)
    {       
       ADCON1bits.ADCS2 = 1; 
       ADCON0bits.ADCS1 = 0;
       ADCON0bits.ADCS0 = 0;
    }
    if (set2 == 6)
    {       
       ADCON1bits.ADCS2 = 1; 
       ADCON0bits.ADCS1 = 0;
       ADCON0bits.ADCS0 = 1;
    }
    if (set2 == 7)
    {       
       ADCON1bits.ADCS2 = 1; 
       ADCON0bits.ADCS1 = 1;
       ADCON0bits.ADCS0 = 0;
    }
    if (set2 == 8)
    {       
       ADCON1bits.ADCS2 = 1; 
       ADCON0bits.ADCS1 = 1;
       ADCON0bits.ADCS0 = 1;
    }
}   
   
  void ADC_Result_Format_Select(char set3)
  {
     
      if (set3 == 0) //justificado a la izquierda
      {
           ADCON1bits.ADFM = 0;   
      }
      if(set3 == 1)//justifiacado a la derecha
      {
          ADCON1bits.ADFM = 1;
      }
  } 
         
  void ADC_ON_OFF(char set4)// //Activamos el ADC   
  {
      if(set4 == 1)
      {
        ADCON0bits.ADON = 1;     
      }
      if (set4 == 2)
      {
        ADCON0bits.ADON = 0;     
      }
  }
 
  unsigned int ADC_READ(unsigned char ch)
  {
    if(ch == 0)
    {
    ADCON0bits.CHS = 0;
    __delay_us(30);
    ADCON0bits.GO_nDONE = 1;
    while(ADCON0bits.GO_nDONE);
    return ((ADRESH<<8)+ADRESL);         
    }
    if(ch == 1)
    {
    ADCON0bits.CHS = 1;
    __delay_us(30);
    ADCON0bits.GO_nDONE = 1;
    while(ADCON0bits.GO_nDONE);
    return ((ADRESH<<8)+ADRESL);
    }
    if(ch == 2)
    {
    ADCON0bits.CHS = 2;
    __delay_us(30);
    ADCON0bits.GO_nDONE = 1;
    while(ADCON0bits.GO_nDONE); 
    return ((ADRESH<<8)+ADRESL);
    }
    if(ch == 3)
    {
    ADCON0bits.CHS = 3;
    __delay_us(30);
    ADCON0bits.GO_nDONE = 1;
    while(ADCON0bits.GO_nDONE);
    return ((ADRESH<<8)+ADRESL);
    }
    if(ch == 4)
    {
    ADCON0bits.CHS = 4;
    __delay_us(30);
    ADCON0bits.GO_nDONE = 1;
    while(ADCON0bits.GO_nDONE);
    return ((ADRESH<<8)+ADRESL);
    }
    if(ch == 5)
    {
    ADCON0bits.CHS = 5;
    __delay_us(30);
    ADCON0bits.GO_nDONE = 1;
    while(ADCON0bits.GO_nDONE);
    return ((ADRESH<<8)+ADRESL);
    }
    if(ch == 6)
    {
    ADCON0bits.CHS = 6;
    __delay_us(30);
    ADCON0bits.GO_nDONE = 1;
    while(ADCON0bits.GO_nDONE);
    return ((ADRESH<<8)+ADRESL);
    }
    if(ch == 7)
    {
    ADCON0bits.CHS = 7;
    __delay_us(30);
    ADCON0bits.GO_nDONE = 1;
    while(ADCON0bits.GO_nDONE);
    return ((ADRESH<<8)+ADRESL);
    } 
  }   
#endif




Ejemplo PIC 16f877a
Código: [Seleccionar]
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define _XTAL_FREQ 4000000
#include"lcd4x20.h"
#include"ADC.h"

#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

void main(void)
{
   
    int adc,adc2;
    float a,b;
    char s[20];
    char s2[20];
     
    TRISA=0b0000011;
   //Inicializacion de ADC
   ADC_Setup(AN_ALL_VREFPOS_VSS);
   ADC_Selec_Fosc(FOSC2);
   ADC_Result_Format_Select(RIGHT);
   ADC_ON_OFF(ON);
   //Incializacion del LCD
   Lcd_int();
   Lcd_clear();
       
   while(1)
   {
        adc= ADC_READ0();
        sprintf(s,"ADC:%04d",adc);
        Lcd_gotoxy(1,1);
        Lcd_printf_String(s);
       
       
        adc2= ADC_READ(1);
        sprintf(s,"ADC:%04d",adc2);     
        Lcd_gotoxy(1,2);
        Lcd_printf_String(s);
   }     
}



Título: Re:Mini curso "Programación en XC8"
Publicado por: Chrisbaf en 06 de Enero de 2019, 01:07:05
gracias por el aporte.
Título: Re:Mini curso "Programación en XC8"
Publicado por: Sebas1010 en 04 de Enero de 2020, 23:50:31
Holas, les consulto por el tema de la memoria eeprom que en esta misma seccion estan las rutina de escritura y lectura, el problema que tengo es que lo logro guardar datos que sean mayores a 255 y necesito por ejemplo guardar valores de 0 a 999 pero no me estoy dando cuenta para modificar esas funciones.

Gracias
Título: Re:Mini curso "Programación en XC8"
Publicado por: KILLERJC en 05 de Enero de 2020, 08:06:19
Holas, les consulto por el tema de la memoria eeprom que en esta misma seccion estan las rutina de escritura y lectura, el problema que tengo es que lo logro guardar datos que sean mayores a 255 y necesito por ejemplo guardar valores de 0 a 999 pero no me estoy dando cuenta para modificar esas funciones.

Gracias

Crea un puntero a char, asignale la memoria de la variable que tengas mas grande, y de alli usa el puntero para guardar el valor. Algo asi:

(No probe el codigo, ni verifique errores, es solo de guia)
Código: C
  1. uint16_t minumero;
  2. char * ptr;
  3.  
  4. ptr = (char *)&minumero;
  5. guardareeprom(0,*ptr++);
  6. guardareeprom(1, *ptr);
  7.  
  8.  
  9. //Para leerlo:
  10.  
  11. ptr = (char *)&minumero;
  12. leereeprom(0,*ptr++);
  13. leereeprom(1, *ptr);
Título: Re:Mini curso "Programación en XC8"
Publicado por: rigaplast en 13 de Octubre de 2020, 19:23:37
Perfecto. ¡Gracias!
Hola amigos, a continuación voy a publicar el mini curso que estoy armando de a poco en el foro uControl. Bienvenidas sugerencias, correcciones y aportes aquí mismo, por Twitter (http://www.twitter.com/lmtreser) o como sea!

Mini curso "Programación de micros en C desde 0"

Introducción

Hola, hoy empiezo este mini curso de programación de microcontroladores PIC en lenguaje C desde 0. La idea es aprender paso a paso, realizar algunos proyectos simples y sumar conocimientos.

Voy a trabajar sobre el sistema operativo Ubuntu, con software libre o gratuito. Para todos aquellos que utilizan Windows no van a tener inconvenientes porque los paquetes de software son multiplataforma. Voy a utilizar como entorno de desarrollo MPLAB X en conjunto con el compilador XC8. No me voy a detener en la instalación y configuración del IDE y del compilador ya que existen muchos tutoriales sobre esto (por ejemplo (http://www.automatismos-mdq.com.ar/blog/2011/04/instalar-mplab-x-en-ubuntu.html)). El microcontrolador por ahora es un PIC16F648A salvo indicación contraria!

El curso lo voy realizando sobre la marcha, en parte leyendo libros, en parte dudas consultadas a los expertos en el foro y en parte en experiencias propias. Por este motivo lo verán formarse "online" y a medida que el tiempo me lo permita ire sumando contenido. Les recomiendo que lean el tutorial sobre XC8 que escribió Suky (http://www.micros-designs.com.ar/tutorial-xc8-introduccion/) que es un buen punto de partida y el "Tutorial MPLAB C18 Desde Cero" (http://www.ucontrol.com.ar/forosmf/tutoriales-guias-y-cursos-en-ucontrol/tutorial-mplab-c18-desde-0/). También es de mucha utilidad tener a mano los ejemplos de Microchip para consulta: Microchip Code Examples (12F & 16F) (http://www.mediafire.com/?ajiish29dzjd09u).

Indice:

1.1. Estructura de un programa en C (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338215#msg338215)
1.2. ¡Hola Mundo! en C (o como hacer destellar un LED) (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338216#msg338216)
1.3. Leer un pulsador (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338217#msg338217)
1.4. Utilizando PWM (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338218#msg338218)
1.5. Uso de funciones (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338219#msg338219)
1.6. Variables y tipos de datos (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338220#msg338220)
1.7. Usando una interrupción por timer0 (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338221#msg338221)
1.8. Interrupciones de alta y baja prioridad (http://www.todopic.com.ar/foros/index.php?topic=40649.msg340202#msg340202)

Ejemplos y rutinas útiles:

2.1. Ejemplo de uso PIC18F4550, delays y USART (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339587#msg339587)
2.2. Escribir y leer una memoria EEPROM (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338370#msg338370)
2.3. Rutina para generar pausas extensas (http://www.todopic.com.ar/foros/index.php?topic=40649.msg338510#msg338510)
2.4. PIC16F819 controlando un modulo LCD 2x16 - 4 bits (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339676#msg339676)
2.5. Conversores ADC/PWM (uso de la función ITOA) (http://www.todopic.com.ar/foros/index.php?topic=40649.msg340679#msg340679)
2.6. Uso de I2C por software (http://www.todopic.com.ar/foros/index.php?topic=40649.msg340651#msg340651)

Bugs, errores, herramientas:

3.1. Corrección del bug "maldita linea roja" (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339853#msg339853)
3.2. Dolor de cabeza con el uso de la librería del LCD xlcd.h (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339865#msg339865)
3.3. Integrar Proteus VSM para hacer debug en los proyectos de MPLABX con el plugin Proteus VSM viewer (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339909#msg339909)
3.4. View Includes Hierarchy (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339910#msg339910)
3.5. View macro expansion (http://www.todopic.com.ar/foros/index.php?topic=40649.msg339911#msg339911)
3.6. Generador de código para los "Bits de configuración" (http://www.todopic.com.ar/foros/index.php?topic=40649.msg340566#msg340566)
Título: Re:Mini curso "Programación en XC8"
Publicado por: estebanfolcher en 21 de Noviembre de 2023, 16:56:08
Buenas tardes.

Tengo un problema, empecé con el cambio de Assembly a c hace unos días y estoy aprendiendo desde 0 aprovechó todo lo que encuentro por ay, para ir avanzando.
Pero me doy cuenta de que a medida que paso de lo simple a lo complicado me salen errores al compilar, los códigos (gran parte de ellos están hechos en versiones antiguas y me temo es ese es el motivo este es el primero a ver si me pueden ayudar.

MPLAB IDE 6.15   XC8 2.45  (C99)

#define <PIC.h>
#define <xc.h>


#define V0 RD0       
unsigned char q;


void interrupt ISR(void)   // aqui marca el error
{
    if(T0IF==1)         
    {
        TMR0=0x13;       
        T0IF=0;           
   
      if(++q>250)       
      {
         q=0;
         V0=!V0;       
      }
    }
}

void main(void)           
{

    TRISD=0B11111110;     
    PORTD=0B00000000;     
    T0CS=0;               
    PSA=0;                 
    PS0=0;                 
    PS1=1;                 
    PS2=0;                 
    TMR0=0x13;             
    T0IF=0;               
    T0IE=1;               
    GIE=1;                 
   
    while(1)               
    {

    }
}

este me da el siguiente error

error : variable has incomplete type 'void'
           

           error: expected ',' after top level declararator

Gracias por las respuestas.

PD; ay alguna hoja donde indique las modificaciones que hace xc8 en sus actualizaciones para poder guiarme yo.
Algo por ejemplo en que diga ( bit ya no funciona ahora es __bit)
Título: Re:Mini curso "Programación en XC8"
Publicado por: DominusDRR en 21 de Noviembre de 2023, 17:23:35
¿No te falta un guion bajo?

 interrupt_ISR
Título: Re:Mini curso "Programación en XC8"
Publicado por: estebanfolcher en 21 de Noviembre de 2023, 17:46:41
Buenas gracias por la ayuda.


pusssssssss. mas que un guion bajo. Ya lo encontre. Antes era ""void interrupt  ISR (void)"" ahora supongo que por la nueva versión de xc8  es ""void __interrrupt() ISR()""

esto es a lo que me refiero si todos te enseñan de una manera como es que esto cambia tanto, ¿esto no es algo estándar?? cada vez que actualizan es como aprender de 0

Gracias. PD: lo encontré en la misma página de microchip.
Título: Re:Mini curso "Programación en XC8"
Publicado por: DominusDRR en 21 de Noviembre de 2023, 17:53:35
Buenas gracias por la ayuda.


pusssssssss. mas que un guion bajo. Ya lo encontre. Antes era ""void interrupt  ISR (void)"" ahora supongo que por la nueva versión de xc8  es ""void __interrrupt() ISR()""

esto es a lo que me refiero si todos te enseñan de una manera como es que esto cambia tanto, ¿esto no es algo estándar?? cada vez que actualizan es como aprender de 0

Gracias. PD: lo encontré en la misma página de microchip.

Deberías leer el manual del compilador